From 27c28fe098b5827769e2d2d3148f322497233a40 Mon Sep 17 00:00:00 2001 From: Hauke Hund Date: Sun, 26 Jan 2020 02:13:52 +0100 Subject: [PATCH 01/55] com.google.common.base.Objects.equal to java.util.Objects.equals --- .../highmed/dsf/fhir/search/parameters/EndpointName.java | 5 ++--- .../dsf/fhir/search/parameters/EndpointStatus.java | 5 ++--- .../dsf/fhir/search/parameters/NamingSystemName.java | 7 +++---- .../dsf/fhir/search/parameters/OrganizationName.java | 5 ++--- .../highmed/dsf/fhir/search/parameters/ResourceId.java | 5 ++--- .../search/parameters/SubscriptionChannelPayload.java | 5 ++--- .../fhir/search/parameters/SubscriptionChannelType.java | 5 ++--- .../dsf/fhir/search/parameters/SubscriptionStatus.java | 5 ++--- .../highmed/dsf/fhir/search/parameters/TaskStatus.java | 5 ++--- .../parameters/basic/AbstractUrlAndVersionParameter.java | 9 ++++----- .../parameters/basic/AbstractVersionParameter.java | 5 ++--- 11 files changed, 25 insertions(+), 36 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointName.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointName.java index 7b5aeedb3..a6b46951e 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointName.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointName.java @@ -3,6 +3,7 @@ import java.sql.Array; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.util.Objects; import org.highmed.dsf.fhir.function.BiFunctionWithSqlException; import org.highmed.dsf.fhir.search.SearchQueryParameter.SearchParameterDefinition; @@ -11,8 +12,6 @@ import org.hl7.fhir.r4.model.Enumerations.SearchParamType; import org.hl7.fhir.r4.model.Resource; -import com.google.common.base.Objects; - @SearchParameterDefinition(name = EndpointName.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Endpoint-name", type = SearchParamType.STRING, documentation = "A name that this endpoint can be identified by") public class EndpointName extends AbstractStringParameter { @@ -80,7 +79,7 @@ public boolean matches(Resource resource) case CONTAINS: return e.getName() != null && e.getName().toLowerCase().contains(valueAndType.value.toLowerCase()); case EXACT: - return Objects.equal(e.getName(), valueAndType.value); + return Objects.equals(e.getName(), valueAndType.value); default: throw notDefined(); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointStatus.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointStatus.java index a7a7ef15b..4138c325b 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointStatus.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointStatus.java @@ -5,6 +5,7 @@ import java.sql.SQLException; import java.util.List; import java.util.Map; +import java.util.Objects; import javax.ws.rs.core.UriBuilder; @@ -19,8 +20,6 @@ import org.hl7.fhir.r4.model.Enumerations.SearchParamType; import org.hl7.fhir.r4.model.Resource; -import com.google.common.base.Objects; - @SearchParameterDefinition(name = EndpointStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Endpoint-status", type = SearchParamType.TOKEN, documentation = "The current status of the Endpoint (usually expected to be active)") public class EndpointStatus extends AbstractTokenParameter { @@ -99,7 +98,7 @@ public boolean matches(Resource resource) if (!(resource instanceof Endpoint)) return false; - return Objects.equal(((Endpoint) resource).getStatus(), status); + return Objects.equals(((Endpoint) resource).getStatus(), status); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/NamingSystemName.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/NamingSystemName.java index 541fffddc..42e9f04db 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/NamingSystemName.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/NamingSystemName.java @@ -3,17 +3,16 @@ import java.sql.Array; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.util.Objects; import org.highmed.dsf.fhir.function.BiFunctionWithSqlException; import org.highmed.dsf.fhir.search.SearchQueryParameter.SearchParameterDefinition; import org.highmed.dsf.fhir.search.parameters.basic.AbstractStringParameter; import org.hl7.fhir.r4.model.Endpoint; -import org.hl7.fhir.r4.model.NamingSystem; import org.hl7.fhir.r4.model.Enumerations.SearchParamType; +import org.hl7.fhir.r4.model.NamingSystem; import org.hl7.fhir.r4.model.Resource; -import com.google.common.base.Objects; - @SearchParameterDefinition(name = NamingSystemName.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/NamingSystem-name", type = SearchParamType.STRING, documentation = "A name that this NamingSystem can be identified by") public class NamingSystemName extends AbstractStringParameter { @@ -81,7 +80,7 @@ public boolean matches(Resource resource) case CONTAINS: return e.getName() != null && e.getName().toLowerCase().contains(valueAndType.value.toLowerCase()); case EXACT: - return Objects.equal(e.getName(), valueAndType.value); + return Objects.equals(e.getName(), valueAndType.value); default: throw notDefined(); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationName.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationName.java index 26f1d35c4..171e870df 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationName.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationName.java @@ -3,6 +3,7 @@ import java.sql.Array; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.util.Objects; import org.highmed.dsf.fhir.function.BiFunctionWithSqlException; import org.highmed.dsf.fhir.search.SearchQueryParameter.SearchParameterDefinition; @@ -11,8 +12,6 @@ import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Resource; -import com.google.common.base.Objects; - @SearchParameterDefinition(name = OrganizationName.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Organization-name", type = SearchParamType.STRING, documentation = "A portion of the organization's name or alias") public class OrganizationName extends AbstractStringParameter { @@ -84,7 +83,7 @@ public boolean matches(Resource resource) case CONTAINS: return o.getName() != null && o.getName().toLowerCase().contains(valueAndType.value.toLowerCase()); case EXACT: - return Objects.equal(o.getName(), valueAndType.value); + return Objects.equals(o.getName(), valueAndType.value); default: throw notDefined(); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ResourceId.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ResourceId.java index cc18f3641..443eeb730 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ResourceId.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ResourceId.java @@ -5,6 +5,7 @@ import java.sql.SQLException; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.UUID; import javax.ws.rs.core.UriBuilder; @@ -18,8 +19,6 @@ import org.hl7.fhir.r4.model.Resource; import org.postgresql.util.PGobject; -import com.google.common.base.Objects; - import ca.uhn.fhir.parser.DataFormatException; @SearchParameterDefinition(name = ResourceId.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Resource-id", type = SearchParamType.TOKEN, documentation = "Logical id of this artifact") @@ -126,7 +125,7 @@ public void modifyBundleUri(UriBuilder bundleUri) public boolean matches(Resource resource) { if (isDefined()) - return Objects.equal(resource.getId(), id.toString()); + return Objects.equals(resource.getId(), id.toString()); else throw notDefined(); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionChannelPayload.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionChannelPayload.java index 442f202b3..841da7c86 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionChannelPayload.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionChannelPayload.java @@ -5,6 +5,7 @@ import java.sql.SQLException; import java.util.List; import java.util.Map; +import java.util.Objects; import javax.ws.rs.core.UriBuilder; @@ -16,8 +17,6 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.Subscription; -import com.google.common.base.Objects; - @SearchParameterDefinition(name = SubscriptionChannelPayload.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Subscription.channel.payload", type = SearchParamType.TOKEN, documentation = "The mime-type of the notification payload") public class SubscriptionChannelPayload extends AbstractTokenParameter { @@ -79,7 +78,7 @@ public boolean matches(Resource resource) if (!(resource instanceof Subscription)) return false; - return Objects.equal(((Subscription) resource).getChannel().getPayload(), payloadMimeType); + return Objects.equals(((Subscription) resource).getChannel().getPayload(), payloadMimeType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionChannelType.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionChannelType.java index f8d61430d..63d830ef6 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionChannelType.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionChannelType.java @@ -5,6 +5,7 @@ import java.sql.SQLException; import java.util.List; import java.util.Map; +import java.util.Objects; import javax.ws.rs.core.UriBuilder; @@ -17,8 +18,6 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.Subscription; -import com.google.common.base.Objects; - @SearchParameterDefinition(name = SubscriptionChannelType.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Subscription.channel.type", type = SearchParamType.TOKEN, documentation = "The type of channel for the sent notifications") public class SubscriptionChannelType extends AbstractTokenParameter { @@ -95,7 +94,7 @@ public boolean matches(Resource resource) if (!(resource instanceof Subscription)) return false; - return Objects.equal(((Subscription) resource).getChannel().getType(), channelType); + return Objects.equals(((Subscription) resource).getChannel().getType(), channelType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionStatus.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionStatus.java index 09a3a0d04..ae93490a6 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionStatus.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionStatus.java @@ -5,6 +5,7 @@ import java.sql.SQLException; import java.util.List; import java.util.Map; +import java.util.Objects; import javax.ws.rs.core.UriBuilder; @@ -17,8 +18,6 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.Subscription; -import com.google.common.base.Objects; - @SearchParameterDefinition(name = SubscriptionStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Subscription.status", type = SearchParamType.TOKEN, documentation = "Search by subscription status") public class SubscriptionStatus extends AbstractTokenParameter { @@ -95,7 +94,7 @@ public boolean matches(Resource resource) if (!(resource instanceof Subscription)) return false; - return Objects.equal(((Subscription) resource).getStatus(), status); + return Objects.equals(((Subscription) resource).getStatus(), status); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/TaskStatus.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/TaskStatus.java index f8a240890..69aa51abd 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/TaskStatus.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/TaskStatus.java @@ -5,6 +5,7 @@ import java.sql.SQLException; import java.util.List; import java.util.Map; +import java.util.Objects; import javax.ws.rs.core.UriBuilder; @@ -19,8 +20,6 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.Task; -import com.google.common.base.Objects; - @SearchParameterDefinition(name = TaskStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Task-status", type = SearchParamType.TOKEN, documentation = "Search by task status") public class TaskStatus extends AbstractTokenParameter { @@ -99,7 +98,7 @@ public boolean matches(Resource resource) if (!(resource instanceof Task)) return false; - return Objects.equal(((Task) resource).getStatus(), status); + return Objects.equals(((Task) resource).getStatus(), status); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/basic/AbstractUrlAndVersionParameter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/basic/AbstractUrlAndVersionParameter.java index 97e0ab2ad..5a5fda208 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/basic/AbstractUrlAndVersionParameter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/basic/AbstractUrlAndVersionParameter.java @@ -3,13 +3,12 @@ import java.sql.Array; import java.sql.PreparedStatement; import java.sql.SQLException; +import java.util.Objects; import org.highmed.dsf.fhir.function.BiFunctionWithSqlException; import org.hl7.fhir.r4.model.MetadataResource; import org.hl7.fhir.r4.model.Resource; -import com.google.common.base.Objects; - public abstract class AbstractUrlAndVersionParameter extends AbstractCanonicalUrlParameter { @@ -83,11 +82,11 @@ public boolean matches(Resource resource) switch (valueAndType.type) { case PRECISE: - return Objects.equal(mRes.getUrl(), valueAndType.url) - && (valueAndType.version == null || Objects.equal(mRes.getVersion(), valueAndType.version)); + return Objects.equals(mRes.getUrl(), valueAndType.url) + && (valueAndType.version == null || Objects.equals(mRes.getVersion(), valueAndType.version)); case BELOW: return mRes.getUrl() != null && mRes.getUrl().startsWith(valueAndType.url) - && (valueAndType.version == null || Objects.equal(mRes.getVersion(), valueAndType.version)); + && (valueAndType.version == null || Objects.equals(mRes.getVersion(), valueAndType.version)); default: throw notDefined(); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/basic/AbstractVersionParameter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/basic/AbstractVersionParameter.java index 4f0eb4dfc..60e1fbcb1 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/basic/AbstractVersionParameter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/basic/AbstractVersionParameter.java @@ -5,6 +5,7 @@ import java.sql.SQLException; import java.util.List; import java.util.Map; +import java.util.Objects; import org.highmed.dsf.fhir.function.BiFunctionWithSqlException; import org.highmed.dsf.fhir.search.SearchQueryParameterError; @@ -12,8 +13,6 @@ import org.hl7.fhir.r4.model.MetadataResource; import org.hl7.fhir.r4.model.Resource; -import com.google.common.base.Objects; - public abstract class AbstractVersionParameter extends AbstractTokenParameter { public static final String PARAMETER_NAME = "version"; @@ -79,7 +78,7 @@ public boolean matches(Resource resource) MetadataResource mRes = (MetadataResource) resource; - return Objects.equal(mRes.getVersion(), version); + return Objects.equals(mRes.getVersion(), version); } @Override From be263c99c9e15dfd0b2b35f2e5bcc7f3696f59f6 Mon Sep 17 00:00:00 2001 From: Hauke Hund Date: Sun, 26 Jan 2020 02:17:21 +0100 Subject: [PATCH 02/55] added resource ActivityDefinition and some search parameters --- .../ActivityDefinitionJsonFhirAdapter.java | 16 +++ .../ActivityDefinitionXmlFhirAdapter.java | 16 +++ .../dsf/fhir/dao/ActivityDefinitionDao.java | 7 ++ .../dao/jdbc/ActivityDefinitionDaoJdbc.java | 29 +++++ .../dsf/fhir/dao/jdbc/CodeSystemDaoJdbc.java | 7 +- .../dsf/fhir/dao/jdbc/ValueSetDaoJdbc.java | 7 +- .../dsf/fhir/dao/provider/DaoProvider.java | 3 + .../fhir/dao/provider/DaoProviderImpl.java | 22 +++- .../ActivityDefinitionIdentifier.java | 32 +++++ .../parameters/ActivityDefinitionName.java | 102 ++++++++++++++++ .../parameters/ActivityDefinitionStatus.java | 110 +++++++++++++++++ .../parameters/ActivityDefinitionUrl.java | 24 ++++ .../parameters/ActivityDefinitionVersion.java | 29 +++++ .../search/parameters/CodeSystemStatus.java | 111 ++++++++++++++++++ .../search/parameters/ValueSetStatus.java | 110 +++++++++++++++++ .../dsf/fhir/service/ReferenceExtractor.java | 4 +- .../fhir/service/ReferenceExtractorImpl.java | 32 +++++ .../dsf/fhir/spring/config/DaoConfig.java | 12 +- .../fhir/spring/config/WebserviceConfig.java | 21 ++++ .../impl/ActivityDefinitionServiceImpl.java | 28 +++++ .../impl/ConformanceServiceImpl.java | 25 +++- .../jaxrs/ActivityDefinitionServiceJaxrs.java | 18 +++ .../ActivityDefinitionServiceSecure.java | 14 +++ .../ActivityDefinitionService.java | 7 ++ ...b.activity_definitions.changelog-0.1.0.xml | 47 ++++++++ .../src/main/resources/db/db.changelog.xml | 1 + .../fhir/dao/ActivityDefinitionDaoTest.java | 53 +++++++++ .../dsf/fhir/test/TestSuiteDbTests.java | 13 +- .../client/FhirWebserviceClientJersey.java | 54 +++++---- 29 files changed, 907 insertions(+), 47 deletions(-) create mode 100644 dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/ActivityDefinitionJsonFhirAdapter.java create mode 100644 dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/ActivityDefinitionXmlFhirAdapter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDao.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionIdentifier.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionName.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionStatus.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionUrl.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionVersion.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemStatus.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetStatus.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ActivityDefinitionServiceImpl.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/jaxrs/ActivityDefinitionServiceJaxrs.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ActivityDefinitionServiceSecure.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/specification/ActivityDefinitionService.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/db/db.activity_definitions.changelog-0.1.0.xml create mode 100644 dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDaoTest.java diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/ActivityDefinitionJsonFhirAdapter.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/ActivityDefinitionJsonFhirAdapter.java new file mode 100644 index 000000000..5b5c365ac --- /dev/null +++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/ActivityDefinitionJsonFhirAdapter.java @@ -0,0 +1,16 @@ +package org.highmed.dsf.fhir.adapter; + +import javax.ws.rs.ext.Provider; + +import org.hl7.fhir.r4.model.ActivityDefinition; + +import ca.uhn.fhir.context.FhirContext; + +@Provider +public class ActivityDefinitionJsonFhirAdapter extends JsonFhirAdapter +{ + public ActivityDefinitionJsonFhirAdapter(FhirContext fhirContext) + { + super(fhirContext, ActivityDefinition.class); + } +} diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/ActivityDefinitionXmlFhirAdapter.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/ActivityDefinitionXmlFhirAdapter.java new file mode 100644 index 000000000..c7f286bd4 --- /dev/null +++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/ActivityDefinitionXmlFhirAdapter.java @@ -0,0 +1,16 @@ +package org.highmed.dsf.fhir.adapter; + +import javax.ws.rs.ext.Provider; + +import org.hl7.fhir.r4.model.ActivityDefinition; + +import ca.uhn.fhir.context.FhirContext; + +@Provider +public class ActivityDefinitionXmlFhirAdapter extends XmlFhirAdapter +{ + public ActivityDefinitionXmlFhirAdapter(FhirContext fhirContext) + { + super(fhirContext, ActivityDefinition.class); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDao.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDao.java new file mode 100644 index 000000000..9fbe1e414 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDao.java @@ -0,0 +1,7 @@ +package org.highmed.dsf.fhir.dao; + +import org.hl7.fhir.r4.model.ActivityDefinition; + +public interface ActivityDefinitionDao extends ResourceDao +{ +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java new file mode 100644 index 000000000..0e33f9798 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java @@ -0,0 +1,29 @@ +package org.highmed.dsf.fhir.dao.jdbc; + +import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; +import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionIdentifier; +import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionName; +import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionStatus; +import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionUrl; +import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionVersion; +import org.hl7.fhir.r4.model.ActivityDefinition; + +import ca.uhn.fhir.context.FhirContext; + +public class ActivityDefinitionDaoJdbc extends AbstractResourceDaoJdbc + implements ActivityDefinitionDao +{ + public ActivityDefinitionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + { + super(dataSource, fhirContext, ActivityDefinition.class, "activity_definitions", "activity_definition", + "activity_definition_id", ActivityDefinitionIdentifier::new, ActivityDefinitionName::new, + ActivityDefinitionStatus::new, ActivityDefinitionUrl::new, ActivityDefinitionVersion::new); + } + + @Override + protected ActivityDefinition copy(ActivityDefinition resource) + { + return resource.copy(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/CodeSystemDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/CodeSystemDaoJdbc.java index 25cca4d18..bb848b6cf 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/CodeSystemDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/CodeSystemDaoJdbc.java @@ -6,6 +6,7 @@ import org.apache.commons.dbcp2.BasicDataSource; import org.highmed.dsf.fhir.dao.CodeSystemDao; import org.highmed.dsf.fhir.search.parameters.CodeSystemIdentifier; +import org.highmed.dsf.fhir.search.parameters.CodeSystemStatus; import org.highmed.dsf.fhir.search.parameters.CodeSystemUrl; import org.highmed.dsf.fhir.search.parameters.CodeSystemVersion; import org.hl7.fhir.r4.model.CodeSystem; @@ -19,10 +20,10 @@ public class CodeSystemDaoJdbc extends AbstractResourceDaoJdbc imple public CodeSystemDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, CodeSystem.class, "code_systems", "code_system", "code_system_id", - CodeSystemUrl::new, CodeSystemVersion::new, CodeSystemIdentifier::new); + CodeSystemIdentifier::new, CodeSystemStatus::new, CodeSystemUrl::new, CodeSystemVersion::new); - readByUrl = new ReadByUrlDaoJdbc<>(this::getDataSource, this::getResource, getResourceTable(), getResourceColumn(), - getResourceIdColumn()); + readByUrl = new ReadByUrlDaoJdbc<>(this::getDataSource, this::getResource, getResourceTable(), + getResourceColumn(), getResourceIdColumn()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ValueSetDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ValueSetDaoJdbc.java index 0e0080012..4513019c1 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ValueSetDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ValueSetDaoJdbc.java @@ -6,6 +6,7 @@ import org.apache.commons.dbcp2.BasicDataSource; import org.highmed.dsf.fhir.dao.ValueSetDao; import org.highmed.dsf.fhir.search.parameters.ValueSetIdentifier; +import org.highmed.dsf.fhir.search.parameters.ValueSetStatus; import org.highmed.dsf.fhir.search.parameters.ValueSetUrl; import org.highmed.dsf.fhir.search.parameters.ValueSetVersion; import org.hl7.fhir.r4.model.ValueSet; @@ -19,10 +20,10 @@ public class ValueSetDaoJdbc extends AbstractResourceDaoJdbc implement public ValueSetDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, ValueSet.class, "value_sets", "value_set", "value_set_id", - ValueSetIdentifier::new, ValueSetUrl::new, ValueSetVersion::new); + ValueSetIdentifier::new, ValueSetStatus::new, ValueSetUrl::new, ValueSetVersion::new); - readByUrl = new ReadByUrlDaoJdbc<>(this::getDataSource, this::getResource, getResourceTable(), getResourceColumn(), - getResourceIdColumn()); + readByUrl = new ReadByUrlDaoJdbc<>(this::getDataSource, this::getResource, getResourceTable(), + getResourceColumn(), getResourceIdColumn()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProvider.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProvider.java index 6eec9dafa..4ac988eef 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProvider.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProvider.java @@ -2,6 +2,7 @@ import java.util.Optional; +import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; import org.highmed.dsf.fhir.dao.BinaryDao; import org.highmed.dsf.fhir.dao.BundleDao; import org.highmed.dsf.fhir.dao.CodeSystemDao; @@ -26,6 +27,8 @@ public interface DaoProvider { + ActivityDefinitionDao getActivityDefinitionDao(); + BinaryDao getBinaryDao(); BundleDao getBundleDao(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProviderImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProviderImpl.java index f66dea7c5..867e81c7f 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProviderImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProviderImpl.java @@ -5,6 +5,7 @@ import java.util.Objects; import java.util.Optional; +import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; import org.highmed.dsf.fhir.dao.BinaryDao; import org.highmed.dsf.fhir.dao.BundleDao; import org.highmed.dsf.fhir.dao.CodeSystemDao; @@ -25,6 +26,7 @@ import org.highmed.dsf.fhir.dao.SubscriptionDao; import org.highmed.dsf.fhir.dao.TaskDao; import org.highmed.dsf.fhir.dao.ValueSetDao; +import org.hl7.fhir.r4.model.ActivityDefinition; import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.CodeSystem; @@ -50,6 +52,7 @@ public class DaoProviderImpl implements DaoProvider, InitializingBean { + private final ActivityDefinitionDao activityDefinitionDao; private final BinaryDao binaryDao; private final BundleDao bundleDao; private final CodeSystemDao codeSystemDao; @@ -73,15 +76,16 @@ public class DaoProviderImpl implements DaoProvider, InitializingBean private final Map, ResourceDao> daosByResourecClass = new HashMap<>(); private final Map> daosByResourceTypeName = new HashMap<>(); - public DaoProviderImpl(BinaryDao binaryDao, BundleDao bundleDao, CodeSystemDao codeSystemDao, - EndpointDao endpointDao, GroupDao groupDao, HealthcareServiceDao healthcareServiceDao, - LocationDao locationDao, NamingSystemDao namingSystemDao, OrganizationDao organizationDao, - PatientDao patientDao, PractitionerDao practitionerDao, PractitionerRoleDao practitionerRoleDao, - ProvenanceDao provenanceDao, ResearchStudyDao researchStudyDao, + public DaoProviderImpl(ActivityDefinitionDao activityDefinitionDao, BinaryDao binaryDao, BundleDao bundleDao, + CodeSystemDao codeSystemDao, EndpointDao endpointDao, GroupDao groupDao, + HealthcareServiceDao healthcareServiceDao, LocationDao locationDao, NamingSystemDao namingSystemDao, + OrganizationDao organizationDao, PatientDao patientDao, PractitionerDao practitionerDao, + PractitionerRoleDao practitionerRoleDao, ProvenanceDao provenanceDao, ResearchStudyDao researchStudyDao, StructureDefinitionDao structureDefinitionDao, StructureDefinitionSnapshotDao structureDefinitionSnapshotDao, SubscriptionDao subscriptionDao, TaskDao taskDao, ValueSetDao valueSetDao) { + this.activityDefinitionDao = activityDefinitionDao; this.binaryDao = binaryDao; this.bundleDao = bundleDao; this.codeSystemDao = codeSystemDao; @@ -102,6 +106,7 @@ public DaoProviderImpl(BinaryDao binaryDao, BundleDao bundleDao, CodeSystemDao c this.taskDao = taskDao; this.valueSetDao = valueSetDao; + daosByResourecClass.put(ActivityDefinition.class, activityDefinitionDao); daosByResourecClass.put(Binary.class, binaryDao); daosByResourecClass.put(Bundle.class, bundleDao); daosByResourecClass.put(CodeSystem.class, codeSystemDao); @@ -127,6 +132,7 @@ public DaoProviderImpl(BinaryDao binaryDao, BundleDao bundleDao, CodeSystemDao c @Override public void afterPropertiesSet() throws Exception { + Objects.requireNonNull(activityDefinitionDao, "activityDefinitionDao"); Objects.requireNonNull(binaryDao, "binaryDao"); Objects.requireNonNull(bundleDao, "bundleDao"); Objects.requireNonNull(codeSystemDao, "codeSystemDao"); @@ -148,6 +154,12 @@ public void afterPropertiesSet() throws Exception Objects.requireNonNull(valueSetDao, "valueSetDao"); } + @Override + public ActivityDefinitionDao getActivityDefinitionDao() + { + return activityDefinitionDao; + } + @Override public BinaryDao getBinaryDao() { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionIdentifier.java new file mode 100644 index 000000000..91d874e71 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionIdentifier.java @@ -0,0 +1,32 @@ +package org.highmed.dsf.fhir.search.parameters; + +import org.highmed.dsf.fhir.search.SearchQueryParameter.SearchParameterDefinition; +import org.highmed.dsf.fhir.search.parameters.basic.AbstractIdentifierParameter; +import org.hl7.fhir.r4.model.ActivityDefinition; +import org.hl7.fhir.r4.model.Enumerations.SearchParamType; +import org.hl7.fhir.r4.model.Resource; + +@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.​identifier", type = SearchParamType.TOKEN, documentation = "External identifier for the activity definition") +public class ActivityDefinitionIdentifier extends AbstractIdentifierParameter +{ + public static final String RESOURCE_COLUMN = "activity_definition"; + + public ActivityDefinitionIdentifier() + { + super(RESOURCE_COLUMN); + } + + @Override + public boolean matches(Resource resource) + { + if (!isDefined()) + throw notDefined(); + + if (!(resource instanceof ActivityDefinition)) + return false; + + ActivityDefinition e = (ActivityDefinition) resource; + + return identifierMatches(e.getIdentifier()); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionName.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionName.java new file mode 100644 index 000000000..281317892 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionName.java @@ -0,0 +1,102 @@ +package org.highmed.dsf.fhir.search.parameters; + +import java.sql.Array; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Objects; + +import org.highmed.dsf.fhir.function.BiFunctionWithSqlException; +import org.highmed.dsf.fhir.search.SearchQueryParameter.SearchParameterDefinition; +import org.highmed.dsf.fhir.search.parameters.basic.AbstractStringParameter; +import org.hl7.fhir.r4.model.ActivityDefinition; +import org.hl7.fhir.r4.model.Enumerations.SearchParamType; +import org.hl7.fhir.r4.model.Resource; + +@SearchParameterDefinition(name = ActivityDefinitionName.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.​name", type = SearchParamType.STRING, documentation = "Computationally friendly name of the activity definition") +public class ActivityDefinitionName extends AbstractStringParameter +{ + public static final String PARAMETER_NAME = "name"; + + public ActivityDefinitionName() + { + super(PARAMETER_NAME); + } + + @Override + public String getFilterQuery() + { + switch (valueAndType.type) + { + case STARTS_WITH: + case CONTAINS: + return "lower(activity_definition->>'name') LIKE ?"; + case EXACT: + return "activity_definition->>'name' = ?"; + default: + return ""; + } + } + + @Override + public int getSqlParameterCount() + { + return 1; + } + + @Override + public void modifyStatement(int parameterIndex, int subqueryParameterIndex, PreparedStatement statement, + BiFunctionWithSqlException arrayCreator) throws SQLException + { + switch (valueAndType.type) + { + case STARTS_WITH: + statement.setString(parameterIndex, valueAndType.value.toLowerCase() + "%"); + return; + case CONTAINS: + statement.setString(parameterIndex, "%" + valueAndType.value.toLowerCase() + "%"); + return; + case EXACT: + statement.setString(parameterIndex, valueAndType.value); + return; + } + } + + @Override + public boolean matches(Resource resource) + { + if (!isDefined()) + throw notDefined(); + + if (!(resource instanceof ActivityDefinition)) + return false; + + ActivityDefinition e = (ActivityDefinition) resource; + + switch (valueAndType.type) + { + case STARTS_WITH: + return e.getName() != null && e.getName().toLowerCase().startsWith(valueAndType.value.toLowerCase()); + case CONTAINS: + return e.getName() != null && e.getName().toLowerCase().contains(valueAndType.value.toLowerCase()); + case EXACT: + return Objects.equals(e.getName(), valueAndType.value); + default: + throw notDefined(); + } + } + + @Override + protected String getSortSql(String sortDirectionWithSpacePrefix) + { + switch (valueAndType.type) + { + case STARTS_WITH: + case CONTAINS: + return "lower(activity_definition->>'name')" + sortDirectionWithSpacePrefix; + case EXACT: + return "activity_definition->>'name'" + sortDirectionWithSpacePrefix; + default: + return ""; + } + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionStatus.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionStatus.java new file mode 100644 index 000000000..5166681b7 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionStatus.java @@ -0,0 +1,110 @@ +package org.highmed.dsf.fhir.search.parameters; + +import java.sql.Array; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import javax.ws.rs.core.UriBuilder; + +import org.highmed.dsf.fhir.function.BiFunctionWithSqlException; +import org.highmed.dsf.fhir.search.SearchQueryParameter.SearchParameterDefinition; +import org.highmed.dsf.fhir.search.SearchQueryParameterError; +import org.highmed.dsf.fhir.search.SearchQueryParameterError.SearchQueryParameterErrorType; +import org.highmed.dsf.fhir.search.parameters.basic.AbstractTokenParameter; +import org.highmed.dsf.fhir.search.parameters.basic.TokenSearchType; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r4.model.ActivityDefinition; +import org.hl7.fhir.r4.model.Enumerations.PublicationStatus; +import org.hl7.fhir.r4.model.Enumerations.SearchParamType; +import org.hl7.fhir.r4.model.Resource; + +@SearchParameterDefinition(name = ActivityDefinitionStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.​status", type = SearchParamType.TOKEN, documentation = "The current status of the activity definition") +public class ActivityDefinitionStatus extends AbstractTokenParameter +{ + public static final String PARAMETER_NAME = "status"; + + private PublicationStatus status; + + public ActivityDefinitionStatus() + { + super(PARAMETER_NAME); + } + + @Override + protected void configureSearchParameter(Map> queryParameters) + { + super.configureSearchParameter(queryParameters); + + if (valueAndType != null && valueAndType.type == TokenSearchType.CODE) + status = toStatus(valueAndType.codeValue, queryParameters.get(parameterName)); + } + + private PublicationStatus toStatus(String status, List parameterValues) + { + if (status == null || status.isBlank()) + return null; + + try + { + return PublicationStatus.fromCode(status); + } + catch (FHIRException e) + { + addError(new SearchQueryParameterError(SearchQueryParameterErrorType.UNPARSABLE_VALUE, parameterName, + parameterValues, e)); + return null; + } + } + + @Override + public boolean isDefined() + { + return super.isDefined() && status != null; + } + + @Override + public String getFilterQuery() + { + return "activity_definition->>'status' = ?"; + } + + @Override + public int getSqlParameterCount() + { + return 1; + } + + @Override + public void modifyStatement(int parameterIndex, int subqueryParameterIndex, PreparedStatement statement, + BiFunctionWithSqlException arrayCreator) throws SQLException + { + statement.setString(parameterIndex, status.toCode()); + } + + @Override + public void modifyBundleUri(UriBuilder bundleUri) + { + bundleUri.replaceQueryParam(PARAMETER_NAME, status.toCode()); + } + + @Override + public boolean matches(Resource resource) + { + if (!isDefined()) + throw notDefined(); + + if (!(resource instanceof ActivityDefinition)) + return false; + + return Objects.equals(((ActivityDefinition) resource).getStatus(), status); + } + + @Override + protected String getSortSql(String sortDirectionWithSpacePrefix) + { + return "activity_definition->>'status'" + sortDirectionWithSpacePrefix; + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionUrl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionUrl.java new file mode 100644 index 000000000..14e63831c --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionUrl.java @@ -0,0 +1,24 @@ +package org.highmed.dsf.fhir.search.parameters; + +import org.highmed.dsf.fhir.search.SearchQueryParameter.SearchParameterDefinition; +import org.highmed.dsf.fhir.search.parameters.basic.AbstractUrlAndVersionParameter; +import org.hl7.fhir.r4.model.ActivityDefinition; +import org.hl7.fhir.r4.model.Enumerations.SearchParamType; +import org.hl7.fhir.r4.model.Resource; + +@SearchParameterDefinition(name = ActivityDefinitionUrl.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.​url", type = SearchParamType.URI, documentation = "The uri that identifies the activity definition") +public class ActivityDefinitionUrl extends AbstractUrlAndVersionParameter +{ + public static final String RESOURCE_COLUMN = "activity_definition"; + + public ActivityDefinitionUrl() + { + super(RESOURCE_COLUMN); + } + + @Override + protected boolean instanceOf(Resource resource) + { + return resource instanceof ActivityDefinition; + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionVersion.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionVersion.java new file mode 100644 index 000000000..b4c1e31cc --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionVersion.java @@ -0,0 +1,29 @@ +package org.highmed.dsf.fhir.search.parameters; + +import org.highmed.dsf.fhir.search.SearchQueryParameter.SearchParameterDefinition; +import org.highmed.dsf.fhir.search.parameters.basic.AbstractVersionParameter; +import org.hl7.fhir.r4.model.ActivityDefinition; +import org.hl7.fhir.r4.model.Enumerations.SearchParamType; +import org.hl7.fhir.r4.model.Resource; + +@SearchParameterDefinition(name = ActivityDefinitionVersion.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.​version", type = SearchParamType.TOKEN, documentation = "The business version of the activity definition") +public class ActivityDefinitionVersion extends AbstractVersionParameter +{ + public static final String RESOURCE_COLUMN = "activity_definition"; + + public ActivityDefinitionVersion() + { + this(RESOURCE_COLUMN); + } + + public ActivityDefinitionVersion(String resourceColumn) + { + super(resourceColumn); + } + + @Override + protected boolean instanceOf(Resource resource) + { + return resource instanceof ActivityDefinition; + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemStatus.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemStatus.java new file mode 100644 index 000000000..713c773c1 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemStatus.java @@ -0,0 +1,111 @@ +package org.highmed.dsf.fhir.search.parameters; + +import java.sql.Array; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import javax.ws.rs.core.UriBuilder; + +import org.highmed.dsf.fhir.function.BiFunctionWithSqlException; +import org.highmed.dsf.fhir.search.SearchQueryParameter.SearchParameterDefinition; +import org.highmed.dsf.fhir.search.SearchQueryParameterError; +import org.highmed.dsf.fhir.search.SearchQueryParameterError.SearchQueryParameterErrorType; +import org.highmed.dsf.fhir.search.parameters.basic.AbstractTokenParameter; +import org.highmed.dsf.fhir.search.parameters.basic.TokenSearchType; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r4.model.CodeSystem; +import org.hl7.fhir.r4.model.Enumerations.PublicationStatus; +import org.hl7.fhir.r4.model.Enumerations.SearchParamType; +import org.hl7.fhir.r4.model.Resource; +import org.hl7.fhir.r4.model.ValueSet; + +@SearchParameterDefinition(name = CodeSystemStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/CodeSystem.​status", type = SearchParamType.TOKEN, documentation = "The current status of the code system") +public class CodeSystemStatus extends AbstractTokenParameter +{ + public static final String PARAMETER_NAME = "status"; + + private PublicationStatus status; + + public CodeSystemStatus() + { + super(PARAMETER_NAME); + } + + @Override + protected void configureSearchParameter(Map> queryParameters) + { + super.configureSearchParameter(queryParameters); + + if (valueAndType != null && valueAndType.type == TokenSearchType.CODE) + status = toStatus(valueAndType.codeValue, queryParameters.get(parameterName)); + } + + private PublicationStatus toStatus(String status, List parameterValues) + { + if (status == null || status.isBlank()) + return null; + + try + { + return PublicationStatus.fromCode(status); + } + catch (FHIRException e) + { + addError(new SearchQueryParameterError(SearchQueryParameterErrorType.UNPARSABLE_VALUE, parameterName, + parameterValues, e)); + return null; + } + } + + @Override + public boolean isDefined() + { + return super.isDefined() && status != null; + } + + @Override + public String getFilterQuery() + { + return "code_system->>'status' = ?"; + } + + @Override + public int getSqlParameterCount() + { + return 1; + } + + @Override + public void modifyStatement(int parameterIndex, int subqueryParameterIndex, PreparedStatement statement, + BiFunctionWithSqlException arrayCreator) throws SQLException + { + statement.setString(parameterIndex, status.toCode()); + } + + @Override + public void modifyBundleUri(UriBuilder bundleUri) + { + bundleUri.replaceQueryParam(PARAMETER_NAME, status.toCode()); + } + + @Override + public boolean matches(Resource resource) + { + if (!isDefined()) + throw notDefined(); + + if (!(resource instanceof ValueSet)) + return false; + + return Objects.equals(((ValueSet) resource).getStatus(), status); + } + + @Override + protected String getSortSql(String sortDirectionWithSpacePrefix) + { + return "code_system->>'status'" + sortDirectionWithSpacePrefix; + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetStatus.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetStatus.java new file mode 100644 index 000000000..091dbed6c --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetStatus.java @@ -0,0 +1,110 @@ +package org.highmed.dsf.fhir.search.parameters; + +import java.sql.Array; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import javax.ws.rs.core.UriBuilder; + +import org.highmed.dsf.fhir.function.BiFunctionWithSqlException; +import org.highmed.dsf.fhir.search.SearchQueryParameter.SearchParameterDefinition; +import org.highmed.dsf.fhir.search.SearchQueryParameterError; +import org.highmed.dsf.fhir.search.SearchQueryParameterError.SearchQueryParameterErrorType; +import org.highmed.dsf.fhir.search.parameters.basic.AbstractTokenParameter; +import org.highmed.dsf.fhir.search.parameters.basic.TokenSearchType; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r4.model.Enumerations.PublicationStatus; +import org.hl7.fhir.r4.model.Enumerations.SearchParamType; +import org.hl7.fhir.r4.model.Resource; +import org.hl7.fhir.r4.model.ValueSet; + +@SearchParameterDefinition(name = ValueSetStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ValueSet.​status", type = SearchParamType.TOKEN, documentation = "The current status of the value set") +public class ValueSetStatus extends AbstractTokenParameter +{ + public static final String PARAMETER_NAME = "status"; + + private PublicationStatus status; + + public ValueSetStatus() + { + super(PARAMETER_NAME); + } + + @Override + protected void configureSearchParameter(Map> queryParameters) + { + super.configureSearchParameter(queryParameters); + + if (valueAndType != null && valueAndType.type == TokenSearchType.CODE) + status = toStatus(valueAndType.codeValue, queryParameters.get(parameterName)); + } + + private PublicationStatus toStatus(String status, List parameterValues) + { + if (status == null || status.isBlank()) + return null; + + try + { + return PublicationStatus.fromCode(status); + } + catch (FHIRException e) + { + addError(new SearchQueryParameterError(SearchQueryParameterErrorType.UNPARSABLE_VALUE, parameterName, + parameterValues, e)); + return null; + } + } + + @Override + public boolean isDefined() + { + return super.isDefined() && status != null; + } + + @Override + public String getFilterQuery() + { + return "value_set->>'status' = ?"; + } + + @Override + public int getSqlParameterCount() + { + return 1; + } + + @Override + public void modifyStatement(int parameterIndex, int subqueryParameterIndex, PreparedStatement statement, + BiFunctionWithSqlException arrayCreator) throws SQLException + { + statement.setString(parameterIndex, status.toCode()); + } + + @Override + public void modifyBundleUri(UriBuilder bundleUri) + { + bundleUri.replaceQueryParam(PARAMETER_NAME, status.toCode()); + } + + @Override + public boolean matches(Resource resource) + { + if (!isDefined()) + throw notDefined(); + + if (!(resource instanceof ValueSet)) + return false; + + return Objects.equals(((ValueSet) resource).getStatus(), status); + } + + @Override + protected String getSortSql(String sortDirectionWithSpacePrefix) + { + return "value_set->>'status'" + sortDirectionWithSpacePrefix; + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractor.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractor.java index 1cbb80bf6..b175735d4 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractor.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractor.java @@ -3,7 +3,7 @@ import java.util.stream.Stream; import org.highmed.dsf.fhir.dao.command.ResourceReference; - +import org.hl7.fhir.r4.model.ActivityDefinition; import org.hl7.fhir.r4.model.Endpoint; import org.hl7.fhir.r4.model.Group; import org.hl7.fhir.r4.model.HealthcareService; @@ -21,6 +21,8 @@ public interface ReferenceExtractor { Stream getReferences(Resource resource); + Stream getReferences(ActivityDefinition resource); + Stream getReferences(Endpoint resource); Stream getReferences(Group group); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractorImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractorImpl.java index 8ff043bbf..3ef7740e1 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractorImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractorImpl.java @@ -7,6 +7,7 @@ import java.util.stream.Stream; import org.highmed.dsf.fhir.dao.command.ResourceReference; +import org.hl7.fhir.r4.model.ActivityDefinition; import org.hl7.fhir.r4.model.BackboneElement; import org.hl7.fhir.r4.model.CareTeam; import org.hl7.fhir.r4.model.ClaimResponse; @@ -19,6 +20,7 @@ import org.hl7.fhir.r4.model.HealthcareService; import org.hl7.fhir.r4.model.Location; import org.hl7.fhir.r4.model.Medication; +import org.hl7.fhir.r4.model.ObservationDefinition; import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.Patient.ContactComponent; @@ -34,6 +36,7 @@ import org.hl7.fhir.r4.model.RelatedPerson; import org.hl7.fhir.r4.model.ResearchStudy; import org.hl7.fhir.r4.model.Resource; +import org.hl7.fhir.r4.model.SpecimenDefinition; import org.hl7.fhir.r4.model.Substance; import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; @@ -200,6 +203,35 @@ else if (resource instanceof DomainResource) } } + @Override + public Stream getReferences(ActivityDefinition resource) + { + if (resource == null) + return Stream.empty(); + + var subjectReference = getReference(resource, ActivityDefinition::hasSubjectReference, + ActivityDefinition::getSubjectReference, "ActivityDefinition.subjectReference", Group.class); + var location = getReference(resource, ActivityDefinition::hasLocation, ActivityDefinition::getLocation, + "ActivityDefinition.location", Location.class); + var productReference = getReference(resource, ActivityDefinition::hasProductReference, + ActivityDefinition::getProductReference, "ActivityDefinition.productReference", Medication.class, + Substance.class); + var specimenRequirement = getReferences(resource, ActivityDefinition::hasSpecimenRequirement, + ActivityDefinition::getSpecimenRequirement, "ActivityDefinition.specimenRequirement", + SpecimenDefinition.class); + var observationRequirement = getReferences(resource, ActivityDefinition::hasObservationRequirement, + ActivityDefinition::getObservationRequirement, "ActivityDefinition.observationRequirement", + ObservationDefinition.class); + var observationResultRequirement = getReferences(resource, ActivityDefinition::hasObservationResultRequirement, + ActivityDefinition::getObservationResultRequirement, "ActivityDefinition.observationResultRequirement", + ObservationDefinition.class); + + var extensionReferences = getExtensionReferences(resource); + + return concat(subjectReference, location, productReference, specimenRequirement, observationRequirement, + observationResultRequirement, extensionReferences); + } + @Override public Stream getReferences(Endpoint resource) { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java index 3915eedb2..94abeb029 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java @@ -1,6 +1,7 @@ package org.highmed.dsf.fhir.spring.config; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; import org.highmed.dsf.fhir.dao.BinaryDao; import org.highmed.dsf.fhir.dao.BundleDao; import org.highmed.dsf.fhir.dao.CodeSystemDao; @@ -21,6 +22,7 @@ import org.highmed.dsf.fhir.dao.TaskDao; import org.highmed.dsf.fhir.dao.ValueSetDao; import org.highmed.dsf.fhir.dao.converter.SnapshotInfoConverter; +import org.highmed.dsf.fhir.dao.jdbc.ActivityDefinitionDaoJdbc; import org.highmed.dsf.fhir.dao.jdbc.BinaryDaoJdbc; import org.highmed.dsf.fhir.dao.jdbc.BundleDaoJdbc; import org.highmed.dsf.fhir.dao.jdbc.CodeSystemDaoJdbc; @@ -81,6 +83,12 @@ public BasicDataSource dataSource() return dataSource; } + @Bean + public ActivityDefinitionDao activityDefinitionDao() + { + return new ActivityDefinitionDaoJdbc(dataSource(), fhirConfig.fhirContext()); + } + @Bean public BinaryDao binaryDao() { @@ -204,8 +212,8 @@ public ValueSetDao valueSetDao() @Bean public DaoProvider daoProvider() { - return new DaoProviderImpl(binaryDao(), bundleDao(), codeSystemDao(), endpointDao(), groupDao(), - healthcareServiceDao(), locationDao(), namingSystemDao(), organizationDao(), patientDao(), + return new DaoProviderImpl(activityDefinitionDao(), binaryDao(), bundleDao(), codeSystemDao(), endpointDao(), + groupDao(), healthcareServiceDao(), locationDao(), namingSystemDao(), organizationDao(), patientDao(), practitionerDao(), practitionerRoleDao(), provenanceDao(), researchStudyDao(), structureDefinitionDao(), structureDefinitionSnapshotDao(), subscriptionDao(), taskDao(), valueSetDao()); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java index 2d9810632..d2868600e 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.spring.config; +import org.highmed.dsf.fhir.webservice.impl.ActivityDefinitionServiceImpl; import org.highmed.dsf.fhir.webservice.impl.BinaryServiceImpl; import org.highmed.dsf.fhir.webservice.impl.BundleServiceImpl; import org.highmed.dsf.fhir.webservice.impl.CodeSystemServiceImpl; @@ -20,6 +21,7 @@ import org.highmed.dsf.fhir.webservice.impl.SubscriptionServiceImpl; import org.highmed.dsf.fhir.webservice.impl.TaskServiceImpl; import org.highmed.dsf.fhir.webservice.impl.ValueSetServiceImpl; +import org.highmed.dsf.fhir.webservice.jaxrs.ActivityDefinitionServiceJaxrs; import org.highmed.dsf.fhir.webservice.jaxrs.BinaryServiceJaxrs; import org.highmed.dsf.fhir.webservice.jaxrs.BundleServiceJaxrs; import org.highmed.dsf.fhir.webservice.jaxrs.CodeSystemServiceJaxrs; @@ -40,6 +42,7 @@ import org.highmed.dsf.fhir.webservice.jaxrs.SubscriptionServiceJaxrs; import org.highmed.dsf.fhir.webservice.jaxrs.TaskServiceJaxrs; import org.highmed.dsf.fhir.webservice.jaxrs.ValueSetServiceJaxrs; +import org.highmed.dsf.fhir.webservice.secure.ActivityDefinitionServiceSecure; import org.highmed.dsf.fhir.webservice.secure.BinaryServiceSecure; import org.highmed.dsf.fhir.webservice.secure.BundleServiceSecure; import org.highmed.dsf.fhir.webservice.secure.CodeSystemServiceSecure; @@ -60,6 +63,7 @@ import org.highmed.dsf.fhir.webservice.secure.SubscriptionServiceSecure; import org.highmed.dsf.fhir.webservice.secure.TaskServiceSecure; import org.highmed.dsf.fhir.webservice.secure.ValueSetServiceSecure; +import org.highmed.dsf.fhir.webservice.specification.ActivityDefinitionService; import org.highmed.dsf.fhir.webservice.specification.BinaryService; import org.highmed.dsf.fhir.webservice.specification.BundleService; import org.highmed.dsf.fhir.webservice.specification.CodeSystemService; @@ -80,6 +84,7 @@ import org.highmed.dsf.fhir.webservice.specification.SubscriptionService; import org.highmed.dsf.fhir.webservice.specification.TaskService; import org.highmed.dsf.fhir.webservice.specification.ValueSetService; +import org.hl7.fhir.r4.model.ActivityDefinition; import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.CodeSystem; @@ -148,6 +153,22 @@ private String resourceTypeName(Class r) return r.getAnnotation(ResourceDef.class).name(); } + @Bean + public ActivityDefinitionService activityDefinitionService() + { + return new ActivityDefinitionServiceJaxrs( + new ActivityDefinitionServiceSecure(activityDefinitionServiceImpl(), helperConfig.responseGenerator())); + } + + private ActivityDefinitionServiceImpl activityDefinitionServiceImpl() + { + return new ActivityDefinitionServiceImpl(resourceTypeName(ActivityDefinition.class), serverBase, + ActivityDefinitionServiceJaxrs.PATH, defaultPageCount, daoConfig.activityDefinitionDao(), + validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), + eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), + commandConfig.referenceExtractor(), commandConfig.referenceResolver()); + } + @Bean public CodeSystemService codeSystemService() { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ActivityDefinitionServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ActivityDefinitionServiceImpl.java new file mode 100644 index 000000000..3d2f1ce7f --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ActivityDefinitionServiceImpl.java @@ -0,0 +1,28 @@ +package org.highmed.dsf.fhir.webservice.impl; + +import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; +import org.highmed.dsf.fhir.event.EventGenerator; +import org.highmed.dsf.fhir.event.EventManager; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; +import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceExtractor; +import org.highmed.dsf.fhir.service.ReferenceResolver; +import org.highmed.dsf.fhir.service.ResourceValidator; +import org.highmed.dsf.fhir.webservice.specification.ActivityDefinitionService; +import org.hl7.fhir.r4.model.ActivityDefinition; + +public class ActivityDefinitionServiceImpl extends AbstractServiceImpl + implements ActivityDefinitionService +{ + public ActivityDefinitionServiceImpl(String resourceTypeName, String serverBase, String path, int defaultPageCount, + ActivityDefinitionDao dao, ResourceValidator validator, EventManager eventManager, + ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, + ParameterConverter parameterConverter, ReferenceExtractor referenceExtractor, + ReferenceResolver referenceResolver) + { + super(ActivityDefinition.class, resourceTypeName, serverBase, path, defaultPageCount, dao, validator, + eventManager, exceptionHandler, eventGenerator, responseGenerator, parameterConverter, + referenceExtractor, referenceResolver); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java index ee8a20ab3..6b2789525 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java @@ -16,9 +16,15 @@ import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.search.SearchQueryParameter.SearchParameterDefinition; +import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionIdentifier; +import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionName; +import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionStatus; +import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionUrl; +import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionVersion; import org.highmed.dsf.fhir.search.parameters.BinaryContentType; import org.highmed.dsf.fhir.search.parameters.BundleIdentifier; import org.highmed.dsf.fhir.search.parameters.CodeSystemIdentifier; +import org.highmed.dsf.fhir.search.parameters.CodeSystemStatus; import org.highmed.dsf.fhir.search.parameters.CodeSystemUrl; import org.highmed.dsf.fhir.search.parameters.CodeSystemVersion; import org.highmed.dsf.fhir.search.parameters.EndpointIdentifier; @@ -55,11 +61,13 @@ import org.highmed.dsf.fhir.search.parameters.TaskRequester; import org.highmed.dsf.fhir.search.parameters.TaskStatus; import org.highmed.dsf.fhir.search.parameters.ValueSetIdentifier; +import org.highmed.dsf.fhir.search.parameters.ValueSetStatus; import org.highmed.dsf.fhir.search.parameters.ValueSetUrl; import org.highmed.dsf.fhir.search.parameters.ValueSetVersion; import org.highmed.dsf.fhir.webservice.specification.ConformanceService; import org.highmed.dsf.fhir.websocket.ServerEndpoint; import org.highmed.dsf.tools.build.BuildInfoReader; +import org.hl7.fhir.r4.model.ActivityDefinition; import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.CapabilityStatement; @@ -186,6 +194,15 @@ private CapabilityStatement createCapabilityStatement(String serverBase, int def var searchParameters = new HashMap, List>(); + var activityDefinitionUrl = createSearchParameter(ActivityDefinitionUrl.class); + var activityDefinitionIdentifier = createSearchParameter(ActivityDefinitionIdentifier.class); + var activityDefinitionVersion = createSearchParameter(ActivityDefinitionVersion.class); + var activityDefinitionName = createSearchParameter(ActivityDefinitionName.class); + var activityDefinitionStatus = createSearchParameter(ActivityDefinitionStatus.class); + searchParameters.put(ActivityDefinition.class, + Arrays.asList(activityDefinitionUrl, activityDefinitionIdentifier, activityDefinitionVersion, + activityDefinitionName, activityDefinitionStatus)); + var binaryContentType = createSearchParameter(BinaryContentType.class); searchParameters.put(Binary.class, Arrays.asList(binaryContentType)); @@ -195,7 +212,9 @@ private CapabilityStatement createCapabilityStatement(String serverBase, int def var codeSystemIdentifier = createSearchParameter(CodeSystemIdentifier.class); var codeSystemUrl = createSearchParameter(CodeSystemUrl.class); var codeSystemVersion = createSearchParameter(CodeSystemVersion.class); - searchParameters.put(CodeSystem.class, Arrays.asList(codeSystemIdentifier, codeSystemUrl, codeSystemVersion)); + var codeSystemStatus = createSearchParameter(CodeSystemStatus.class); + searchParameters.put(CodeSystem.class, + Arrays.asList(codeSystemIdentifier, codeSystemUrl, codeSystemVersion, codeSystemStatus)); var endpointIdentifier = createSearchParameter(EndpointIdentifier.class); var endpointName = createSearchParameter(EndpointName.class); @@ -260,7 +279,9 @@ private CapabilityStatement createCapabilityStatement(String serverBase, int def var valueSetIdentifier = createSearchParameter(ValueSetIdentifier.class); var valueSetUrl = createSearchParameter(ValueSetUrl.class); var valueSetVersion = createSearchParameter(ValueSetVersion.class); - searchParameters.put(ValueSet.class, Arrays.asList(valueSetIdentifier, valueSetUrl, valueSetVersion)); + var valueSetStatus = createSearchParameter(ValueSetStatus.class); + searchParameters.put(ValueSet.class, + Arrays.asList(valueSetIdentifier, valueSetUrl, valueSetVersion, valueSetStatus)); var operations = new HashMap, List>(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/jaxrs/ActivityDefinitionServiceJaxrs.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/jaxrs/ActivityDefinitionServiceJaxrs.java new file mode 100644 index 000000000..bc5e4192b --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/jaxrs/ActivityDefinitionServiceJaxrs.java @@ -0,0 +1,18 @@ +package org.highmed.dsf.fhir.webservice.jaxrs; + +import javax.ws.rs.Path; + +import org.highmed.dsf.fhir.webservice.specification.ActivityDefinitionService; +import org.hl7.fhir.r4.model.ActivityDefinition; + +@Path(ActivityDefinitionServiceJaxrs.PATH) +public class ActivityDefinitionServiceJaxrs extends AbstractServiceJaxrs + implements ActivityDefinitionService +{ + public static final String PATH = "ActivityDefinition"; + + public ActivityDefinitionServiceJaxrs(ActivityDefinitionService delegate) + { + super(delegate); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ActivityDefinitionServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ActivityDefinitionServiceSecure.java new file mode 100644 index 000000000..12824ff02 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ActivityDefinitionServiceSecure.java @@ -0,0 +1,14 @@ +package org.highmed.dsf.fhir.webservice.secure; + +import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.webservice.specification.ActivityDefinitionService; +import org.hl7.fhir.r4.model.ActivityDefinition; + +public class ActivityDefinitionServiceSecure extends + AbstractServiceSecure implements ActivityDefinitionService +{ + public ActivityDefinitionServiceSecure(ActivityDefinitionService delegate, ResponseGenerator responseGenerator) + { + super(delegate, responseGenerator); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/specification/ActivityDefinitionService.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/specification/ActivityDefinitionService.java new file mode 100644 index 000000000..6fa2f2f0e --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/specification/ActivityDefinitionService.java @@ -0,0 +1,7 @@ +package org.highmed.dsf.fhir.webservice.specification; + +import org.hl7.fhir.r4.model.ActivityDefinition; + +public interface ActivityDefinitionService extends BasicService +{ +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/db/db.activity_definitions.changelog-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/db/db.activity_definitions.changelog-0.1.0.xml new file mode 100644 index 000000000..46c6a92f1 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/db/db.activity_definitions.changelog-0.1.0.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + ALTER TABLE activity_definitions OWNER TO ${db.liquibase_user}; + GRANT ALL ON TABLE activity_definitions TO ${db.liquibase_user}; + GRANT SELECT, INSERT, UPDATE ON TABLE activity_definitions TO ${db.server_users_group}; + CREATE INDEX activity_definition_id_index ON activity_definitions USING btree (activity_definition_id); + CREATE INDEX activity_definition_index ON activity_definitions USING gin (activity_definition); + CREATE INDEX activity_definition_id_version_index ON activity_definitions USING btree (activity_definition_id, version); + + + + SELECT DISTINCT ON (activity_definition_id) activity_definition_id, version, activity_definition + FROM activity_definitions WHERE NOT deleted ORDER BY activity_definition_id, version DESC + + + + ALTER TABLE current_activity_definitions OWNER TO ${db.liquibase_user}; + GRANT ALL ON TABLE current_activity_definitions TO ${db.liquibase_user}; + GRANT SELECT ON TABLE current_activity_definitions TO ${db.server_users_group}; + + + \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/db/db.changelog.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/db/db.changelog.xml index f1c8c4745..e585d0921 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/db/db.changelog.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/db/db.changelog.xml @@ -5,6 +5,7 @@ + diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDaoTest.java new file mode 100644 index 000000000..ef93df470 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDaoTest.java @@ -0,0 +1,53 @@ +package org.highmed.dsf.fhir.dao; + +import static org.junit.Assert.assertEquals; + +import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.dao.jdbc.ActivityDefinitionDaoJdbc; +import org.hl7.fhir.r4.model.ActivityDefinition; + +import ca.uhn.fhir.context.FhirContext; + +public class ActivityDefinitionDaoTest extends AbstractResourceDaoTest +{ + private static final String name = "Demo ActivityDefinition Name"; + private static final String title = "Demo ActivityDefinition Title"; + + public ActivityDefinitionDaoTest() + { + super(ActivityDefinition.class); + } + + @Override + protected ActivityDefinitionDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + { + return new ActivityDefinitionDaoJdbc(dataSource, fhirContext); + } + + @Override + protected ActivityDefinition createResource() + { + ActivityDefinition activityDefinition = new ActivityDefinition(); + activityDefinition.setName(name); + return activityDefinition; + } + + @Override + protected void checkCreated(ActivityDefinition resource) + { + assertEquals(name, resource.getName()); + } + + @Override + protected ActivityDefinition updateResource(ActivityDefinition resource) + { + resource.setTitle(title); + return resource; + } + + @Override + protected void checkUpdates(ActivityDefinition resource) + { + assertEquals(title, resource.getTitle()); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/test/TestSuiteDbTests.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/test/TestSuiteDbTests.java index 486f435ce..0738eb905 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/test/TestSuiteDbTests.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/test/TestSuiteDbTests.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.test; +import org.highmed.dsf.fhir.dao.ActivityDefinitionDaoTest; import org.highmed.dsf.fhir.dao.BinaryDaoTest; import org.highmed.dsf.fhir.dao.BundleDaoTest; import org.highmed.dsf.fhir.dao.CodeSystemDaoTest; @@ -25,12 +26,12 @@ import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) -@SuiteClasses({ BinaryDaoTest.class, BundleDaoTest.class, CodeSystemDaoTest.class, EndpointDaoTest.class, - GroupDaoTest.class, HealthcareServiceDaoTest.class, LocationDaoTest.class, NamingSystemDaoTest.class, - OrganizationDaoTest.class, PatientDaoTest.class, PractitionerDaoTest.class, PractitionerRoleDaoTest.class, - ProvenanceDaoTest.class, ResearchStudyDaoTest.class, StructureDefinitionDaoTest.class, - StructureDefinitionSnapshotDaoTest.class, SubscriptionDaoTest.class, TaskDaoTest.class, ValueSetDaoTest.class, - TestSuiteIntegrationTests.class }) +@SuiteClasses({ ActivityDefinitionDaoTest.class, BinaryDaoTest.class, BundleDaoTest.class, CodeSystemDaoTest.class, + EndpointDaoTest.class, GroupDaoTest.class, HealthcareServiceDaoTest.class, LocationDaoTest.class, + NamingSystemDaoTest.class, OrganizationDaoTest.class, PatientDaoTest.class, PractitionerDaoTest.class, + PractitionerRoleDaoTest.class, ProvenanceDaoTest.class, ResearchStudyDaoTest.class, + StructureDefinitionDaoTest.class, StructureDefinitionSnapshotDaoTest.class, SubscriptionDaoTest.class, + TaskDaoTest.class, ValueSetDaoTest.class, TestSuiteIntegrationTests.class }) public class TestSuiteDbTests { @ClassRule diff --git a/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java b/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java index 0c8b42471..f9ebcb212 100755 --- a/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java +++ b/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java @@ -17,6 +17,8 @@ import javax.ws.rs.core.Response.Status; import org.highmed.dsf.fhir.adapter.AbstractFhirAdapter; +import org.highmed.dsf.fhir.adapter.ActivityDefinitionJsonFhirAdapter; +import org.highmed.dsf.fhir.adapter.ActivityDefinitionXmlFhirAdapter; import org.highmed.dsf.fhir.adapter.BinaryJsonFhirAdapter; import org.highmed.dsf.fhir.adapter.BinaryXmlFhirAdapter; import org.highmed.dsf.fhir.adapter.BundleJsonFhirAdapter; @@ -91,27 +93,29 @@ public FhirWebserviceClientJersey(String baseUrl, KeyStore trustStore, KeyStore public static List> components(FhirContext fhirContext) { - return Arrays.asList(new BinaryJsonFhirAdapter(fhirContext), new BinaryXmlFhirAdapter(fhirContext), - new BundleJsonFhirAdapter(fhirContext), new BundleXmlFhirAdapter(fhirContext), - new CapabilityStatementJsonFhirAdapter(fhirContext), new CapabilityStatementXmlFhirAdapter(fhirContext), - new CodeSystemJsonFhirAdapter(fhirContext), new CodeSystemXmlFhirAdapter(fhirContext), - new GroupJsonFhirAdapter(fhirContext), new GroupXmlFhirAdapter(fhirContext), - new EndpointJsonFhirAdapter(fhirContext), new EndpointXmlFhirAdapter(fhirContext), - new HealthcareServiceJsonFhirAdapter(fhirContext), new HealthcareServiceXmlFhirAdapter(fhirContext), - new LocationJsonFhirAdapter(fhirContext), new LocationXmlFhirAdapter(fhirContext), - new NamingSystemJsonFhirAdapter(fhirContext), new NamingSystemXmlFhirAdapter(fhirContext), - new OperationOutcomeJsonFhirAdapter(fhirContext), new OperationOutcomeXmlFhirAdapter(fhirContext), - new OrganizationJsonFhirAdapter(fhirContext), new OrganizationXmlFhirAdapter(fhirContext), - new ParametersJsonFhirAdapter(fhirContext), new ParametersXmlFhirAdapter(fhirContext), - new PatientJsonFhirAdapter(fhirContext), new PatientXmlFhirAdapter(fhirContext), - new PractitionerJsonFhirAdapter(fhirContext), new PractitionerXmlFhirAdapter(fhirContext), - new PractitionerRoleJsonFhirAdapter(fhirContext), new PractitionerRoleXmlFhirAdapter(fhirContext), - new ProvenanceJsonFhirAdapter(fhirContext), new ProvenanceXmlFhirAdapter(fhirContext), - new ResearchStudyJsonFhirAdapter(fhirContext), new ResearchStudyXmlFhirAdapter(fhirContext), - new StructureDefinitionJsonFhirAdapter(fhirContext), new StructureDefinitionXmlFhirAdapter(fhirContext), - new SubscriptionJsonFhirAdapter(fhirContext), new SubscriptionXmlFhirAdapter(fhirContext), - new TaskJsonFhirAdapter(fhirContext), new TaskXmlFhirAdapter(fhirContext), - new ValueSetJsonFhirAdapter(fhirContext), new ValueSetXmlFhirAdapter(fhirContext)); + return Arrays.asList(new ActivityDefinitionJsonFhirAdapter(fhirContext), + new ActivityDefinitionXmlFhirAdapter(fhirContext), new BinaryJsonFhirAdapter(fhirContext), + new BinaryXmlFhirAdapter(fhirContext), new BundleJsonFhirAdapter(fhirContext), + new BundleXmlFhirAdapter(fhirContext), new CapabilityStatementJsonFhirAdapter(fhirContext), + new CapabilityStatementXmlFhirAdapter(fhirContext), new CodeSystemJsonFhirAdapter(fhirContext), + new CodeSystemXmlFhirAdapter(fhirContext), new GroupJsonFhirAdapter(fhirContext), + new GroupXmlFhirAdapter(fhirContext), new EndpointJsonFhirAdapter(fhirContext), + new EndpointXmlFhirAdapter(fhirContext), new HealthcareServiceJsonFhirAdapter(fhirContext), + new HealthcareServiceXmlFhirAdapter(fhirContext), new LocationJsonFhirAdapter(fhirContext), + new LocationXmlFhirAdapter(fhirContext), new NamingSystemJsonFhirAdapter(fhirContext), + new NamingSystemXmlFhirAdapter(fhirContext), new OperationOutcomeJsonFhirAdapter(fhirContext), + new OperationOutcomeXmlFhirAdapter(fhirContext), new OrganizationJsonFhirAdapter(fhirContext), + new OrganizationXmlFhirAdapter(fhirContext), new ParametersJsonFhirAdapter(fhirContext), + new ParametersXmlFhirAdapter(fhirContext), new PatientJsonFhirAdapter(fhirContext), + new PatientXmlFhirAdapter(fhirContext), new PractitionerJsonFhirAdapter(fhirContext), + new PractitionerXmlFhirAdapter(fhirContext), new PractitionerRoleJsonFhirAdapter(fhirContext), + new PractitionerRoleXmlFhirAdapter(fhirContext), new ProvenanceJsonFhirAdapter(fhirContext), + new ProvenanceXmlFhirAdapter(fhirContext), new ResearchStudyJsonFhirAdapter(fhirContext), + new ResearchStudyXmlFhirAdapter(fhirContext), new StructureDefinitionJsonFhirAdapter(fhirContext), + new StructureDefinitionXmlFhirAdapter(fhirContext), new SubscriptionJsonFhirAdapter(fhirContext), + new SubscriptionXmlFhirAdapter(fhirContext), new TaskJsonFhirAdapter(fhirContext), + new TaskXmlFhirAdapter(fhirContext), new ValueSetJsonFhirAdapter(fhirContext), + new ValueSetXmlFhirAdapter(fhirContext)); } @Override @@ -241,8 +245,8 @@ public void delete(Class resourceClass, String id) logger.debug("HTTP header ETag: {}", response.getHeaderString(HttpHeaders.ETAG)); logger.debug("HTTP header Last-Modified: {}", response.getHeaderString(HttpHeaders.LAST_MODIFIED)); - if (Status.OK.getStatusCode() != response.getStatus() && Status.NO_CONTENT.getStatusCode() != response - .getStatus()) + if (Status.OK.getStatusCode() != response.getStatus() + && Status.NO_CONTENT.getStatusCode() != response.getStatus()) throw new WebApplicationException(response); } @@ -266,8 +270,8 @@ public void deleteConditionaly(Class resourceClass, Map Date: Mon, 17 Feb 2020 10:17:56 +0100 Subject: [PATCH 03/55] security facade rework --- ...lityFromMedicsViaMedic1ExampleStarter.java | 5 +- .../Ping3MedicFromTtpExampleStarter.java | 5 +- ...UpdateResource3MedicTtpExampleStarter.java | 5 +- ...pdateWhiteList3MedicTtpExampleStarter.java | 5 +- .../dsf/bpe/spring/config/FhirConfig.java | 27 +- .../fhir/client/FhirClientProviderImpl.java | 27 +- .../dsf/fhir/adapter/AbstractFhirAdapter.java | 11 + .../dsf/fhir/service/ReferenceExtractor.java | 1 - .../fhir/service/ReferenceExtractorImpl.java | 27 +- .../dsf/fhir/service}/ResourceReference.java | 14 +- .../dsf/fhir/authentication/UserProvider.java | 7 + .../dsf/fhir/client/ClientProviderImpl.java | 30 +- .../org/highmed/dsf/fhir/dao/ResourceDao.java | 20 + .../dao/command/ResolveReferencesCommand.java | 1 + .../dsf/fhir/dao/command/UpdateCommand.java | 2 +- .../dao/jdbc/AbstractResourceDaoJdbc.java | 46 +- .../dsf/fhir/help/ExceptionHandler.java | 4 +- .../dsf/fhir/help/ParameterConverter.java | 16 +- .../dsf/fhir/help/ResponseGenerator.java | 24 +- .../dsf/fhir/service/ReferenceResolver.java | 35 +- .../fhir/service/ReferenceResolverImpl.java | 256 ++++++++- .../dsf/fhir/spring/config/ClientConfig.java | 7 +- .../dsf/fhir/spring/config/CommandConfig.java | 2 +- .../fhir/spring/config/WebserviceConfig.java | 85 ++- .../impl/AbstractResourceServiceImpl.java | 241 ++++---- .../secure/AbstractResourceServiceSecure.java | 522 ++++++++++++++---- .../secure/AbstractServiceSecure.java | 94 +++- .../ActivityDefinitionServiceSecure.java | 17 +- .../secure/BinaryServiceSecure.java | 14 +- .../secure/BundleServiceSecure.java | 14 +- .../secure/CodeSystemServiceSecure.java | 13 +- .../secure/ConformanceServiceSecure.java | 9 +- .../secure/EndpointServiceSecure.java | 32 +- .../webservice/secure/GroupServiceSecure.java | 14 +- .../HealthcareServiceServiceSecure.java | 15 +- .../secure/LocationServiceSecure.java | 13 +- .../secure/NamingSystemServiceSecure.java | 15 +- .../secure/OrganizationServiceSecure.java | 15 +- .../secure/PatientServiceSecure.java | 14 +- .../secure/PractitionerRoleServiceSecure.java | 13 +- .../secure/PractitionerServiceSecure.java | 15 +- .../secure/ProvenanceServiceSecure.java | 13 +- .../secure/ResearchStudyServiceSecure.java | 14 +- .../webservice/secure/RootServiceSecure.java | 39 +- .../secure/StaticResourcesServiceSecure.java | 10 +- .../StructureDefinitionServiceSecure.java | 29 +- .../secure/SubscriptionServiceSecure.java | 15 +- .../webservice/secure/TaskServiceSecure.java | 84 ++- .../secure/ValueSetServiceSecure.java | 14 +- .../dsf/fhir/client/ClientProviderTest.java | 18 +- .../dao/command/ResourceReferenceTest.java | 52 +- .../integration/AbstractIntegrationTest.java | 6 +- .../fhir/client/AbstractJerseyClient.java | 4 + .../fhir/client/FhirWebserviceClient.java | 4 + .../client/FhirWebserviceClientJersey.java | 118 ++-- .../fhir/client/TestFhirJerseyClient.java | 5 +- .../dsf-tools-test-data-generator/pom.xml | 4 + dsf-tools/pom.xml | 5 + 58 files changed, 1644 insertions(+), 522 deletions(-) rename dsf-fhir/{dsf-fhir-server => dsf-fhir-rest-adapter}/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractor.java (96%) mode change 100755 => 100644 rename dsf-fhir/{dsf-fhir-server => dsf-fhir-rest-adapter}/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractorImpl.java (93%) mode change 100755 => 100644 rename dsf-fhir/{dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command => dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service}/ResourceReference.java (95%) mode change 100755 => 100644 diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java b/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java index adba8d4cf..68f36a124 100644 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java @@ -12,6 +12,8 @@ import javax.ws.rs.WebApplicationException; import org.highmed.dsf.bpe.Constants; +import org.highmed.dsf.fhir.service.ReferenceExtractor; +import org.highmed.dsf.fhir.service.ReferenceExtractorImpl; import org.highmed.fhir.client.FhirWebserviceClient; import org.highmed.fhir.client.FhirWebserviceClientJersey; import org.hl7.fhir.r4.model.BooleanType; @@ -51,8 +53,9 @@ public static void main(String[] args) KeyStore trustStore = CertificateHelper.extractTrust(keyStore); FhirContext context = FhirContext.forR4(); + ReferenceExtractor referenceExtractor = new ReferenceExtractorImpl(); FhirWebserviceClient client = new FhirWebserviceClientJersey("https://medic1/fhir/", trustStore, keyStore, - keyStorePassword, null, null, null, 0, 0, null, context); + keyStorePassword, null, null, null, 0, 0, null, context, referenceExtractor); try { diff --git a/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java b/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java index b3c65f4af..41d63b53f 100644 --- a/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java @@ -8,6 +8,8 @@ import java.security.cert.CertificateException; import java.util.Date; +import org.highmed.dsf.fhir.service.ReferenceExtractor; +import org.highmed.dsf.fhir.service.ReferenceExtractorImpl; import org.highmed.fhir.client.FhirWebserviceClient; import org.highmed.fhir.client.FhirWebserviceClientJersey; import org.hl7.fhir.r4.model.StringType; @@ -31,8 +33,9 @@ public static void main(String[] args) KeyStore trustStore = CertificateHelper.extractTrust(keyStore); FhirContext context = FhirContext.forR4(); + ReferenceExtractor referenceExtractor = new ReferenceExtractorImpl(); FhirWebserviceClient client = new FhirWebserviceClientJersey("https://ttp/fhir/", trustStore, keyStore, - keyStorePassword, null, null, null, 0, 0, null, context); + keyStorePassword, null, null, null, 0, 0, null, context, referenceExtractor); Task task = new Task(); task.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"); diff --git a/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java b/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java index 5d173c1e2..17d12d6cb 100644 --- a/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java @@ -10,6 +10,8 @@ import java.util.Date; import java.util.Map; +import org.highmed.dsf.fhir.service.ReferenceExtractor; +import org.highmed.dsf.fhir.service.ReferenceExtractorImpl; import org.highmed.fhir.client.FhirWebserviceClient; import org.highmed.fhir.client.FhirWebserviceClientJersey; import org.hl7.fhir.r4.model.Bundle; @@ -35,8 +37,9 @@ public static void main(String[] args) KeyStore trustStore = CertificateHelper.extractTrust(keyStore); FhirContext context = FhirContext.forR4(); + ReferenceExtractor referenceExtractor = new ReferenceExtractorImpl(); FhirWebserviceClient client = new FhirWebserviceClientJersey("https://ttp/fhir/", trustStore, keyStore, - keyStorePassword, null, null, null, 0, 0, null, context); + keyStorePassword, null, null, null, 0, 0, null, context, referenceExtractor); Bundle searchResult = client.search(Bundle.class, Map.of("identifier", Collections.singletonList("http://highmed.org/fhir/CodeSystem/update-whitelist|HiGHmed_white_list"))); diff --git a/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java b/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java index d53df06a3..3231a0e46 100644 --- a/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java @@ -8,6 +8,8 @@ import java.security.cert.CertificateException; import java.util.Date; +import org.highmed.dsf.fhir.service.ReferenceExtractor; +import org.highmed.dsf.fhir.service.ReferenceExtractorImpl; import org.highmed.fhir.client.FhirWebserviceClient; import org.highmed.fhir.client.FhirWebserviceClientJersey; import org.hl7.fhir.r4.model.StringType; @@ -31,8 +33,9 @@ public static void main(String[] args) KeyStore trustStore = CertificateHelper.extractTrust(keyStore); FhirContext context = FhirContext.forR4(); + ReferenceExtractor referenceExtractor = new ReferenceExtractorImpl(); FhirWebserviceClient client = new FhirWebserviceClientJersey("https://ttp/fhir/", trustStore, keyStore, - keyStorePassword, null, null, null, 0, 0, null, context); + keyStorePassword, null, null, null, 0, 0, null, context, referenceExtractor); Task task = new Task(); task.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-update-whitelist"); diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/FhirConfig.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/FhirConfig.java index 23c43d399..754ecbdcc 100755 --- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/FhirConfig.java +++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/FhirConfig.java @@ -17,6 +17,8 @@ import org.highmed.dsf.fhir.group.GroupHelperImpl; import org.highmed.dsf.fhir.organization.OrganizationProvider; import org.highmed.dsf.fhir.organization.OrganizationProviderImpl; +import org.highmed.dsf.fhir.service.ReferenceExtractor; +import org.highmed.dsf.fhir.service.ReferenceExtractorImpl; import org.highmed.dsf.fhir.task.TaskHandler; import org.highmed.dsf.fhir.task.TaskHelper; import org.highmed.dsf.fhir.task.TaskHelperImpl; @@ -46,7 +48,6 @@ import com.fasterxml.jackson.databind.module.SimpleModule; import ca.uhn.fhir.context.FhirContext; - import de.rwh.utils.crypto.CertificateHelper; import de.rwh.utils.crypto.io.CertificateReader; @@ -144,6 +145,12 @@ public FhirContext fhirContext() return FhirContext.forR4(); } + @Bean + public ReferenceExtractor referenceExtractor() + { + return new ReferenceExtractorImpl(); + } + @Bean public ProcessEnginePlugin fhirPlugin() { @@ -218,8 +225,8 @@ public FhirWebsocketClientProvider clientProvider() throw new IOException( "Webservice keystore file '" + localWebserviceKsFile.toString() + "' not readable"); - KeyStore localWebserviceKeyStore = CertificateReader - .fromPkcs12(localWebserviceKsFile, webserviceKeyStorePassword); + KeyStore localWebserviceKeyStore = CertificateReader.fromPkcs12(localWebserviceKsFile, + webserviceKeyStorePassword); KeyStore localWebserviceTrustStore = CertificateHelper.extractTrust(localWebserviceKeyStore); Path localWebsocketKsFile = Paths.get(localWebsocketKeyStoreFile); @@ -227,15 +234,15 @@ public FhirWebsocketClientProvider clientProvider() if (!Files.isReadable(localWebsocketKsFile)) throw new IOException("Websocket keystore file '" + localWebsocketKsFile.toString() + "' not readable"); - KeyStore localWebsocketKeyStore = CertificateReader - .fromPkcs12(localWebsocketKsFile, localWebsocketKeyStorePassword); + KeyStore localWebsocketKeyStore = CertificateReader.fromPkcs12(localWebsocketKsFile, + localWebsocketKeyStorePassword); KeyStore localWebsocketTrustStore = CertificateHelper.extractTrust(localWebsocketKeyStore); - return new FhirClientProviderImpl(fhirContext(), localWebserviceBaseUrl, localReadTimeout, - localConnectTimeout, localWebserviceTrustStore, localWebserviceKeyStore, webserviceKeyStorePassword, - remoteReadTimeout, remoteConnectTimeout, remoteProxyPassword, remoteProxyUsername, - remoteProxySchemeHostPort, localWebsocketUrl, localWebsocketTrustStore, localWebsocketKeyStore, - localWebsocketKeyStorePassword); + return new FhirClientProviderImpl(fhirContext(), referenceExtractor(), localWebserviceBaseUrl, + localReadTimeout, localConnectTimeout, localWebserviceTrustStore, localWebserviceKeyStore, + webserviceKeyStorePassword, remoteReadTimeout, remoteConnectTimeout, remoteProxyPassword, + remoteProxyUsername, remoteProxySchemeHostPort, localWebsocketUrl, localWebsocketTrustStore, + localWebsocketKeyStore, localWebsocketKeyStorePassword); } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) { diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirClientProviderImpl.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirClientProviderImpl.java index 4521f9ec9..8d64a0097 100755 --- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirClientProviderImpl.java +++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirClientProviderImpl.java @@ -8,6 +8,7 @@ import java.util.Objects; import java.util.stream.Collectors; +import org.highmed.dsf.fhir.service.ReferenceExtractor; import org.highmed.fhir.client.FhirWebserviceClient; import org.highmed.fhir.client.FhirWebserviceClientJersey; import org.highmed.fhir.client.WebsocketClient; @@ -22,7 +23,8 @@ import ca.uhn.fhir.context.FhirContext; -public class FhirClientProviderImpl implements FhirWebserviceClientProvider, FhirWebsocketClientProvider, InitializingBean +public class FhirClientProviderImpl + implements FhirWebserviceClientProvider, FhirWebsocketClientProvider, InitializingBean { private static final Logger logger = LoggerFactory.getLogger(FhirClientProviderImpl.class); @@ -30,6 +32,7 @@ public class FhirClientProviderImpl implements FhirWebserviceClientProvider, Fhi private final Map websocketClientsBySubscriptionId = new HashMap<>(); private final FhirContext fhirContext; + private final ReferenceExtractor referenceExtractor; private final String localBaseUrl; private final int localReadTimeout; @@ -50,14 +53,15 @@ public class FhirClientProviderImpl implements FhirWebserviceClientProvider, Fhi private final KeyStore localWebsocketKeyStore; private final String localWebsocketKeyStorePassword; - public FhirClientProviderImpl(FhirContext fhirContext, String localBaseUrl, int localReadTimeout, - int localConnectTimeout, KeyStore webserviceTrustStore, KeyStore webserviceKeyStore, + public FhirClientProviderImpl(FhirContext fhirContext, ReferenceExtractor referenceExtractor, String localBaseUrl, + int localReadTimeout, int localConnectTimeout, KeyStore webserviceTrustStore, KeyStore webserviceKeyStore, String webserviceKeyStorePassword, int remoteReadTimeout, int remoteConnectTimeout, String remoteProxyPassword, String remoteProxyUsername, String remoteProxySchemeHostPort, String localWebsocketUrl, KeyStore localWebsocketTrustStore, KeyStore localWebsocketKeyStore, String localWebsocketKeyStorePassword) { this.fhirContext = fhirContext; + this.referenceExtractor = referenceExtractor; this.localBaseUrl = localBaseUrl; this.localReadTimeout = localReadTimeout; this.localConnectTimeout = localConnectTimeout; @@ -120,11 +124,12 @@ private FhirWebserviceClient getClient(String webserviceUrl) if (localBaseUrl.equals(webserviceUrl)) client = new FhirWebserviceClientJersey(webserviceUrl, webserviceTrustStore, webserviceKeyStore, webserviceKeyStorePassword, null, null, null, localConnectTimeout, localReadTimeout, null, - fhirContext); + fhirContext, referenceExtractor); else client = new FhirWebserviceClientJersey(webserviceUrl, webserviceTrustStore, webserviceKeyStore, webserviceKeyStorePassword, remoteProxySchemeHostPort, remoteProxyUsername, - remoteProxyPassword, remoteConnectTimeout, remoteReadTimeout, null, fhirContext); + remoteProxyPassword, remoteConnectTimeout, remoteReadTimeout, null, fhirContext, + referenceExtractor); webserviceClientsByUrl.put(webserviceUrl, client); return client; @@ -172,9 +177,8 @@ private Endpoint searchForEndpoint(String searchParameter, String searchParamete Collections.singletonList("Organization:endpoint"))); if (resultSet.getTotal() != 1 || resultSet.getEntry().size() != 2) - throw new IllegalStateException( - "Resultset with total 1 and 2 entries expected, but got (" + resultSet.getTotal() + "/" + resultSet - .getEntry().size() + ")"); + throw new IllegalStateException("Resultset with total 1 and 2 entries expected, but got (" + + resultSet.getTotal() + "/" + resultSet.getEntry().size() + ")"); final Endpoint endpoint; if (resultSet.getEntry().get(1).getResource() instanceof Endpoint) @@ -186,9 +190,10 @@ else if (resultSet.getEntry().get(0).getResource() instanceof Endpoint) if (endpoint == null) throw new IllegalStateException( - "Resultset missing resource of type " + Endpoint.class.getName() + ", found (" + resultSet - .getEntry().stream().map(e -> e.getResource().getClass().getName()) - .collect(Collectors.joining(", ")) + ")"); + "Resultset missing resource of type " + + Endpoint.class.getName() + ", found (" + resultSet.getEntry().stream() + .map(e -> e.getResource().getClass().getName()).collect(Collectors.joining(", ")) + + ")"); return endpoint; } diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/AbstractFhirAdapter.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/AbstractFhirAdapter.java index ad248ce82..32c1ac6f4 100755 --- a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/AbstractFhirAdapter.java +++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/AbstractFhirAdapter.java @@ -17,6 +17,7 @@ import org.hl7.fhir.r4.model.BaseResource; +import ca.uhn.fhir.model.api.annotation.ResourceDef; import ca.uhn.fhir.parser.IParser; public abstract class AbstractFhirAdapter implements MessageBodyReader, MessageBodyWriter @@ -32,6 +33,16 @@ protected AbstractFhirAdapter(Class resourceType, Supplier parser) this.parser = parser; } + public final Class getResourceType() + { + return resourceType; + } + + public final String getResourceTypeName() + { + return getResourceType().getAnnotation(ResourceDef.class).name(); + } + private IParser getParser(MediaType mediaType) { /* Parsers are not guaranteed to be thread safe */ diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractor.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractor.java old mode 100755 new mode 100644 similarity index 96% rename from dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractor.java rename to dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractor.java index b175735d4..88c69827b --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractor.java +++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractor.java @@ -2,7 +2,6 @@ import java.util.stream.Stream; -import org.highmed.dsf.fhir.dao.command.ResourceReference; import org.hl7.fhir.r4.model.ActivityDefinition; import org.hl7.fhir.r4.model.Endpoint; import org.hl7.fhir.r4.model.Group; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractorImpl.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractorImpl.java old mode 100755 new mode 100644 similarity index 93% rename from dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractorImpl.java rename to dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractorImpl.java index 3ef7740e1..2cb4fb2c2 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractorImpl.java +++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ReferenceExtractorImpl.java @@ -6,7 +6,6 @@ import java.util.function.Predicate; import java.util.stream.Stream; -import org.highmed.dsf.fhir.dao.command.ResourceReference; import org.hl7.fhir.r4.model.ActivityDefinition; import org.hl7.fhir.r4.model.BackboneElement; import org.hl7.fhir.r4.model.CareTeam; @@ -317,7 +316,7 @@ public Stream getReferences(Organization resource) @Override public Stream getReferences(Patient resource) { - var contacts_organization = getBackboneElementsReference(resource, Patient::hasContact, Patient::getContact, + var contactsOrganization = getBackboneElementsReference(resource, Patient::hasContact, Patient::getContact, ContactComponent::hasOrganization, ContactComponent::getOrganization, "Patient.contact.organization", Organization.class); var generalPractitioners = getReferences(resource, Patient::hasGeneralPractitioner, @@ -325,26 +324,26 @@ public Stream getReferences(Patient resource) PractitionerRole.class); var managingOrganization = getReference(resource, Patient::hasManagingOrganization, Patient::getManagingOrganization, "Patient.managingOrganization", Organization.class); - var links_other = getBackboneElementsReference(resource, Patient::hasLink, Patient::getLink, + var linksOther = getBackboneElementsReference(resource, Patient::hasLink, Patient::getLink, PatientLinkComponent::hasOther, PatientLinkComponent::getOther, "Patient.link.other", Patient.class, RelatedPerson.class); var extensionReferences = getExtensionReferences(resource); - return concat(contacts_organization, generalPractitioners, managingOrganization, links_other, + return concat(contactsOrganization, generalPractitioners, managingOrganization, linksOther, extensionReferences); } @Override public Stream getReferences(Practitioner resource) { - var qualifications_issuer = getBackboneElementsReference(resource, Practitioner::hasQualification, + var qualificationsIssuer = getBackboneElementsReference(resource, Practitioner::hasQualification, Practitioner::getQualification, PractitionerQualificationComponent::hasIssuer, PractitionerQualificationComponent::getIssuer, "Practitioner.qualification.issuer", Organization.class); var extensionReferences = getExtensionReferences(resource); - return concat(qualifications_issuer, extensionReferences); + return concat(qualificationsIssuer, extensionReferences); } @Override @@ -372,20 +371,20 @@ public Stream getReferences(Provenance resource) var targets = getReferences(resource, Provenance::hasTarget, Provenance::getTarget, "Provenance.target"); var location = getReference(resource, Provenance::hasLocation, Provenance::getLocation, "Provenance.location", Location.class); - var agents_who = getBackboneElementsReference(resource, Provenance::hasAgent, Provenance::getAgent, + var agentsWho = getBackboneElementsReference(resource, Provenance::hasAgent, Provenance::getAgent, ProvenanceAgentComponent::hasWho, ProvenanceAgentComponent::getWho, "Provenance.agent.who", Practitioner.class, PractitionerRole.class, RelatedPerson.class, Patient.class, Device.class, Organization.class); - var agents_onBehalfOf = getBackboneElementsReference(resource, Provenance::hasAgent, Provenance::getAgent, + var agentsOnBehalfOf = getBackboneElementsReference(resource, Provenance::hasAgent, Provenance::getAgent, ProvenanceAgentComponent::hasOnBehalfOf, ProvenanceAgentComponent::getOnBehalfOf, "Provenance.agent.onBehalfOf", Practitioner.class, PractitionerRole.class, RelatedPerson.class, Patient.class, Device.class, Organization.class); - var entities_what = getBackboneElementsReference(resource, Provenance::hasEntity, Provenance::getEntity, + var entitiesWhat = getBackboneElementsReference(resource, Provenance::hasEntity, Provenance::getEntity, ProvenanceEntityComponent::hasWhat, ProvenanceEntityComponent::getWhat, "Provenance.entity.what"); var extensionReferences = getExtensionReferences(resource); - return concat(targets, location, agents_who, agents_onBehalfOf, entities_what, extensionReferences); + return concat(targets, location, agentsWho, agentsOnBehalfOf, entitiesWhat, extensionReferences); } @Override @@ -416,7 +415,7 @@ public Stream getReferences(Task resource) var basedOns = getReferences(resource, Task::hasBasedOn, Task::getBasedOn, "Task.basedOn"); var partOfs = getReferences(resource, Task::hasPartOf, Task::getPartOf, "Task.partOf", Task.class); var focus = getReference(resource, Task::hasFocus, Task::getFocus, "Task.focus"); - var for_ = getReference(resource, Task::hasFor, Task::getFor, "Task.for"); + var forRef = getReference(resource, Task::hasFor, Task::getFor, "Task.for"); var encounter = getReference(resource, Task::hasEncounter, Task::getEncounter, "Task.encounter", Encounter.class); var requester = getReference(resource, Task::hasRequester, Task::getRequester, "Task.requester", Device.class, @@ -431,7 +430,7 @@ public Stream getReferences(Task resource) Coverage.class, ClaimResponse.class); var relevanteHistories = getReferences(resource, Task::hasRelevantHistory, Task::getRelevantHistory, "Task.relevantHistory", Provenance.class); - var restriction_recipiets = getBackboneElementReferences(resource, Task::hasRestriction, Task::getRestriction, + var restrictionRecipiets = getBackboneElementReferences(resource, Task::hasRestriction, Task::getRestriction, Task.TaskRestrictionComponent::hasRecipient, Task.TaskRestrictionComponent::getRecipient, "Task.restriction.recipient", Patient.class, Practitioner.class, PractitionerRole.class, RelatedPerson.class, Group.class, Organization.class); @@ -440,8 +439,8 @@ public Stream getReferences(Task resource) var outputReferences = getOutputReferences(resource); var extensionReferences = getExtensionReferences(resource); - return concat(basedOns, partOfs, focus, for_, encounter, requester, owner, location, reasonReference, insurance, - relevanteHistories, restriction_recipiets, inputReferences, outputReferences, extensionReferences); + return concat(basedOns, partOfs, focus, forRef, encounter, requester, owner, location, reasonReference, insurance, + relevanteHistories, restrictionRecipiets, inputReferences, outputReferences, extensionReferences); } private Stream getInputReferences(Task resource) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResourceReference.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ResourceReference.java old mode 100755 new mode 100644 similarity index 95% rename from dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResourceReference.java rename to dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ResourceReference.java index 62777411b..3a871fb86 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResourceReference.java +++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/service/ResourceReference.java @@ -1,6 +1,8 @@ -package org.highmed.dsf.fhir.dao.command; +package org.highmed.dsf.fhir.service; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Objects; @@ -13,7 +15,7 @@ public class ResourceReference { - private static final Pattern TEMP_ID_PATTERN = Pattern.compile(Command.URL_UUID_PREFIX + ".+"); + private static final Pattern TEMP_ID_PATTERN = Pattern.compile("urn:uuid:.+"); private static final Pattern ID_PATTERN = Pattern .compile("(?(http|https):\\/\\/([A-Za-z0-9\\-\\\\\\.\\:\\%\\$]*\\/)+)?" @@ -101,8 +103,14 @@ public static enum ReferenceType private final Reference reference; private final List> referenceTypes = new ArrayList<>(); + @SafeVarargs + public ResourceReference(String referenceLocation, Reference reference, Class... referenceTypes) + { + this(referenceLocation, reference, Arrays.asList(referenceTypes)); + } + public ResourceReference(String referenceLocation, Reference reference, - List> referenceTypes) + Collection> referenceTypes) { this.referenceLocation = referenceLocation; this.reference = reference; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/UserProvider.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/UserProvider.java index 7c1ba15cb..26d32bf42 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/UserProvider.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/UserProvider.java @@ -27,6 +27,12 @@ public User getCurrentUser() return (User) httpRequest.get().getSession().getAttribute(AuthenticationFilter.USER_PROPERTY); } + /** + * @param expectedRoles + * @throws WebApplicationException + * with status {@link Status#UNAUTHORIZED} if there is no current user, with status + * {@link Status#FORBIDDEN} if the current user does not have one of the provided role + */ public void checkCurrentUserHasOneOfRoles(UserRole... expectedRoles) { User user = getCurrentUser(); @@ -45,4 +51,5 @@ else if (!UserRole.userHasOneOfRoles(user, expectedRoles)) throw new WebApplicationException(Status.FORBIDDEN); } } + } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/client/ClientProviderImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/client/ClientProviderImpl.java index daa7487e1..858e78294 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/client/ClientProviderImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/client/ClientProviderImpl.java @@ -1,18 +1,21 @@ package org.highmed.dsf.fhir.client; import java.security.KeyStore; +import java.util.Objects; import java.util.Optional; import org.highmed.dsf.fhir.dao.EndpointDao; import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.service.ReferenceExtractor; import org.highmed.fhir.client.FhirWebserviceClient; import org.highmed.fhir.client.FhirWebserviceClientJersey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; import ca.uhn.fhir.context.FhirContext; -public class ClientProviderImpl implements ClientProvider +public class ClientProviderImpl implements ClientProvider, InitializingBean { private static final Logger logger = LoggerFactory.getLogger(ClientProviderImpl.class); @@ -26,13 +29,15 @@ public class ClientProviderImpl implements ClientProvider private final String remoteProxyUsername; private final String remoteProxySchemeHostPort; private final FhirContext fhirContext; + private final ReferenceExtractor referenceExtractor; private final EndpointDao endpointDao; private final ExceptionHandler exceptionHandler; public ClientProviderImpl(KeyStore webserviceTrustStore, KeyStore webserviceKeyStore, String webserviceKeyStorePassword, int remoteReadTimeout, int remoteConnectTimeout, String remoteProxyPassword, String remoteProxyUsername, String remoteProxySchemeHostPort, - FhirContext fhirContext, EndpointDao endpointDao, ExceptionHandler exceptionHandler) + FhirContext fhirContext, ReferenceExtractor referenceExtractor, EndpointDao endpointDao, + ExceptionHandler exceptionHandler) { this.webserviceTrustStore = webserviceTrustStore; this.webserviceKeyStore = webserviceKeyStore; @@ -43,10 +48,24 @@ public ClientProviderImpl(KeyStore webserviceTrustStore, KeyStore webserviceKeyS this.remoteProxyUsername = remoteProxyUsername; this.remoteProxySchemeHostPort = remoteProxySchemeHostPort; this.fhirContext = fhirContext; + this.referenceExtractor = referenceExtractor; this.endpointDao = endpointDao; this.exceptionHandler = exceptionHandler; } + @Override + public void afterPropertiesSet() throws Exception + { + Objects.requireNonNull(webserviceTrustStore, "webserviceTrustStore"); + Objects.requireNonNull(webserviceKeyStore, "webserviceKeyStore"); + Objects.requireNonNull(webserviceKeyStorePassword, "webserviceKeyStorePassword"); + + Objects.requireNonNull(fhirContext, "fhirContext"); + Objects.requireNonNull(referenceExtractor, "referenceExtractor"); + Objects.requireNonNull(endpointDao, "endpointDao"); + Objects.requireNonNull(exceptionHandler, "exceptionHandler"); + } + @Override public Optional getClient(String serverBase) { @@ -55,9 +74,10 @@ public Optional getClient(String serverBase) if (endpointExists) { - FhirWebserviceClient client = new FhirWebserviceClientJersey(serverBase, webserviceTrustStore, webserviceKeyStore, - webserviceKeyStorePassword, remoteProxySchemeHostPort, remoteProxyUsername, remoteProxyPassword, - remoteConnectTimeout, remoteReadTimeout, null, fhirContext); + FhirWebserviceClient client = new FhirWebserviceClientJersey(serverBase, webserviceTrustStore, + webserviceKeyStore, webserviceKeyStorePassword, remoteProxySchemeHostPort, remoteProxyUsername, + remoteProxyPassword, remoteConnectTimeout, remoteReadTimeout, null, fhirContext, + referenceExtractor); return Optional.of(client); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResourceDao.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResourceDao.java index 79d8dbdb2..d787414cb 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResourceDao.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResourceDao.java @@ -110,6 +110,26 @@ public interface ResourceDao */ Optional readVersionWithTransaction(Connection connection, UUID uuid, long version) throws SQLException; + /** + * @param uuid + * may be null + * @return {@link Optional#empty()} if the given uuid is null or no resource could be found for the + * given uuid + * @throws SQLException + */ + Optional readIncludingDeleted(UUID uuid) throws SQLException; + + /** + * @param connection + * not null + * @param uuid + * may be null + * @return {@link Optional#empty()} if the given uuid is null or no resource could be found for the + * given uuid + * @throws SQLException + */ + Optional readIncludingDeletedWithTransaction(Connection connection, UUID uuid) throws SQLException; + /** * @param id * not null diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java index e9e359b5c..eaeadd025 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java @@ -16,6 +16,7 @@ import org.highmed.dsf.fhir.help.ResponseGenerator; import org.highmed.dsf.fhir.service.ReferenceExtractor; import org.highmed.dsf.fhir.service.ReferenceResolver; +import org.highmed.dsf.fhir.service.ResourceReference; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r4.model.IdType; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java index 55fb43d65..914ce93d8 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java @@ -140,7 +140,7 @@ private void updateById(Map idTranslationTable, Connection conne Optional ifMatch = Optional.ofNullable(entry.getRequest().getIfMatch()) .flatMap(parameterConverter::toEntityTag).flatMap(parameterConverter::toVersion); - updatedResource = exceptionHandler.handleSqlExAndResourceNotFoundExForUpdateAsCreateAndResouceVersionNonMatchEx( + updatedResource = exceptionHandler.handleSqlExAndResourceNotFoundExAndResouceVersionNonMatchEx( resourceTypeName, () -> dao.updateWithTransaction(connection, resource, ifMatch.orElse(null))); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java index 33e08ea83..8df047aaf 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java @@ -428,6 +428,50 @@ public Optional readVersionWithTransaction(Connection connection, UUID uuid, } } + @Override + public Optional readIncludingDeleted(UUID uuid) throws SQLException + { + if (uuid == null) + return Optional.empty(); + + try (Connection connection = dataSource.getConnection()) + { + return readIncludingDeletedWithTransaction(connection, uuid); + } + } + + @Override + public Optional readIncludingDeletedWithTransaction(Connection connection, UUID uuid) throws SQLException + { + Objects.requireNonNull(connection, "connection"); + if (uuid == null) + return Optional.empty(); + + try (PreparedStatement statement = connection.prepareStatement(preparedStatementFactory.getReadByIdSql())) + { + preparedStatementFactory.configureReadByIdStatement(statement, uuid); + + logger.trace("Executing query '{}'", statement); + try (ResultSet result = statement.executeQuery()) + { + if (result.next()) + { + if (preparedStatementFactory.isReadByIdDeleted(result)) + logger.warn("{} with IdPart {} found, but marked as deleted", resourceTypeName, uuid); + else + logger.debug("{} with IdPart {} found", resourceTypeName, uuid); + + return Optional.of(preparedStatementFactory.getReadByIdResource(result)); + } + else + { + logger.debug("{} with IdPart {} not found", resourceTypeName, uuid); + return Optional.empty(); + } + } + } + } + @Override public boolean existsNotDeleted(String idString, String versionString) throws SQLException { @@ -800,7 +844,7 @@ public PartialResult searchWithTransaction(Connection connection, DbSearchQue List partialResult = new ArrayList<>(); List includes = new ArrayList<>(); - + if (!query.isCountOnly(overallCount)) // TODO ask db if count 0 { try (PreparedStatement statement = connection.prepareStatement(query.getSearchSql())) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ExceptionHandler.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ExceptionHandler.java index da1d03b11..1fec6e6a6 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ExceptionHandler.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ExceptionHandler.java @@ -104,7 +104,7 @@ public WebApplicationException internalServerErrorBundleBatch(Exception e) return new WebApplicationException(Response.status(Status.INTERNAL_SERVER_ERROR).entity(outcome).build()); } - public T handleSqlExAndResourceNotFoundExForUpdateAsCreateAndResouceVersionNonMatchEx(String resourceTypeName, + public T handleSqlExAndResourceNotFoundExAndResouceVersionNonMatchEx(String resourceTypeName, SupplierWithSqlAndResourceNotFoundAndResouceVersionNoMatchException s) { try @@ -136,7 +136,7 @@ private WebApplicationException resourceVersionNoMatch(String resourceTypeName, return new WebApplicationException(Response.status(Status.PRECONDITION_FAILED).entity(outcome).build()); } - public WebApplicationException notFound(String resourceTypeName, IllegalArgumentException e) + public WebApplicationException notFound(String resourceTypeName) { logger.error("{} with id (not a UUID) not found", resourceTypeName); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ParameterConverter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ParameterConverter.java index 03471bd92..b414bce09 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ParameterConverter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ParameterConverter.java @@ -56,14 +56,26 @@ public UUID toUuid(String resourceTypeName, String id) if (id == null) return null; + return toUuid(id).orElseThrow(() -> exceptionHandler.notFound(resourceTypeName)); + } + + /** + * @param id + * @return {@link Optional#empty()} if the given id is null or is not a {@link UUID} + */ + public Optional toUuid(String id) + { + if (id == null) + return Optional.empty(); + // TODO control flow by exception try { - return UUID.fromString(id); + return Optional.of(UUID.fromString(id)); } catch (IllegalArgumentException e) { - throw exceptionHandler.notFound(resourceTypeName, e); + return Optional.empty(); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ResponseGenerator.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ResponseGenerator.java index a6e118dc3..d3fa59112 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ResponseGenerator.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ResponseGenerator.java @@ -14,9 +14,9 @@ import javax.ws.rs.core.UriBuilder; import org.highmed.dsf.fhir.authentication.User; -import org.highmed.dsf.fhir.dao.command.ResourceReference; import org.highmed.dsf.fhir.search.PartialResult; import org.highmed.dsf.fhir.search.SearchQueryParameterError; +import org.highmed.dsf.fhir.service.ResourceReference; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r4.model.Bundle.BundleType; @@ -392,7 +392,7 @@ public Response noEndpointFoundForLiteralExternalReference(Integer bundleIndex, return Response.status(Status.BAD_REQUEST).entity(outcome).build(); } - public Response badReference(boolean logicalNoConditional, Integer bundleIndex, Resource resource, + public Response badReference(boolean logicalNotConditional, Integer bundleIndex, Resource resource, ResourceReference resourceReference, String queryParameters, List unsupportedQueryParameters) { @@ -402,18 +402,18 @@ public Response badReference(boolean logicalNoConditional, Integer bundleIndex, if (bundleIndex == null) logger.warn( "{} reference {} at {} in resource of type {} with id {} contains unsupported queryparameter{} {}", - logicalNoConditional ? "Logical" : "Conditional", queryParameters, + logicalNotConditional ? "Logical" : "Conditional", queryParameters, resourceReference.getReferenceLocation(), resource.getResourceType().name(), resource.getId(), unsupportedQueryParameters.size() != 1 ? "s" : "", unsupportedQueryParametersString); else logger.warn( "{} reference {} at {} in resource of type {} with id {} at bundle index {} contains unsupported queryparameter{} {}", - logicalNoConditional ? "Logical" : "Conditional", queryParameters, + logicalNotConditional ? "Logical" : "Conditional", queryParameters, resourceReference.getReferenceLocation(), resource.getResourceType().name(), resource.getId(), bundleIndex, unsupportedQueryParameters.size() != 1 ? "s" : "", unsupportedQueryParametersString); OperationOutcome outcome = createOutcome(IssueSeverity.ERROR, IssueType.PROCESSING, - (logicalNoConditional ? "Logical" : "Conditional") + " reference " + queryParameters + " at " + (logicalNotConditional ? "Logical" : "Conditional") + " reference " + queryParameters + " at " + resourceReference.getReferenceLocation() + " in resource of type " + resource.getResourceType().name() + " with id " + resource.getId() + (bundleIndex == null ? "" : " at bundle index " + bundleIndex) @@ -707,13 +707,21 @@ public Response badBundleEntryFullUrlVsResourceId(int bundleIndex, String fullUr return Response.status(Status.BAD_REQUEST).entity(out).build(); } - public Response forbiddenNotAllowed(String operation, User user, String reason) + public Response forbiddenNotAllowed(String operation, User user) { - logger.warn("Operation {} forbidden for user '{}'{}", operation, user.getName(), - reason != null ? " " + reason : ""); + logger.warn("Operation {} forbidden for user '{}'", operation, user.getName()); OperationOutcome out = createOutcome(IssueSeverity.ERROR, IssueType.FORBIDDEN, "Operation " + operation + " forbidden"); return Response.status(Status.FORBIDDEN).entity(out).build(); } + + public Response notFound(String id, String resourceTypeName) + { + logger.warn("{} with id {} not found", resourceTypeName, id); + + OperationOutcome outcome = createOutcome(IssueSeverity.ERROR, IssueType.PROCESSING, + resourceTypeName + " with id " + id + " not found"); + return Response.status(Status.NOT_FOUND).entity(outcome).build(); + } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolver.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolver.java index d591d326f..0593fd4aa 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolver.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolver.java @@ -1,14 +1,43 @@ package org.highmed.dsf.fhir.service; import java.sql.Connection; +import java.util.List; +import java.util.Optional; import javax.ws.rs.WebApplicationException; -import org.highmed.dsf.fhir.dao.command.ResourceReference; +import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.Resource; public interface ReferenceResolver { + /** + * @param referenceLocation + * @param reference + * not null + * @param referenceTypes + * @return {@link Optional#empty()} if the reference could not be resolved + * @throws IllegalArgumentException + * if the reference is not of type {@link ResourceReference.ReferenceType#LITERAL_INTERNAL}, + * {@link ResourceReference.ReferenceType#LITERAL_EXTERNAL}, + * {@link ResourceReference.ReferenceType#CONDITIONAL} or + * {@link ResourceReference.ReferenceType#LOGICAL} + */ + Optional resolveReference(String referenceLocation, Reference reference, + List> referenceTypes); + + /** + * @param reference + * not null + * @return {@link Optional#empty()} if the reference could not be resolved + * @throws IllegalArgumentException + * if the reference is not of type {@link ResourceReference.ReferenceType#LITERAL_INTERNAL}, + * {@link ResourceReference.ReferenceType#LITERAL_EXTERNAL}, + * {@link ResourceReference.ReferenceType#CONDITIONAL} or + * {@link ResourceReference.ReferenceType#LOGICAL} + */ + Optional resolveReference(ResourceReference reference); + /** * @param resource * not null @@ -142,8 +171,8 @@ boolean resolveLiteralExternalReference(Resource resource, Integer bundleIndex, * if the reference is not of type {@link ResourceReference.ReferenceType#CONDITIONAL} * @see ResourceReference#getType(String) */ - boolean resolveConditionalReference(Resource resource, ResourceReference resourceReference, - Connection connection) throws WebApplicationException, IllegalArgumentException; + boolean resolveConditionalReference(Resource resource, ResourceReference resourceReference, Connection connection) + throws WebApplicationException, IllegalArgumentException; /** * @param resource diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolverImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolverImpl.java index acc5a0be3..1dc016f87 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolverImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolverImpl.java @@ -8,23 +8,25 @@ import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; +import java.util.UUID; import java.util.stream.Collectors; import javax.ws.rs.WebApplicationException; import org.highmed.dsf.fhir.client.ClientProvider; import org.highmed.dsf.fhir.dao.ResourceDao; -import org.highmed.dsf.fhir.dao.command.ResourceReference; -import org.highmed.dsf.fhir.dao.command.ResourceReference.ReferenceType; import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; import org.highmed.dsf.fhir.search.PartialResult; import org.highmed.dsf.fhir.search.SearchQuery; import org.highmed.dsf.fhir.search.SearchQueryParameterError; +import org.highmed.dsf.fhir.service.ResourceReference.ReferenceType; import org.highmed.fhir.client.FhirWebserviceClient; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.Identifier; +import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,15 +44,17 @@ public class ReferenceResolverImpl implements ReferenceResolver, InitializingBea private final ResponseGenerator responseGenerator; private final ExceptionHandler exceptionHandler; private final ClientProvider clientProvider; + private final ParameterConverter parameterConverter; public ReferenceResolverImpl(String serverBase, DaoProvider daoProvider, ResponseGenerator responseGenerator, - ExceptionHandler exceptionHandler, ClientProvider clientProvider) + ExceptionHandler exceptionHandler, ClientProvider clientProvider, ParameterConverter parameterConverter) { this.serverBase = serverBase; this.daoProvider = daoProvider; this.responseGenerator = responseGenerator; this.exceptionHandler = exceptionHandler; this.clientProvider = clientProvider; + this.parameterConverter = parameterConverter; } @Override @@ -61,6 +65,35 @@ public void afterPropertiesSet() throws Exception Objects.requireNonNull(responseGenerator, "responseGenerator"); Objects.requireNonNull(exceptionHandler, "exceptionHandler"); Objects.requireNonNull(clientProvider, "clientProvider"); + Objects.requireNonNull(parameterConverter, "parameterConverter"); + } + + @Override + public Optional resolveReference(String referenceLocation, Reference reference, + List> referenceTypes) + { + Objects.requireNonNull(reference, "reference"); + return resolveReference(new ResourceReference(referenceLocation, reference, referenceTypes)); + } + + @Override + public Optional resolveReference(ResourceReference reference) + { + Objects.requireNonNull(reference, "reference"); + switch (reference.getType(serverBase)) + { + case LITERAL_INTERNAL: + return resolveLiteralInternalReference(reference); + case LITERAL_EXTERNAL: + return resolveLiteralExternalReference(reference); + case CONDITIONAL: + return resolveConditionalReference(reference); + case LOGICAL: + return resolveLogicalReference(reference); + default: + throw new IllegalArgumentException( + "Reference of type " + reference.getType(serverBase) + " not supported"); + } } @Override @@ -93,6 +126,43 @@ public boolean resolveReference(Resource resource, Integer bundleIndex, Resource } } + private Optional resolveLiteralInternalReference(ResourceReference resourceReference) + { + Objects.requireNonNull(resourceReference, "resourceReference"); + if (!ReferenceType.LITERAL_INTERNAL.equals(resourceReference.getType(serverBase))) + throw new IllegalArgumentException("Not a literal internal reference"); + + IdType id = new IdType(resourceReference.getReference().getReference()); + Optional> referenceDao = daoProvider.getDao(id.getResourceType()); + + if (referenceDao.isEmpty()) + { + logger.warn("Reference target type of reference at {} not supported by this implementation", + resourceReference.getReferenceLocation()); + return Optional.empty(); + } + else + { + @SuppressWarnings("unchecked") + ResourceDao d = (ResourceDao) referenceDao.get(); + if (!resourceReference.supportsType(d.getResourceType())) + { + logger.warn("Reference target type of reference at {} not supported", + resourceReference.getReferenceLocation()); + return Optional.empty(); + } + + Optional uuid = parameterConverter.toUuid(id.getIdPart()); + + if (id.hasVersionIdPart()) + return uuid.flatMap(i -> exceptionHandler.catchAndLogSqlAndResourceDeletedExceptionAndIfReturn( + () -> d.read(i), Optional::empty, Optional::empty)); + else + return uuid.flatMap(i -> exceptionHandler.catchAndLogSqlAndResourceDeletedExceptionAndIfReturn( + () -> d.readVersion(i, id.getVersionIdPartAsLong()), Optional::empty, Optional::empty)); + } + } + @Override public boolean resolveLiteralInternalReference(Resource resource, ResourceReference resourceReference, Connection connection) throws WebApplicationException, IllegalArgumentException @@ -134,6 +204,36 @@ public boolean resolveLiteralInternalReference(Resource resource, Integer bundle return false; // throws exception if reference could not be resolved } + private Optional resolveLiteralExternalReference(ResourceReference resourceReference) + { + Objects.requireNonNull(resourceReference, "resourceReference"); + if (!ReferenceType.LITERAL_EXTERNAL.equals(resourceReference.getType(serverBase))) + throw new IllegalArgumentException("Not a literal external reference"); + + String remoteServerBase = resourceReference.getServerBase(serverBase); + Optional client = clientProvider.getClient(remoteServerBase); + + if (client.isEmpty()) + { + logger.warn( + "Error while resolving literal external reference {}, no remote client found for server base {}", + resourceReference.getReference().getReference(), remoteServerBase); + return Optional.empty(); + } + else + { + IdType referenceId = new IdType(resourceReference.getReference().getReference()); + logger.debug("Trying to resolve literal external reference {}, at remote server {}", + resourceReference.getReference().getReference(), remoteServerBase); + + if (!referenceId.hasVersionIdPart()) + return Optional.ofNullable(client.get().read(referenceId.getResourceType(), referenceId.getIdPart())); + else + return Optional.ofNullable(client.get().read(referenceId.getResourceType(), referenceId.getIdPart(), + referenceId.getVersionIdPart())); + } + } + @Override public boolean resolveLiteralExternalReference(Resource resource, ResourceReference resourceReference) throws WebApplicationException, IllegalArgumentException @@ -179,6 +279,44 @@ public boolean resolveLiteralExternalReference(Resource resource, Integer bundle return true; // throws exception if reference could not be resolved } + private Optional resolveConditionalReference(ResourceReference resourceReference) + { + Objects.requireNonNull(resourceReference, "resourceReference"); + if (!ReferenceType.CONDITIONAL.equals(resourceReference.getType(serverBase))) + throw new IllegalArgumentException("Not a conditional reference"); + + UriComponents condition = UriComponentsBuilder.fromUriString(resourceReference.getReference().getReference()) + .build(); + String path = condition.getPath(); + if (path == null || path.isBlank()) + { + logger.warn("Bad conditional reference target '{}' of reference at {}", + resourceReference.getReference().getReference(), resourceReference.getReferenceLocation()); + return Optional.empty(); + } + + Optional> referenceDao = daoProvider.getDao(path); + + if (referenceDao.isEmpty()) + { + logger.warn("Reference target type of reference at {} not supported by this implementation", + resourceReference.getReferenceLocation()); + return Optional.empty(); + } + else + { + ResourceDao d = referenceDao.get(); + if (!resourceReference.supportsType(d.getResourceType())) + { + logger.warn("Reference target type of reference at {} not supported", + resourceReference.getReferenceLocation()); + return Optional.empty(); + } + + return search(d, resourceReference, condition.getQueryParams(), true); + } + } + @Override public boolean resolveConditionalReference(Resource resource, ResourceReference resourceReference, Connection connection) throws WebApplicationException, IllegalArgumentException @@ -226,6 +364,38 @@ public boolean resolveConditionalReference(Resource resource, Integer bundleInde return true; // throws exception if reference could not be resolved } + private Optional resolveLogicalReference(ResourceReference resourceReference) + { + Objects.requireNonNull(resourceReference, "resourceReference"); + if (!ReferenceType.LOGICAL.equals(resourceReference.getType(serverBase))) + throw new IllegalArgumentException("Not a logical reference"); + + String targetType = resourceReference.getReference().getType(); + + Optional> referenceDao = daoProvider.getDao(targetType); + + if (referenceDao.isEmpty()) + { + logger.warn("Reference target type of reference at {} not supported by this implementation", + resourceReference.getReferenceLocation()); + return Optional.empty(); + } + else + { + ResourceDao d = referenceDao.get(); + if (!resourceReference.supportsType(d.getResourceType())) + { + logger.warn("Reference target type of reference at {} not supported by this implementation", + resourceReference.getReferenceLocation()); + return Optional.empty(); + } + + Identifier targetIdentifier = resourceReference.getReference().getIdentifier(); + return search(d, resourceReference, Map.of("identifier", + Collections.singletonList(targetIdentifier.getSystem() + "|" + targetIdentifier.getValue())), true); + } + } + @Override public boolean resolveLogicalReference(Resource resource, ResourceReference resourceReference, Connection connection) throws WebApplicationException, IllegalArgumentException @@ -268,9 +438,81 @@ public boolean resolveLogicalReference(Resource resource, Integer bundleIndex, R return true; // throws exception if reference could not be resolved } + private Optional search(ResourceDao referenceTargetDao, ResourceReference resourceReference, + Map> queryParameters, boolean logicalNotConditional) + { + if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) + { + logger.warn( + "Query contains parameter not applicable in this resolve reference context: '{}', parameters {} will be ignored", + UriComponentsBuilder.newInstance() + .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), + Arrays.toString(SearchQuery.STANDARD_PARAMETERS)); + + queryParameters = queryParameters.entrySet().stream() + .filter(e -> !Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(p -> p.equals(e.getKey()))) + .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + } + + SearchQuery query = referenceTargetDao.createSearchQuery(1, 1); + query.configureParameters(queryParameters); + + List unsupportedQueryParameters = query + .getUnsupportedQueryParameters(queryParameters); + if (!unsupportedQueryParameters.isEmpty()) + { + String unsupportedQueryParametersString = unsupportedQueryParameters.stream() + .map(SearchQueryParameterError::toString).collect(Collectors.joining("; ")); + + logger.warn("{} reference {} at {} in resource contains unsupported queryparameter{} {}", + logicalNotConditional ? "Logical" : "Conditional", queryParameters, + resourceReference.getReferenceLocation(), unsupportedQueryParameters.size() != 1 ? "s" : "", + unsupportedQueryParametersString); + + return Optional.empty(); + } + + PartialResult result = exceptionHandler.handleSqlException(() -> referenceTargetDao.search(query)); + + if (result.getOverallCount() <= 0) + { + if (logicalNotConditional) + logger.warn("Reference target by identifier '{}|{}' of reference at {} in resource", + resourceReference.getReference().getIdentifier().getSystem(), + resourceReference.getReference().getIdentifier().getValue(), + resourceReference.getReferenceLocation()); + else + logger.warn("Reference target by identifier '{}|{}' of reference at {} in resource", + resourceReference.getReference().getIdentifier().getSystem(), + resourceReference.getReference().getIdentifier().getValue(), + resourceReference.getReferenceLocation()); + return Optional.empty(); + } + else if (result.getOverallCount() == 1) + { + return Optional.of(result.getPartialResult().get(0)); + } + else // if (result.getOverallCount() > 1) + { + int overallCount = result.getOverallCount(); + + if (logicalNotConditional) + logger.warn( + "Found {} matches for reference target by identifier '{}|{}' of reference at {} in resource", + overallCount, resourceReference.getReference().getIdentifier().getSystem(), + resourceReference.getReference().getIdentifier().getValue(), + resourceReference.getReferenceLocation()); + else + logger.warn("Found {} matches for reference target by condition '{}' of reference at {} in resource", + overallCount, queryParameters, resourceReference.getReferenceLocation()); + + return Optional.empty(); + } + } + private Resource search(Resource resource, Integer bundleIndex, Connection connection, ResourceDao referenceTargetDao, ResourceReference resourceReference, - Map> queryParameters, boolean logicalNoConditional) + Map> queryParameters, boolean logicalNotConditional) { if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) { @@ -292,7 +534,7 @@ private Resource search(Resource resource, Integer bundleIndex, Connection conne .getUnsupportedQueryParameters(queryParameters); if (!unsupportedQueryParameters.isEmpty()) throw new WebApplicationException( - responseGenerator.badReference(logicalNoConditional, bundleIndex, resource, resourceReference, + responseGenerator.badReference(logicalNotConditional, bundleIndex, resource, resourceReference, UriComponentsBuilder.newInstance() .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), unsupportedQueryParameters)); @@ -302,7 +544,7 @@ private Resource search(Resource resource, Integer bundleIndex, Connection conne if (result.getOverallCount() <= 0) { - if (logicalNoConditional) + if (logicalNotConditional) throw new WebApplicationException(responseGenerator .referenceTargetNotFoundLocallyByIdentifier(bundleIndex, resource, resourceReference)); else @@ -316,7 +558,7 @@ else if (result.getOverallCount() == 1) } else // if (result.getOverallCount() > 1) { - if (logicalNoConditional) + if (logicalNotConditional) throw new WebApplicationException(responseGenerator.referenceTargetMultipleMatchesLocallyByIdentifier( bundleIndex, resource, resourceReference, result.getOverallCount())); else diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/ClientConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/ClientConfig.java index 22ebd0091..077ea2dfd 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/ClientConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/ClientConfig.java @@ -52,6 +52,9 @@ public class ClientConfig @Autowired private HelperConfig helperConfig; + @Autowired + private CommandConfig commandConfig; + @Bean public ClientProvider clientProvider() { @@ -67,8 +70,8 @@ public ClientProvider clientProvider() return new ClientProviderImpl(webserviceTrustStore, webserviceKeyStore, webserviceKeyStorePassword, remoteReadTimeout, remoteConnectTimeout, remoteProxyPassword, remoteProxyUsername, - remoteProxySchemeHostPort, fhirConfig.fhirContext(), daoConfig.endpointDao(), - helperConfig.exceptionHandler()); + remoteProxySchemeHostPort, fhirConfig.fhirContext(), commandConfig.referenceExtractor(), + daoConfig.endpointDao(), helperConfig.exceptionHandler()); } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/CommandConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/CommandConfig.java index 6eb46d8c8..919aab13b 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/CommandConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/CommandConfig.java @@ -44,7 +44,7 @@ public ReferenceExtractorImpl referenceExtractor() public ReferenceResolver referenceResolver() { return new ReferenceResolverImpl(serverBase, daoConfig.daoProvider(), helperConfig.responseGenerator(), - helperConfig.exceptionHandler(), clientConfig.clientProvider()); + helperConfig.exceptionHandler(), clientConfig.clientProvider(), helperConfig.parameterConverter()); } @Bean diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java index 75ef4a422..86aa1251a 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java @@ -138,7 +138,9 @@ public ActivityDefinitionService activityDefinitionService() private ActivityDefinitionServiceSecure activityDefinitionServiceSecure() { - return new ActivityDefinitionServiceSecure(activityDefinitionServiceImpl(), helperConfig.responseGenerator()); + return new ActivityDefinitionServiceSecure(activityDefinitionServiceImpl(), serverBase, + helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.activityDefinitionDao(), + helperConfig.exceptionHandler(), helperConfig.parameterConverter()); } private ActivityDefinitionServiceImpl activityDefinitionServiceImpl() @@ -158,7 +160,9 @@ public CodeSystemService codeSystemService() private CodeSystemServiceSecure codeSystemServiceSecure() { - return new CodeSystemServiceSecure(codeSystemServiceImpl(), helperConfig.responseGenerator()); + return new CodeSystemServiceSecure(codeSystemServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver(), daoConfig.codeSystemDao(), helperConfig.exceptionHandler(), + helperConfig.parameterConverter()); } private CodeSystemServiceImpl codeSystemServiceImpl() @@ -178,7 +182,9 @@ public BinaryService binaryService() private BinaryServiceSecure binaryServiceSecure() { - return new BinaryServiceSecure(binaryServiceImpl(), helperConfig.responseGenerator()); + return new BinaryServiceSecure(binaryServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver(), daoConfig.binaryDao(), helperConfig.exceptionHandler(), + helperConfig.parameterConverter()); } private BinaryService binaryServiceImpl() @@ -197,7 +203,9 @@ public BundleService bundleService() private BundleServiceSecure bundleServiceSecure() { - return new BundleServiceSecure(bundleServiceImpl(), helperConfig.responseGenerator()); + return new BundleServiceSecure(bundleServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver(), daoConfig.bundleDao(), helperConfig.exceptionHandler(), + helperConfig.parameterConverter()); } private BundleService bundleServiceImpl() @@ -216,7 +224,9 @@ public EndpointService endpointService() private EndpointServiceSecure endpointServiceSecure() { - return new EndpointServiceSecure(endpointServiceImpl(), helperConfig.responseGenerator()); + return new EndpointServiceSecure(endpointServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver(), daoConfig.endpointDao(), helperConfig.exceptionHandler(), + helperConfig.parameterConverter()); } private EndpointServiceImpl endpointServiceImpl() @@ -235,7 +245,9 @@ public GroupService groupService() private GroupServiceSecure groupServiceSecure() { - return new GroupServiceSecure(groupServiceImpl(), helperConfig.responseGenerator()); + return new GroupServiceSecure(groupServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver(), daoConfig.groupDao(), helperConfig.exceptionHandler(), + helperConfig.parameterConverter()); } private GroupServiceImpl groupServiceImpl() @@ -254,7 +266,9 @@ public HealthcareServiceService healthcareServiceService() private HealthcareServiceServiceSecure healthcareServiceServiceSecure() { - return new HealthcareServiceServiceSecure(healthcareServiceServiceImpl(), helperConfig.responseGenerator()); + return new HealthcareServiceServiceSecure(healthcareServiceServiceImpl(), serverBase, + helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.healthcareServiceDao(), + helperConfig.exceptionHandler(), helperConfig.parameterConverter()); } private HealthcareServiceServiceImpl healthcareServiceServiceImpl() @@ -274,7 +288,9 @@ public LocationService locationService() private LocationServiceSecure locationServiceSecure() { - return new LocationServiceSecure(locationServiceImpl(), helperConfig.responseGenerator()); + return new LocationServiceSecure(locationServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver(), daoConfig.locationDao(), helperConfig.exceptionHandler(), + helperConfig.parameterConverter()); } private LocationServiceImpl locationServiceImpl() @@ -293,7 +309,9 @@ public NamingSystemService namingSystemService() private NamingSystemServiceSecure namingSystemServiceSecure() { - return new NamingSystemServiceSecure(namingSystemServiceImpl(), helperConfig.responseGenerator()); + return new NamingSystemServiceSecure(namingSystemServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver(), daoConfig.namingSystemDao(), helperConfig.exceptionHandler(), + helperConfig.parameterConverter()); } private NamingSystemService namingSystemServiceImpl() @@ -313,7 +331,9 @@ public OrganizationService organizationService() private OrganizationServiceSecure organizationServiceSecure() { - return new OrganizationServiceSecure(organizationServiceImpl(), helperConfig.responseGenerator()); + return new OrganizationServiceSecure(organizationServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver(), daoConfig.organizationDao(), helperConfig.exceptionHandler(), + helperConfig.parameterConverter()); } private OrganizationServiceImpl organizationServiceImpl() @@ -333,7 +353,9 @@ public PatientService patientService() private PatientServiceSecure patientServiceSecure() { - return new PatientServiceSecure(patientServiceImpl(), helperConfig.responseGenerator()); + return new PatientServiceSecure(patientServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver(), daoConfig.patientDao(), helperConfig.exceptionHandler(), + helperConfig.parameterConverter()); } private PatientServiceImpl patientServiceImpl() @@ -352,7 +374,9 @@ public PractitionerRoleService practitionerRoleService() private PractitionerRoleServiceSecure practitionerRoleServiceSecure() { - return new PractitionerRoleServiceSecure(practitionerRoleServiceImpl(), helperConfig.responseGenerator()); + return new PractitionerRoleServiceSecure(practitionerRoleServiceImpl(), serverBase, + helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.practitionerRoleDao(), + helperConfig.exceptionHandler(), helperConfig.parameterConverter()); } private PractitionerRoleServiceImpl practitionerRoleServiceImpl() @@ -372,7 +396,9 @@ public PractitionerService practitionerService() private PractitionerServiceSecure practitionerServiceSecure() { - return new PractitionerServiceSecure(practitionerServiceImpl(), helperConfig.responseGenerator()); + return new PractitionerServiceSecure(practitionerServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver(), daoConfig.practitionerDao(), helperConfig.exceptionHandler(), + helperConfig.parameterConverter()); } private PractitionerServiceImpl practitionerServiceImpl() @@ -392,7 +418,9 @@ public ProvenanceService provenanceService() private ProvenanceServiceSecure provenanceServiceSecure() { - return new ProvenanceServiceSecure(provenanceServiceImpl(), helperConfig.responseGenerator()); + return new ProvenanceServiceSecure(provenanceServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver(), daoConfig.provenanceDao(), helperConfig.exceptionHandler(), + helperConfig.parameterConverter()); } private ProvenanceServiceImpl provenanceServiceImpl() @@ -412,7 +440,9 @@ public ResearchStudyService researchStudyService() private ResearchStudyServiceSecure researchStudyServiceSecure() { - return new ResearchStudyServiceSecure(researchStudyServiceImpl(), helperConfig.responseGenerator()); + return new ResearchStudyServiceSecure(researchStudyServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver(), daoConfig.researchStudyDao(), helperConfig.exceptionHandler(), + helperConfig.parameterConverter()); } private ResearchStudyServiceImpl researchStudyServiceImpl() @@ -432,7 +462,9 @@ public StructureDefinitionService structureDefinitionService() private StructureDefinitionServiceSecure structureDefinitionServiceSecure() { - return new StructureDefinitionServiceSecure(structureDefinitionServiceImpl(), helperConfig.responseGenerator()); + return new StructureDefinitionServiceSecure(structureDefinitionServiceImpl(), serverBase, + helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.structureDefinitionDao(), + helperConfig.exceptionHandler(), helperConfig.parameterConverter()); } private StructureDefinitionServiceImpl structureDefinitionServiceImpl() @@ -453,7 +485,9 @@ public SubscriptionService subscriptionService() private SubscriptionServiceSecure subscriptionServiceSecure() { - return new SubscriptionServiceSecure(subscriptionServiceImpl(), helperConfig.responseGenerator()); + return new SubscriptionServiceSecure(subscriptionServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver(), daoConfig.subscriptionDao(), helperConfig.exceptionHandler(), + helperConfig.parameterConverter()); } private SubscriptionServiceImpl subscriptionServiceImpl() @@ -473,7 +507,9 @@ public TaskService taskService() private TaskServiceSecure taskServiceSecure() { - return new TaskServiceSecure(taskServiceImpl(), helperConfig.responseGenerator()); + return new TaskServiceSecure(taskServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver(), daoConfig.taskDao(), helperConfig.exceptionHandler(), + helperConfig.parameterConverter(), daoConfig.activityDefinitionDao()); } private TaskServiceImpl taskServiceImpl() @@ -492,7 +528,9 @@ public ValueSetService valueSetService() private ValueSetServiceSecure valueSetServiceSecure() { - return new ValueSetServiceSecure(valueSetServiceImpl(), helperConfig.responseGenerator()); + return new ValueSetServiceSecure(valueSetServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver(), daoConfig.valueSetDao(), helperConfig.exceptionHandler(), + helperConfig.parameterConverter()); } private ValueSetServiceImpl valueSetServiceImpl() @@ -511,7 +549,8 @@ public RootService rootService() private RootServiceSecure rootServiceSecure() { - return new RootServiceSecure(rootServiceImpl(), helperConfig.responseGenerator()); + return new RootServiceSecure(rootServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver()); } private RootServiceImpl rootServiceImpl() @@ -528,7 +567,8 @@ public ConformanceService conformanceService() private ConformanceServiceSecure conformanceServiceSecure() { - return new ConformanceServiceSecure(conformanceServiceImpl(), helperConfig.responseGenerator()); + return new ConformanceServiceSecure(conformanceServiceImpl(), serverBase, helperConfig.responseGenerator(), + commandConfig.referenceResolver()); } private ConformanceServiceImpl conformanceServiceImpl() @@ -545,7 +585,8 @@ public StaticResourcesService staticResourcesService() private StaticResourcesServiceSecure staticResourcesServiceSecure() { - return new StaticResourcesServiceSecure(staticResourcesServiceImpl(), helperConfig.responseGenerator()); + return new StaticResourcesServiceSecure(staticResourcesServiceImpl(), serverBase, + helperConfig.responseGenerator(), commandConfig.referenceResolver()); } private StaticResourcesServiceImpl staticResourcesServiceImpl() diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java index a4f6ac07f..24bad652d 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java @@ -29,7 +29,6 @@ import javax.ws.rs.core.UriInfo; import org.highmed.dsf.fhir.dao.ResourceDao; -import org.highmed.dsf.fhir.dao.command.ResourceReference; import org.highmed.dsf.fhir.dao.exception.ResourceNotFoundException; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -41,6 +40,7 @@ import org.highmed.dsf.fhir.search.SearchQueryParameterError; import org.highmed.dsf.fhir.service.ReferenceExtractor; import org.highmed.dsf.fhir.service.ReferenceResolver; +import org.highmed.dsf.fhir.service.ResourceReference; import org.highmed.dsf.fhir.service.ResourceValidator; import org.highmed.dsf.fhir.webservice.specification.BasicResourceService; import org.hl7.fhir.r4.model.Bundle; @@ -61,7 +61,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.CollectionUtils; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; @@ -76,7 +75,7 @@ public abstract class AbstractResourceServiceImpl, R ex { private static final Logger logger = LoggerFactory.getLogger(AbstractResourceServiceImpl.class); - protected final Class resourceType; + protected final Class resourceType; protected final String resourceTypeName; protected final String serverBase; protected final int defaultPageCount; @@ -90,7 +89,7 @@ public abstract class AbstractResourceServiceImpl, R ex protected final ReferenceExtractor referenceExtractor; protected final ReferenceResolver referenceResolver; - public AbstractResourceServiceImpl(String path, Class resourceType, String serverBase, + public AbstractResourceServiceImpl(String path, Class resourceType, String serverBase, int defaultPageCount, D dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, ReferenceExtractor referenceExtractor, @@ -379,7 +378,7 @@ public Response update(String id, R resource, UriInfo uri, HttpHeaders headers) .flatMap(parameterConverter::toEntityTag).flatMap(parameterConverter::toVersion); R updatedResource = exceptionHandler - .handleSqlExAndResourceNotFoundExForUpdateAsCreateAndResouceVersionNonMatchEx(resourceTypeName, () -> + .handleSqlExAndResourceNotFoundExAndResouceVersionNonMatchEx(resourceTypeName, () -> { try (Connection connection = dao.getNewTransaction()) { @@ -430,77 +429,79 @@ protected Consumer preUpdate(R resource) @Override public Response update(R resource, UriInfo uri, HttpHeaders headers) { - Map> queryParameters = uri.getQueryParameters(); - if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) - { - logger.warn( - "Query contains parameter not applicable in this conditional update context: '{}', parameters {} will be ignored", - UriComponentsBuilder.newInstance() - .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), - Arrays.toString(SearchQuery.STANDARD_PARAMETERS)); - - queryParameters = queryParameters.entrySet().stream() - .filter(e -> !Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(p -> p.equals(e.getKey()))) - .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); - } - - SearchQuery query = dao.createSearchQuery(1, 1); - query.configureParameters(queryParameters); - - List unsupportedQueryParameters = query - .getUnsupportedQueryParameters(queryParameters); - if (!unsupportedQueryParameters.isEmpty()) - return responseGenerator.badRequest( - UriComponentsBuilder.newInstance() - .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), - unsupportedQueryParameters); - - PartialResult result = exceptionHandler.handleSqlException(() -> dao.search(query)); - - // No matches, no id provided: The server creates the resource. - if (result.getOverallCount() <= 0 && !resource.hasId()) - return create(resource, uri, headers); - - // No matches, id provided: The server treats the interaction as an Update as Create interaction (or rejects it, - // if it does not support Update as Create) -> reject - else if (result.getOverallCount() <= 0 && resource.hasId()) - return responseGenerator.updateAsCreateNotAllowed(resourceTypeName, resource.getId()); - - // One Match, no resource id provided OR (resource id provided and it matches the found resource): - // The server performs the update against the matching resource - else if (result.getOverallCount() == 1) - { - R dbResource = result.getPartialResult().get(0); - IdType dbResourceId = dbResource.getIdElement(); - - // BaseUrl - The server base URL (e.g. "http://example.com/fhir") - // ResourceType - The resource type (e.g. "Patient") - // IdPart - The ID (e.g. "123") - // Version - The version ID ("e.g. "456") - if (!resource.hasId()) - { - resource.setIdElement(dbResourceId); - return update(resource.getIdElement().getIdPart(), resource, uri, headers); - } - else if (resource.hasId() - && (!resource.getIdElement().hasBaseUrl() - || serverBase.equals(resource.getIdElement().getBaseUrl())) - && (!resource.getIdElement().hasResourceType() - || resourceTypeName.equals(resource.getIdElement().getResourceType())) - && (dbResourceId.getIdPart().equals(resource.getIdElement().getIdPart()))) - return update(resource.getIdElement().getIdPart(), resource, uri, headers); - else - return responseGenerator.badRequestIdsNotMatching( - dbResourceId.withServerBase(serverBase, resourceTypeName), - resource.getIdElement().hasBaseUrl() && resource.getIdElement().hasResourceType() - ? resource.getIdElement() - : resource.getIdElement().withServerBase(serverBase, resourceTypeName)); - } - // Multiple matches: The server returns a 412 Precondition Failed error indicating the client's criteria were - // not selective enough preferably with an OperationOutcome - else // if (result.getOverallCount() > 1) - throw new WebApplicationException(responseGenerator.multipleExists(resourceTypeName, UriComponentsBuilder - .newInstance().replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString())); + throw new UnsupportedOperationException("Implemented and delegated by security layer"); + +// Map> queryParameters = uri.getQueryParameters(); +// if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) +// { +// logger.warn( +// "Query contains parameter not applicable in this conditional update context: '{}', parameters {} will be ignored", +// UriComponentsBuilder.newInstance() +// .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), +// Arrays.toString(SearchQuery.STANDARD_PARAMETERS)); +// +// queryParameters = queryParameters.entrySet().stream() +// .filter(e -> !Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(p -> p.equals(e.getKey()))) +// .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); +// } +// +// SearchQuery query = dao.createSearchQuery(1, 1); +// query.configureParameters(queryParameters); +// +// List unsupportedQueryParameters = query +// .getUnsupportedQueryParameters(queryParameters); +// if (!unsupportedQueryParameters.isEmpty()) +// return responseGenerator.badRequest( +// UriComponentsBuilder.newInstance() +// .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), +// unsupportedQueryParameters); +// +// PartialResult result = exceptionHandler.handleSqlException(() -> dao.search(query)); +// +// // No matches, no id provided: The server creates the resource. +// if (result.getOverallCount() <= 0 && !resource.hasId()) +// return create(resource, uri, headers); +// +// // No matches, id provided: The server treats the interaction as an Update as Create interaction (or rejects it, +// // if it does not support Update as Create) -> reject +// else if (result.getOverallCount() <= 0 && resource.hasId()) +// return responseGenerator.updateAsCreateNotAllowed(resourceTypeName, resource.getId()); +// +// // One Match, no resource id provided OR (resource id provided and it matches the found resource): +// // The server performs the update against the matching resource +// else if (result.getOverallCount() == 1) +// { +// R dbResource = result.getPartialResult().get(0); +// IdType dbResourceId = dbResource.getIdElement(); +// +// // BaseUrl - The server base URL (e.g. "http://example.com/fhir") +// // ResourceType - The resource type (e.g. "Patient") +// // IdPart - The ID (e.g. "123") +// // Version - The version ID ("e.g. "456") +// if (!resource.hasId()) +// { +// resource.setIdElement(dbResourceId); +// return update(resource.getIdElement().getIdPart(), resource, uri, headers); +// } +// else if (resource.hasId() +// && (!resource.getIdElement().hasBaseUrl() +// || serverBase.equals(resource.getIdElement().getBaseUrl())) +// && (!resource.getIdElement().hasResourceType() +// || resourceTypeName.equals(resource.getIdElement().getResourceType())) +// && (dbResourceId.getIdPart().equals(resource.getIdElement().getIdPart()))) +// return update(resource.getIdElement().getIdPart(), resource, uri, headers); +// else +// return responseGenerator.badRequestIdsNotMatching( +// dbResourceId.withServerBase(serverBase, resourceTypeName), +// resource.getIdElement().hasBaseUrl() && resource.getIdElement().hasResourceType() +// ? resource.getIdElement() +// : resource.getIdElement().withServerBase(serverBase, resourceTypeName)); +// } +// // Multiple matches: The server returns a 412 Precondition Failed error indicating the client's criteria were +// // not selective enough preferably with an OperationOutcome +// else // if (result.getOverallCount() > 1) +// throw new WebApplicationException(responseGenerator.multipleExists(resourceTypeName, UriComponentsBuilder +// .newInstance().replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString())); } @Override @@ -541,49 +542,51 @@ protected Consumer preDelete(String id) @Override public Response delete(UriInfo uri, HttpHeaders headers) { - Map> queryParameters = uri.getQueryParameters(); - if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) - { - logger.warn( - "Query contains parameter not applicable in this conditional delete context: '{}', parameters {} will be ignored", - UriComponentsBuilder.newInstance() - .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), - Arrays.toString(SearchQuery.STANDARD_PARAMETERS)); - - queryParameters = queryParameters.entrySet().stream() - .filter(e -> !Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(p -> p.equals(e.getKey()))) - .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); - } - - SearchQuery query = dao.createSearchQuery(1, 1); - query.configureParameters(queryParameters); - - List unsupportedQueryParameters = query - .getUnsupportedQueryParameters(queryParameters); - if (!unsupportedQueryParameters.isEmpty()) - return responseGenerator.badRequest( - UriComponentsBuilder.newInstance() - .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), - unsupportedQueryParameters); - - PartialResult result = exceptionHandler.handleSqlException(() -> dao.search(query)); - - // No matches - if (result.getOverallCount() <= 0) - { - return Response.noContent().build(); // TODO return OperationOutcome - } - // One Match: The server performs an ordinary delete on the matching resource - else if (result.getOverallCount() == 1) - { - R resource = result.getPartialResult().get(0); - return delete(resource.getIdElement().getIdPart(), uri, headers); - } - // Multiple matches: A server may choose to delete all the matching resources, or it may choose to return a 412 - // Precondition Failed error indicating the client's criteria were not selective enough. - else - throw new WebApplicationException(responseGenerator.multipleExists(resourceTypeName, UriComponentsBuilder - .newInstance().replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString())); + throw new UnsupportedOperationException("Implemented and delegated by security layer"); + +// Map> queryParameters = uri.getQueryParameters(); +// if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) +// { +// logger.warn( +// "Query contains parameter not applicable in this conditional delete context: '{}', parameters {} will be ignored", +// UriComponentsBuilder.newInstance() +// .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), +// Arrays.toString(SearchQuery.STANDARD_PARAMETERS)); +// +// queryParameters = queryParameters.entrySet().stream() +// .filter(e -> !Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(p -> p.equals(e.getKey()))) +// .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); +// } +// +// SearchQuery query = dao.createSearchQuery(1, 1); +// query.configureParameters(queryParameters); +// +// List unsupportedQueryParameters = query +// .getUnsupportedQueryParameters(queryParameters); +// if (!unsupportedQueryParameters.isEmpty()) +// return responseGenerator.badRequest( +// UriComponentsBuilder.newInstance() +// .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), +// unsupportedQueryParameters); +// +// PartialResult result = exceptionHandler.handleSqlException(() -> dao.search(query)); +// +// // No matches +// if (result.getOverallCount() <= 0) +// { +// return Response.noContent().build(); // TODO return OperationOutcome +// } +// // One Match: The server performs an ordinary delete on the matching resource +// else if (result.getOverallCount() == 1) +// { +// R resource = result.getPartialResult().get(0); +// return delete(resource.getIdElement().getIdPart(), uri, headers); +// } +// // Multiple matches: A server may choose to delete all the matching resources, or it may choose to return a 412 +// // Precondition Failed error indicating the client's criteria were not selective enough. +// else +// throw new WebApplicationException(responseGenerator.multipleExists(resourceTypeName, UriComponentsBuilder +// .newInstance().replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString())); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java index 57166c8c9..2e103f53d 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java @@ -1,91 +1,205 @@ package org.highmed.dsf.fhir.webservice.secure; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.Optional; +import java.util.stream.Collectors; +import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; -import org.highmed.dsf.fhir.authentication.UserRole; +import org.highmed.dsf.fhir.dao.ResourceDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.search.PartialResult; +import org.highmed.dsf.fhir.search.SearchQuery; +import org.highmed.dsf.fhir.search.SearchQueryParameterError; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.BasicResourceService; +import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.OperationOutcome; import org.hl7.fhir.r4.model.Parameters; import org.hl7.fhir.r4.model.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.util.CollectionUtils; +import org.springframework.web.util.UriComponentsBuilder; -public abstract class AbstractResourceServiceSecure> +import ca.uhn.fhir.model.api.annotation.ResourceDef; + +public abstract class AbstractResourceServiceSecure, R extends Resource, S extends BasicResourceService> extends AbstractServiceSecure implements BasicResourceService { private static final Logger logger = LoggerFactory.getLogger(AbstractResourceServiceSecure.class); - public AbstractResourceServiceSecure(S delegate, ResponseGenerator responseGenerator) + protected final Class resourceType; + protected final String resourceTypeName; + protected final String serverBase; + protected final D dao; + protected final ExceptionHandler exceptionHandler; + protected final ParameterConverter parameterConverter; + + public AbstractResourceServiceSecure(S delegate, String serverBase, ResponseGenerator responseGenerator, + ReferenceResolver referenceResolver, Class resourceType, D dao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver); + + this.resourceType = resourceType; + this.resourceTypeName = resourceType.getAnnotation(ResourceDef.class).name(); + this.serverBase = serverBase; + this.dao = dao; + this.exceptionHandler = exceptionHandler; + this.parameterConverter = parameterConverter; } @Override public Response create(R resource, UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); + logger.debug("Current user '{}', role '{}'", userProvider.getCurrentUser().getName(), + userProvider.getCurrentUser().getRole()); - return reasonCreateNotAllowed(resource).map(forbidden("create")) - .orElse(delegate.create(resource, uri, headers)); + Optional reasonCreateAllowed = reasonCreateAllowed(resource); + + if (reasonCreateAllowed.isEmpty()) + { + audit.info("Create of resource {} denied for user '{}'", resourceTypeName, getCurrentUser().getName()); + return forbidden("create"); + } + else + { + audit.info("Create of resource {} allowed for user '{}'", resourceTypeName, getCurrentUser().getName()); + return delegate.create(resource, uri, headers); + } } /** - * Override this method for non default behavior. Default: Not allowed if user role not {@link UserRole#LOCAL}. + * Override this method for non default behavior. Default: Not allowed. * * @param resource - * @return {@link Optional#empty()} if create(resource) allowed + * @return Reason as String in {@link Optional#of(Object))} if create allowed */ - protected Optional reasonCreateNotAllowed(R resource) + protected Optional reasonCreateAllowed(R resource) { - if (!UserRole.LOCAL.equals(provider.getCurrentUser().getRole())) - return Optional.of("Missing role 'LOCAL'"); - else - return Optional.empty(); + return Optional.empty(); } @Override public Response read(String id, UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); - - return reasonReadNotAllowed(id).map(forbidden("read")).orElse(delegate.read(id, uri, headers)); - } + logger.debug("Current user '{}', role '{}'", userProvider.getCurrentUser().getName(), + userProvider.getCurrentUser().getRole()); + + Response read = delegate.read(id, uri, headers); + + if (read.hasEntity() && resourceType.isInstance(read.getEntity())) + { + R entity = resourceType.cast(read.getEntity()); + Optional reasonReadAllowed = reasonReadAllowed(entity); + + if (reasonReadAllowed.isEmpty()) + { + audit.info("Read of resource {} denied for user '{}'", entity.getIdElement().getValue(), + getCurrentUser().getName()); + return forbidden("read"); + } + else + { + audit.info("Read of resource {} allowed for user '{}'", entity.getIdElement().getValue(), + getCurrentUser().getName()); + return read; + } + } + else if (read.hasEntity() && read.getEntity() instanceof OperationOutcome) + { + audit.info("Read of resource {} for user '{}' returned with OperationOutcome, status {}", + resourceTypeName + "/" + id, getCurrentUser().getName(), read.getStatus()); + + logger.info("Returning with OperationOutcome, status {}", read.getStatus()); + return read; + } + else if (read.hasEntity()) + { + audit.info("Read of resource {} denied for user '{}', not a {}", resourceTypeName + "/" + id, + getCurrentUser().getName(), resourceTypeName); + + logger.warn("Not allowing access to entity of type {}", read.getEntity().getClass().getName()); + return forbidden("read"); + } + else + { + audit.info("Read of resource {} for user '{}' returned without entity, status {}", + resourceTypeName + "/" + id, getCurrentUser().getName(), read.getStatus()); - /** - * Override this method for non default behavior. Default: Always allowed. - * - * @param id - * @return {@link Optional#empty()} if read(id) allowed - */ - protected Optional reasonReadNotAllowed(String id) - { - return Optional.empty(); + logger.warn("Returning with status {}, but no entity", read.getStatus()); + return read; + } } @Override public Response vread(String id, long version, UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); + logger.debug("Current user '{}', role '{}'", userProvider.getCurrentUser().getName(), + userProvider.getCurrentUser().getRole()); + + Response read = delegate.vread(id, version, uri, headers); + + if (read.hasEntity() && resourceType.isInstance(read.getEntity())) + { + R entity = resourceType.cast(read.getEntity()); + Optional reasonReadAllowed = reasonReadAllowed(entity); + + if (reasonReadAllowed.isEmpty()) + { + audit.info("Read of resource {} denied for user '{}'", entity.getIdElement().getValue(), + getCurrentUser().getName()); + return forbidden("read"); + } + else + { + audit.info("Read of resource {} allowed for user '{}'", entity.getIdElement().getValue(), + getCurrentUser().getName()); + return read; + } + } + else if (read.hasEntity() && read.getEntity() instanceof OperationOutcome) + { + audit.info("Read of resource {} for user '{}' returned with OperationOutcome, status {}", + resourceTypeName + "/" + id + "/_history/" + version, getCurrentUser().getName(), read.getStatus()); + + logger.info("Returning with OperationOutcome, status {}", read.getStatus()); + return read; + } + else if (read.hasEntity()) + { + audit.info("Read of resource {} denied for user '{}', not a {}", + resourceTypeName + "/" + id + "/_history/" + version, getCurrentUser().getName(), resourceTypeName); + + logger.warn("Not allowing access to entity of type {}", read.getEntity().getClass().getName()); + return forbidden("read"); + } + else + { + audit.info("Read of resource {} for user '{}' returned without entity, status {}", + resourceTypeName + "/" + id + "/_history/" + version, getCurrentUser().getName(), read.getStatus()); - return reasonReadNotAllowed(id, version).map(forbidden("read")) - .orElse(delegate.vread(id, version, uri, headers)); + logger.warn("Returning with status {}, but no entity", read.getStatus()); + return read; + } } /** - * Override this method for non default behavior. Default: Always allowed. + * Override this method for non default behavior. Default: Not allowed. * - * @param id - * @param version - * @return {@link Optional#empty()} if read(id, version) allowed + * @param resource + * @return Reason as String in {@link Optional#of(Object)} if read allowed */ - protected Optional reasonReadNotAllowed(String id, long version) + protected Optional reasonReadAllowed(R resource) { return Optional.empty(); } @@ -93,113 +207,307 @@ protected Optional reasonReadNotAllowed(String id, long version) @Override public Response update(String id, R resource, UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); + logger.debug("Current user '{}', role '{}'", userProvider.getCurrentUser().getName(), + userProvider.getCurrentUser().getRole()); + + Optional dbResource = exceptionHandler.handleSqlAndResourceDeletedException(resourceTypeName, + () -> dao.read(parameterConverter.toUuid(resourceTypeName, id))); + + if (dbResource.isEmpty()) + { + audit.info("Create as Update of non existing resource {} denied for user '{}'", resourceTypeName + "/" + id, + getCurrentUser().getName()); + return responseGenerator.updateAsCreateNotAllowed(resourceTypeName, resourceTypeName + "/" + id); + } + else + return update(id, resource, uri, headers, dbResource.get()); + } - return reasonUpdateNotAllowed(id, resource).map(forbidden("update")) - .orElse(delegate.update(id, resource, uri, headers)); + private Response update(String id, R newResource, UriInfo uri, HttpHeaders headers, R oldResource) + { + Optional reasonUpdateAllowed = reasonUpdateAllowed(oldResource, newResource); + + if (reasonUpdateAllowed.isEmpty()) + { + audit.info("Update of resource {} denied for user '{}'", oldResource.getIdElement().getValue(), + getCurrentUser().getName()); + return forbidden("update"); + } + else + { + audit.info("Update of resource {} allowed for user '{}'", oldResource.getIdElement().getValue(), + getCurrentUser().getName()); + + Response update = delegate.update(id, newResource, uri, headers); + + if (update.hasEntity() && !(update.getEntity() instanceof OperationOutcome)) + logger.warn("Update returned with entity of type {}", update.getEntity().getClass().getName()); + else + logger.info("Update returned with status {}, but no entity", update.getStatus()); + + return update; + } } /** - * Override this method for non default behavior. Default: Not allowed if user role not {@link UserRole#LOCAL}. + * Override this method for non default behavior. Default: Not allowed. * - * @param id - * @param resource - * @return {@link Optional#empty()} if update(id, resource) allowed + * @param oldResource + * @param newResource + * @return Reason as String in {@link Optional#of(Object))} if update allowed */ - protected Optional reasonUpdateNotAllowed(String id, R resource) + protected Optional reasonUpdateAllowed(R oldResource, R newResource) { - if (!UserRole.LOCAL.equals(provider.getCurrentUser().getRole())) - return Optional.of("Missing role 'LOCAL'"); - else - return Optional.empty(); + return Optional.empty(); } @Override public Response update(R resource, UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); - - return reasonUpdateNotAllowed(resource, uri).map(forbidden("update")) - .orElse(delegate.update(resource, uri, headers)); + logger.debug("Current user '{}', role '{}'", userProvider.getCurrentUser().getName(), + userProvider.getCurrentUser().getRole()); + + Map> queryParameters = uri.getQueryParameters(); + PartialResult result = getExisting(queryParameters); + + // No matches, no id provided: The server creates the resource. + if (result.getOverallCount() <= 0 && !resource.hasId()) + { + // more security checks and audit log in create method + return create(resource, uri, headers); + } + + // No matches, id provided: The server treats the interaction as an Update as Create interaction (or rejects it, + // if it does not support Update as Create) -> reject + else if (result.getOverallCount() <= 0 && resource.hasId()) + { + audit.info("Create as Update of non existing resource {} denied for user '{}'", + resource.getIdElement().getValue(), getCurrentUser().getName()); + return responseGenerator.updateAsCreateNotAllowed(resourceTypeName, resource.getIdElement().getValue()); + } + + // One Match, no resource id provided OR (resource id provided and it matches the found resource): + // The server performs the update against the matching resource + else if (result.getOverallCount() == 1) + { + R dbResource = result.getPartialResult().get(0); + IdType dbResourceId = dbResource.getIdElement(); + + // update resource has no id + if (!resource.hasId()) + { + resource.setIdElement(dbResourceId); + // more security checks and audit log in update method + return update(resource.getIdElement().getIdPart(), resource, uri, headers, resource); + } + + // update resource has same id + else if (resource.hasId() + && (!resource.getIdElement().hasBaseUrl() + || serverBase.equals(resource.getIdElement().getBaseUrl())) + && (!resource.getIdElement().hasResourceType() + || resourceTypeName.equals(resource.getIdElement().getResourceType())) + && (dbResourceId.getIdPart().equals(resource.getIdElement().getIdPart()))) + // more security checks and audit log in update method + return update(resource.getIdElement().getIdPart(), resource, uri, headers, resource); + + // update resource has different id -> 400 Bad Request + else + { + // TODO audit log + return responseGenerator.badRequestIdsNotMatching( + dbResourceId.withServerBase(serverBase, resourceTypeName), + resource.getIdElement().hasBaseUrl() && resource.getIdElement().hasResourceType() + ? resource.getIdElement() + : resource.getIdElement().withServerBase(serverBase, resourceTypeName)); + } + } + + // Multiple matches: The server returns a 412 Precondition Failed error indicating the client's criteria were + // not selective enough preferably with an OperationOutcome + else // if (result.getOverallCount() > 1) + { + // TODO audit log + return responseGenerator.multipleExists(resourceTypeName, UriComponentsBuilder.newInstance() + .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString()); + } } - /** - * Override this method for non default behavior. Default: Not allowed if user role not {@link UserRole#LOCAL}. - * - * @param resource - * @param uri - * @return {@link Optional#empty()} if update(resource, uri) allowed - */ - protected Optional reasonUpdateNotAllowed(R resource, UriInfo uri) + private PartialResult getExisting(Map> queryParameters) { - if (!UserRole.LOCAL.equals(provider.getCurrentUser().getRole())) - return Optional.of("Missing role 'LOCAL'"); - else - return Optional.empty(); + if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) + { + logger.warn( + "Query contains parameter not applicable in this conditional update context: '{}', parameters {} will be ignored", + UriComponentsBuilder.newInstance() + .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), + Arrays.toString(SearchQuery.STANDARD_PARAMETERS)); + + queryParameters = queryParameters.entrySet().stream() + .filter(e -> !Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(p -> p.equals(e.getKey()))) + .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + } + + SearchQuery query = dao.createSearchQuery(1, 1); + query.configureParameters(queryParameters); + + List unsupportedQueryParameters = query + .getUnsupportedQueryParameters(queryParameters); + if (!unsupportedQueryParameters.isEmpty()) + { + // TODO audit log + throw new WebApplicationException(responseGenerator.badRequest( + UriComponentsBuilder.newInstance() + .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), + unsupportedQueryParameters)); + } + + return exceptionHandler.handleSqlException(() -> dao.search(query)); } @Override public Response delete(String id, UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); - - return reasonDeleteNotAllowed(id).map(forbidden("delete")).orElse(delegate.delete(id, uri, headers)); + logger.debug("Current user '{}', role '{}'", userProvider.getCurrentUser().getName(), + userProvider.getCurrentUser().getRole()); + + Optional dbResource = exceptionHandler + .handleSqlException(() -> dao.readIncludingDeleted(parameterConverter.toUuid(resourceTypeName, id))); + + if (dbResource.isPresent()) + { + R oldResource = dbResource.get(); + + Optional reasonDeleteAllowed = reasonDeleteAllowed(oldResource); + if (reasonDeleteAllowed.isEmpty()) + { + audit.info("Delete of resource {} denied for user '{}'", oldResource.getIdElement().getValue(), + getCurrentUser().getName()); + return forbidden("delete"); + } + else + { + audit.info("Delete of resource {} allowed for user '{}'", oldResource.getIdElement().getValue(), + getCurrentUser().getName()); + return delegate.delete(id, uri, headers); + } + } + else + { + audit.info("Resource to delete {} not found for user '{}'", resourceTypeName + "/" + id, + getCurrentUser().getName()); + return responseGenerator.notFound(id, resourceTypeName); + } } /** - * Override this method for non default behavior. Default: Not allowed if user role not {@link UserRole#LOCAL}. + * Override this method for non default behavior. Default: Not allowed. * - * @param id - * @return {@link Optional#empty()} if delete(id) allowed + * @param oldResource + * @return Reason as String in {@link Optional#of(Object)} if delete allowed */ - protected Optional reasonDeleteNotAllowed(String id) + protected Optional reasonDeleteAllowed(R oldResource) { - if (!UserRole.LOCAL.equals(provider.getCurrentUser().getRole())) - return Optional.of("Missing role 'LOCAL'"); - else - return Optional.empty(); + return Optional.empty(); } @Override public Response delete(UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); + logger.debug("Current user '{}', role '{}'", userProvider.getCurrentUser().getName(), + userProvider.getCurrentUser().getRole()); + + Map> queryParameters = uri.getQueryParameters(); + if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) + { + logger.warn( + "Query contains parameter not applicable in this conditional delete context: '{}', parameters {} will be ignored", + UriComponentsBuilder.newInstance() + .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), + Arrays.toString(SearchQuery.STANDARD_PARAMETERS)); + + queryParameters = queryParameters.entrySet().stream() + .filter(e -> !Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(p -> p.equals(e.getKey()))) + .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + } + + SearchQuery query = dao.createSearchQuery(1, 1); + query.configureParameters(queryParameters); + + List unsupportedQueryParameters = query + .getUnsupportedQueryParameters(queryParameters); + if (!unsupportedQueryParameters.isEmpty()) + { + // TODO audit log + return responseGenerator.badRequest( + UriComponentsBuilder.newInstance() + .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), + unsupportedQueryParameters); + } + + PartialResult result = exceptionHandler.handleSqlException(() -> dao.search(query)); + + // No matches + if (result.getOverallCount() <= 0) + { + // TODO audit log + return Response.noContent().build(); // TODO return OperationOutcome + } + + // One Match: The server performs an ordinary delete on the matching resource + else if (result.getOverallCount() == 1) + { + R resource = result.getPartialResult().get(0); + + // more security checks and audit log in delete method + return delete(resource.getIdElement().getIdPart(), uri, headers); + } + + // Multiple matches: A server may choose to delete all the matching resources, or it may choose to return a 412 + // Precondition Failed error indicating the client's criteria were not selective enough. + else + { + // TODO audit log + return responseGenerator.multipleExists(resourceTypeName, UriComponentsBuilder.newInstance() + .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString()); + } + } - return reasonDeleteNotAllowed(uri).map(forbidden("delete")).orElse(delegate.delete(uri, headers)); + @Override + public Response search(UriInfo uri, HttpHeaders headers) + { + logger.debug("Current user '{}', role '{}'", userProvider.getCurrentUser().getName(), + userProvider.getCurrentUser().getRole()); + + Optional reasonSearchAllowed = reasonSearchAllowed(); + if (reasonSearchAllowed.isEmpty()) + { + audit.info("Search of resource {} denied for user '{}'", resourceTypeName, getCurrentUser().getName()); + return forbidden("search"); + } + else + { + audit.info("Search of resource {} allowed for user '{}'", resourceTypeName, getCurrentUser().getName()); + return delegate.search(uri, headers); + } } /** - * Override this method for non default behavior. Default: Not allowed if user role not {@link UserRole#LOCAL}. + * Override this method for non default behavior. Default: Not allowed. * * @param uri - * @return {@link Optional#empty()} if delete(uri) allowed + * @return Reason as String in {@link Optional#of(Object)} if delete allowed */ - protected Optional reasonDeleteNotAllowed(UriInfo uri) - { - if (!UserRole.LOCAL.equals(provider.getCurrentUser().getRole())) - return Optional.of("Missing role 'LOCAL'"); - else - return Optional.empty(); - } - - @Override - public Response search(UriInfo uri, HttpHeaders headers) + protected Optional reasonSearchAllowed() { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); - - return delegate.search(uri, headers); + return Optional.empty(); } @Override public Response postValidateNew(String validate, Parameters parameters, UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); + logger.debug("Current user '{}', role '{}'", userProvider.getCurrentUser().getName(), + userProvider.getCurrentUser().getRole()); return delegate.postValidateNew(validate, parameters, uri, headers); } @@ -207,8 +515,8 @@ public Response postValidateNew(String validate, Parameters parameters, UriInfo @Override public Response getValidateNew(String validate, UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); + logger.debug("Current user '{}', role '{}'", userProvider.getCurrentUser().getName(), + userProvider.getCurrentUser().getRole()); return delegate.getValidateNew(validate, uri, headers); } @@ -217,8 +525,8 @@ public Response getValidateNew(String validate, UriInfo uri, HttpHeaders headers public Response postValidateExisting(String validate, String id, Parameters parameters, UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); + logger.debug("Current user '{}', role '{}'", userProvider.getCurrentUser().getName(), + userProvider.getCurrentUser().getRole()); return delegate.postValidateExisting(validate, id, parameters, uri, headers); } @@ -226,8 +534,8 @@ public Response postValidateExisting(String validate, String id, Parameters para @Override public Response getValidateExisting(String validate, String id, UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); + logger.debug("Current user '{}', role '{}'", userProvider.getCurrentUser().getName(), + userProvider.getCurrentUser().getRole()); return delegate.getValidateExisting(validate, id, uri, headers); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractServiceSecure.java index 6ecaecba7..779f61c4e 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractServiceSecure.java @@ -1,25 +1,44 @@ package org.highmed.dsf.fhir.webservice.secure; +import java.util.Collection; +import java.util.EnumSet; import java.util.Objects; -import java.util.function.Function; +import java.util.Optional; import javax.ws.rs.core.Response; +import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.authentication.UserProvider; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; +import org.highmed.dsf.fhir.service.ResourceReference; +import org.highmed.dsf.fhir.service.ResourceReference.ReferenceType; import org.highmed.dsf.fhir.webservice.specification.BasicService; +import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; public abstract class AbstractServiceSecure implements BasicService, InitializingBean { + protected static final Logger audit = LoggerFactory.getLogger("dsf-audit-logger"); + private static final Logger logger = LoggerFactory.getLogger(AbstractServiceSecure.class); + protected final S delegate; + protected final String serverBase; protected final ResponseGenerator responseGenerator; + protected final ReferenceResolver referenceResolver; - protected UserProvider provider; + protected UserProvider userProvider; - public AbstractServiceSecure(S delegate, ResponseGenerator responseGenerator) + public AbstractServiceSecure(S delegate, String serverBase, ResponseGenerator responseGenerator, + ReferenceResolver referenceResolver) { + this.serverBase = serverBase; this.delegate = delegate; + this.referenceResolver = referenceResolver; this.responseGenerator = responseGenerator; } @@ -27,15 +46,74 @@ public AbstractServiceSecure(S delegate, ResponseGenerator responseGenerator) public void afterPropertiesSet() throws Exception { Objects.requireNonNull(delegate, "delegate"); + Objects.requireNonNull(serverBase, "serverBase"); Objects.requireNonNull(responseGenerator, "responseGenerator"); + Objects.requireNonNull(referenceResolver, "referenceResolver"); } @Override - public final void setUserProvider(UserProvider provider) + public final void setUserProvider(UserProvider userProvider) { - delegate.setUserProvider(provider); + delegate.setUserProvider(userProvider); + + this.userProvider = userProvider; + } + + protected final User getCurrentUser() + { + return userProvider.getCurrentUser(); + } + + protected final boolean isCurrentUserPartOfReferencedOrganizations(String referenceLocation, + Collection references) + { + return references.stream().anyMatch(r -> isCurrentUserPartOfReferencedOrganization(referenceLocation, r)); + } + + protected final boolean isCurrentUserPartOfReferencedOrganization(String referenceLocation, Reference reference) + { + if (userProvider.getCurrentUser() == null || userProvider.getCurrentUser().getOrganization() == null) + { + logger.warn( + "No current user or current user without organization while checking if user part of referenced organization"); + return false; + } + else if (reference == null) + { + logger.warn("Null reference while checking if user part of referenced organization"); + return false; + } + else + { + ResourceReference resReference = new ResourceReference(referenceLocation, reference, Organization.class); + + if (!EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL) + .contains(resReference.getType(serverBase))) + { + logger.warn("Reference of type {} not supported while checking if user part of referenced organization", + resReference.getType(serverBase)); + return false; + } + + Optional resource = referenceResolver.resolveReference(resReference); + if (resource.isPresent() && resource.get() instanceof Organization) + { + boolean sameOrganization = userProvider.getCurrentUser().getOrganization().getIdElement() + .equals(resource.get().getIdElement()); + if (!sameOrganization) + logger.warn( + "Current user not part organization {} while checking if user part of referenced organization", + resource.get().getIdElement().getValue()); - this.provider = provider; + return sameOrganization; + } + else + { + logger.warn( + "Reference to organization could not be resolved while checking if user part of referenced organization"); + return false; + } + } } @Override @@ -44,8 +122,8 @@ public final String getPath() return delegate.getPath(); } - protected final Function forbidden(String operation) + protected final Response forbidden(String operation) { - return reason -> responseGenerator.forbiddenNotAllowed(operation, provider.getCurrentUser(), reason); + return responseGenerator.forbiddenNotAllowed(operation, userProvider.getCurrentUser()); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ActivityDefinitionServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ActivityDefinitionServiceSecure.java index 7f63daea3..060335f56 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ActivityDefinitionServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ActivityDefinitionServiceSecure.java @@ -1,14 +1,23 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.ActivityDefinitionService; import org.hl7.fhir.r4.model.ActivityDefinition; -public class ActivityDefinitionServiceSecure extends - AbstractResourceServiceSecure implements ActivityDefinitionService +public class ActivityDefinitionServiceSecure + extends AbstractResourceServiceSecure + implements ActivityDefinitionService { - public ActivityDefinitionServiceSecure(ActivityDefinitionService delegate, ResponseGenerator responseGenerator) + public ActivityDefinitionServiceSecure(ActivityDefinitionService delegate, String serverBase, ResponseGenerator responseGenerator, + ReferenceResolver referenceResolver, ActivityDefinitionDao activityDefinitionDao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, ActivityDefinition.class, + activityDefinitionDao, exceptionHandler, + parameterConverter); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/BinaryServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/BinaryServiceSecure.java index 23af55fdc..13c674842 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/BinaryServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/BinaryServiceSecure.java @@ -1,13 +1,21 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.dao.BinaryDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.BinaryService; import org.hl7.fhir.r4.model.Binary; -public class BinaryServiceSecure extends AbstractResourceServiceSecure implements BinaryService +public class BinaryServiceSecure extends AbstractResourceServiceSecure + implements BinaryService { - public BinaryServiceSecure(BinaryService delegate, ResponseGenerator responseGenerator) + public BinaryServiceSecure(BinaryService delegate, String serverBase, ResponseGenerator responseGenerator, + ReferenceResolver referenceResolver, BinaryDao binaryDao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, Binary.class, binaryDao, exceptionHandler, + parameterConverter); } } \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/BundleServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/BundleServiceSecure.java index 4ae52e43a..d2d0d3002 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/BundleServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/BundleServiceSecure.java @@ -1,13 +1,21 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.dao.BundleDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.BundleService; import org.hl7.fhir.r4.model.Bundle; -public class BundleServiceSecure extends AbstractResourceServiceSecure implements BundleService +public class BundleServiceSecure extends AbstractResourceServiceSecure + implements BundleService { - public BundleServiceSecure(BundleService delegate, ResponseGenerator responseGenerator) + public BundleServiceSecure(BundleService delegate, String serverBase, ResponseGenerator responseGenerator, + ReferenceResolver referenceResolver, BundleDao bundleDao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, Bundle.class, bundleDao, exceptionHandler, + parameterConverter); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/CodeSystemServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/CodeSystemServiceSecure.java index 27d0f3c3d..e5c911090 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/CodeSystemServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/CodeSystemServiceSecure.java @@ -1,14 +1,21 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.dao.CodeSystemDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.CodeSystemService; import org.hl7.fhir.r4.model.CodeSystem; -public class CodeSystemServiceSecure extends AbstractResourceServiceSecure +public class CodeSystemServiceSecure extends AbstractResourceServiceSecure implements CodeSystemService { - public CodeSystemServiceSecure(CodeSystemService delegate, ResponseGenerator responseGenerator) + public CodeSystemServiceSecure(CodeSystemService delegate, String serverBase, ResponseGenerator responseGenerator, + ReferenceResolver referenceResolver, CodeSystemDao codeSystemDao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, CodeSystem.class, codeSystemDao, + exceptionHandler, parameterConverter); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ConformanceServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ConformanceServiceSecure.java index b45a8313d..8c4164090 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ConformanceServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ConformanceServiceSecure.java @@ -5,6 +5,7 @@ import javax.ws.rs.core.UriInfo; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.ConformanceService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,16 +14,16 @@ public class ConformanceServiceSecure extends AbstractServiceSecure implements EndpointService +public class EndpointServiceSecure extends AbstractResourceServiceSecure + implements EndpointService { - public EndpointServiceSecure(EndpointService delegate, ResponseGenerator responseGenerator) + public EndpointServiceSecure(EndpointService delegate, String serverBase, ResponseGenerator responseGenerator, + ReferenceResolver referenceResolver, EndpointDao endpointDao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter) { - super(delegate, responseGenerator); - } - - @Override - protected Optional reasonCreateNotAllowed(Endpoint resource) - { - // TODO validate unique on Endpoint.address - - return super.reasonCreateNotAllowed(resource); + super(delegate, serverBase, responseGenerator, referenceResolver, Endpoint.class, endpointDao, exceptionHandler, + parameterConverter); } @Override - protected Optional reasonUpdateNotAllowed(String id, Endpoint resource) + protected Optional reasonCreateAllowed(Endpoint resource) { // TODO validate unique on Endpoint.address - return super.reasonUpdateNotAllowed(id, resource); + return Optional.empty(); } @Override - protected Optional reasonUpdateNotAllowed(Endpoint resource, UriInfo uri) + protected Optional reasonUpdateAllowed(Endpoint oldResource, Endpoint newResource) { // TODO validate unique on Endpoint.address - return super.reasonUpdateNotAllowed(resource, uri); + return Optional.empty(); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/GroupServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/GroupServiceSecure.java index eab1a6170..f7d1678df 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/GroupServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/GroupServiceSecure.java @@ -1,13 +1,21 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.dao.GroupDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.GroupService; import org.hl7.fhir.r4.model.Group; -public class GroupServiceSecure extends AbstractResourceServiceSecure implements GroupService +public class GroupServiceSecure extends AbstractResourceServiceSecure + implements GroupService { - public GroupServiceSecure(GroupService delegate, ResponseGenerator responseGenerator) + public GroupServiceSecure(GroupService delegate, String serverBase, ResponseGenerator responseGenerator, + ReferenceResolver referenceResolver, GroupDao groupDao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, Group.class, groupDao, exceptionHandler, + parameterConverter); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/HealthcareServiceServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/HealthcareServiceServiceSecure.java index 5dba8e827..c6348230b 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/HealthcareServiceServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/HealthcareServiceServiceSecure.java @@ -1,14 +1,23 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.dao.HealthcareServiceDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.HealthcareServiceService; import org.hl7.fhir.r4.model.HealthcareService; -public class HealthcareServiceServiceSecure extends AbstractResourceServiceSecure +public class HealthcareServiceServiceSecure + extends AbstractResourceServiceSecure implements HealthcareServiceService { - public HealthcareServiceServiceSecure(HealthcareServiceService delegate, ResponseGenerator responseGenerator) + public HealthcareServiceServiceSecure(HealthcareServiceService delegate, String serverBase, + ResponseGenerator responseGenerator, ReferenceResolver referenceResolver, + HealthcareServiceDao healthcareServiceDao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, HealthcareService.class, healthcareServiceDao, + exceptionHandler, parameterConverter); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/LocationServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/LocationServiceSecure.java index af8ed358c..c45874bda 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/LocationServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/LocationServiceSecure.java @@ -1,13 +1,20 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.dao.LocationDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.LocationService; import org.hl7.fhir.r4.model.Location; -public class LocationServiceSecure extends AbstractResourceServiceSecure implements LocationService +public class LocationServiceSecure extends AbstractResourceServiceSecure implements LocationService { - public LocationServiceSecure(LocationService delegate, ResponseGenerator responseGenerator) + public LocationServiceSecure(LocationService delegate, String serverBase, ResponseGenerator responseGenerator, + ReferenceResolver referenceResolver, LocationDao locationDao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, Location.class, locationDao, exceptionHandler, + parameterConverter); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/NamingSystemServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/NamingSystemServiceSecure.java index 5f28122a6..45936d91b 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/NamingSystemServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/NamingSystemServiceSecure.java @@ -1,14 +1,21 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.dao.NamingSystemDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.NamingSystemService; import org.hl7.fhir.r4.model.NamingSystem; -public class NamingSystemServiceSecure extends AbstractResourceServiceSecure - implements NamingSystemService +public class NamingSystemServiceSecure extends + AbstractResourceServiceSecure implements NamingSystemService { - public NamingSystemServiceSecure(NamingSystemService delegate, ResponseGenerator responseGenerator) + public NamingSystemServiceSecure(NamingSystemService delegate, String serverBase, + ResponseGenerator responseGenerator, ReferenceResolver referenceResolver, NamingSystemDao naminngSystemDao, + ExceptionHandler exceptionHandler, ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, NamingSystem.class, naminngSystemDao, + exceptionHandler, parameterConverter); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/OrganizationServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/OrganizationServiceSecure.java index 417af83c7..ac4c9887c 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/OrganizationServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/OrganizationServiceSecure.java @@ -4,16 +4,23 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; +import org.highmed.dsf.fhir.dao.OrganizationDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.OrganizationService; import org.hl7.fhir.r4.model.Organization; -public class OrganizationServiceSecure extends AbstractResourceServiceSecure - implements OrganizationService +public class OrganizationServiceSecure extends + AbstractResourceServiceSecure implements OrganizationService { - public OrganizationServiceSecure(OrganizationService delegate, ResponseGenerator responseGenerator) + public OrganizationServiceSecure(OrganizationService delegate, String serverBase, + ResponseGenerator responseGenerator, ReferenceResolver referenceResolver, OrganizationDao organizationDao, + ExceptionHandler exceptionHandler, ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, Organization.class, organizationDao, + exceptionHandler, parameterConverter); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PatientServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PatientServiceSecure.java index 709afa55b..b769a492e 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PatientServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PatientServiceSecure.java @@ -1,13 +1,21 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.dao.PatientDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.PatientService; import org.hl7.fhir.r4.model.Patient; -public class PatientServiceSecure extends AbstractResourceServiceSecure implements PatientService +public class PatientServiceSecure extends AbstractResourceServiceSecure + implements PatientService { - public PatientServiceSecure(PatientService delegate, ResponseGenerator responseGenerator) + public PatientServiceSecure(PatientService delegate, String serverBase, ResponseGenerator responseGenerator, + ReferenceResolver referenceResolver, PatientDao patientDao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, Patient.class, patientDao, exceptionHandler, + parameterConverter); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PractitionerRoleServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PractitionerRoleServiceSecure.java index aa8085323..204b3cc4a 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PractitionerRoleServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PractitionerRoleServiceSecure.java @@ -1,14 +1,21 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.dao.PractitionerRoleDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.PractitionerRoleService; import org.hl7.fhir.r4.model.PractitionerRole; -public class PractitionerRoleServiceSecure extends AbstractResourceServiceSecure +public class PractitionerRoleServiceSecure extends AbstractResourceServiceSecure implements PractitionerRoleService { - public PractitionerRoleServiceSecure(PractitionerRoleService delegate, ResponseGenerator responseGenerator) + public PractitionerRoleServiceSecure(PractitionerRoleService delegate, String serverBase, ResponseGenerator responseGenerator, + ReferenceResolver referenceResolver, PractitionerRoleDao practitionerRoleDao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, PractitionerRole.class, practitionerRoleDao, exceptionHandler, + parameterConverter); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PractitionerServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PractitionerServiceSecure.java index 020e8c6ce..135a11051 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PractitionerServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PractitionerServiceSecure.java @@ -1,14 +1,21 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.dao.PractitionerDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.PractitionerService; import org.hl7.fhir.r4.model.Practitioner; -public class PractitionerServiceSecure extends AbstractResourceServiceSecure - implements PractitionerService +public class PractitionerServiceSecure extends + AbstractResourceServiceSecure implements PractitionerService { - public PractitionerServiceSecure(PractitionerService delegate, ResponseGenerator responseGenerator) + public PractitionerServiceSecure(PractitionerService delegate, String serverBase, + ResponseGenerator responseGenerator, ReferenceResolver referenceResolver, PractitionerDao practitionerDao, + ExceptionHandler exceptionHandler, ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, Practitioner.class, practitionerDao, + exceptionHandler, parameterConverter); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ProvenanceServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ProvenanceServiceSecure.java index 56d273033..fa571da46 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ProvenanceServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ProvenanceServiceSecure.java @@ -1,14 +1,21 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.dao.ProvenanceDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.ProvenanceService; import org.hl7.fhir.r4.model.Provenance; -public class ProvenanceServiceSecure extends AbstractResourceServiceSecure +public class ProvenanceServiceSecure extends AbstractResourceServiceSecure implements ProvenanceService { - public ProvenanceServiceSecure(ProvenanceService delegate, ResponseGenerator responseGenerator) + public ProvenanceServiceSecure(ProvenanceService delegate, String serverBase, ResponseGenerator responseGenerator, + ReferenceResolver referenceResolver, ProvenanceDao provenanceDao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, Provenance.class, provenanceDao, + exceptionHandler, parameterConverter); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ResearchStudyServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ResearchStudyServiceSecure.java index 17c5cab56..9116aa375 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ResearchStudyServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ResearchStudyServiceSecure.java @@ -1,14 +1,22 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.dao.ResearchStudyDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.ResearchStudyService; import org.hl7.fhir.r4.model.ResearchStudy; -public class ResearchStudyServiceSecure extends AbstractResourceServiceSecure +public class ResearchStudyServiceSecure + extends AbstractResourceServiceSecure implements ResearchStudyService { - public ResearchStudyServiceSecure(ResearchStudyService delegate, ResponseGenerator responseGenerator) + public ResearchStudyServiceSecure(ResearchStudyService delegate, String serverBase, + ResponseGenerator responseGenerator, ReferenceResolver referenceResolver, ResearchStudyDao researchStudyDao, + ExceptionHandler exceptionHandler, ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, ResearchStudy.class, researchStudyDao, + exceptionHandler, parameterConverter); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/RootServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/RootServiceSecure.java index 91672cc20..95fdbe513 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/RootServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/RootServiceSecure.java @@ -6,8 +6,8 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; -import org.highmed.dsf.fhir.authentication.UserRole; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.RootService; import org.hl7.fhir.r4.model.Bundle; import org.slf4j.Logger; @@ -17,16 +17,17 @@ public class RootServiceSecure extends AbstractServiceSecure implem { private static final Logger logger = LoggerFactory.getLogger(AbstractResourceServiceSecure.class); - public RootServiceSecure(RootService delegate, ResponseGenerator responseGenerator) + public RootServiceSecure(RootService delegate, String serverBase, ResponseGenerator responseGenerator, + ReferenceResolver referenceResolver) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver); } @Override public Response root(UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); + logger.debug("Current user '{}', role '{}'", userProvider.getCurrentUser().getName(), + userProvider.getCurrentUser().getRole()); // get root allowed for all authenticated users @@ -36,23 +37,33 @@ public Response root(UriInfo uri, HttpHeaders headers) @Override public Response handleBundle(Bundle bundle, UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); + logger.debug("Current user '{}', role '{}'", userProvider.getCurrentUser().getName(), + userProvider.getCurrentUser().getRole()); - return reasonHandleBundleNotAllowed(bundle).map(forbidden("POST")) - .orElse(delegate.handleBundle(bundle, uri, headers)); + Optional reasonHandleBundleAllowed = reasonHandleBundleAllowed(bundle); + + if (reasonHandleBundleAllowed.isEmpty()) + { + audit.info("Handling of transaction and batch bundles denied for user '{}'", getCurrentUser().getName()); + return forbidden("bundle"); + } + else + { + audit.info("Handling of transaction or batch bundle allowed for user '{}'", getCurrentUser().getName()); + return delegate.handleBundle(bundle, uri, headers); + } } - private Optional reasonHandleBundleNotAllowed(Bundle bundle) + private Optional reasonHandleBundleAllowed(Bundle bundle) { /* * TODO check if operation for each entry in transaction / batch bundle is allowed, batch can have not allowed * operations and will return 403 for those, transaction can't and will return 403 for all */ - if (!UserRole.LOCAL.equals(provider.getCurrentUser().getRole())) - return Optional.of("Missing role 'LOCAL'"); - else - return Optional.empty(); + // if (!UserRole.LOCAL.equals(userProvider.getCurrentUser().getRole())) + // return Optional.of("Missing role 'LOCAL'"); + // else + return Optional.empty(); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/StaticResourcesServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/StaticResourcesServiceSecure.java index c214d68a4..1997453ea 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/StaticResourcesServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/StaticResourcesServiceSecure.java @@ -5,6 +5,7 @@ import javax.ws.rs.core.UriInfo; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.StaticResourcesService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,16 +15,17 @@ public class StaticResourcesServiceSecure extends AbstractServiceSecure implements StructureDefinitionService +public class StructureDefinitionServiceSecure + extends AbstractResourceServiceSecure + implements StructureDefinitionService { private static final Logger logger = LoggerFactory.getLogger(StructureDefinitionServiceSecure.class); - public StructureDefinitionServiceSecure(StructureDefinitionService delegate, ResponseGenerator responseGenerator) + public StructureDefinitionServiceSecure(StructureDefinitionService delegate, String serverBase, + ResponseGenerator responseGenerator, ReferenceResolver referenceResolver, + StructureDefinitionDao structureDefinitionDao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, StructureDefinition.class, + structureDefinitionDao, exceptionHandler, parameterConverter); } @Override @@ -65,8 +74,7 @@ public Response delete(String id, UriInfo uri, HttpHeaders headers) @Override public Response postSnapshotNew(String snapshotPath, Parameters parameters, UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); + logger.debug("Current user '{}', role '{}'", getCurrentUser().getName(), getCurrentUser().getRole()); return delegate.postSnapshotNew(snapshotPath, parameters, uri, headers); } @@ -74,8 +82,7 @@ public Response postSnapshotNew(String snapshotPath, Parameters parameters, UriI @Override public Response getSnapshotNew(String snapshotPath, UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); + logger.debug("Current user '{}', role '{}'", getCurrentUser().getName(), getCurrentUser().getRole()); return delegate.getSnapshotNew(snapshotPath, uri, headers); } @@ -83,8 +90,7 @@ public Response getSnapshotNew(String snapshotPath, UriInfo uri, HttpHeaders hea @Override public Response postSnapshotExisting(String snapshotPath, String id, UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); + logger.debug("Current user '{}', role '{}'", getCurrentUser().getName(), getCurrentUser().getRole()); return delegate.postSnapshotExisting(snapshotPath, id, uri, headers); } @@ -92,8 +98,7 @@ public Response postSnapshotExisting(String snapshotPath, String id, UriInfo uri @Override public Response getSnapshotExisting(String snapshotPath, String id, UriInfo uri, HttpHeaders headers) { - logger.debug("Current user '{}', role '{}'", provider.getCurrentUser().getName(), - provider.getCurrentUser().getRole()); + logger.debug("Current user '{}', role '{}'", getCurrentUser().getName(), getCurrentUser().getRole()); return delegate.getSnapshotExisting(snapshotPath, id, uri, headers); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/SubscriptionServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/SubscriptionServiceSecure.java index 39c94816b..858a21ca5 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/SubscriptionServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/SubscriptionServiceSecure.java @@ -4,16 +4,23 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; +import org.highmed.dsf.fhir.dao.SubscriptionDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.SubscriptionService; import org.hl7.fhir.r4.model.Subscription; -public class SubscriptionServiceSecure extends AbstractResourceServiceSecure - implements SubscriptionService +public class SubscriptionServiceSecure extends + AbstractResourceServiceSecure implements SubscriptionService { - public SubscriptionServiceSecure(SubscriptionService delegate, ResponseGenerator responseGenerator) + public SubscriptionServiceSecure(SubscriptionService delegate, String serverBase, + ResponseGenerator responseGenerator, ReferenceResolver referenceResolver, SubscriptionDao subscriptionDao, + ExceptionHandler exceptionHandler, ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, Subscription.class, subscriptionDao, + exceptionHandler, parameterConverter); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/TaskServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/TaskServiceSecure.java index 13cc9505c..48af68706 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/TaskServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/TaskServiceSecure.java @@ -1,33 +1,85 @@ package org.highmed.dsf.fhir.webservice.secure; +import java.util.Objects; import java.util.Optional; -import javax.ws.rs.core.UriInfo; - +import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; +import org.highmed.dsf.fhir.dao.TaskDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.TaskService; import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.Task.TaskStatus; -public class TaskServiceSecure extends AbstractResourceServiceSecure implements TaskService +public class TaskServiceSecure extends AbstractResourceServiceSecure implements TaskService { - public TaskServiceSecure(TaskService delegate, ResponseGenerator responseGenerator) + private final ActivityDefinitionDao activityDefinitionDao; + + public TaskServiceSecure(TaskService delegate, String serverBase, ResponseGenerator responseGenerator, + ReferenceResolver referenceResolver, TaskDao taskDao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter, ActivityDefinitionDao activityDefinitionDao) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, Task.class, taskDao, exceptionHandler, + parameterConverter); + + this.activityDefinitionDao = activityDefinitionDao; } @Override - protected Optional reasonCreateNotAllowed(Task resource) + public void afterPropertiesSet() throws Exception { - // TODO authorization rules + super.afterPropertiesSet(); + + Objects.requireNonNull(activityDefinitionDao, "activityDefinitionDao"); + } + + @Override + protected Optional reasonReadAllowed(Task resource) + { +// if (!resource.hasRestriction() || !resource.getRestriction().hasRecipient() || !resource.hasRequester()) +// return Optional.of("Current user not Task.requester or Task.restriction.recipient"); +// else if (!isCurrentUserPartOfReferencedOrganizations("Task.restriction.recipient", +// resource.getRestriction().getRecipient()) +// && !isCurrentUserPartOfReferencedOrganization("Task.requester", resource.getRequester())) +// return Optional.of("Current user not Task.requester or Task.restriction.recipient"); +// else +// return Optional.of(""); + + return Optional.empty(); + } + + @Override + protected Optional reasonCreateAllowed(Task resource) + { + // FIXME authorization rules // allowed status draft | requested for all users // task.requester must be organization of current user + return Optional.empty(); } @Override - protected Optional reasonUpdateNotAllowed(String id, Task resource) + protected Optional reasonUpdateAllowed(Task oldResource, Task newResource) { - // TODO authorization rules + if (TaskStatus.DRAFT.equals(oldResource.getStatus())) + { + return Optional.of("TODO oldResource DRAFT"); + } + else if (TaskStatus.REQUESTED.equals(oldResource.getStatus())) + { + return Optional.of("TODO oldResource REQUESTED"); + } + else if (TaskStatus.COMPLETED.equals(oldResource.getStatus())) + { + return Optional.of("TODO oldResource REQUESTED"); + } + else if (TaskStatus.FAILED.equals(oldResource.getStatus())) + { + return Optional.of("TODO oldResource REQUESTED"); + } + // FIXME authorization rules // allowed status change from draft to requested for remote users // update only allowed at status draft for remote users // task.requester must be organization of current user or local user @@ -37,9 +89,19 @@ protected Optional reasonUpdateNotAllowed(String id, Task resource) } @Override - protected Optional reasonUpdateNotAllowed(Task resource, UriInfo uri) + protected Optional reasonDeleteAllowed(Task oldResource) { - // TODO authorization rules, see above + // TODO authorization rules + // allowed if oldResouce created by current user and status draft + + return Optional.empty(); + } + + @Override + protected Optional reasonSearchAllowed() + { + // TODO authorization rules + return Optional.empty(); } } \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ValueSetServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ValueSetServiceSecure.java index b2afeac26..f6c1d0cdb 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ValueSetServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ValueSetServiceSecure.java @@ -1,13 +1,21 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.dao.ValueSetDao; +import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.ValueSetService; import org.hl7.fhir.r4.model.ValueSet; -public class ValueSetServiceSecure extends AbstractResourceServiceSecure implements ValueSetService +public class ValueSetServiceSecure extends AbstractResourceServiceSecure + implements ValueSetService { - public ValueSetServiceSecure(ValueSetService delegate, ResponseGenerator responseGenerator) + public ValueSetServiceSecure(ValueSetService delegate, String serverBase, ResponseGenerator responseGenerator, + ReferenceResolver referenceResolver, ValueSetDao valueSetDao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter) { - super(delegate, responseGenerator); + super(delegate, serverBase, responseGenerator, referenceResolver, ValueSet.class, valueSetDao, exceptionHandler, + parameterConverter); } } diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/client/ClientProviderTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/client/ClientProviderTest.java index 9b9040085..4ddd93ce9 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/client/ClientProviderTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/client/ClientProviderTest.java @@ -15,6 +15,7 @@ import org.highmed.dsf.fhir.dao.EndpointDao; import org.highmed.dsf.fhir.function.SupplierWithSqlException; import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.service.ReferenceExtractor; import org.highmed.fhir.client.FhirWebserviceClient; import org.junit.Before; import org.junit.Test; @@ -23,6 +24,7 @@ public class ClientProviderTest { + private ReferenceExtractor referenceExtractor; private EndpointDao endpointDao; private ExceptionHandler exceptionHandler; private ClientProvider provider; @@ -32,10 +34,9 @@ public void before() throws Exception { KeyStore webserviceKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); webserviceKeyStore.load(null); - + KeyStore webserviceTrustStore = KeyStore.getInstance(KeyStore.getDefaultType()); webserviceTrustStore.load(null); - String webserviceKeyStorePassword = "password"; int remoteReadTimeout = 0; @@ -44,12 +45,13 @@ public void before() throws Exception String remoteProxyUsername = null; String remoteProxySchemeHostPort = null; FhirContext fhirContext = mock(FhirContext.class); + referenceExtractor = mock(ReferenceExtractor.class); endpointDao = mock(EndpointDao.class); exceptionHandler = mock(ExceptionHandler.class); provider = new ClientProviderImpl(webserviceTrustStore, webserviceKeyStore, webserviceKeyStorePassword, remoteReadTimeout, remoteConnectTimeout, remoteProxyPassword, remoteProxyUsername, - remoteProxySchemeHostPort, fhirContext, endpointDao, exceptionHandler); + remoteProxySchemeHostPort, fhirContext, referenceExtractor, endpointDao, exceptionHandler); } @Test @@ -59,14 +61,14 @@ public void testGetClientExisting() throws Exception final String serverBase = "http://foo/fhir/"; when(exceptionHandler.handleSqlException(any(SupplierWithSqlException.class))).thenReturn(true); - + Optional client = provider.getClient(serverBase); assertNotNull(client); assertTrue(client.isPresent()); assertEquals(serverBase, client.get().getBaseUrl()); verify(exceptionHandler).handleSqlException(any(SupplierWithSqlException.class)); - verifyNoMoreInteractions(endpointDao, exceptionHandler); + verifyNoMoreInteractions(referenceExtractor, endpointDao, exceptionHandler); } @Test @@ -74,12 +76,12 @@ public void testGetClientExisting() throws Exception public void testGetClientExistingNotFound() throws Exception { when(exceptionHandler.handleSqlException(any(SupplierWithSqlException.class))).thenReturn(false); - + Optional client = provider.getClient("http://does.not/exists/"); assertNotNull(client); assertTrue(client.isEmpty()); - + verify(exceptionHandler).handleSqlException(any(SupplierWithSqlException.class)); - verifyNoMoreInteractions(endpointDao, exceptionHandler); + verifyNoMoreInteractions(referenceExtractor, endpointDao, exceptionHandler); } } diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/command/ResourceReferenceTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/command/ResourceReferenceTest.java index 1282cebc7..ae4b94aa9 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/command/ResourceReferenceTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/command/ResourceReferenceTest.java @@ -4,7 +4,8 @@ import java.util.UUID; -import org.highmed.dsf.fhir.dao.command.ResourceReference.ReferenceType; +import org.highmed.dsf.fhir.service.ResourceReference; +import org.highmed.dsf.fhir.service.ResourceReference.ReferenceType; import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.Reference; import org.junit.Test; @@ -16,9 +17,9 @@ public class ResourceReferenceTest @Test public void testGetTypeTemporary() throws Exception { - var r1 = new ResourceReference("Foo.bar", new Reference(Command.URL_UUID_PREFIX + UUID.randomUUID().toString()), - null); - var r2 = new ResourceReference("Foo.bar", new Reference(UUID.randomUUID().toString()), null); + var r1 = new ResourceReference("Foo.bar", + new Reference(Command.URL_UUID_PREFIX + UUID.randomUUID().toString())); + var r2 = new ResourceReference("Foo.bar", new Reference(UUID.randomUUID().toString())); assertEquals(ReferenceType.TEMPORARY, r1.getType(serverBase)); assertEquals(ReferenceType.UNKNOWN, r2.getType(serverBase)); @@ -27,21 +28,20 @@ public void testGetTypeTemporary() throws Exception @Test public void testGetTypeLiteralInternal() throws Exception { - var r1 = new ResourceReference("Foo.bar", new Reference("Patient/" + UUID.randomUUID().toString()), null); + var r1 = new ResourceReference("Foo.bar", new Reference("Patient/" + UUID.randomUUID().toString())); var r2 = new ResourceReference("Foo.bar", - new Reference("Patient/" + UUID.randomUUID().toString() + "/_history/123"), null); + new Reference("Patient/" + UUID.randomUUID().toString() + "/_history/123")); var r3 = new ResourceReference("Foo.bar", - new Reference(serverBase + "/Patient/" + UUID.randomUUID().toString()), null); + new Reference(serverBase + "/Patient/" + UUID.randomUUID().toString())); var r4 = new ResourceReference("Foo.bar", - new Reference(serverBase + "/Patient/" + UUID.randomUUID().toString() + "/_history/123"), null); - var r5 = new ResourceReference("Foo.bar", new Reference("Patient/" + UUID.randomUUID().toString() + "/foo"), - null); + new Reference(serverBase + "/Patient/" + UUID.randomUUID().toString() + "/_history/123")); + var r5 = new ResourceReference("Foo.bar", new Reference("Patient/" + UUID.randomUUID().toString() + "/foo")); var r6 = new ResourceReference("Foo.bar", - new Reference("Patient/" + UUID.randomUUID().toString() + "/_history/123/foo"), null); + new Reference("Patient/" + UUID.randomUUID().toString() + "/_history/123/foo")); var r7 = new ResourceReference("Foo.bar", - new Reference(serverBase + "/Patient/" + UUID.randomUUID().toString() + "/foo"), null); + new Reference(serverBase + "/Patient/" + UUID.randomUUID().toString() + "/foo")); var r8 = new ResourceReference("Foo.bar", - new Reference(serverBase + "/Patient/" + UUID.randomUUID().toString() + "/_history/123/foo"), null); + new Reference(serverBase + "/Patient/" + UUID.randomUUID().toString() + "/_history/123/foo")); assertEquals(ReferenceType.LITERAL_INTERNAL, r1.getType(serverBase)); assertEquals(ReferenceType.LITERAL_INTERNAL, r2.getType(serverBase)); @@ -58,14 +58,13 @@ public void testGetTypeLiteralInternal() throws Exception public void testGetTypeLiteralExternal() throws Exception { var r1 = new ResourceReference("Foo.bar", - new Reference("http://blub.com/fhir/Patient/" + UUID.randomUUID().toString()), null); + new Reference("http://blub.com/fhir/Patient/" + UUID.randomUUID().toString())); var r2 = new ResourceReference("Foo.bar", - new Reference("http://blub.com/fhir/Patient/" + UUID.randomUUID().toString() + "/_history/123"), null); + new Reference("http://blub.com/fhir/Patient/" + UUID.randomUUID().toString() + "/_history/123")); var r3 = new ResourceReference("Foo.bar", - new Reference("http://blub.com/fhir/Patient/" + UUID.randomUUID().toString() + "/foo"), null); + new Reference("http://blub.com/fhir/Patient/" + UUID.randomUUID().toString() + "/foo")); var r4 = new ResourceReference("Foo.bar", - new Reference("http://blub.com/fhir/Patient/" + UUID.randomUUID().toString() + "/_history/123/foo"), - null); + new Reference("http://blub.com/fhir/Patient/" + UUID.randomUUID().toString() + "/_history/123/foo")); assertEquals(ReferenceType.LITERAL_EXTERNAL, r1.getType(serverBase)); assertEquals(ReferenceType.LITERAL_EXTERNAL, r2.getType(serverBase)); @@ -77,8 +76,8 @@ public void testGetTypeLiteralExternal() throws Exception @Test public void testGetTypeConditional() throws Exception { - var r1 = new ResourceReference("Foo.bar", new Reference("Patient?foo=bar"), null); - var r2 = new ResourceReference("Foo.bar", new Reference("?foo=bar"), null); + var r1 = new ResourceReference("Foo.bar", new Reference("Patient?foo=bar")); + var r2 = new ResourceReference("Foo.bar", new Reference("?foo=bar")); assertEquals(ReferenceType.CONDITIONAL, r1.getType(serverBase)); @@ -89,16 +88,15 @@ public void testGetTypeConditional() throws Exception public void testGetTypeLogical() throws Exception { var r1 = new ResourceReference("Foo.bar", new Reference().setType("Patient") - .setIdentifier(new Identifier().setSystem("system").setValue("value")), null); + .setIdentifier(new Identifier().setSystem("system").setValue("value"))); var r2 = new ResourceReference("Foo.bar", - new Reference().setIdentifier(new Identifier().setSystem("system").setValue("value")), null); - var r3 = new ResourceReference("Foo.bar", new Reference().setType("Patient"), null); - var r4 = new ResourceReference("Foo.bar", new Reference().setType("Patient").setIdentifier(new Identifier()), - null); + new Reference().setIdentifier(new Identifier().setSystem("system").setValue("value"))); + var r3 = new ResourceReference("Foo.bar", new Reference().setType("Patient")); + var r4 = new ResourceReference("Foo.bar", new Reference().setType("Patient").setIdentifier(new Identifier())); var r5 = new ResourceReference("Foo.bar", - new Reference().setType("Patient").setIdentifier(new Identifier().setValue("value")), null); + new Reference().setType("Patient").setIdentifier(new Identifier().setValue("value"))); var r6 = new ResourceReference("Foo.bar", - new Reference().setType("Patient").setIdentifier(new Identifier().setSystem("system")), null); + new Reference().setType("Patient").setIdentifier(new Identifier().setSystem("system"))); assertEquals(ReferenceType.LOGICAL, r1.getType(serverBase)); diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java index ed150f11e..eb9ccb913 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java @@ -113,17 +113,17 @@ public static void beforeClass() throws Exception logger.info("Creating webservice client ..."); webserviceClient = createWebserviceClient(certificates.getClientCertificate().getTrustStore(), certificates.getClientCertificate().getKeyStore(), - certificates.getClientCertificate().getKeyStorePassword(), fhirContext); + certificates.getClientCertificate().getKeyStorePassword(), fhirContext, extractor); logger.info("Starting FHIR Server ..."); fhirServer = startFhirServer(); } private static FhirWebserviceClient createWebserviceClient(KeyStore trustStore, KeyStore keyStore, - String keyStorePassword, FhirContext fhirContext) + String keyStorePassword, FhirContext fhirContext, ReferenceExtractor referenceExtractor) { return new FhirWebserviceClientJersey(BASE_URL, trustStore, keyStore, keyStorePassword, null, null, null, 0, 0, - null, fhirContext); + null, fhirContext, referenceExtractor); } private static WebsocketClient createWebsocketClient(KeyStore trustStore, KeyStore keyStore, diff --git a/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/AbstractJerseyClient.java b/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/AbstractJerseyClient.java index 9c5259bc6..9383bc186 100644 --- a/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/AbstractJerseyClient.java +++ b/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/AbstractJerseyClient.java @@ -22,6 +22,8 @@ public class AbstractJerseyClient { private final Client client; private final String baseUrl; + + protected final List registeredComponents; public AbstractJerseyClient(String baseUrl, KeyStore trustStore, KeyStore keyStore, String keyStorePassword, ObjectMapper objectMapper, List componentsToRegister) @@ -70,6 +72,8 @@ else if (trustStore != null && keyStore != null && keyStorePassword != null) this.baseUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/"; // making sure the root url works, this might be a workaround for a jersey client bug + + this.registeredComponents = componentsToRegister; } protected WebTarget getResource() diff --git a/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClient.java b/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClient.java index c90d488bc..138aa865f 100755 --- a/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClient.java +++ b/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClient.java @@ -25,10 +25,14 @@ public interface FhirWebserviceClient void deleteConditionaly(Class resourceClass, Map> criteria); + Resource read(String resourceTypeName, String id); + R read(Class resourceType, String id); boolean exists(Class resourceType, String id); + Resource read(String resourceTypeName, String id, String version); + R read(Class resourceType, String id, String version); boolean exists(Class resourceType, String id, String version); diff --git a/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java b/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java index f9ebcb212..37efe748d 100755 --- a/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java +++ b/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java @@ -2,10 +2,12 @@ import java.security.KeyStore; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import java.util.stream.Stream; import javax.ws.rs.WebApplicationException; import javax.ws.rs.client.Entity; @@ -61,11 +63,11 @@ import org.highmed.dsf.fhir.adapter.TaskXmlFhirAdapter; import org.highmed.dsf.fhir.adapter.ValueSetJsonFhirAdapter; import org.highmed.dsf.fhir.adapter.ValueSetXmlFhirAdapter; +import org.highmed.dsf.fhir.service.ReferenceExtractor; +import org.highmed.dsf.fhir.service.ResourceReference; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.CapabilityStatement; -import org.hl7.fhir.r4.model.Endpoint; import org.hl7.fhir.r4.model.IdType; -import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Parameters; import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.StructureDefinition; @@ -83,12 +85,20 @@ public class FhirWebserviceClientJersey extends AbstractJerseyClient implements { private static final Logger logger = LoggerFactory.getLogger(FhirWebserviceClientJersey.class); + private final ReferenceExtractor referenceExtractor; + private final Map> resourceTypeByNames = new HashMap<>(); + public FhirWebserviceClientJersey(String baseUrl, KeyStore trustStore, KeyStore keyStore, String keyStorePassword, String proxySchemeHostPort, String proxyUserName, String proxyPassword, int connectTimeout, int readTimeout, - ObjectMapper objectMapper, FhirContext fhirContext) + ObjectMapper objectMapper, FhirContext fhirContext, ReferenceExtractor referenceExtractor) { super(baseUrl, trustStore, keyStore, keyStorePassword, proxySchemeHostPort, proxyUserName, proxyPassword, connectTimeout, readTimeout, objectMapper, components(fhirContext)); + + this.referenceExtractor = referenceExtractor; + + registeredComponents.stream().filter(e -> e instanceof AbstractFhirAdapter).map(e -> (AbstractFhirAdapter) e) + .forEach(a -> resourceTypeByNames.put(a.getResourceTypeName(), a.getResourceType())); } public static List> components(FhirContext fhirContext) @@ -343,7 +353,68 @@ public R read(Class resourceType, String id) response.getStatusInfo().getReasonPhrase()); if (Status.OK.getStatusCode() == response.getStatus()) // TODO remove workaround if HAPI bug fixed - return fixBundle(resourceType, response.readEntity(resourceType)); + return fixBundle(response.readEntity(resourceType)); + else + throw new WebApplicationException(response); + } + + @Override + public R read(Class resourceType, String id, String version) + { + Objects.requireNonNull(resourceType, "resourceType"); + Objects.requireNonNull(id, "id"); + Objects.requireNonNull(version, "version"); + + Response response = getResource().path(resourceType.getAnnotation(ResourceDef.class).name()).path(id) + .path("_history").path(version).request().accept(Constants.CT_FHIR_JSON_NEW).get(); + + logger.debug("HTTP {}: {}", response.getStatusInfo().getStatusCode(), + response.getStatusInfo().getReasonPhrase()); + if (Status.OK.getStatusCode() == response.getStatus()) + // TODO remove workaround if HAPI bug fixed + return fixBundle(response.readEntity(resourceType)); + else + throw new WebApplicationException(response); + } + + @Override + public Resource read(String resourceTypeName, String id) + { + Objects.requireNonNull(resourceTypeName, "resourceTypeName"); + Objects.requireNonNull(id, "id"); + if (!resourceTypeByNames.containsKey(resourceTypeName)) + throw new IllegalArgumentException("Resource of type " + resourceTypeName + " not supported"); + + Response response = getResource().path(resourceTypeName).path(id).request().accept(Constants.CT_FHIR_JSON_NEW) + .get(); + + logger.debug("HTTP {}: {}", response.getStatusInfo().getStatusCode(), + response.getStatusInfo().getReasonPhrase()); + if (Status.OK.getStatusCode() == response.getStatus()) + // TODO remove workaround if HAPI bug fixed + return fixBundle((Resource) response.readEntity(resourceTypeByNames.get(resourceTypeName))); + else + throw new WebApplicationException(response); + + } + + @Override + public Resource read(String resourceTypeName, String id, String version) + { + Objects.requireNonNull(resourceTypeName, "resourceTypeName"); + Objects.requireNonNull(id, "id"); + Objects.requireNonNull(version, "version"); + if (!resourceTypeByNames.containsKey(resourceTypeName)) + throw new IllegalArgumentException("Resource of type " + resourceTypeName + " not supported"); + + Response response = getResource().path(resourceTypeName).path(id).path("_history").path(version).request() + .accept(Constants.CT_FHIR_JSON_NEW).get(); + + logger.debug("HTTP {}: {}", response.getStatusInfo().getStatusCode(), + response.getStatusInfo().getReasonPhrase()); + if (Status.OK.getStatusCode() == response.getStatus()) + // TODO remove workaround if HAPI bug fixed + return fixBundle((Resource) response.readEntity(resourceTypeByNames.get(resourceTypeName))); else throw new WebApplicationException(response); } @@ -394,48 +465,21 @@ else if (Status.NOT_FOUND.getStatusCode() == response.getStatus()) } // FIXME bug in HAPI framework - // TODO workaround using ReferenceExtractorImpl to remove all reference->resources - private R fixBundle(Class resourceType, R readEntity) + private R fixBundle(R readEntity) { - if (Bundle.class.equals(resourceType)) + if (readEntity instanceof Bundle) { Bundle b = (Bundle) readEntity; - b.getEntry().stream().filter(e -> e.hasResource() && e.getResource() instanceof Organization) - .map(e -> (Organization) e.getResource()).forEach(this::fixOrganization); - b.getEntry().stream().filter(e -> e.hasResource() && e.getResource() instanceof Endpoint) - .map(e -> (Endpoint) e.getResource()).forEach(this::fixEndpoint); + b.getEntry().stream().map(e -> e.getResource()).forEach(this::fix); } return readEntity; } - private void fixOrganization(Organization organization) + private void fix(Resource resource) { - organization.getEndpoint().forEach(ref -> ref.setResource(null)); - } - - private void fixEndpoint(Endpoint endpoint) - { - endpoint.getManagingOrganization().setResource(null); - } - - @Override - public R read(Class resourceType, String id, String version) - { - Objects.requireNonNull(resourceType, "resourceType"); - Objects.requireNonNull(id, "id"); - Objects.requireNonNull(version, "version"); - - Response response = getResource().path(resourceType.getAnnotation(ResourceDef.class).name()).path(id) - .path("_history").path(version).request().accept(Constants.CT_FHIR_JSON_NEW).get(); - - logger.debug("HTTP {}: {}", response.getStatusInfo().getStatusCode(), - response.getStatusInfo().getReasonPhrase()); - if (Status.OK.getStatusCode() == response.getStatus()) - // TODO remove workaround if HAPI bug fixed - return fixBundle(resourceType, response.readEntity(resourceType)); - else - throw new WebApplicationException(response); + Stream references = referenceExtractor.getReferences(resource); + references.forEach(r -> r.getReference().setResource(null)); } @Override diff --git a/dsf-fhir/dsf-fhir-webservice-client/src/test/java/org/highmed/fhir/client/TestFhirJerseyClient.java b/dsf-fhir/dsf-fhir-webservice-client/src/test/java/org/highmed/fhir/client/TestFhirJerseyClient.java index c4aa5403a..012189332 100755 --- a/dsf-fhir/dsf-fhir-webservice-client/src/test/java/org/highmed/fhir/client/TestFhirJerseyClient.java +++ b/dsf-fhir/dsf-fhir-webservice-client/src/test/java/org/highmed/fhir/client/TestFhirJerseyClient.java @@ -12,6 +12,8 @@ import javax.ws.rs.WebApplicationException; +import org.highmed.dsf.fhir.service.ReferenceExtractor; +import org.highmed.dsf.fhir.service.ReferenceExtractorImpl; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleType; import org.hl7.fhir.r4.model.Bundle.HTTPVerb; @@ -38,8 +40,9 @@ public static void main(String[] args) KeyStore trustStore = CertificateHelper.extractTrust(keyStore); FhirContext context = FhirContext.forR4(); + ReferenceExtractor referenceExtractor = new ReferenceExtractorImpl(); FhirWebserviceClient client = new FhirWebserviceClientJersey("https://localhost:8001/fhir/", trustStore, keyStore, - keyStorePassword, null, null, null, 0, 0, null, context); + keyStorePassword, null, null, null, 0, 0, null, context, referenceExtractor); try { diff --git a/dsf-tools/dsf-tools-test-data-generator/pom.xml b/dsf-tools/dsf-tools-test-data-generator/pom.xml index 36eafc957..c9fc77aed 100755 --- a/dsf-tools/dsf-tools-test-data-generator/pom.xml +++ b/dsf-tools/dsf-tools-test-data-generator/pom.xml @@ -19,6 +19,10 @@ de.hs-heilbronn.mi crypto-utils + + org.highmed.dsf + dsf-fhir-rest-adapter + org.highmed.dsf dsf-fhir-server diff --git a/dsf-tools/pom.xml b/dsf-tools/pom.xml index 4f1a693ca..62c30a847 100755 --- a/dsf-tools/pom.xml +++ b/dsf-tools/pom.xml @@ -36,6 +36,11 @@ dsf-tools-bundle-generator ${project.version} + + org.highmed.dsf + dsf-fhir-rest-adapter + ${project.version} + org.highmed.dsf dsf-fhir-server From f6d8bc068e8c9043d85feb21cb1e4a4e051f47cf Mon Sep 17 00:00:00 2001 From: Hauke Hund Date: Wed, 19 Feb 2020 01:57:05 +0100 Subject: [PATCH 04/55] work on authorization rules --- .../highmed/dsf/fhir/OrganizationType.java | 23 ++ .../AbstractAuthorizationRule.java | 61 +++++ .../ActivityDefinitionAuthorizationRule.java | 52 ++++ .../fhir/authorization/AuthorizationRule.java | 64 +++++ .../BinaryAuthorizationRule.java | 50 ++++ .../BundleAuthorizationRule.java | 50 ++++ .../CodeSystemAuthorizationRule.java | 148 ++++++++++ .../EndpointAuthorizationRule.java | 52 ++++ .../authorization/GroupAuthorizationRule.java | 50 ++++ .../HealthcareServiceAuthorizationRule.java | 50 ++++ .../LocationAuthorizationRule.java | 50 ++++ .../NamingSystemAuthorizationRule.java | 50 ++++ .../OrganizationAuthorizationRule.java | 56 ++++ .../PatientAuthorizationRule.java | 50 ++++ .../PractitionerAuthorizationRule.java | 50 ++++ .../PractitionerRoleAuthorizationRule.java | 50 ++++ .../ProvenanceAuthorizationRule.java | 50 ++++ .../ResearchStudyAuthorizationRule.java | 50 ++++ .../StructureDefinitionAuthorizationRule.java | 61 +++++ .../SubscriptionAuthorizationRule.java | 55 ++++ .../authorization/TaskAuthorizationRule.java | 60 +++++ .../ValueSetAuthorizationRule.java | 147 ++++++++++ .../highmed/dsf/fhir/dao/ReadByUrlDao.java | 8 +- .../org/highmed/dsf/fhir/dao/ResourceDao.java | 7 +- .../dsf/fhir/dao/command/AbstractCommand.java | 6 +- .../command/AbstractCommandWithResource.java | 7 +- .../dsf/fhir/dao/command/CommandFactory.java | 11 +- .../fhir/dao/command/CommandFactoryImpl.java | 63 +++-- .../dsf/fhir/dao/command/CreateCommand.java | 9 +- .../CreateStructureDefinitionCommand.java | 16 +- .../dsf/fhir/dao/command/DeleteCommand.java | 7 +- .../dsf/fhir/dao/command/ReadCommand.java | 11 +- .../dao/command/ResolveReferencesCommand.java | 12 +- .../dao/command/TransactionEventManager.java | 5 +- .../dsf/fhir/dao/command/UpdateCommand.java | 13 +- .../UpdateStructureDefinitionCommand.java | 16 +- .../dao/jdbc/AbstractResourceDaoJdbc.java | 28 +- .../AbstractStructureDefinitionDaoJdbc.java | 31 ++- .../dao/jdbc/ActivityDefinitionDaoJdbc.java | 10 +- .../dsf/fhir/dao/jdbc/BinaryDaoJdbc.java | 7 +- .../dsf/fhir/dao/jdbc/BundleDaoJdbc.java | 8 +- .../dsf/fhir/dao/jdbc/CodeSystemDaoJdbc.java | 23 +- .../dsf/fhir/dao/jdbc/EndpointDaoJdbc.java | 7 +- .../dsf/fhir/dao/jdbc/GroupDaoJdbc.java | 8 +- .../dao/jdbc/HealthcareServiceDaoJdbc.java | 8 +- .../dsf/fhir/dao/jdbc/LocationDaoJdbc.java | 8 +- .../fhir/dao/jdbc/NamingSystemDaoJdbc.java | 7 +- .../fhir/dao/jdbc/OrganizationDaoJdbc.java | 8 +- .../dsf/fhir/dao/jdbc/PatientDaoJdbc.java | 8 +- .../fhir/dao/jdbc/PractitionerDaoJdbc.java | 5 +- .../dao/jdbc/PractitionerRoleDaoJdbc.java | 8 +- .../dsf/fhir/dao/jdbc/ProvenanceDaoJdbc.java | 7 +- .../dsf/fhir/dao/jdbc/ReadByUrlDaoJdbc.java | 56 +++- .../fhir/dao/jdbc/ResearchStudyDaoJdbc.java | 5 +- .../dao/jdbc/StructureDefinitionDaoJdbc.java | 8 +- .../StructureDefinitionSnapshotDaoJdbc.java | 9 +- .../fhir/dao/jdbc/SubscriptionDaoJdbc.java | 8 +- .../dsf/fhir/dao/jdbc/TaskDaoJdbc.java | 6 +- .../dsf/fhir/dao/jdbc/ValueSetDaoJdbc.java | 25 +- .../highmed/dsf/fhir/event/EventManager.java | 4 +- .../dsf/fhir/event/EventManagerImpl.java | 29 +- .../dsf/fhir/event/MatcherFactory.java | 2 +- .../highmed/dsf/fhir/search/SearchQuery.java | 53 +++- .../fhir/search/SearchQueryUserFilter.java | 17 ++ .../parameters/SubscriptionCriteria.java | 2 +- ...actMetaTagAuthorizationRoleUserFilter.java | 69 +++++ .../parameters/user/AbstractUserFilter.java | 17 ++ .../user/ActivityDefinitionUserFilter.java | 43 +++ .../parameters/user/BinaryUserFilter.java | 43 +++ .../parameters/user/BundleUserFilter.java | 12 + .../parameters/user/CodeSystemUserFilter.java | 12 + .../parameters/user/EndpointUserFilter.java | 12 + .../parameters/user/GroupUserFilter.java | 43 +++ .../user/HealthcareServiceUserFilter.java | 12 + .../parameters/user/LocationUserFilter.java | 12 + .../user/NamingSystemUserFilter.java | 12 + .../user/OrganizationUserFilter.java | 12 + .../parameters/user/PatientUserFilter.java | 43 +++ .../user/PractitionerRoleUserFilter.java | 43 +++ .../user/PractitionerUserFilter.java | 43 +++ .../parameters/user/ProvenanceUserFilter.java | 43 +++ .../user/ResearchStudyUserFilter.java | 43 +++ ...StructureDefinitionSnapshotUserFilter.java | 12 + .../user/StructureDefinitionUserFilter.java | 12 + .../user/SubscriptionUserFilter.java | 12 + .../parameters/user/TaskUserFilter.java | 43 +++ .../parameters/user/ValueSetUserFilter.java | 12 + ...ofileValidationSupportWithFetchFromDb.java | 8 +- .../fhir/service/InitialDataLoaderImpl.java | 6 +- .../dsf/fhir/service/ReferenceResolver.java | 43 ++- .../fhir/service/ReferenceResolverImpl.java | 65 +++-- .../spring/config/AuthorizationConfig.java | 145 ++++++++++ .../dsf/fhir/spring/config/DaoConfig.java | 51 ++-- .../fhir/spring/config/WebserviceConfig.java | 45 ++-- .../webservice/base/AbstractBasicService.java | 42 +++ .../base/AbstractDelegatingBasicService.java | 44 +++ .../{specification => base}/BasicService.java | 2 +- .../impl/AbstractResourceServiceImpl.java | 255 +++++++++--------- .../webservice/impl/AbstractServiceImpl.java | 34 --- .../impl/ConformanceServiceImpl.java | 3 +- .../fhir/webservice/impl/RootServiceImpl.java | 6 +- .../impl/StaticResourcesServiceImpl.java | 3 +- .../impl/StructureDefinitionServiceImpl.java | 2 +- .../jaxrs/AbstractServiceJaxrs.java | 24 +- .../secure/AbstractResourceServiceSecure.java | 83 ++---- .../secure/AbstractServiceSecure.java | 38 +-- .../ActivityDefinitionServiceSecure.java | 11 +- .../secure/BinaryServiceSecure.java | 5 +- .../secure/BundleServiceSecure.java | 5 +- .../secure/CodeSystemServiceSecure.java | 5 +- .../secure/EndpointServiceSecure.java | 23 +- .../webservice/secure/GroupServiceSecure.java | 5 +- .../HealthcareServiceServiceSecure.java | 5 +- .../secure/LocationServiceSecure.java | 8 +- .../secure/NamingSystemServiceSecure.java | 6 +- .../secure/OrganizationServiceSecure.java | 39 +-- .../secure/PatientServiceSecure.java | 5 +- .../secure/PractitionerRoleServiceSecure.java | 15 +- .../secure/PractitionerServiceSecure.java | 6 +- .../secure/ProvenanceServiceSecure.java | 5 +- .../secure/ResearchStudyServiceSecure.java | 6 +- .../StructureDefinitionServiceSecure.java | 46 +--- .../secure/SubscriptionServiceSecure.java | 40 +-- .../webservice/secure/TaskServiceSecure.java | 92 +------ .../secure/ValueSetServiceSecure.java | 5 +- .../specification/BasicResourceService.java | 1 + .../specification/ConformanceService.java | 2 + .../webservice/specification/RootService.java | 1 + .../specification/StaticResourcesService.java | 2 + .../dsf/fhir/websocket/ServerEndpoint.java | 2 +- .../fhir/CodeSystem/authorization-0.1.0.xml | 32 +++ .../CodeSystem/authorization-0.1.0.xml.put | 1 + .../fhir/CodeSystem/bpmn-message-0.1.0.xml | 6 + .../dsf/fhir/dao/AbstractResourceDaoTest.java | 160 +++++++++-- .../fhir/dao/ActivityDefinitionDaoTest.java | 6 +- .../highmed/dsf/fhir/dao/BinaryDaoTest.java | 8 +- .../highmed/dsf/fhir/dao/BundleDaoTest.java | 6 +- .../dsf/fhir/dao/CodeSystemDaoTest.java | 6 +- .../highmed/dsf/fhir/dao/EndpointDaoTest.java | 20 +- .../highmed/dsf/fhir/dao/GroupDaoTest.java | 5 +- .../fhir/dao/HealthcareServiceDaoTest.java | 6 +- .../highmed/dsf/fhir/dao/LocationDaoTest.java | 6 +- .../dsf/fhir/dao/NamingSystemDaoTest.java | 6 +- .../dsf/fhir/dao/OrganizationDaoTest.java | 32 ++- .../highmed/dsf/fhir/dao/PatientDaoTest.java | 6 +- .../dsf/fhir/dao/PractitionerDaoTest.java | 6 +- .../dsf/fhir/dao/PractitionerRoleDaoTest.java | 6 +- .../dsf/fhir/dao/ProvenanceDaoTest.java | 6 +- .../dsf/fhir/dao/ResearchStudyDaoTest.java | 6 +- .../fhir/dao/StructureDefinitionDaoTest.java | 9 +- .../StructureDefinitionSnapshotDaoTest.java | 7 +- .../dsf/fhir/dao/SubscriptionDaoTest.java | 6 +- .../org/highmed/dsf/fhir/dao/TaskDaoTest.java | 5 +- .../highmed/dsf/fhir/dao/ValueSetDaoTest.java | 6 +- .../org/highmed/dsf/fhir/hapi/MetaTest.java | 33 +++ .../java-test-fhir-config.properties | 1 + 156 files changed, 3318 insertions(+), 848 deletions(-) create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/OrganizationType.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ValueSetAuthorizationRule.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQueryUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/AbstractMetaTagAuthorizationRoleUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/AbstractUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ActivityDefinitionUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BundleUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/CodeSystemUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/EndpointUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/GroupUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/HealthcareServiceUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/LocationUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/NamingSystemUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/OrganizationUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PatientUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerRoleUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ProvenanceUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ResearchStudyUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/StructureDefinitionSnapshotUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/StructureDefinitionUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/SubscriptionUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/TaskUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ValueSetUserFilter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthorizationConfig.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/base/AbstractBasicService.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/base/AbstractDelegatingBasicService.java rename dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/{specification => base}/BasicService.java (80%) delete mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractServiceImpl.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-0.1.0.xml create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-0.1.0.xml.put create mode 100644 dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/MetaTest.java diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/OrganizationType.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/OrganizationType.java new file mode 100644 index 000000000..ab8a7c2f4 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/OrganizationType.java @@ -0,0 +1,23 @@ +package org.highmed.dsf.fhir; + +public enum OrganizationType +{ + MeDIC("MeDIC"), TTP("TTP"); + + private final String code; + + OrganizationType(String code) + { + this.code = code; + } + + public String getCode() + { + return code; + } + + public String getSystem() + { + return "http://highmed.org/fhir/CodeSystem/organization-type"; + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java new file mode 100644 index 000000000..703719fb1 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java @@ -0,0 +1,61 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Objects; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.authentication.UserRole; +import org.highmed.dsf.fhir.dao.ResourceDao; +import org.highmed.dsf.fhir.search.SearchQueryUserFilter; +import org.hl7.fhir.r4.model.Resource; +import org.springframework.beans.factory.InitializingBean; + +public abstract class AbstractAuthorizationRule> + implements AuthorizationRule, InitializingBean +{ + protected final D dao; + + public AbstractAuthorizationRule(D dao) + { + this.dao = dao; + } + + @Override + public void afterPropertiesSet() throws Exception + { + Objects.requireNonNull(dao, "dao"); + } + + protected final boolean isLocalUser(User user) + { + return user != null && UserRole.LOCAL.equals(user.getRole()); + } + + protected final boolean isRemoteUser(User user) + { + return user != null && UserRole.REMOTE.equals(user.getRole()); + } + + protected final boolean hasLocalOrRemoteAuthorizationRole(Resource resource) + { + return resource.hasMeta() && resource.getMeta().getTag().stream() + .anyMatch(c -> SearchQueryUserFilter.AUTHORIZATION_ROLE_SYSTEM.equals(c.getSystem()) + && (SearchQueryUserFilter.AUTHORIZATION_ROLE_VALUE_LOCAL.equals(c.getCode()) + || SearchQueryUserFilter.AUTHORIZATION_ROLE_VALUE_REMOTE.equals(c.getCode()))); + } + + protected final boolean hasLocalAuthorizationRole(Resource resource) + { + return hasAuthorizationRole(resource, SearchQueryUserFilter.AUTHORIZATION_ROLE_VALUE_LOCAL); + } + + protected final boolean hasRemoteAuthorizationRole(Resource resource) + { + return hasAuthorizationRole(resource, SearchQueryUserFilter.AUTHORIZATION_ROLE_VALUE_REMOTE); + } + + private boolean hasAuthorizationRole(Resource resource, String role) + { + return resource.hasMeta() && resource.getMeta().getTag().stream().anyMatch( + c -> SearchQueryUserFilter.AUTHORIZATION_ROLE_SYSTEM.equals(c.getSystem()) && role.equals(c.getCode())); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java new file mode 100644 index 000000000..d0c928b13 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java @@ -0,0 +1,52 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; +import org.hl7.fhir.r4.model.ActivityDefinition; + +public class ActivityDefinitionAuthorizationRule + extends AbstractAuthorizationRule +{ + public ActivityDefinitionAuthorizationRule(ActivityDefinitionDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, ActivityDefinition newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, ActivityDefinition existingResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, ActivityDefinition oldResource, + ActivityDefinition newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, ActivityDefinition oldResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRule.java new file mode 100644 index 000000000..7eb0ed7ec --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRule.java @@ -0,0 +1,64 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.hl7.fhir.r4.model.Resource; + +public interface AuthorizationRule +{ + /** + * Override this method for non default behavior. Default: Not allowed. + * + * @param user + * not null + * @param newResource + * not null + * @return Reason as String in {@link Optional#of(Object))} if create allowed + */ + Optional reasonCreateAllowed(User user, R newResource); + + /** + * Override this method for non default behavior. Default: Not allowed. + * + * @param user + * not null + * @param existingResource + * not null + * @return Reason as String in {@link Optional#of(Object)} if read allowed + */ + Optional reasonReadAllowed(User user, R existingResource); + + /** + * Override this method for non default behavior. Default: Not allowed. + * + * @param user + * not null + * @param oldResource + * not null + * @param newResource + * not null + * @return Reason as String in {@link Optional#of(Object))} if update allowed + */ + Optional reasonUpdateAllowed(User user, R oldResource, R newResource); + + /** + * Override this method for non default behavior. Default: Not allowed. + * + * @param user + * not null + * @param oldResource + * not null + * @return Reason as String in {@link Optional#of(Object)} if delete allowed + */ + Optional reasonDeleteAllowed(User user, R oldResource); + + /** + * Override this method for non default behavior. Default: Not allowed. + * + * @param user + * not null + * @return Reason as String in {@link Optional#of(Object)} if delete allowed + */ + Optional reasonSearchAllowed(User user); +} \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java new file mode 100644 index 000000000..62a552451 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java @@ -0,0 +1,50 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.BinaryDao; +import org.hl7.fhir.r4.model.Binary; + +public class BinaryAuthorizationRule extends AbstractAuthorizationRule +{ + public BinaryAuthorizationRule(BinaryDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, Binary newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, Binary existingResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, Binary oldResource, Binary newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, Binary oldResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java new file mode 100644 index 000000000..683e49ba5 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java @@ -0,0 +1,50 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.BundleDao; +import org.hl7.fhir.r4.model.Bundle; + +public class BundleAuthorizationRule extends AbstractAuthorizationRule +{ + public BundleAuthorizationRule(BundleDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, Bundle newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, Bundle existingResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, Bundle oldResource, Bundle newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, Bundle oldResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java new file mode 100644 index 000000000..ed922ca95 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java @@ -0,0 +1,148 @@ +package org.highmed.dsf.fhir.authorization; + +import java.sql.SQLException; +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.CodeSystemDao; +import org.hl7.fhir.r4.model.CodeSystem; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CodeSystemAuthorizationRule extends AbstractAuthorizationRule +{ + private static final Logger logger = LoggerFactory.getLogger(CodeSystemAuthorizationRule.class); + + public CodeSystemAuthorizationRule(CodeSystemDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, CodeSystem newResource) + { + if (isLocalUser(user)) + { + if (newResource.hasUrl() && newResource.hasVersion() && hasLocalOrRemoteAuthorizationRole(newResource)) + { + try + { + // TODO move check for url, version, authorization tag, to validation layer + Optional existing = dao.readByUrlAndVersion(newResource.getUrl(), + newResource.getVersion()); + if (existing.isEmpty()) + { + logger.info( + "Create of CodeSystem authorized for local user '{}', CodeSystem with version and url does not exist", + user.getName()); + return Optional.of("local user, CodeSystem with version and url does not exist yet"); + } + else + { + logger.warn( + "Create of CodeSystem unauthorized, CodeSystem wirh url and version already exists"); + return Optional.empty(); + } + } + catch (SQLException e) + { + logger.warn( + "Create of CodeSystem unauthorized, error while checking for existing CodeSystem with version and url", + e); + return Optional.empty(); + } + } + else + { + logger.warn("Create of CodeSystem unauthorized, missing url or version or authorization tag"); + return Optional.empty(); + } + } + else + { + logger.warn("Create of CodeSystem unauthorized, not a local user"); + return Optional.empty(); + } + } + + @Override + public Optional reasonReadAllowed(User user, CodeSystem existingResource) + { + if (isLocalUser(user) && hasLocalOrRemoteAuthorizationRole(existingResource)) + { + logger.info( + "Read of CodeSystem authorized for local user '{}', CodeSystem has local or remote authorization role", + user.getName()); + return Optional.of("local user, local or remote authorized CodeSystem"); + } + else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) + { + logger.info("Read of CodeSystem authorized for remote user '{}', CodeSystem has remote authorization role", + user.getName()); + return Optional.of("remote user, remote authorized CodeSystem"); + } + else + { + logger.warn("Read of CodeSystem unauthorized, no matching user role resource authorization role found"); + return Optional.empty(); + } + } + + @Override + public Optional reasonUpdateAllowed(User user, CodeSystem oldResource, CodeSystem newResource) + { + if (isLocalUser(user)) + { + // TODO move check for url, version, authorization tag, to validation layer + if (newResource.hasUrl() && newResource.hasVersion() && hasLocalOrRemoteAuthorizationRole(newResource)) + { + if (oldResource.getUrl().equals(newResource.getUrl()) + && oldResource.getVersion().equals(newResource.getVersion())) + { + logger.info( + "Update of CodeSystem authorized for local user '{}', version and url same as existing one", + user.getName()); + return Optional.of("local user, CodeSystem with version and url does not exist yet"); + } + else + { + logger.warn("Update of CodeSystem unauthorized, new url or version not equal to existing resource"); + return Optional.empty(); + } + } + else + { + logger.warn("Update of CodeSystem unauthorized, missing url or version or authorization tag"); + return Optional.empty(); + } + } + else + { + logger.warn("Update of CodeSystem unauthorized, not a local user"); + return Optional.empty(); + } + } + + @Override + public Optional reasonDeleteAllowed(User user, CodeSystem oldResource) + { + if (isLocalUser(user)) + { + logger.info("Delete of new CodeSystem authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Update of CodeSystem unauthorized, not a local user"); + return Optional.empty(); + } + } + + @Override + public Optional reasonSearchAllowed(User user) + { + logger.info("Search of CodeSystem authorized for {} user '{}', will be fitered by user role", user.getRole(), + user.getName()); + return Optional.of("Allowed for all, filtered by user role"); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java new file mode 100644 index 000000000..55fe3d9db --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java @@ -0,0 +1,52 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.EndpointDao; +import org.hl7.fhir.r4.model.Endpoint; + +public class EndpointAuthorizationRule extends AbstractAuthorizationRule +{ + public EndpointAuthorizationRule(EndpointDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, Endpoint newResource) + { + // TODO validate unique on Endpoint.address + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, Endpoint existingResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, Endpoint oldResource, Endpoint newResource) + { + // TODO validate unique on Endpoint.address + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, Endpoint oldResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java new file mode 100644 index 000000000..195a04fa1 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java @@ -0,0 +1,50 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.GroupDao; +import org.hl7.fhir.r4.model.Group; + +public class GroupAuthorizationRule extends AbstractAuthorizationRule +{ + public GroupAuthorizationRule(GroupDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, Group newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, Group existingResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, Group oldResource, Group newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, Group oldResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java new file mode 100644 index 000000000..20c480dd9 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java @@ -0,0 +1,50 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.HealthcareServiceDao; +import org.hl7.fhir.r4.model.HealthcareService; + +public class HealthcareServiceAuthorizationRule extends AbstractAuthorizationRule +{ + public HealthcareServiceAuthorizationRule(HealthcareServiceDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, HealthcareService newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, HealthcareService existingResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, HealthcareService oldResource, HealthcareService newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, HealthcareService oldResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java new file mode 100644 index 000000000..ccb07d514 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java @@ -0,0 +1,50 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.LocationDao; +import org.hl7.fhir.r4.model.Location; + +public class LocationAuthorizationRule extends AbstractAuthorizationRule +{ + public LocationAuthorizationRule(LocationDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, Location newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, Location existingResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, Location oldResource, Location newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, Location oldResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java new file mode 100644 index 000000000..e2356fa51 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java @@ -0,0 +1,50 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.NamingSystemDao; +import org.hl7.fhir.r4.model.NamingSystem; + +public class NamingSystemAuthorizationRule extends AbstractAuthorizationRule +{ + public NamingSystemAuthorizationRule(NamingSystemDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, NamingSystem newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, NamingSystem existingResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, NamingSystem oldResource, NamingSystem newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, NamingSystem oldResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java new file mode 100644 index 000000000..a733baa7f --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java @@ -0,0 +1,56 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.OrganizationDao; +import org.hl7.fhir.r4.model.Organization; + +public class OrganizationAuthorizationRule extends AbstractAuthorizationRule +{ + public OrganizationAuthorizationRule(OrganizationDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, Organization newResource) + { + // check organization not existing if contains identifier with identifier.system (or extension) + // http://highmed.org/fhir/NamingSystem/certificate-thumbprint-hex with same identifier.value + // no two organizations can have the same certificate thumb-print + + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, Organization existingResource) + { + // see create, no two organizations can have the same certificate thumb-print + + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, Organization oldResource, Organization newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, Organization oldResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java new file mode 100644 index 000000000..57f1e435f --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java @@ -0,0 +1,50 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.PatientDao; +import org.hl7.fhir.r4.model.Patient; + +public class PatientAuthorizationRule extends AbstractAuthorizationRule +{ + public PatientAuthorizationRule(PatientDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, Patient newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, Patient existingResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, Patient oldResource, Patient newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, Patient oldResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java new file mode 100644 index 000000000..9e0291537 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java @@ -0,0 +1,50 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.PractitionerDao; +import org.hl7.fhir.r4.model.Practitioner; + +public class PractitionerAuthorizationRule extends AbstractAuthorizationRule +{ + public PractitionerAuthorizationRule(PractitionerDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, Practitioner newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, Practitioner existingResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, Practitioner oldResource, Practitioner newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, Practitioner oldResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java new file mode 100644 index 000000000..162384968 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java @@ -0,0 +1,50 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.PractitionerRoleDao; +import org.hl7.fhir.r4.model.PractitionerRole; + +public class PractitionerRoleAuthorizationRule extends AbstractAuthorizationRule +{ + public PractitionerRoleAuthorizationRule(PractitionerRoleDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, PractitionerRole newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, PractitionerRole existingResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, PractitionerRole oldResource, PractitionerRole newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, PractitionerRole oldResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java new file mode 100644 index 000000000..3fe5c090a --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java @@ -0,0 +1,50 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.ProvenanceDao; +import org.hl7.fhir.r4.model.Provenance; + +public class ProvenanceAuthorizationRule extends AbstractAuthorizationRule +{ + public ProvenanceAuthorizationRule(ProvenanceDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, Provenance newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, Provenance existingResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, Provenance oldResource, Provenance newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, Provenance oldResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java new file mode 100644 index 000000000..30c4e753c --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java @@ -0,0 +1,50 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.ResearchStudyDao; +import org.hl7.fhir.r4.model.ResearchStudy; + +public class ResearchStudyAuthorizationRule extends AbstractAuthorizationRule +{ + public ResearchStudyAuthorizationRule(ResearchStudyDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, ResearchStudy newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, ResearchStudy existingResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, ResearchStudy oldResource, ResearchStudy newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, ResearchStudy oldResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java new file mode 100644 index 000000000..40461b8e9 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java @@ -0,0 +1,61 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.StructureDefinitionDao; +import org.hl7.fhir.r4.model.StructureDefinition; + +public class StructureDefinitionAuthorizationRule + extends AbstractAuthorizationRule +{ + public StructureDefinitionAuthorizationRule(StructureDefinitionDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, StructureDefinition newResource) + { + // check logged in, check "local" user (local user only could be default) + // check against existing profiles, no create if profile with same URL, version and status exists + + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, StructureDefinition existingResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, StructureDefinition oldResource, + StructureDefinition newResource) + { + // check logged in, check "local" user (local user only could be default) + // check resource exists for given path id + // check against existing profile (by path id), no update if profile has different URL, version or status, + // status change via create + // check against existing profile (by path id), no update if status ACTIVE or RETIRED + + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, StructureDefinition oldResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java new file mode 100644 index 000000000..fc5e2261d --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java @@ -0,0 +1,55 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.SubscriptionDao; +import org.hl7.fhir.r4.model.Subscription; + +public class SubscriptionAuthorizationRule extends AbstractAuthorizationRule +{ + public SubscriptionAuthorizationRule(SubscriptionDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, Subscription newResource) + { + // check subscription.channel.payload null or one of the supported mimetypes + // check subscription.channel.type = websocket + // check subscription.criteria is implemented as search query + // check if subscription.channel.type = websocket, Task unique on subscription.criteria + + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, Subscription existingResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, Subscription oldResource, Subscription newResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, Subscription oldResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java new file mode 100644 index 000000000..ead057701 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java @@ -0,0 +1,60 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.TaskDao; +import org.hl7.fhir.r4.model.Task; + +public class TaskAuthorizationRule extends AbstractAuthorizationRule +{ + public TaskAuthorizationRule(TaskDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, Task newResource) + { + // allowed status draft | requested for all users + // task.requester must be organization of current user + + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonReadAllowed(User user, Task existingResource) + { + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonUpdateAllowed(User user, Task oldResource, Task newResource) + { + // allowed status change from draft to requested for remote users + // update only allowed at status draft for remote users + // task.requester must be organization of current user or local user + // only update of tasks with requester = current user allowed for remote users + + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonDeleteAllowed(User user, Task oldResource) + { + // allowed if oldResouce created by current user and status draft + + // TODO Auto-generated method stub + return Optional.empty(); + } + + @Override + public Optional reasonSearchAllowed(User user) + { + // TODO Auto-generated method stub + return Optional.empty(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ValueSetAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ValueSetAuthorizationRule.java new file mode 100644 index 000000000..f8d567e62 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ValueSetAuthorizationRule.java @@ -0,0 +1,147 @@ +package org.highmed.dsf.fhir.authorization; + +import java.sql.SQLException; +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.ValueSetDao; +import org.hl7.fhir.r4.model.ValueSet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ValueSetAuthorizationRule extends AbstractAuthorizationRule +{ + private static final Logger logger = LoggerFactory.getLogger(ValueSetAuthorizationRule.class); + + public ValueSetAuthorizationRule(ValueSetDao dao) + { + super(dao); + } + + @Override + public Optional reasonCreateAllowed(User user, ValueSet newResource) + { + if (isLocalUser(user)) + { + if (newResource.hasUrl() && newResource.hasVersion() && hasLocalOrRemoteAuthorizationRole(newResource)) + { + try + { + // TODO move check for url, version, authorization tag, to validation layer + Optional existing = dao.readByUrlAndVersion(newResource.getUrl(), + newResource.getVersion()); + if (existing.isEmpty()) + { + logger.info( + "Create of ValueSet authorized for local user '{}', ValueSet with version and url does not exist", + user.getName()); + return Optional.of("local user, ValueSet with version and url does not exist yet"); + } + else + { + logger.warn("Create of ValueSet unauthorized, ValueSet wirh url and version already exists"); + return Optional.empty(); + } + } + catch (SQLException e) + { + logger.warn( + "Create of ValueSet unauthorized, error while checking for existing ValueSet with version and url", + e); + return Optional.empty(); + } + } + else + { + logger.warn("Create of ValueSet unauthorized, missing url or version or authorization tag"); + return Optional.empty(); + } + } + else + { + logger.warn("Create of ValueSet unauthorized, not a local user"); + return Optional.empty(); + } + } + + @Override + public Optional reasonReadAllowed(User user, ValueSet existingResource) + { + if (isLocalUser(user) && hasLocalOrRemoteAuthorizationRole(existingResource)) + { + logger.info( + "Read of ValueSet authorized for local user '{}', ValueSet has local or remote authorization role", + user.getName()); + return Optional.of("local user, local or remote authorized ValueSet"); + } + else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) + { + logger.info("Read of ValueSet authorized for remote user '{}', ValueSet has remote authorization role", + user.getName()); + return Optional.of("remote user, remote authorized ValueSet"); + } + else + { + logger.warn("Read of ValueSet unauthorized, no matching user role resource authorization role found"); + return Optional.empty(); + } + } + + @Override + public Optional reasonUpdateAllowed(User user, ValueSet oldResource, ValueSet newResource) + { + if (isLocalUser(user)) + { + // TODO move check for url, version, authorization tag, to validation layer + if (newResource.hasUrl() && newResource.hasVersion() && hasLocalOrRemoteAuthorizationRole(newResource)) + { + if (oldResource.getUrl().equals(newResource.getUrl()) + && oldResource.getVersion().equals(newResource.getVersion())) + { + logger.info( + "Update of ValueSet authorized for local user '{}', version and url same as existing one", + user.getName()); + return Optional.of("local user, ValueSet with version and url does not exist yet"); + } + else + { + logger.warn("Update of ValueSet unauthorized, new url or version not equal to existing resource"); + return Optional.empty(); + } + } + else + { + logger.warn("Update of ValueSet unauthorized, missing url or version or authorization tag"); + return Optional.empty(); + } + } + else + { + logger.warn("Update of ValueSet unauthorized, not a local user"); + return Optional.empty(); + } + } + + @Override + public Optional reasonDeleteAllowed(User user, ValueSet oldResource) + { + if (isLocalUser(user)) + { + logger.info("Delete of new ValueSet authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Update of ValueSet unauthorized, not a local user"); + return Optional.empty(); + } + } + + @Override + public Optional reasonSearchAllowed(User user) + { + logger.info("Search of ValueSet authorized for {} user '{}', will be fitered by user role", user.getRole(), + user.getName()); + return Optional.of("Allowed for all, filtered by user role"); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ReadByUrlDao.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ReadByUrlDao.java index dbcd2d4b6..96f2d5868 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ReadByUrlDao.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ReadByUrlDao.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.dao; +import java.sql.Connection; import java.sql.SQLException; import java.util.Optional; @@ -7,5 +8,10 @@ public interface ReadByUrlDao { - Optional readByUrl(String urlAndVersion) throws SQLException; + Optional readByUrlAndVersion(String urlAndVersion) throws SQLException; + + Optional readByUrlAndVersion(String url, String version) throws SQLException; + + Optional readByUrlAndVersionWithTransaction(Connection connection, String url, String version) + throws SQLException; } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResourceDao.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResourceDao.java index d787414cb..8bdf8d4f4 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResourceDao.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResourceDao.java @@ -5,6 +5,7 @@ import java.util.Optional; import java.util.UUID; +import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.exception.ResourceDeletedException; import org.highmed.dsf.fhir.dao.exception.ResourceNotFoundException; import org.highmed.dsf.fhir.dao.exception.ResourceVersionNoMatchException; @@ -129,7 +130,7 @@ public interface ResourceDao * @throws SQLException */ Optional readIncludingDeletedWithTransaction(Connection connection, UUID uuid) throws SQLException; - + /** * @param id * not null @@ -278,5 +279,7 @@ R updateWithTransaction(Connection connection, R resource, Long expectedVersion) */ PartialResult searchWithTransaction(Connection connection, DbSearchQuery query) throws SQLException; - SearchQuery createSearchQuery(int page, int count); + SearchQuery createSearchQuery(User user, int page, int count); + + SearchQuery createSearchQueryWithoutUserFilter(int page, int count); } \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommand.java index 99eb1ae61..c39382106 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommand.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.dao.command; +import org.highmed.dsf.fhir.authentication.User; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; @@ -9,17 +10,20 @@ public abstract class AbstractCommand implements Command protected final int index; + protected final User user; protected final Bundle bundle; protected final BundleEntryComponent entry; protected final String serverBase; - public AbstractCommand(int transactionPriority, int index, Bundle bundle, BundleEntryComponent entry, + public AbstractCommand(int transactionPriority, int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase) { this.transactionPriority = transactionPriority; this.index = index; + + this.user = user; this.bundle = bundle; this.entry = entry; this.serverBase = serverBase; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommandWithResource.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommandWithResource.java index 5dc12a649..94304cdc5 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommandWithResource.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommandWithResource.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.dao.command; +import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ResourceDao; import org.highmed.dsf.fhir.help.ExceptionHandler; import org.highmed.dsf.fhir.help.ParameterConverter; @@ -15,11 +16,11 @@ public abstract class AbstractCommandWithResourcenull + * @param user + * not null + * @return + * @throws BadBundleException + */ + CommandList createCommands(Bundle bundle, User user) throws BadBundleException; } \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CommandFactoryImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CommandFactoryImpl.java index d394b06f1..46382d33d 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CommandFactoryImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CommandFactoryImpl.java @@ -10,6 +10,7 @@ import javax.sql.DataSource; +import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ResourceDao; import org.highmed.dsf.fhir.dao.StructureDefinitionDao; import org.highmed.dsf.fhir.dao.exception.BadBundleException; @@ -85,14 +86,14 @@ public void afterPropertiesSet() throws Exception } // read, vread - private Command get(Bundle bundle, int index, BundleEntryComponent entry) + private Command get(int index, User user, Bundle bundle, BundleEntryComponent entry) { - return new ReadCommand(index, bundle, entry, serverBase, defaultPageCount, daoProvider, parameterConverter, - responseGenerator, exceptionHandler); + return new ReadCommand(index, user, bundle, entry, serverBase, defaultPageCount, daoProvider, + parameterConverter, responseGenerator, exceptionHandler); } // create, conditional create - private Command post(Bundle bundle, int index, BundleEntryComponent entry, + private Command post(int index, User user, Bundle bundle, BundleEntryComponent entry, EventManager eventManager, R resource) { if (resource.getResourceType().name().equals(entry.getRequest().getUrl())) @@ -102,14 +103,15 @@ private Command post(Bundle bundle, int index, BundleEntryC .getDao(resource.getClass()); if (resource instanceof StructureDefinition) - return new CreateStructureDefinitionCommand(index, bundle, entry, serverBase, + return new CreateStructureDefinitionCommand(index, user, bundle, entry, serverBase, (StructureDefinition) resource, (StructureDefinitionDao) dao.get(), exceptionHandler, parameterConverter, responseGenerator, eventManager, eventGenerator, daoProvider.getStructureDefinitionSnapshotDao(), snapshotGenerator, snapshotDependencyAnalyzer); else return dao - .map(d -> new CreateCommand>(index, bundle, entry, serverBase, resource, d, - exceptionHandler, parameterConverter, responseGenerator, eventManager, eventGenerator)) + .map(d -> new CreateCommand>(index, user, bundle, entry, serverBase, resource, + d, exceptionHandler, parameterConverter, responseGenerator, eventManager, + eventGenerator)) .orElseThrow(() -> new IllegalStateException( "Resource of type " + resource.getClass().getName() + " not supported")); } @@ -119,7 +121,7 @@ private Command post(Bundle bundle, int index, BundleEntryC } // update, conditional update - private Command put(Bundle bundle, int index, BundleEntryComponent entry, + private Command put(int index, User user, Bundle bundle, BundleEntryComponent entry, EventManager eventManager, R resource) { if (entry.getRequest().getUrl() != null && !entry.getRequest().getUrl().isBlank() @@ -130,14 +132,15 @@ private Command put(Bundle bundle, int index, BundleE .getDao(resource.getClass()); if (resource instanceof StructureDefinition) - return new UpdateStructureDefinitionCommand(index, bundle, entry, serverBase, + return new UpdateStructureDefinitionCommand(index, user, bundle, entry, serverBase, (StructureDefinition) resource, (StructureDefinitionDao) dao.get(), exceptionHandler, parameterConverter, responseGenerator, eventManager, eventGenerator, daoProvider.getStructureDefinitionSnapshotDao(), snapshotGenerator, snapshotDependencyAnalyzer); else return dao - .map(d -> new UpdateCommand>(index, bundle, entry, serverBase, resource, d, - exceptionHandler, parameterConverter, responseGenerator, eventManager, eventGenerator)) + .map(d -> new UpdateCommand>(index, user, bundle, entry, serverBase, resource, + d, exceptionHandler, parameterConverter, responseGenerator, eventManager, + eventGenerator)) .orElseThrow(() -> new IllegalStateException( "Resource of type " + resource.getClass().getName() + " not supported")); } @@ -147,12 +150,12 @@ private Command put(Bundle bundle, int index, BundleE } // delete, conditional delete - private Command delete(Bundle bundle, int index, BundleEntryComponent entry, EventManager eventManager) + private Command delete(int index, User user, Bundle bundle, BundleEntryComponent entry, EventManager eventManager) { if (entry.getRequest().getUrl() != null && !entry.getRequest().getUrl().isBlank()) { - return new DeleteCommand(index, bundle, entry, serverBase, responseGenerator, daoProvider, exceptionHandler, - parameterConverter, eventManager, eventGenerator); + return new DeleteCommand(index, user, bundle, entry, serverBase, responseGenerator, daoProvider, + exceptionHandler, parameterConverter, eventManager, eventGenerator); } else throw new BadBundleException( @@ -160,9 +163,10 @@ private Command delete(Bundle bundle, int index, BundleEntryComponent entry, Eve } @Override - public CommandList createCommands(Bundle bundle) throws BadBundleException + public CommandList createCommands(Bundle bundle, User user) throws BadBundleException { Objects.requireNonNull(bundle, "bundle"); + Objects.requireNonNull(user, "user"); if (bundle.getType() != null) { @@ -173,7 +177,7 @@ public CommandList createCommands(Bundle bundle) throws BadBundleException eventManager = this.eventManager; List commands = IntStream.range(0, bundle.getEntry().size()) - .mapToObj(index -> createCommand(bundle, index, bundle.getEntry().get(index), eventManager)) + .mapToObj(index -> createCommand(index, bundle, user, bundle.getEntry().get(index), eventManager)) .flatMap(Function.identity()).collect(Collectors.toList()); switch (bundle.getType()) @@ -191,7 +195,7 @@ public CommandList createCommands(Bundle bundle) throws BadBundleException throw new BadBundleException("Missing bundle type"); } - protected Stream createCommand(Bundle bundle, int index, BundleEntryComponent entry, + protected Stream createCommand(int index, Bundle bundle, User user, BundleEntryComponent entry, EventManager eventManager) { if (entry.hasRequest() && entry.getRequest().hasMethod()) @@ -201,9 +205,9 @@ protected Stream createCommand(Bundle bundle, int index, BundleEntryCom switch (entry.getRequest().getMethod()) { case GET: - return Stream.of(get(bundle, index, entry)); + return Stream.of(get(index, user, bundle, entry)); case DELETE: - return Stream.of(delete(bundle, index, entry, eventManager)); + return Stream.of(delete(index, user, bundle, entry, eventManager)); default: throw new BadBundleException("Request method " + entry.getRequest().getMethod() + " at index " + index + " not supported without resource of type " + DomainResource.class.getName()); @@ -214,11 +218,14 @@ else if (entry.getResource() instanceof DomainResource) switch (entry.getRequest().getMethod()) { case POST: // create - Command post = post(bundle, index, entry, eventManager, (DomainResource) entry.getResource()); - return resolveReferences(post, bundle, index, entry, (DomainResource) entry.getResource()); + Command post = post(index, user, bundle, entry, eventManager, + (DomainResource) entry.getResource()); + return resolveReferences(post, index, user, bundle, entry, + (DomainResource) entry.getResource()); case PUT: // update - Command put = put(bundle, index, entry, eventManager, (DomainResource) entry.getResource()); - return resolveReferences(put, bundle, index, entry, (DomainResource) entry.getResource()); + Command put = put(index, user, bundle, entry, eventManager, + (DomainResource) entry.getResource()); + return resolveReferences(put, index, user, bundle, entry, (DomainResource) entry.getResource()); default: throw new BadBundleException("Request method " + entry.getRequest().getMethod() + " at index " + index + " not supported with resource"); @@ -232,8 +239,8 @@ else if (entry.getResource() instanceof DomainResource) throw new BadBundleException("BundleEntry at index " + index + " has no request or request has no method"); } - private Stream resolveReferences(Command cmd, Bundle bundle, int index, - BundleEntryComponent entry, R resource) + private Stream resolveReferences(Command cmd, int index, User user, + Bundle bundle, BundleEntryComponent entry, R resource) { @SuppressWarnings("unchecked") Optional> dao = (Optional>) daoProvider @@ -243,9 +250,9 @@ private Stream resolveReferences(Command cmd { return dao .map(d -> Stream.of(cmd, - new ResolveReferencesCommand>(index, bundle, entry, serverBase, resource, - d, exceptionHandler, parameterConverter, referenceExtractor, responseGenerator, - referenceResolver))) + new ResolveReferencesCommand>(index, user, bundle, entry, serverBase, + resource, d, exceptionHandler, parameterConverter, referenceExtractor, + responseGenerator, referenceResolver))) .orElseThrow(() -> new IllegalStateException( "Resource of type " + resource.getClass().getName() + " not supported")); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateCommand.java index 25dc5382a..2c81f549a 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateCommand.java @@ -15,6 +15,7 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; +import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ResourceDao; import org.highmed.dsf.fhir.dao.exception.ResourceNotFoundException; import org.highmed.dsf.fhir.event.EventGenerator; @@ -50,11 +51,11 @@ public class CreateCommand> extends protected R createdResource; protected Response responseResult; - public CreateCommand(int index, Bundle bundle, BundleEntryComponent entry, String serverBase, R resource, D dao, - ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, + public CreateCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, R resource, + D dao, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, ResponseGenerator responseGenerator, EventManager eventManager, EventGenerator eventGenerator) { - super(2, index, bundle, entry, serverBase, resource, dao, exceptionHandler, parameterConverter); + super(2, index, user, bundle, entry, serverBase, resource, dao, exceptionHandler, parameterConverter); this.responseGenerator = responseGenerator; this.eventManager = eventManager; @@ -121,7 +122,7 @@ private Optional checkAlreadyExists(Connection connection, String ifNo .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); } - SearchQuery query = dao.createSearchQuery(1, 1); + SearchQuery query = dao.createSearchQuery(user, 1, 1); query.configureParameters(queryParameters); List unsupportedQueryParameters = query diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateStructureDefinitionCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateStructureDefinitionCommand.java index 94e945ac4..5b7003fd1 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateStructureDefinitionCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateStructureDefinitionCommand.java @@ -3,6 +3,7 @@ import java.sql.Connection; import java.util.Map; +import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.StructureDefinitionDao; import org.highmed.dsf.fhir.dao.StructureDefinitionSnapshotDao; import org.highmed.dsf.fhir.event.EventGenerator; @@ -33,14 +34,15 @@ public class CreateStructureDefinitionCommand extends CreateCommand resourceType; private String id; - public DeleteCommand(int index, Bundle bundle, BundleEntryComponent entry, String serverBase, + public DeleteCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, ResponseGenerator responseGenerator, DaoProvider daoProvider, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, EventManager eventManager, EventGenerator eventGenerator) { - super(1, index, bundle, entry, serverBase); + super(1, index, user, bundle, entry, serverBase); this.responseGenerator = responseGenerator; this.daoProvider = daoProvider; @@ -142,7 +143,7 @@ private Optional search(Connection connection, ResourceDao dao, .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); } - SearchQuery query = dao.createSearchQuery(1, 1); + SearchQuery query = dao.createSearchQuery(user, 1, 1); query.configureParameters(queryParameters); List unsupportedQueryParameters = query diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ReadCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ReadCommand.java index 64b0523ab..d34e7889d 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ReadCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ReadCommand.java @@ -14,6 +14,7 @@ import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriBuilder; +import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ResourceDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.help.ExceptionHandler; @@ -51,11 +52,11 @@ public class ReadCommand extends AbstractCommand implements Command private Resource singleResult; private Response responseResult; - public ReadCommand(int index, Bundle bundle, BundleEntryComponent entry, String serverBase, int defaultPageCount, - DaoProvider daoProvider, ParameterConverter parameterConverter, ResponseGenerator responseGenerator, - ExceptionHandler exceptionHandler) + public ReadCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, + int defaultPageCount, DaoProvider daoProvider, ParameterConverter parameterConverter, + ResponseGenerator responseGenerator, ExceptionHandler exceptionHandler) { - super(5, index, bundle, entry, serverBase); + super(5, index, user, bundle, entry, serverBase); this.defaultPageCount = defaultPageCount; @@ -179,7 +180,7 @@ private void readByCondition(Connection connection, String resourceTypeName, Integer count = parameterConverter.getFirstInt(cleanQueryParameters, SearchQuery.PARAMETER_COUNT); int effectiveCount = (count == null || count < 0) ? defaultPageCount : count; - SearchQuery query = optDao.get().createSearchQuery(effectivePage, effectiveCount); + SearchQuery query = optDao.get().createSearchQuery(user, effectivePage, effectiveCount); query.configureParameters(cleanQueryParameters); List errors = query.getUnsupportedQueryParameters(cleanQueryParameters); // TODO throw error if strict param handling is configured, include warning else diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java index eaeadd025..b3f69d6a9 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java @@ -8,6 +8,7 @@ import javax.ws.rs.WebApplicationException; +import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ResourceDao; import org.highmed.dsf.fhir.dao.exception.ResourceDeletedException; import org.highmed.dsf.fhir.dao.exception.ResourceNotFoundException; @@ -29,12 +30,12 @@ public class ResolveReferencesCommand idTranslationTable, Connect case LITERAL_EXTERNAL: return referenceResolver.resolveLiteralExternalReference(resource, index, resourceReference); case CONDITIONAL: - return referenceResolver.resolveConditionalReference(resource, index, resourceReference, connection); + return referenceResolver.resolveConditionalReference(user, resource, index, resourceReference, + connection); case LOGICAL: - return referenceResolver.resolveLogicalReference(resource, index, resourceReference, connection); + return referenceResolver.resolveLogicalReference(user, resource, index, resourceReference, connection); case UNKNOWN: default: throw new WebApplicationException( diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/TransactionEventManager.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/TransactionEventManager.java index d82a7bcc1..c1ec37d4e 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/TransactionEventManager.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/TransactionEventManager.java @@ -5,6 +5,7 @@ import javax.websocket.RemoteEndpoint.Async; +import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.event.Event; import org.highmed.dsf.fhir.event.EventManager; @@ -36,9 +37,9 @@ public void commitEvents() } @Override - public void bind(String sessionId, Async asyncRemote, String subscriptionIdPart) + public void bind(User user, String sessionId, Async asyncRemote, String subscriptionIdPart) { - delegate.bind(sessionId, asyncRemote, subscriptionIdPart); + delegate.bind(user, sessionId, asyncRemote, subscriptionIdPart); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java index 914ce93d8..e7ab2c87b 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java @@ -15,6 +15,7 @@ import javax.ws.rs.core.EntityTag; import javax.ws.rs.core.Response.Status; +import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ResourceDao; import org.highmed.dsf.fhir.dao.exception.ResourceNotFoundException; import org.highmed.dsf.fhir.event.EventGenerator; @@ -48,11 +49,11 @@ public class UpdateCommand> extends protected UUID id; protected R updatedResource; - public UpdateCommand(int index, Bundle bundle, BundleEntryComponent entry, String serverBase, R resource, D dao, - ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, + public UpdateCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, R resource, + D dao, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, ResponseGenerator responseGenerator, EventManager eventManager, EventGenerator eventGenerator) { - super(3, index, bundle, entry, serverBase, resource, dao, exceptionHandler, parameterConverter); + super(3, index, user, bundle, entry, serverBase, resource, dao, exceptionHandler, parameterConverter); this.responseGenerator = responseGenerator; this.eventManager = eventManager; @@ -140,8 +141,8 @@ private void updateById(Map idTranslationTable, Connection conne Optional ifMatch = Optional.ofNullable(entry.getRequest().getIfMatch()) .flatMap(parameterConverter::toEntityTag).flatMap(parameterConverter::toVersion); - updatedResource = exceptionHandler.handleSqlExAndResourceNotFoundExAndResouceVersionNonMatchEx( - resourceTypeName, () -> dao.updateWithTransaction(connection, resource, ifMatch.orElse(null))); + updatedResource = exceptionHandler.handleSqlExAndResourceNotFoundExAndResouceVersionNonMatchEx(resourceTypeName, + () -> dao.updateWithTransaction(connection, resource, ifMatch.orElse(null))); } private void updateByCondition(Map idTranslationTable, Connection connection, @@ -160,7 +161,7 @@ private void updateByCondition(Map idTranslationTable, Connectio .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); } - SearchQuery query = dao.createSearchQuery(1, 1); + SearchQuery query = dao.createSearchQuery(user, 1, 1); query.configureParameters(queryParameters); List unsupportedParams = query.getUnsupportedQueryParameters(queryParameters); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateStructureDefinitionCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateStructureDefinitionCommand.java index 843730ea4..04bce61d7 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateStructureDefinitionCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateStructureDefinitionCommand.java @@ -3,6 +3,7 @@ import java.sql.Connection; import java.util.Map; +import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.StructureDefinitionDao; import org.highmed.dsf.fhir.dao.StructureDefinitionSnapshotDao; import org.highmed.dsf.fhir.event.EventGenerator; @@ -34,14 +35,15 @@ public class UpdateStructureDefinitionCommand extends UpdateCommand preparedStatementFactory; + private final OrganizationType organizationType; + private final BiFunction userFilter; private final List>> searchParameterFactories = new ArrayList<>(); private final List> searchRevIncludeParameterFactories = new ArrayList<>(); - private final PreparedStatementFactory preparedStatementFactory; - @SafeVarargs protected static List with(T... t) { @@ -123,14 +128,15 @@ protected static List with(T... t) * created on a request basis */ AbstractResourceDaoJdbc(DataSource dataSource, FhirContext fhirContext, Class resourceType, String resourceTable, - String resourceColumn, String resourceIdColumn, + String resourceColumn, String resourceIdColumn, OrganizationType organizationType, + BiFunction userFilter, List>> searchParameterFactories, List> searchRevIncludeParameterFactories) { this(dataSource, fhirContext, resourceType, resourceTable, resourceColumn, resourceIdColumn, new PreparedStatementFactoryDefault<>(fhirContext, resourceType, resourceTable, resourceIdColumn, resourceColumn), - searchParameterFactories, searchRevIncludeParameterFactories); + organizationType, userFilter, searchParameterFactories, searchRevIncludeParameterFactories); } /* @@ -139,6 +145,7 @@ protected static List with(T... t) */ AbstractResourceDaoJdbc(DataSource dataSource, FhirContext fhirContext, Class resourceType, String resourceTable, String resourceColumn, String resourceIdColumn, PreparedStatementFactory preparedStatementFactory, + OrganizationType organizationType, BiFunction userFilter, List>> searchParameterFactories, List> searchRevIncludeParameterFactories) { @@ -153,6 +160,9 @@ protected static List with(T... t) this.preparedStatementFactory = preparedStatementFactory; + this.organizationType = organizationType; + this.userFilter = userFilter; + if (searchParameterFactories != null) this.searchParameterFactories.addAll(searchParameterFactories); if (searchRevIncludeParameterFactories != null) @@ -918,13 +928,21 @@ private void getResources(ResultSet result, int columnIndex, List createSearchQuery(int page, int count) + public final SearchQuery createSearchQuery(User user, int page, int count) { return SearchQueryBuilder.create(resourceType, getResourceTable(), getResourceColumn(), page, count) + .with(userFilter.apply(organizationType, user)) .with(new ResourceId(getResourceIdColumn()), new ResourceLastUpdated(getResourceColumn())) .with(searchParameterFactories.stream().map(Supplier::get).toArray(SearchQueryParameter[]::new)) .withRevInclude(searchRevIncludeParameterFactories.stream().map(Supplier::get) .toArray(SearchQueryRevIncludeParameterFactory[]::new)) .build(); } + + @Override + public SearchQuery createSearchQueryWithoutUserFilter(int page, int count) + { + // TODO Auto-generated method stub + return null; + } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractStructureDefinitionDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractStructureDefinitionDaoJdbc.java index ae5ac1c6f..26918b4ea 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractStructureDefinitionDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractStructureDefinitionDaoJdbc.java @@ -7,8 +7,13 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.function.BiFunction; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.StructureDefinitionDaoBase; +import org.highmed.dsf.fhir.search.SearchQueryUserFilter; import org.highmed.dsf.fhir.search.parameters.StructureDefinitionIdentifier; import org.highmed.dsf.fhir.search.parameters.StructureDefinitionUrl; import org.highmed.dsf.fhir.search.parameters.StructureDefinitionVersion; @@ -19,15 +24,18 @@ import ca.uhn.fhir.context.FhirContext; abstract class AbstractStructureDefinitionDaoJdbc extends AbstractResourceDaoJdbc + implements StructureDefinitionDaoBase { private static final Logger logger = LoggerFactory.getLogger(AbstractStructureDefinitionDaoJdbc.class); private final ReadByUrlDaoJdbc readByUrl; - public AbstractStructureDefinitionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, String resourceTable, - String resourceColumn, String resourceIdColumn) + public AbstractStructureDefinitionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType, String resourceTable, String resourceColumn, String resourceIdColumn, + BiFunction userFilter) { super(dataSource, fhirContext, StructureDefinition.class, resourceTable, resourceColumn, resourceIdColumn, + organizationType, userFilter, with(() -> new StructureDefinitionIdentifier(resourceColumn), () -> new StructureDefinitionUrl(resourceColumn), () -> new StructureDefinitionVersion(resourceColumn)), @@ -37,6 +45,7 @@ public AbstractStructureDefinitionDaoJdbc(BasicDataSource dataSource, FhirContex resourceColumn, resourceIdColumn); } + @Override public List readAll() throws SQLException { try (Connection connection = getDataSource().getConnection(); @@ -57,8 +66,22 @@ public List readAll() throws SQLException } } - public Optional readByUrl(String urlAndVersion) throws SQLException + @Override + public Optional readByUrlAndVersion(String urlAndVersion) throws SQLException { - return readByUrl.readByUrl(urlAndVersion); + return readByUrl.readByUrlAndVersion(urlAndVersion); + } + + @Override + public Optional readByUrlAndVersion(String url, String version) throws SQLException + { + return readByUrl.readByUrlAndVersion(url, version); + } + + @Override + public Optional readByUrlAndVersionWithTransaction(Connection connection, String url, + String version) throws SQLException + { + return readByUrl.readByUrlAndVersionWithTransaction(connection, url, version); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java index 517e5b9cf..ee6c4dc40 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java @@ -1,12 +1,14 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionIdentifier; import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionName; import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionStatus; import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionUrl; import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionVersion; +import org.highmed.dsf.fhir.search.parameters.user.ActivityDefinitionUserFilter; import org.hl7.fhir.r4.model.ActivityDefinition; import ca.uhn.fhir.context.FhirContext; @@ -14,11 +16,13 @@ public class ActivityDefinitionDaoJdbc extends AbstractResourceDaoJdbc implements ActivityDefinitionDao { - public ActivityDefinitionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public ActivityDefinitionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { super(dataSource, fhirContext, ActivityDefinition.class, "activity_definitions", "activity_definition", - "activity_definition_id", with(ActivityDefinitionIdentifier::new, ActivityDefinitionName::new, - ActivityDefinitionStatus::new, ActivityDefinitionUrl::new, ActivityDefinitionVersion::new), + "activity_definition_id", organizationType, ActivityDefinitionUserFilter::new, + with(ActivityDefinitionIdentifier::new, ActivityDefinitionName::new, ActivityDefinitionStatus::new, + ActivityDefinitionUrl::new, ActivityDefinitionVersion::new), with()); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/BinaryDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/BinaryDaoJdbc.java index 0b7b5325a..d6e7a611b 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/BinaryDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/BinaryDaoJdbc.java @@ -6,8 +6,10 @@ import java.sql.SQLException; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.BinaryDao; import org.highmed.dsf.fhir.search.parameters.BinaryContentType; +import org.highmed.dsf.fhir.search.parameters.user.BinaryUserFilter; import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.IdType; @@ -15,10 +17,11 @@ public class BinaryDaoJdbc extends AbstractResourceDaoJdbc implements BinaryDao { - public BinaryDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public BinaryDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) { super(dataSource, fhirContext, Binary.class, "binaries", "binary_json", "binary_id", - new PreparedStatementFactoryBinary(fhirContext), with(BinaryContentType::new), with()); + new PreparedStatementFactoryBinary(fhirContext), organizationType, BinaryUserFilter::new, + with(BinaryContentType::new), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/BundleDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/BundleDaoJdbc.java index 0e0306033..c8dda87c5 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/BundleDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/BundleDaoJdbc.java @@ -4,8 +4,10 @@ import java.sql.SQLException; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.BundleDao; import org.highmed.dsf.fhir.search.parameters.BundleIdentifier; +import org.highmed.dsf.fhir.search.parameters.user.BundleUserFilter; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.IdType; @@ -13,10 +15,10 @@ public class BundleDaoJdbc extends AbstractResourceDaoJdbc implements BundleDao { - public BundleDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public BundleDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) { - super(dataSource, fhirContext, Bundle.class, "bundles", "bundle", "bundle_id", with(BundleIdentifier::new), - with()); + super(dataSource, fhirContext, Bundle.class, "bundles", "bundle", "bundle_id", organizationType, + BundleUserFilter::new, with(BundleIdentifier::new), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/CodeSystemDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/CodeSystemDaoJdbc.java index 501133efc..1799f60f7 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/CodeSystemDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/CodeSystemDaoJdbc.java @@ -1,14 +1,17 @@ package org.highmed.dsf.fhir.dao.jdbc; +import java.sql.Connection; import java.sql.SQLException; import java.util.Optional; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.CodeSystemDao; import org.highmed.dsf.fhir.search.parameters.CodeSystemIdentifier; import org.highmed.dsf.fhir.search.parameters.CodeSystemStatus; import org.highmed.dsf.fhir.search.parameters.CodeSystemUrl; import org.highmed.dsf.fhir.search.parameters.CodeSystemVersion; +import org.highmed.dsf.fhir.search.parameters.user.CodeSystemUserFilter; import org.hl7.fhir.r4.model.CodeSystem; import ca.uhn.fhir.context.FhirContext; @@ -17,9 +20,10 @@ public class CodeSystemDaoJdbc extends AbstractResourceDaoJdbc imple { private final ReadByUrlDaoJdbc readByUrl; - public CodeSystemDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public CodeSystemDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) { super(dataSource, fhirContext, CodeSystem.class, "code_systems", "code_system", "code_system_id", + organizationType, CodeSystemUserFilter::new, with(CodeSystemIdentifier::new, CodeSystemStatus::new, CodeSystemUrl::new, CodeSystemVersion::new), with()); @@ -34,8 +38,21 @@ protected CodeSystem copy(CodeSystem resource) } @Override - public Optional readByUrl(String urlAndVersion) throws SQLException + public Optional readByUrlAndVersion(String urlAndVersion) throws SQLException { - return readByUrl.readByUrl(urlAndVersion); + return readByUrl.readByUrlAndVersion(urlAndVersion); + } + + @Override + public Optional readByUrlAndVersion(String url, String version) throws SQLException + { + return readByUrl.readByUrlAndVersion(url, version); + } + + @Override + public Optional readByUrlAndVersionWithTransaction(Connection connection, String url, String version) + throws SQLException + { + return readByUrl.readByUrlAndVersionWithTransaction(connection, url, version); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/EndpointDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/EndpointDaoJdbc.java index bb6d3f0e5..1f231e301 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/EndpointDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/EndpointDaoJdbc.java @@ -6,12 +6,14 @@ import java.sql.SQLException; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.EndpointDao; import org.highmed.dsf.fhir.search.parameters.EndpointIdentifier; import org.highmed.dsf.fhir.search.parameters.EndpointName; import org.highmed.dsf.fhir.search.parameters.EndpointOrganization; import org.highmed.dsf.fhir.search.parameters.EndpointStatus; import org.highmed.dsf.fhir.search.parameters.rev.include.OrganizationEndpointRevInclude; +import org.highmed.dsf.fhir.search.parameters.user.EndpointUserFilter; import org.hl7.fhir.r4.model.Endpoint; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,9 +24,10 @@ public class EndpointDaoJdbc extends AbstractResourceDaoJdbc implement { private static final Logger logger = LoggerFactory.getLogger(EndpointDaoJdbc.class); - public EndpointDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public EndpointDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) { - super(dataSource, fhirContext, Endpoint.class, "endpoints", "endpoint", "endpoint_id", + super(dataSource, fhirContext, Endpoint.class, "endpoints", "endpoint", "endpoint_id", organizationType, + EndpointUserFilter::new, with(EndpointOrganization::new, EndpointIdentifier::new, EndpointName::new, EndpointStatus::new), with(OrganizationEndpointRevInclude::new)); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/GroupDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/GroupDaoJdbc.java index eba2ec585..2e1e3a221 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/GroupDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/GroupDaoJdbc.java @@ -1,18 +1,20 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.GroupDao; import org.highmed.dsf.fhir.search.parameters.rev.include.ResearchStudyEnrollmentRevInclude; +import org.highmed.dsf.fhir.search.parameters.user.GroupUserFilter; import org.hl7.fhir.r4.model.Group; import ca.uhn.fhir.context.FhirContext; public class GroupDaoJdbc extends AbstractResourceDaoJdbc implements GroupDao { - public GroupDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public GroupDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) { - super(dataSource, fhirContext, Group.class, "groups", "group_json", "group_id", with(), - with(ResearchStudyEnrollmentRevInclude::new)); + super(dataSource, fhirContext, Group.class, "groups", "group_json", "group_id", organizationType, + GroupUserFilter::new, with(), with(ResearchStudyEnrollmentRevInclude::new)); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/HealthcareServiceDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/HealthcareServiceDaoJdbc.java index 3ecb8640f..3fb1546dd 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/HealthcareServiceDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/HealthcareServiceDaoJdbc.java @@ -1,19 +1,23 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.HealthcareServiceDao; import org.highmed.dsf.fhir.search.parameters.HealthcareServiceActive; import org.highmed.dsf.fhir.search.parameters.HealthcareServiceIdentifier; +import org.highmed.dsf.fhir.search.parameters.user.HealthcareServiceUserFilter; import org.hl7.fhir.r4.model.HealthcareService; import ca.uhn.fhir.context.FhirContext; public class HealthcareServiceDaoJdbc extends AbstractResourceDaoJdbc implements HealthcareServiceDao { - public HealthcareServiceDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public HealthcareServiceDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { super(dataSource, fhirContext, HealthcareService.class, "healthcare_services", "healthcare_service", - "healthcare_service_id", with(HealthcareServiceIdentifier::new, HealthcareServiceActive::new), with()); + "healthcare_service_id", organizationType, HealthcareServiceUserFilter::new, + with(HealthcareServiceIdentifier::new, HealthcareServiceActive::new), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/LocationDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/LocationDaoJdbc.java index 712dd43b0..2f718d0dd 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/LocationDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/LocationDaoJdbc.java @@ -1,18 +1,20 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.LocationDao; import org.highmed.dsf.fhir.search.parameters.LocationIdentifier; +import org.highmed.dsf.fhir.search.parameters.user.LocationUserFilter; import org.hl7.fhir.r4.model.Location; import ca.uhn.fhir.context.FhirContext; public class LocationDaoJdbc extends AbstractResourceDaoJdbc implements LocationDao { - public LocationDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public LocationDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) { - super(dataSource, fhirContext, Location.class, "locations", "location", "location_id", - with(LocationIdentifier::new), with()); + super(dataSource, fhirContext, Location.class, "locations", "location", "location_id", organizationType, + LocationUserFilter::new, with(LocationIdentifier::new), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/NamingSystemDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/NamingSystemDaoJdbc.java index 3f3eb33bf..cf82203b4 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/NamingSystemDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/NamingSystemDaoJdbc.java @@ -1,19 +1,20 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.NamingSystemDao; import org.highmed.dsf.fhir.search.parameters.NamingSystemName; +import org.highmed.dsf.fhir.search.parameters.user.NamingSystemUserFilter; import org.hl7.fhir.r4.model.NamingSystem; import ca.uhn.fhir.context.FhirContext; public class NamingSystemDaoJdbc extends AbstractResourceDaoJdbc implements NamingSystemDao { - public NamingSystemDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public NamingSystemDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) { super(dataSource, fhirContext, NamingSystem.class, "naming_systems", "naming_system", "naming_system_id", - with(NamingSystemName::new), with()); - + organizationType, NamingSystemUserFilter::new, with(NamingSystemName::new), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java index fcc465179..459f18804 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java @@ -14,6 +14,7 @@ import org.highmed.dsf.fhir.search.parameters.OrganizationName; import org.highmed.dsf.fhir.search.parameters.OrganizationType; import org.highmed.dsf.fhir.search.parameters.rev.include.EndpointOrganizationRevInclude; +import org.highmed.dsf.fhir.search.parameters.user.OrganizationUserFilter; import org.hl7.fhir.r4.model.Organization; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,11 +25,12 @@ public class OrganizationDaoJdbc extends AbstractResourceDaoJdbc i { private static final Logger logger = LoggerFactory.getLogger(OrganizationDaoJdbc.class); - public OrganizationDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public OrganizationDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, + org.highmed.dsf.fhir.OrganizationType organizationType) { super(dataSource, fhirContext, Organization.class, "organizations", "organization", "organization_id", - with(OrganizationName::new, OrganizationEndpoint::new, OrganizationIdentifier::new, - OrganizationActive::new, OrganizationType::new), + organizationType, OrganizationUserFilter::new, with(OrganizationName::new, OrganizationEndpoint::new, + OrganizationIdentifier::new, OrganizationActive::new, OrganizationType::new), with(EndpointOrganizationRevInclude::new)); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PatientDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PatientDaoJdbc.java index c5c0bfbcf..0e76d4b8d 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PatientDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PatientDaoJdbc.java @@ -1,19 +1,21 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.PatientDao; import org.highmed.dsf.fhir.search.parameters.PatientActive; import org.highmed.dsf.fhir.search.parameters.PatientIdentifier; +import org.highmed.dsf.fhir.search.parameters.user.PatientUserFilter; import org.hl7.fhir.r4.model.Patient; import ca.uhn.fhir.context.FhirContext; public class PatientDaoJdbc extends AbstractResourceDaoJdbc implements PatientDao { - public PatientDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public PatientDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) { - super(dataSource, fhirContext, Patient.class, "patients", "patient", "patient_id", - with(PatientIdentifier::new, PatientActive::new), with()); + super(dataSource, fhirContext, Patient.class, "patients", "patient", "patient_id", organizationType, + PatientUserFilter::new, with(PatientIdentifier::new, PatientActive::new), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerDaoJdbc.java index 1dd82998b..046831412 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerDaoJdbc.java @@ -1,18 +1,21 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.PractitionerDao; import org.highmed.dsf.fhir.search.parameters.PractitionerActive; import org.highmed.dsf.fhir.search.parameters.PractitionerIdentifier; +import org.highmed.dsf.fhir.search.parameters.user.PractitionerUserFilter; import org.hl7.fhir.r4.model.Practitioner; import ca.uhn.fhir.context.FhirContext; public class PractitionerDaoJdbc extends AbstractResourceDaoJdbc implements PractitionerDao { - public PractitionerDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public PractitionerDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) { super(dataSource, fhirContext, Practitioner.class, "practitioners", "practitioner", "practitioner_id", + organizationType, PractitionerUserFilter::new, with(PractitionerIdentifier::new, PractitionerActive::new), with()); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerRoleDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerRoleDaoJdbc.java index f7b5b9488..8d42bcc01 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerRoleDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerRoleDaoJdbc.java @@ -1,19 +1,23 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.PractitionerRoleDao; import org.highmed.dsf.fhir.search.parameters.PractitionerRoleActive; import org.highmed.dsf.fhir.search.parameters.PractitionerRoleIdentifier; +import org.highmed.dsf.fhir.search.parameters.user.PractitionerRoleUserFilter; import org.hl7.fhir.r4.model.PractitionerRole; import ca.uhn.fhir.context.FhirContext; public class PractitionerRoleDaoJdbc extends AbstractResourceDaoJdbc implements PractitionerRoleDao { - public PractitionerRoleDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public PractitionerRoleDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { super(dataSource, fhirContext, PractitionerRole.class, "practitioner_roles", "practitioner_role", - "practitioner_role_id", with(PractitionerRoleIdentifier::new, PractitionerRoleActive::new), with()); + "practitioner_role_id", organizationType, PractitionerRoleUserFilter::new, + with(PractitionerRoleIdentifier::new, PractitionerRoleActive::new), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ProvenanceDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ProvenanceDaoJdbc.java index e35d40919..aef539f5e 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ProvenanceDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ProvenanceDaoJdbc.java @@ -1,16 +1,19 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.ProvenanceDao; +import org.highmed.dsf.fhir.search.parameters.user.PatientUserFilter; import org.hl7.fhir.r4.model.Provenance; import ca.uhn.fhir.context.FhirContext; public class ProvenanceDaoJdbc extends AbstractResourceDaoJdbc implements ProvenanceDao { - public ProvenanceDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public ProvenanceDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) { - super(dataSource, fhirContext, Provenance.class, "provenances", "provenance", "provenance_id", with(), with()); + super(dataSource, fhirContext, Provenance.class, "provenances", "provenance", "provenance_id", organizationType, + PatientUserFilter::new, with(), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ReadByUrlDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ReadByUrlDaoJdbc.java index 1e19a6188..ae06e9e6d 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ReadByUrlDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ReadByUrlDaoJdbc.java @@ -4,6 +4,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; @@ -36,7 +37,13 @@ class ReadByUrlDaoJdbc this.resourceIdColumn = resourceIdColumn; } - Optional readByUrl(String urlAndVersion) throws SQLException + /** + * @param urlAndVersion + * not null, url|version + * @return {@link Optional#empty()} if param urlAndVersion is null or {@link String#isBlank()} + * @throws SQLException + */ + Optional readByUrlAndVersion(String urlAndVersion) throws SQLException { if (urlAndVersion == null || urlAndVersion.isBlank()) return Optional.empty(); @@ -45,17 +52,52 @@ Optional readByUrl(String urlAndVersion) throws SQLException if (split.length < 1 || split.length > 2) return Optional.empty(); - String versionSql = split.length == 2 ? ("AND " + resourceColumn + "->>'version' = ? ") : ""; + return readByUrlAndVersion(split[0], split.length == 2 ? split[1] : null); + } + + /** + * @param url + * not null + * @param version + * may be null + * @return {@link Optional#empty()} if param url is null or {@link String#isBlank()} + * @throws SQLException + */ + Optional readByUrlAndVersion(String url, String version) throws SQLException + { + try (Connection connection = dataSourceSupplier.get().getConnection()) + { + return readByUrlAndVersionWithTransaction(connection, url, version); + } + } + + /** + * @param connection + * not null + * @param url + * not null + * @param version + * may be null + * @return {@link Optional#empty()} if param url is null or {@link String#isBlank()} + * @throws SQLException + */ + Optional readByUrlAndVersionWithTransaction(Connection connection, String url, String version) + throws SQLException + { + Objects.requireNonNull(connection, "connection"); + if (url == null || url.isBlank()) + return Optional.empty(); + + String versionSql = version == null || version.isBlank() ? ("AND " + resourceColumn + "->>'version' = ? ") : ""; String sql = "SELECT DISTINCT ON(" + resourceIdColumn + ") " + resourceColumn + " FROM " + resourceTable + " WHERE NOT deleted AND " + resourceColumn + "->>'url' = ? " + versionSql + "ORDER BY " + resourceIdColumn + ", version LIMIT 1"; - try (Connection connection = dataSourceSupplier.get().getConnection(); - PreparedStatement statement = connection.prepareStatement(sql)) + try (PreparedStatement statement = connection.prepareStatement(sql)) { - statement.setString(1, split[0]); - if (split.length == 2) - statement.setString(2, split[1]); + statement.setString(1, url); + if (version == null || version.isBlank()) + statement.setString(2, version); logger.trace("Executing query '{}'", statement); try (ResultSet result = statement.executeQuery()) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java index 27dcd73fb..60e50f126 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java @@ -1,18 +1,21 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.ResearchStudyDao; import org.highmed.dsf.fhir.search.parameters.ResearchStudyEnrollment; import org.highmed.dsf.fhir.search.parameters.ResearchStudyIdentifier; +import org.highmed.dsf.fhir.search.parameters.user.ResearchStudyUserFilter; import org.hl7.fhir.r4.model.ResearchStudy; import ca.uhn.fhir.context.FhirContext; public class ResearchStudyDaoJdbc extends AbstractResourceDaoJdbc implements ResearchStudyDao { - public ResearchStudyDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public ResearchStudyDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) { super(dataSource, fhirContext, ResearchStudy.class, "research_studies", "research_study", "research_study_id", + organizationType, ResearchStudyUserFilter::new, with(ResearchStudyIdentifier::new, ResearchStudyEnrollment::new), with()); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/StructureDefinitionDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/StructureDefinitionDaoJdbc.java index edeedeb18..76b0686c5 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/StructureDefinitionDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/StructureDefinitionDaoJdbc.java @@ -1,16 +1,20 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.StructureDefinitionDao; +import org.highmed.dsf.fhir.search.parameters.user.StructureDefinitionUserFilter; import org.hl7.fhir.r4.model.StructureDefinition; import ca.uhn.fhir.context.FhirContext; public class StructureDefinitionDaoJdbc extends AbstractStructureDefinitionDaoJdbc implements StructureDefinitionDao { - public StructureDefinitionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public StructureDefinitionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - super(dataSource, fhirContext, "structure_definitions", "structure_definition", "structure_definition_id"); + super(dataSource, fhirContext, organizationType, "structure_definitions", "structure_definition", + "structure_definition_id", StructureDefinitionUserFilter::new); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/StructureDefinitionSnapshotDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/StructureDefinitionSnapshotDaoJdbc.java index 1344375f8..d3402e76f 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/StructureDefinitionSnapshotDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/StructureDefinitionSnapshotDaoJdbc.java @@ -8,9 +8,11 @@ import java.util.UUID; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.StructureDefinitionSnapshotDao; import org.highmed.dsf.fhir.dao.converter.SnapshotInfoConverter; import org.highmed.dsf.fhir.dao.exception.ResourceNotFoundException; +import org.highmed.dsf.fhir.search.parameters.user.StructureDefinitionSnapshotUserFilter; import org.highmed.dsf.fhir.service.SnapshotInfo; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.StructureDefinition; @@ -27,10 +29,11 @@ public class StructureDefinitionSnapshotDaoJdbc extends AbstractStructureDefinit private final SnapshotInfoConverter converter; public StructureDefinitionSnapshotDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, - SnapshotInfoConverter converter) + OrganizationType organizationType, SnapshotInfoConverter converter) { - super(dataSource, fhirContext, "structure_definition_snapshots", "structure_definition_snapshot", - "structure_definition_snapshot_id"); + super(dataSource, fhirContext, organizationType, "structure_definition_snapshots", + "structure_definition_snapshot", "structure_definition_snapshot_id", + StructureDefinitionSnapshotUserFilter::new); this.converter = converter; } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/SubscriptionDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/SubscriptionDaoJdbc.java index f4c1bf3a2..1b2b6ae19 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/SubscriptionDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/SubscriptionDaoJdbc.java @@ -9,11 +9,13 @@ import java.util.List; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.SubscriptionDao; import org.highmed.dsf.fhir.search.parameters.SubscriptionChannelPayload; import org.highmed.dsf.fhir.search.parameters.SubscriptionChannelType; import org.highmed.dsf.fhir.search.parameters.SubscriptionCriteria; import org.highmed.dsf.fhir.search.parameters.SubscriptionStatus; +import org.highmed.dsf.fhir.search.parameters.user.SubscriptionUserFilter; import org.hl7.fhir.r4.model.Subscription; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,11 +26,11 @@ public class SubscriptionDaoJdbc extends AbstractResourceDaoJdbc i { private static final Logger logger = LoggerFactory.getLogger(SubscriptionDaoJdbc.class); - public SubscriptionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public SubscriptionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) { super(dataSource, fhirContext, Subscription.class, "subscriptions", "subscription", "subscription_id", - with(SubscriptionCriteria::new, SubscriptionStatus::new, SubscriptionChannelType::new, - SubscriptionChannelPayload::new), + organizationType, SubscriptionUserFilter::new, with(SubscriptionCriteria::new, SubscriptionStatus::new, + SubscriptionChannelType::new, SubscriptionChannelPayload::new), with()); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/TaskDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/TaskDaoJdbc.java index 71963c714..f961ec66f 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/TaskDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/TaskDaoJdbc.java @@ -1,19 +1,21 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.TaskDao; import org.highmed.dsf.fhir.search.parameters.TaskIdentifier; import org.highmed.dsf.fhir.search.parameters.TaskRequester; import org.highmed.dsf.fhir.search.parameters.TaskStatus; +import org.highmed.dsf.fhir.search.parameters.user.TaskUserFilter; import org.hl7.fhir.r4.model.Task; import ca.uhn.fhir.context.FhirContext; public class TaskDaoJdbc extends AbstractResourceDaoJdbc implements TaskDao { - public TaskDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public TaskDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) { - super(dataSource, fhirContext, Task.class, "tasks", "task", "task_id", + super(dataSource, fhirContext, Task.class, "tasks", "task", "task_id", organizationType, TaskUserFilter::new, with(TaskIdentifier::new, TaskRequester::new, TaskStatus::new), with()); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ValueSetDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ValueSetDaoJdbc.java index 1f6f7af56..35a150520 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ValueSetDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ValueSetDaoJdbc.java @@ -1,14 +1,17 @@ package org.highmed.dsf.fhir.dao.jdbc; +import java.sql.Connection; import java.sql.SQLException; import java.util.Optional; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.ValueSetDao; import org.highmed.dsf.fhir.search.parameters.ValueSetIdentifier; import org.highmed.dsf.fhir.search.parameters.ValueSetStatus; import org.highmed.dsf.fhir.search.parameters.ValueSetUrl; import org.highmed.dsf.fhir.search.parameters.ValueSetVersion; +import org.highmed.dsf.fhir.search.parameters.user.ValueSetUserFilter; import org.hl7.fhir.r4.model.ValueSet; import ca.uhn.fhir.context.FhirContext; @@ -17,9 +20,10 @@ public class ValueSetDaoJdbc extends AbstractResourceDaoJdbc implement { private final ReadByUrlDaoJdbc readByUrl; - public ValueSetDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) + public ValueSetDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) { - super(dataSource, fhirContext, ValueSet.class, "value_sets", "value_set", "value_set_id", + super(dataSource, fhirContext, ValueSet.class, "value_sets", "value_set", "value_set_id", organizationType, + ValueSetUserFilter::new, with(ValueSetIdentifier::new, ValueSetStatus::new, ValueSetUrl::new, ValueSetVersion::new), with()); readByUrl = new ReadByUrlDaoJdbc<>(this::getDataSource, this::getResource, getResourceTable(), @@ -33,8 +37,21 @@ protected ValueSet copy(ValueSet resource) } @Override - public Optional readByUrl(String urlAndVersion) throws SQLException + public Optional readByUrlAndVersion(String urlAndVersion) throws SQLException { - return readByUrl.readByUrl(urlAndVersion); + return readByUrl.readByUrlAndVersion(urlAndVersion); + } + + @Override + public Optional readByUrlAndVersion(String url, String version) throws SQLException + { + return readByUrl.readByUrlAndVersion(url, version); + } + + @Override + public Optional readByUrlAndVersionWithTransaction(Connection connection, String url, String version) + throws SQLException + { + return readByUrl.readByUrlAndVersionWithTransaction(connection, url, version); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/event/EventManager.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/event/EventManager.java index 060d246be..c476c735c 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/event/EventManager.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/event/EventManager.java @@ -4,13 +4,15 @@ import javax.websocket.RemoteEndpoint.Async; +import org.highmed.dsf.fhir.authentication.User; + public interface EventManager { void handleEvent(Event event); void handleEvents(List events); - void bind(String sessionId, Async asyncRemote, String subscriptionIdPart); + void bind(User user, String sessionId, Async asyncRemote, String subscriptionIdPart); void close(String sessionId); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/event/EventManagerImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/event/EventManagerImpl.java index 7df7f99aa..6b1c54ce8 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/event/EventManagerImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/event/EventManagerImpl.java @@ -17,6 +17,7 @@ import javax.websocket.RemoteEndpoint.Async; +import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.SubscriptionDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.help.ExceptionHandler; @@ -65,11 +66,13 @@ boolean matches(Resource resource, DaoProvider daoProvider) private static class SessionIdAndRemoteAsync { + final User user; final String sessionId; final Async remoteAsync; - SessionIdAndRemoteAsync(String sessionId, Async remoteAsync) + SessionIdAndRemoteAsync(User user, String sessionId, Async remoteAsync) { + this.user = user; this.sessionId = sessionId; this.remoteAsync = remoteAsync; } @@ -272,9 +275,21 @@ else if (Constants.CT_FHIR_XML_NEW.contentEquals(s.getChannel().getPayload())) logger.debug("Calling {} remote{} connected to subscription with id {}", optRemotes.get().size(), optRemotes.get().size() != 1 ? "s" : "", s.getIdElement().getIdPart()); - // defensive copy since since list could be changed by other threads while we are reading + // defensive copy because list could be changed by other threads while we are reading List remotes = new ArrayList<>(optRemotes.get()); - remotes.forEach(r -> send(r, text)); + remotes.stream().filter(r -> filterByReadAccess(r, event)).forEach(r -> send(r, text)); + } + + private boolean filterByReadAccess(SessionIdAndRemoteAsync sessionAndRemote, Event event) + { + // TODO Filter by read access + + User user = sessionAndRemote.user; + logger.warn("Implement filter by read access in EventManagerImpl for user '{}' and event {} with resource {}", + user.getName(), event.getClass().getName(), event.getResource() == null ? "" + : event.getResource().getClass().getAnnotation(ResourceDef.class).name()); + + return true; } private void send(SessionIdAndRemoteAsync sessionAndRemote, String text) @@ -290,7 +305,7 @@ private void send(SessionIdAndRemoteAsync sessionAndRemote, String text) } @Override - public void bind(String sessionId, Async asyncRemote, String subscriptionIdPart) + public void bind(User user, String sessionId, Async asyncRemote, String subscriptionIdPart) { if (firstCall.get()) refreshMatchers(); @@ -303,12 +318,12 @@ public void bind(String sessionId, Async asyncRemote, String subscriptionIdPart) if (list == null) { List newList = new ArrayList<>(); - newList.add(new SessionIdAndRemoteAsync(sessionId, asyncRemote)); + newList.add(new SessionIdAndRemoteAsync(user, sessionId, asyncRemote)); return newList; } else { - list.add(new SessionIdAndRemoteAsync(sessionId, asyncRemote)); + list.add(new SessionIdAndRemoteAsync(user, sessionId, asyncRemote)); return list; } }); @@ -328,6 +343,6 @@ public void close(String sessionId) { logger.debug("Removing websocket session {}", sessionId); asyncRemotesBySubscriptionIdPart.removeWhereValueMatches(list -> list.isEmpty(), - list -> list.remove(new SessionIdAndRemoteAsync(sessionId, null))); + list -> list.remove(new SessionIdAndRemoteAsync(null, sessionId, null))); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/event/MatcherFactory.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/event/MatcherFactory.java index 9269d377c..c093e7e47 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/event/MatcherFactory.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/event/MatcherFactory.java @@ -32,7 +32,7 @@ public Optional createMatcher(String uri) if (daosByResourceName.containsKey(path)) { ResourceDao dao = daosByResourceName.get(path); - SearchQuery query = dao.createSearchQuery(1, 1); + SearchQuery query = dao.createSearchQueryWithoutUserFilter(1, 1); query.configureParameters(queryParameters); return Optional.of(query); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQuery.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQuery.java index 9ddc3dd02..91c759709 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQuery.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQuery.java @@ -13,6 +13,7 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.ws.rs.core.UriBuilder; @@ -47,22 +48,32 @@ public static SearchQueryBuilder create(Class resourc private final Class resourceType; private final String resourceTable; private final String resourceColumn; + private final int page; private final int count; private final List> searchParameters = new ArrayList>(); private final List revIncludeParameters = new ArrayList<>(); + private SearchQueryUserFilter userFilter; // may be null + private SearchQueryBuilder(Class resourceType, String resourceTable, String resourceColumn, int page, int count) { this.resourceType = resourceType; this.resourceTable = resourceTable; this.resourceColumn = resourceColumn; + this.page = page; this.count = count; } + public SearchQueryBuilder with(SearchQueryUserFilter userFilter) + { + this.userFilter = userFilter; + return this; + } + public SearchQueryBuilder with(SearchQueryParameter searchParameters) { this.searchParameters.add(searchParameters); @@ -99,8 +110,8 @@ public SearchQueryBuilder withRevInclude(List build() { - return new SearchQuery(resourceType, resourceTable, resourceColumn, page, count, searchParameters, - revIncludeParameters); + return new SearchQuery(resourceType, resourceTable, resourceColumn, userFilter, page, count, + searchParameters, revIncludeParameters); } } @@ -109,9 +120,13 @@ public SearchQuery build() private final Class resourceType; private final String resourceColumn; private final String resourceTable; + + private final SearchQueryUserFilter userFilter; + + private final PageAndCount pageAndCount; + private final List> searchParameters = new ArrayList<>(); private final List revIncludeParameterFactories = new ArrayList<>(); - private final PageAndCount pageAndCount; private String filterQuery; private String sortSql; @@ -121,17 +136,20 @@ public SearchQuery build() private List includeParameters = Collections.emptyList(); private List revIncludeParameters = Collections.emptyList(); - SearchQuery(Class resourceType, String resourceTable, String resourceColumn, int page, int count, - List> searchParameters, + SearchQuery(Class resourceType, String resourceTable, String resourceColumn, SearchQueryUserFilter userFilter, + int page, int count, List> searchParameters, List revIncludeParameters) { this.resourceType = resourceType; this.resourceTable = resourceTable; this.resourceColumn = resourceColumn; + this.userFilter = userFilter; + + this.pageAndCount = new PageAndCount(page, count); + this.searchParameters.addAll(searchParameters); this.revIncludeParameterFactories.addAll(revIncludeParameters); - this.pageAndCount = new PageAndCount(page, count); } public void configureParameters(Map> queryParameters) @@ -142,12 +160,23 @@ public void configureParameters(Map> queryParameters) Collections.emptyList()); revIncludeParameterFactories.forEach(p -> p.configure(revIncludeParameterValues)); - filterQuery = searchParameters.stream().filter(SearchQueryParameter::isDefined) - .map(SearchQueryParameter::getFilterQuery).collect(Collectors.joining(" AND ")); - - sortSql = createSortSql(getFirst(queryParameters, PARAMETER_SORT)); includeSql = createIncludeSql(queryParameters.get(PARAMETER_INCLUDE)); revIncludeSql = createRevIncludeSql(); + + filterQuery = createFilterQuery(); + + sortSql = createSortSql(getFirst(queryParameters, PARAMETER_SORT)); + } + + private String createFilterQuery() + { + Stream elements = searchParameters.stream().filter(SearchQueryParameter::isDefined) + .map(SearchQueryParameter::getFilterQuery); + + if (userFilter != null) + elements = Stream.concat(Stream.of(userFilter.getFilterQuery()), elements); + + return elements.collect(Collectors.joining(" AND ")); } public List getUnsupportedQueryParameters(Map> queryParameters) @@ -283,6 +312,10 @@ public void modifyStatement(PreparedStatement statement, .collect(Collectors.toList()); int index = 0; + if (userFilter != null) + while (index < userFilter.getSqlParameterCount()) + userFilter.modifyStatement(++index, statement); + for (SearchQueryParameter q : filtered) for (int i = 0; i < q.getSqlParameterCount(); i++) q.modifyStatement(++index, i + 1, statement, arrayCreator); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQueryUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQueryUserFilter.java new file mode 100644 index 000000000..90fe31913 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQueryUserFilter.java @@ -0,0 +1,17 @@ +package org.highmed.dsf.fhir.search; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +public interface SearchQueryUserFilter +{ + String AUTHORIZATION_ROLE_SYSTEM = "http://highmed.org/fhir/CodeSystem/authorization"; + String AUTHORIZATION_ROLE_VALUE_REMOTE = "REMOTE"; + String AUTHORIZATION_ROLE_VALUE_LOCAL = "LOCAL"; + + String getFilterQuery(); + + int getSqlParameterCount(); + + void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException; +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionCriteria.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionCriteria.java index a42f9803d..47cf7fda6 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionCriteria.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionCriteria.java @@ -38,7 +38,7 @@ public int getSqlParameterCount() public void modifyStatement(int parameterIndex, int subqueryParameterIndex, PreparedStatement statement, BiFunctionWithSqlException arrayCreator) throws SQLException { - statement.setString(1, valueAndType.value); + statement.setString(parameterIndex, valueAndType.value); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/AbstractMetaTagAuthorizationRoleUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/AbstractMetaTagAuthorizationRoleUserFilter.java new file mode 100644 index 000000000..cd1aab2bb --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/AbstractMetaTagAuthorizationRoleUserFilter.java @@ -0,0 +1,69 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.authentication.UserRole; + +abstract class AbstractMetaTagAuthorizationRoleUserFilter extends AbstractUserFilter +{ + private final String resourceColumn; + + public AbstractMetaTagAuthorizationRoleUserFilter(OrganizationType organizationType, User user, + String resourceColumn) + { + super(organizationType, user); + + this.resourceColumn = resourceColumn; + } + + @Override + public String getFilterQuery() + { + switch (user.getRole()) + { + case LOCAL: // parameterIndex 1 and 2 + return "(" + resourceColumn + "->'meta'->'tag' @> ?::jsonb OR " + resourceColumn + + "->'meta'->'tag' @> ?::jsonb)"; + + case REMOTE: // parameterIndex 1 + return resourceColumn + "->'meta'->'tag' @> ?::jsonb"; + + default: + throw new IllegalStateException( + "Value " + user.getRole() + " of " + UserRole.class.getName() + " not implemented"); + } + } + + @Override + public int getSqlParameterCount() + { + switch (user.getRole()) + { + case LOCAL: + return 2; + + case REMOTE: + return 1; + + default: + throw new IllegalStateException( + "Value " + user.getRole() + " of " + UserRole.class.getName() + " not implemented"); + } + } + + @Override + public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException + { + if (parameterIndex == 1) + statement.setString(parameterIndex, "[{\"code\": \"" + AUTHORIZATION_ROLE_VALUE_REMOTE + + "\", \"system\": \"" + AUTHORIZATION_ROLE_SYSTEM + "\"}]"); + else if (parameterIndex == 2) + statement.setString(parameterIndex, "[{\"code\": \"" + AUTHORIZATION_ROLE_VALUE_LOCAL + "\", \"system\": \"" + + AUTHORIZATION_ROLE_SYSTEM + "\"}]"); + else + throw new IllegalStateException("Unexpected paramterIndex " + parameterIndex); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/AbstractUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/AbstractUserFilter.java new file mode 100644 index 000000000..584569d9d --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/AbstractUserFilter.java @@ -0,0 +1,17 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.search.SearchQueryUserFilter; + +abstract class AbstractUserFilter implements SearchQueryUserFilter +{ + protected final OrganizationType organizationType; + protected final User user; + + public AbstractUserFilter(OrganizationType organizationType, User user) + { + this.organizationType = organizationType; + this.user = user; + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ActivityDefinitionUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ActivityDefinitionUserFilter.java new file mode 100644 index 000000000..49331c364 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ActivityDefinitionUserFilter.java @@ -0,0 +1,43 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ActivityDefinitionUserFilter extends AbstractUserFilter +{ + private static final Logger logger = LoggerFactory.getLogger(ActivityDefinitionUserFilter.class); + + public ActivityDefinitionUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user); + } + + @Override + public String getFilterQuery() + { + // TODO implement + + logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); + return "false"; + } + + @Override + public int getSqlParameterCount() + { + logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); + return 0; + } + + @Override + public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException + { + // TODO implement + + logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java new file mode 100644 index 000000000..07f5b5452 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java @@ -0,0 +1,43 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BinaryUserFilter extends AbstractUserFilter +{ + private static final Logger logger = LoggerFactory.getLogger(BinaryUserFilter.class); + + public BinaryUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user); + } + + @Override + public String getFilterQuery() + { + // TODO implement + + logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); + return "false"; + } + + @Override + public int getSqlParameterCount() + { + logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); + return 0; + } + + @Override + public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException + { + // TODO implement + + logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BundleUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BundleUserFilter.java new file mode 100644 index 000000000..39072911d --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BundleUserFilter.java @@ -0,0 +1,12 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; + +public class BundleUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter +{ + public BundleUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user, "bundle"); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/CodeSystemUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/CodeSystemUserFilter.java new file mode 100644 index 000000000..d180af084 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/CodeSystemUserFilter.java @@ -0,0 +1,12 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; + +public class CodeSystemUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter +{ + public CodeSystemUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user, "code_system"); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/EndpointUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/EndpointUserFilter.java new file mode 100644 index 000000000..684511f34 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/EndpointUserFilter.java @@ -0,0 +1,12 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; + +public class EndpointUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter +{ + public EndpointUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user, "endpoint"); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/GroupUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/GroupUserFilter.java new file mode 100644 index 000000000..89db54cb3 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/GroupUserFilter.java @@ -0,0 +1,43 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GroupUserFilter extends AbstractUserFilter +{ + private static final Logger logger = LoggerFactory.getLogger(GroupUserFilter.class); + + public GroupUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user); + } + + @Override + public String getFilterQuery() + { + // TODO implement + + logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); + return "false"; + } + + @Override + public int getSqlParameterCount() + { + logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); + return 0; + } + + @Override + public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException + { + // TODO implement + + logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/HealthcareServiceUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/HealthcareServiceUserFilter.java new file mode 100644 index 000000000..134691973 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/HealthcareServiceUserFilter.java @@ -0,0 +1,12 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; + +public class HealthcareServiceUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter +{ + public HealthcareServiceUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user, "healthcare_service"); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/LocationUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/LocationUserFilter.java new file mode 100644 index 000000000..15663912a --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/LocationUserFilter.java @@ -0,0 +1,12 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; + +public class LocationUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter +{ + public LocationUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user, "location"); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/NamingSystemUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/NamingSystemUserFilter.java new file mode 100644 index 000000000..6834d8f68 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/NamingSystemUserFilter.java @@ -0,0 +1,12 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; + +public class NamingSystemUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter +{ + public NamingSystemUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user, "naming_system"); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/OrganizationUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/OrganizationUserFilter.java new file mode 100644 index 000000000..52e4da8a7 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/OrganizationUserFilter.java @@ -0,0 +1,12 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; + +public class OrganizationUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter +{ + public OrganizationUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user, "organization"); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PatientUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PatientUserFilter.java new file mode 100644 index 000000000..8bdb19bc8 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PatientUserFilter.java @@ -0,0 +1,43 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PatientUserFilter extends AbstractUserFilter +{ + private static final Logger logger = LoggerFactory.getLogger(PatientUserFilter.class); + + public PatientUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user); + } + + @Override + public String getFilterQuery() + { + // TODO implement + + logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); + return "false"; + } + + @Override + public int getSqlParameterCount() + { + logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); + return 0; + } + + @Override + public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException + { + // TODO implement + + logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerRoleUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerRoleUserFilter.java new file mode 100644 index 000000000..0e9759312 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerRoleUserFilter.java @@ -0,0 +1,43 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PractitionerRoleUserFilter extends AbstractUserFilter +{ + private static final Logger logger = LoggerFactory.getLogger(PractitionerRoleUserFilter.class); + + public PractitionerRoleUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user); + } + + @Override + public String getFilterQuery() + { + // TODO implement + + logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); + return "false"; + } + + @Override + public int getSqlParameterCount() + { + logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); + return 0; + } + + @Override + public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException + { + // TODO implement + + logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerUserFilter.java new file mode 100644 index 000000000..1cad112ac --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerUserFilter.java @@ -0,0 +1,43 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PractitionerUserFilter extends AbstractUserFilter +{ + private static final Logger logger = LoggerFactory.getLogger(PractitionerUserFilter.class); + + public PractitionerUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user); + } + + @Override + public String getFilterQuery() + { + // TODO implement + + logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); + return "false"; + } + + @Override + public int getSqlParameterCount() + { + logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); + return 0; + } + + @Override + public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException + { + // TODO implement + + logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ProvenanceUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ProvenanceUserFilter.java new file mode 100644 index 000000000..eaaf651b2 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ProvenanceUserFilter.java @@ -0,0 +1,43 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ProvenanceUserFilter extends AbstractUserFilter +{ + private static final Logger logger = LoggerFactory.getLogger(ProvenanceUserFilter.class); + + public ProvenanceUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user); + } + + @Override + public String getFilterQuery() + { + // TODO implement + + logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); + return "false"; + } + + @Override + public int getSqlParameterCount() + { + logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); + return 0; + } + + @Override + public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException + { + // TODO implement + + logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ResearchStudyUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ResearchStudyUserFilter.java new file mode 100644 index 000000000..5ebf86fe9 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ResearchStudyUserFilter.java @@ -0,0 +1,43 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ResearchStudyUserFilter extends AbstractUserFilter +{ + private static final Logger logger = LoggerFactory.getLogger(ResearchStudyUserFilter.class); + + public ResearchStudyUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user); + } + + @Override + public String getFilterQuery() + { + // TODO implement + + logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); + return "false"; + } + + @Override + public int getSqlParameterCount() + { + logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); + return 0; + } + + @Override + public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException + { + // TODO implement + + logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/StructureDefinitionSnapshotUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/StructureDefinitionSnapshotUserFilter.java new file mode 100644 index 000000000..a86e13394 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/StructureDefinitionSnapshotUserFilter.java @@ -0,0 +1,12 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; + +public class StructureDefinitionSnapshotUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter +{ + public StructureDefinitionSnapshotUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user, "structure_definition_snapshot"); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/StructureDefinitionUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/StructureDefinitionUserFilter.java new file mode 100644 index 000000000..3dc131a9d --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/StructureDefinitionUserFilter.java @@ -0,0 +1,12 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; + +public class StructureDefinitionUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter +{ + public StructureDefinitionUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user, "structure_definition"); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/SubscriptionUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/SubscriptionUserFilter.java new file mode 100644 index 000000000..48905012d --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/SubscriptionUserFilter.java @@ -0,0 +1,12 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; + +public class SubscriptionUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter +{ + public SubscriptionUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user, "subscription"); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/TaskUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/TaskUserFilter.java new file mode 100644 index 000000000..51217a853 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/TaskUserFilter.java @@ -0,0 +1,43 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TaskUserFilter extends AbstractUserFilter +{ + private static final Logger logger = LoggerFactory.getLogger(TaskUserFilter.class); + + public TaskUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user); + } + + @Override + public String getFilterQuery() + { + // TODO implement + + logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); + return "false"; + } + + @Override + public int getSqlParameterCount() + { + logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); + return 0; + } + + @Override + public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException + { + // TODO implement + + logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ValueSetUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ValueSetUserFilter.java new file mode 100644 index 000000000..f87edfcc6 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ValueSetUserFilter.java @@ -0,0 +1,12 @@ +package org.highmed.dsf.fhir.search.parameters.user; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.User; + +public class ValueSetUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter +{ + public ValueSetUserFilter(OrganizationType organizationType, User user) + { + super(organizationType, user, "value_set"); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/DefaultProfileValidationSupportWithFetchFromDb.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/DefaultProfileValidationSupportWithFetchFromDb.java index 7e37302a8..fb3aecce3 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/DefaultProfileValidationSupportWithFetchFromDb.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/DefaultProfileValidationSupportWithFetchFromDb.java @@ -67,11 +67,11 @@ public List fetchAllStructureDefinitions(FhirContext contex public StructureDefinition fetchStructureDefinition(FhirContext context, String url) { Optional structureDefinition = null; - structureDefinition = throwRuntimeException(() -> structureDefinitionSnapshotDao.readByUrl(url)); + structureDefinition = throwRuntimeException(() -> structureDefinitionSnapshotDao.readByUrlAndVersion(url)); if (structureDefinition.isPresent()) return structureDefinition.get(); - structureDefinition = throwRuntimeException(() -> structureDefinitionDao.readByUrl(url)); + structureDefinition = throwRuntimeException(() -> structureDefinitionDao.readByUrlAndVersion(url)); if (structureDefinition.isPresent()) return structureDefinition.get(); @@ -94,7 +94,7 @@ private R throwRuntimeException(SupplierWithSqlException reader) @Override public CodeSystem fetchCodeSystem(FhirContext context, String url) { - Optional codeSystem = throwRuntimeException(() -> codeSystemDao.readByUrl(url)); + Optional codeSystem = throwRuntimeException(() -> codeSystemDao.readByUrlAndVersion(url)); if (codeSystem.isPresent()) return codeSystem.get(); @@ -104,7 +104,7 @@ public CodeSystem fetchCodeSystem(FhirContext context, String url) @Override public ValueSet fetchValueSet(FhirContext context, String url) { - Optional valueSet = throwRuntimeException(() -> valueSetDao.readByUrl(url)); + Optional valueSet = throwRuntimeException(() -> valueSetDao.readByUrlAndVersion(url)); if (valueSet.isPresent()) return valueSet.get(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/InitialDataLoaderImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/InitialDataLoaderImpl.java index a2fd67776..40c127294 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/InitialDataLoaderImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/InitialDataLoaderImpl.java @@ -2,10 +2,13 @@ import java.util.Objects; +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.authentication.UserRole; import org.highmed.dsf.fhir.dao.command.CommandFactory; import org.highmed.dsf.fhir.dao.command.CommandList; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; +import org.hl7.fhir.r4.model.Organization; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; @@ -41,7 +44,8 @@ public void load(Bundle bundle) return; } - CommandList commands = commandFactory.createCommands(bundle); + CommandList commands = commandFactory.createCommands(bundle, + new User(new Organization().setName("Initial Data Loader"), UserRole.LOCAL)); logger.debug("Executing command list for bundle with {} entries", bundle.getEntry().size()); Bundle result = commands.execute(); result.getEntry().forEach(this::logResult); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolver.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolver.java index 0593fd4aa..165828577 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolver.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolver.java @@ -6,12 +6,15 @@ import javax.ws.rs.WebApplicationException; +import org.highmed.dsf.fhir.authentication.User; import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.Resource; public interface ReferenceResolver { /** + * @param user + * not null * @param referenceLocation * @param reference * not null @@ -23,10 +26,12 @@ public interface ReferenceResolver * {@link ResourceReference.ReferenceType#CONDITIONAL} or * {@link ResourceReference.ReferenceType#LOGICAL} */ - Optional resolveReference(String referenceLocation, Reference reference, + Optional resolveReference(User user, String referenceLocation, Reference reference, List> referenceTypes); /** + * @param user + * not null * @param reference * not null * @return {@link Optional#empty()} if the reference could not be resolved @@ -36,9 +41,11 @@ Optional resolveReference(String referenceLocation, Reference referenc * {@link ResourceReference.ReferenceType#CONDITIONAL} or * {@link ResourceReference.ReferenceType#LOGICAL} */ - Optional resolveReference(ResourceReference reference); + Optional resolveReference(User user, ResourceReference reference); /** + * @param user + * not null * @param resource * not null * @param resourceReference @@ -56,9 +63,11 @@ Optional resolveReference(String referenceLocation, Reference referenc * {@link ResourceReference.ReferenceType#LOGICAL} * @see ResourceReference#getType(String) */ - boolean resolveReference(Resource resource, ResourceReference resourceReference, Connection connection); + boolean resolveReference(User user, Resource resource, ResourceReference resourceReference, Connection connection); /** + * @param user + * not null * @param resource * not null * @param bundleIndex @@ -78,7 +87,7 @@ Optional resolveReference(String referenceLocation, Reference referenc * {@link ResourceReference.ReferenceType#LOGICAL} * @see ResourceReference#getType(String) */ - boolean resolveReference(Resource resource, Integer bundleIndex, ResourceReference resourceReference, + boolean resolveReference(User user, Resource resource, Integer bundleIndex, ResourceReference resourceReference, Connection connection) throws WebApplicationException, IllegalArgumentException; /** @@ -157,6 +166,8 @@ boolean resolveLiteralExternalReference(Resource resource, Integer bundleIndex, throws WebApplicationException, IllegalArgumentException; /** + * @param user + * not null * @param resource * not null * @param resourceReference @@ -171,10 +182,12 @@ boolean resolveLiteralExternalReference(Resource resource, Integer bundleIndex, * if the reference is not of type {@link ResourceReference.ReferenceType#CONDITIONAL} * @see ResourceReference#getType(String) */ - boolean resolveConditionalReference(Resource resource, ResourceReference resourceReference, Connection connection) - throws WebApplicationException, IllegalArgumentException; + boolean resolveConditionalReference(User user, Resource resource, ResourceReference resourceReference, + Connection connection) throws WebApplicationException, IllegalArgumentException; /** + * @param user + * not null * @param resource * not null * @param bundleIndex @@ -191,10 +204,13 @@ boolean resolveConditionalReference(Resource resource, ResourceReference resourc * if the reference is not of type {@link ResourceReference.ReferenceType#CONDITIONAL} * @see ResourceReference#getType(String) */ - boolean resolveConditionalReference(Resource resource, Integer bundleIndex, ResourceReference resourceReference, - Connection connection) throws WebApplicationException, IllegalArgumentException; + boolean resolveConditionalReference(User user, Resource resource, Integer bundleIndex, + ResourceReference resourceReference, Connection connection) + throws WebApplicationException, IllegalArgumentException; /** + * @param user + * not null * @param resource * not null * @param resourceReference @@ -209,10 +225,12 @@ boolean resolveConditionalReference(Resource resource, Integer bundleIndex, Reso * if the reference is not of type {@link ResourceReference.ReferenceType#LOGICAL} * @see ResourceReference#getType(String) */ - boolean resolveLogicalReference(Resource resource, ResourceReference resourceReference, Connection connection) - throws WebApplicationException, IllegalArgumentException; + boolean resolveLogicalReference(User user, Resource resource, ResourceReference resourceReference, + Connection connection) throws WebApplicationException, IllegalArgumentException; /** + * @param user + * not null * @param resource * not null * @param bundleIndex @@ -229,6 +247,7 @@ boolean resolveLogicalReference(Resource resource, ResourceReference resourceRef * if the reference is not of type {@link ResourceReference.ReferenceType#LOGICAL} * @see ResourceReference#getType(String) */ - boolean resolveLogicalReference(Resource resource, Integer bundleIndex, ResourceReference resourceReference, - Connection connection) throws WebApplicationException, IllegalArgumentException; + boolean resolveLogicalReference(User user, Resource resource, Integer bundleIndex, + ResourceReference resourceReference, Connection connection) + throws WebApplicationException, IllegalArgumentException; } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolverImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolverImpl.java index 1dc016f87..5543a3e95 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolverImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolverImpl.java @@ -13,6 +13,7 @@ import javax.ws.rs.WebApplicationException; +import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.client.ClientProvider; import org.highmed.dsf.fhir.dao.ResourceDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; @@ -69,17 +70,21 @@ public void afterPropertiesSet() throws Exception } @Override - public Optional resolveReference(String referenceLocation, Reference reference, + public Optional resolveReference(User user, String referenceLocation, Reference reference, List> referenceTypes) { + Objects.requireNonNull(user, "user"); Objects.requireNonNull(reference, "reference"); - return resolveReference(new ResourceReference(referenceLocation, reference, referenceTypes)); + + return resolveReference(user, new ResourceReference(referenceLocation, reference, referenceTypes)); } @Override - public Optional resolveReference(ResourceReference reference) + public Optional resolveReference(User user, ResourceReference reference) { + Objects.requireNonNull(user, "user"); Objects.requireNonNull(reference, "reference"); + switch (reference.getType(serverBase)) { case LITERAL_INTERNAL: @@ -87,9 +92,9 @@ public Optional resolveReference(ResourceReference reference) case LITERAL_EXTERNAL: return resolveLiteralExternalReference(reference); case CONDITIONAL: - return resolveConditionalReference(reference); + return resolveConditionalReference(user, reference); case LOGICAL: - return resolveLogicalReference(reference); + return resolveLogicalReference(user, reference); default: throw new IllegalArgumentException( "Reference of type " + reference.getType(serverBase) + " not supported"); @@ -97,15 +102,16 @@ public Optional resolveReference(ResourceReference reference) } @Override - public boolean resolveReference(Resource resource, ResourceReference resourceReference, Connection connection) + public boolean resolveReference(User user, Resource resource, ResourceReference resourceReference, Connection connection) { - return resolveReference(resource, null, resourceReference, connection); + return resolveReference(user, resource, null, resourceReference, connection); } @Override - public boolean resolveReference(Resource resource, Integer bundleIndex, ResourceReference resourceReference, - Connection connection) + public boolean resolveReference(User user, Resource resource, Integer bundleIndex, + ResourceReference resourceReference, Connection connection) { + Objects.requireNonNull(user, "user"); Objects.requireNonNull(resource, "resource"); Objects.requireNonNull(resourceReference, "resourceReference"); Objects.requireNonNull(connection, "connection"); @@ -117,9 +123,9 @@ public boolean resolveReference(Resource resource, Integer bundleIndex, Resource case LITERAL_EXTERNAL: return resolveLiteralExternalReference(resource, bundleIndex, resourceReference); case CONDITIONAL: - return resolveConditionalReference(resource, bundleIndex, resourceReference, connection); + return resolveConditionalReference(user, resource, bundleIndex, resourceReference, connection); case LOGICAL: - return resolveLogicalReference(resource, bundleIndex, resourceReference, connection); + return resolveLogicalReference(user, resource, bundleIndex, resourceReference, connection); default: throw new IllegalArgumentException( "Reference of type " + resourceReference.getType(serverBase) + " not supported"); @@ -279,7 +285,7 @@ public boolean resolveLiteralExternalReference(Resource resource, Integer bundle return true; // throws exception if reference could not be resolved } - private Optional resolveConditionalReference(ResourceReference resourceReference) + private Optional resolveConditionalReference(User user, ResourceReference resourceReference) { Objects.requireNonNull(resourceReference, "resourceReference"); if (!ReferenceType.CONDITIONAL.equals(resourceReference.getType(serverBase))) @@ -313,22 +319,23 @@ private Optional resolveConditionalReference(ResourceReference resourc return Optional.empty(); } - return search(d, resourceReference, condition.getQueryParams(), true); + return search(user, d, resourceReference, condition.getQueryParams(), true); } } @Override - public boolean resolveConditionalReference(Resource resource, ResourceReference resourceReference, + public boolean resolveConditionalReference(User user, Resource resource, ResourceReference resourceReference, Connection connection) throws WebApplicationException, IllegalArgumentException { - return resolveConditionalReference(resource, null, resourceReference, connection); + return resolveConditionalReference(user, resource, null, resourceReference, connection); } @Override - public boolean resolveConditionalReference(Resource resource, Integer bundleIndex, + public boolean resolveConditionalReference(User user, Resource resource, Integer bundleIndex, ResourceReference resourceReference, Connection connection) throws WebApplicationException, IllegalArgumentException { + Objects.requireNonNull(user, "user"); Objects.requireNonNull(resource, "resource"); Objects.requireNonNull(resourceReference, "resourceReference"); Objects.requireNonNull(connection, "connection"); @@ -354,7 +361,7 @@ public boolean resolveConditionalReference(Resource resource, Integer bundleInde throw new WebApplicationException(responseGenerator .referenceTargetTypeNotSupportedByResource(bundleIndex, resource, resourceReference)); - Resource target = search(resource, bundleIndex, connection, d, resourceReference, + Resource target = search(user, resource, bundleIndex, connection, d, resourceReference, condition.getQueryParams(), true); resourceReference.getReference().setIdentifier(null).setReferenceElement( @@ -364,7 +371,7 @@ public boolean resolveConditionalReference(Resource resource, Integer bundleInde return true; // throws exception if reference could not be resolved } - private Optional resolveLogicalReference(ResourceReference resourceReference) + private Optional resolveLogicalReference(User user, ResourceReference resourceReference) { Objects.requireNonNull(resourceReference, "resourceReference"); if (!ReferenceType.LOGICAL.equals(resourceReference.getType(serverBase))) @@ -391,22 +398,24 @@ private Optional resolveLogicalReference(ResourceReference resourceRef } Identifier targetIdentifier = resourceReference.getReference().getIdentifier(); - return search(d, resourceReference, Map.of("identifier", + return search(user, d, resourceReference, Map.of("identifier", Collections.singletonList(targetIdentifier.getSystem() + "|" + targetIdentifier.getValue())), true); } } @Override - public boolean resolveLogicalReference(Resource resource, ResourceReference resourceReference, + public boolean resolveLogicalReference(User user, Resource resource, ResourceReference resourceReference, Connection connection) throws WebApplicationException, IllegalArgumentException { - return resolveLogicalReference(resource, null, resourceReference, connection); + return resolveLogicalReference(user, resource, null, resourceReference, connection); } @Override - public boolean resolveLogicalReference(Resource resource, Integer bundleIndex, ResourceReference resourceReference, - Connection connection) throws WebApplicationException, IllegalArgumentException + public boolean resolveLogicalReference(User user, Resource resource, Integer bundleIndex, + ResourceReference resourceReference, Connection connection) + throws WebApplicationException, IllegalArgumentException { + Objects.requireNonNull(user, "user"); Objects.requireNonNull(resource, "resource"); Objects.requireNonNull(resourceReference, "resourceReference"); Objects.requireNonNull(connection, "connection"); @@ -428,7 +437,7 @@ public boolean resolveLogicalReference(Resource resource, Integer bundleIndex, R .referenceTargetTypeNotSupportedByResource(bundleIndex, resource, resourceReference)); Identifier targetIdentifier = resourceReference.getReference().getIdentifier(); - Resource target = search(resource, bundleIndex, connection, d, resourceReference, Map.of("identifier", + Resource target = search(user, resource, bundleIndex, connection, d, resourceReference, Map.of("identifier", Collections.singletonList(targetIdentifier.getSystem() + "|" + targetIdentifier.getValue())), true); resourceReference.getReference().setIdentifier(null).setReferenceElement( @@ -438,7 +447,7 @@ public boolean resolveLogicalReference(Resource resource, Integer bundleIndex, R return true; // throws exception if reference could not be resolved } - private Optional search(ResourceDao referenceTargetDao, ResourceReference resourceReference, + private Optional search(User user, ResourceDao referenceTargetDao, ResourceReference resourceReference, Map> queryParameters, boolean logicalNotConditional) { if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) @@ -454,7 +463,7 @@ private Optional search(ResourceDao referenceTargetDao, ResourceRef .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); } - SearchQuery query = referenceTargetDao.createSearchQuery(1, 1); + SearchQuery query = referenceTargetDao.createSearchQuery(user, 1, 1); query.configureParameters(queryParameters); List unsupportedQueryParameters = query @@ -510,7 +519,7 @@ else if (result.getOverallCount() == 1) } } - private Resource search(Resource resource, Integer bundleIndex, Connection connection, + private Resource search(User user, Resource resource, Integer bundleIndex, Connection connection, ResourceDao referenceTargetDao, ResourceReference resourceReference, Map> queryParameters, boolean logicalNotConditional) { @@ -527,7 +536,7 @@ private Resource search(Resource resource, Integer bundleIndex, Connection conne .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); } - SearchQuery query = referenceTargetDao.createSearchQuery(1, 1); + SearchQuery query = referenceTargetDao.createSearchQuery(user, 1, 1); query.configureParameters(queryParameters); List unsupportedQueryParameters = query diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthorizationConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthorizationConfig.java new file mode 100644 index 000000000..56bc4fe85 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthorizationConfig.java @@ -0,0 +1,145 @@ +package org.highmed.dsf.fhir.spring.config; + +import org.highmed.dsf.fhir.authorization.ActivityDefinitionAuthorizationRule; +import org.highmed.dsf.fhir.authorization.BinaryAuthorizationRule; +import org.highmed.dsf.fhir.authorization.BundleAuthorizationRule; +import org.highmed.dsf.fhir.authorization.CodeSystemAuthorizationRule; +import org.highmed.dsf.fhir.authorization.EndpointAuthorizationRule; +import org.highmed.dsf.fhir.authorization.GroupAuthorizationRule; +import org.highmed.dsf.fhir.authorization.HealthcareServiceAuthorizationRule; +import org.highmed.dsf.fhir.authorization.LocationAuthorizationRule; +import org.highmed.dsf.fhir.authorization.NamingSystemAuthorizationRule; +import org.highmed.dsf.fhir.authorization.OrganizationAuthorizationRule; +import org.highmed.dsf.fhir.authorization.PatientAuthorizationRule; +import org.highmed.dsf.fhir.authorization.PractitionerAuthorizationRule; +import org.highmed.dsf.fhir.authorization.PractitionerRoleAuthorizationRule; +import org.highmed.dsf.fhir.authorization.ProvenanceAuthorizationRule; +import org.highmed.dsf.fhir.authorization.ResearchStudyAuthorizationRule; +import org.highmed.dsf.fhir.authorization.StructureDefinitionAuthorizationRule; +import org.highmed.dsf.fhir.authorization.SubscriptionAuthorizationRule; +import org.highmed.dsf.fhir.authorization.TaskAuthorizationRule; +import org.highmed.dsf.fhir.authorization.ValueSetAuthorizationRule; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AuthorizationConfig +{ + @Autowired + private DaoConfig daoConfig; + + @Bean + public ActivityDefinitionAuthorizationRule activityDefinitionAuthorizationRule() + { + return new ActivityDefinitionAuthorizationRule(daoConfig.activityDefinitionDao()); + } + + @Bean + public BinaryAuthorizationRule binaryAuthorizationRule() + { + return new BinaryAuthorizationRule(daoConfig.binaryDao()); + } + + @Bean + public BundleAuthorizationRule bundleAuthorizationRule() + { + return new BundleAuthorizationRule(daoConfig.bundleDao()); + } + + @Bean + public CodeSystemAuthorizationRule codeSystemAuthorizationRule() + { + return new CodeSystemAuthorizationRule(daoConfig.codeSystemDao()); + } + + @Bean + public EndpointAuthorizationRule endpointAuthorizationRule() + { + return new EndpointAuthorizationRule(daoConfig.endpointDao()); + } + + @Bean + public GroupAuthorizationRule groupAuthorizationRule() + { + return new GroupAuthorizationRule(daoConfig.groupDao()); + } + + @Bean + public HealthcareServiceAuthorizationRule healthcareServiceAuthorizationRule() + { + return new HealthcareServiceAuthorizationRule(daoConfig.healthcareServiceDao()); + } + + @Bean + public LocationAuthorizationRule locationAuthorizationRule() + { + return new LocationAuthorizationRule(daoConfig.locationDao()); + } + + @Bean + public NamingSystemAuthorizationRule namingSystemAuthorizationRule() + { + return new NamingSystemAuthorizationRule(daoConfig.namingSystemDao()); + } + + @Bean + public OrganizationAuthorizationRule organizationAuthorizationRule() + { + return new OrganizationAuthorizationRule(daoConfig.organizationDao()); + } + + @Bean + public PatientAuthorizationRule patientAuthorizationRule() + { + return new PatientAuthorizationRule(daoConfig.patientDao()); + } + + @Bean + public PractitionerAuthorizationRule practitionerAuthorizationRule() + { + return new PractitionerAuthorizationRule(daoConfig.practitionerDao()); + } + + @Bean + public PractitionerRoleAuthorizationRule practitionerRoleAuthorizationRule() + { + return new PractitionerRoleAuthorizationRule(daoConfig.practitionerRoleDao()); + } + + @Bean + public ProvenanceAuthorizationRule provenanceAuthorizationRule() + { + return new ProvenanceAuthorizationRule(daoConfig.provenanceDao()); + } + + @Bean + public ResearchStudyAuthorizationRule researchStudyAuthorizationRule() + { + return new ResearchStudyAuthorizationRule(daoConfig.researchStudyDao()); + } + + @Bean + public StructureDefinitionAuthorizationRule structureDefinitionAuthorizationRule() + { + return new StructureDefinitionAuthorizationRule(daoConfig.structureDefinitionDao()); + } + + @Bean + public SubscriptionAuthorizationRule subscriptionAuthorizationRule() + { + return new SubscriptionAuthorizationRule(daoConfig.subscriptionDao()); + } + + @Bean + public TaskAuthorizationRule taskAuthorizationRule() + { + return new TaskAuthorizationRule(daoConfig.taskDao()); + } + + @Bean + public ValueSetAuthorizationRule valueSetAuthorizationRule() + { + return new ValueSetAuthorizationRule(daoConfig.valueSetDao()); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java index 94abeb029..db8648d45 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java @@ -1,6 +1,7 @@ package org.highmed.dsf.fhir.spring.config; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; import org.highmed.dsf.fhir.dao.BinaryDao; import org.highmed.dsf.fhir.dao.BundleDao; @@ -62,6 +63,9 @@ public class DaoConfig @Value("${org.highmed.dsf.fhir.db.server_user_password}") private String dbPassword; + @Value("${org.highmed.dsf.fhir.organizationType}") + private String organizationType; + @Autowired private FhirConfig fhirConfig; @@ -83,100 +87,106 @@ public BasicDataSource dataSource() return dataSource; } + @Bean + public OrganizationType organizationType() + { + return OrganizationType.valueOf(organizationType); + } + @Bean public ActivityDefinitionDao activityDefinitionDao() { - return new ActivityDefinitionDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new ActivityDefinitionDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public BinaryDao binaryDao() { - return new BinaryDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new BinaryDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public BundleDao bundleDao() { - return new BundleDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new BundleDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public CodeSystemDao codeSystemDao() { - return new CodeSystemDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new CodeSystemDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public EndpointDao endpointDao() { - return new EndpointDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new EndpointDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public GroupDao groupDao() { - return new GroupDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new GroupDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public HealthcareServiceDao healthcareServiceDao() { - return new HealthcareServiceDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new HealthcareServiceDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public LocationDao locationDao() { - return new LocationDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new LocationDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public NamingSystemDao namingSystemDao() { - return new NamingSystemDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new NamingSystemDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public OrganizationDao organizationDao() { - return new OrganizationDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new OrganizationDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public PatientDao patientDao() { - return new PatientDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new PatientDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public PractitionerDao practitionerDao() { - return new PractitionerDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new PractitionerDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public PractitionerRoleDao practitionerRoleDao() { - return new PractitionerRoleDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new PractitionerRoleDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public ProvenanceDao provenanceDao() { - return new ProvenanceDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new ProvenanceDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public ResearchStudyDao researchStudyDao() { - return new ResearchStudyDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new ResearchStudyDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public StructureDefinitionDao structureDefinitionDao() { - return new StructureDefinitionDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new StructureDefinitionDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean @@ -188,25 +198,26 @@ public SnapshotInfoConverter snapshotInfoConverter() @Bean public StructureDefinitionSnapshotDao structureDefinitionSnapshotDao() { - return new StructureDefinitionSnapshotDaoJdbc(dataSource(), fhirConfig.fhirContext(), snapshotInfoConverter()); + return new StructureDefinitionSnapshotDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType(), + snapshotInfoConverter()); } @Bean public SubscriptionDao subscriptionDao() { - return new SubscriptionDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new SubscriptionDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public TaskDao taskDao() { - return new TaskDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new TaskDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean public ValueSetDao valueSetDao() { - return new ValueSetDaoJdbc(dataSource(), fhirConfig.fhirContext()); + return new ValueSetDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); } @Bean diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java index 86aa1251a..5bcdf52ce 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java @@ -124,6 +124,9 @@ public class WebserviceConfig @Autowired private BuildInfoReaderConfig buildInfoReaderConfig; + @Autowired + private AuthorizationConfig authorizationConfig; + @Bean public ServerBaseProvider serverBaseProvider() { @@ -140,7 +143,8 @@ private ActivityDefinitionServiceSecure activityDefinitionServiceSecure() { return new ActivityDefinitionServiceSecure(activityDefinitionServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.activityDefinitionDao(), - helperConfig.exceptionHandler(), helperConfig.parameterConverter()); + helperConfig.exceptionHandler(), helperConfig.parameterConverter(), + authorizationConfig.activityDefinitionAuthorizationRule()); } private ActivityDefinitionServiceImpl activityDefinitionServiceImpl() @@ -162,7 +166,7 @@ private CodeSystemServiceSecure codeSystemServiceSecure() { return new CodeSystemServiceSecure(codeSystemServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.codeSystemDao(), helperConfig.exceptionHandler(), - helperConfig.parameterConverter()); + helperConfig.parameterConverter(), authorizationConfig.codeSystemAuthorizationRule()); } private CodeSystemServiceImpl codeSystemServiceImpl() @@ -184,7 +188,7 @@ private BinaryServiceSecure binaryServiceSecure() { return new BinaryServiceSecure(binaryServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.binaryDao(), helperConfig.exceptionHandler(), - helperConfig.parameterConverter()); + helperConfig.parameterConverter(), authorizationConfig.binaryAuthorizationRule()); } private BinaryService binaryServiceImpl() @@ -205,7 +209,7 @@ private BundleServiceSecure bundleServiceSecure() { return new BundleServiceSecure(bundleServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.bundleDao(), helperConfig.exceptionHandler(), - helperConfig.parameterConverter()); + helperConfig.parameterConverter(), authorizationConfig.bundleAuthorizationRule()); } private BundleService bundleServiceImpl() @@ -226,7 +230,7 @@ private EndpointServiceSecure endpointServiceSecure() { return new EndpointServiceSecure(endpointServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.endpointDao(), helperConfig.exceptionHandler(), - helperConfig.parameterConverter()); + helperConfig.parameterConverter(), authorizationConfig.endpointAuthorizationRule()); } private EndpointServiceImpl endpointServiceImpl() @@ -247,7 +251,7 @@ private GroupServiceSecure groupServiceSecure() { return new GroupServiceSecure(groupServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.groupDao(), helperConfig.exceptionHandler(), - helperConfig.parameterConverter()); + helperConfig.parameterConverter(), authorizationConfig.groupAuthorizationRule()); } private GroupServiceImpl groupServiceImpl() @@ -268,7 +272,8 @@ private HealthcareServiceServiceSecure healthcareServiceServiceSecure() { return new HealthcareServiceServiceSecure(healthcareServiceServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.healthcareServiceDao(), - helperConfig.exceptionHandler(), helperConfig.parameterConverter()); + helperConfig.exceptionHandler(), helperConfig.parameterConverter(), + authorizationConfig.healthcareServiceAuthorizationRule()); } private HealthcareServiceServiceImpl healthcareServiceServiceImpl() @@ -290,7 +295,7 @@ private LocationServiceSecure locationServiceSecure() { return new LocationServiceSecure(locationServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.locationDao(), helperConfig.exceptionHandler(), - helperConfig.parameterConverter()); + helperConfig.parameterConverter(), authorizationConfig.locationAuthorizationRule()); } private LocationServiceImpl locationServiceImpl() @@ -311,7 +316,7 @@ private NamingSystemServiceSecure namingSystemServiceSecure() { return new NamingSystemServiceSecure(namingSystemServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.namingSystemDao(), helperConfig.exceptionHandler(), - helperConfig.parameterConverter()); + helperConfig.parameterConverter(), authorizationConfig.namingSystemAuthorizationRule()); } private NamingSystemService namingSystemServiceImpl() @@ -333,7 +338,7 @@ private OrganizationServiceSecure organizationServiceSecure() { return new OrganizationServiceSecure(organizationServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.organizationDao(), helperConfig.exceptionHandler(), - helperConfig.parameterConverter()); + helperConfig.parameterConverter(), authorizationConfig.organizationAuthorizationRule()); } private OrganizationServiceImpl organizationServiceImpl() @@ -355,7 +360,7 @@ private PatientServiceSecure patientServiceSecure() { return new PatientServiceSecure(patientServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.patientDao(), helperConfig.exceptionHandler(), - helperConfig.parameterConverter()); + helperConfig.parameterConverter(), authorizationConfig.patientAuthorizationRule()); } private PatientServiceImpl patientServiceImpl() @@ -376,7 +381,8 @@ private PractitionerRoleServiceSecure practitionerRoleServiceSecure() { return new PractitionerRoleServiceSecure(practitionerRoleServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.practitionerRoleDao(), - helperConfig.exceptionHandler(), helperConfig.parameterConverter()); + helperConfig.exceptionHandler(), helperConfig.parameterConverter(), + authorizationConfig.practitionerRoleAuthorizationRule()); } private PractitionerRoleServiceImpl practitionerRoleServiceImpl() @@ -398,7 +404,7 @@ private PractitionerServiceSecure practitionerServiceSecure() { return new PractitionerServiceSecure(practitionerServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.practitionerDao(), helperConfig.exceptionHandler(), - helperConfig.parameterConverter()); + helperConfig.parameterConverter(), authorizationConfig.practitionerAuthorizationRule()); } private PractitionerServiceImpl practitionerServiceImpl() @@ -420,7 +426,7 @@ private ProvenanceServiceSecure provenanceServiceSecure() { return new ProvenanceServiceSecure(provenanceServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.provenanceDao(), helperConfig.exceptionHandler(), - helperConfig.parameterConverter()); + helperConfig.parameterConverter(), authorizationConfig.provenanceAuthorizationRule()); } private ProvenanceServiceImpl provenanceServiceImpl() @@ -442,7 +448,7 @@ private ResearchStudyServiceSecure researchStudyServiceSecure() { return new ResearchStudyServiceSecure(researchStudyServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.researchStudyDao(), helperConfig.exceptionHandler(), - helperConfig.parameterConverter()); + helperConfig.parameterConverter(), authorizationConfig.researchStudyAuthorizationRule()); } private ResearchStudyServiceImpl researchStudyServiceImpl() @@ -464,7 +470,8 @@ private StructureDefinitionServiceSecure structureDefinitionServiceSecure() { return new StructureDefinitionServiceSecure(structureDefinitionServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.structureDefinitionDao(), - helperConfig.exceptionHandler(), helperConfig.parameterConverter()); + helperConfig.exceptionHandler(), helperConfig.parameterConverter(), + authorizationConfig.structureDefinitionAuthorizationRule()); } private StructureDefinitionServiceImpl structureDefinitionServiceImpl() @@ -487,7 +494,7 @@ private SubscriptionServiceSecure subscriptionServiceSecure() { return new SubscriptionServiceSecure(subscriptionServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.subscriptionDao(), helperConfig.exceptionHandler(), - helperConfig.parameterConverter()); + helperConfig.parameterConverter(), authorizationConfig.subscriptionAuthorizationRule()); } private SubscriptionServiceImpl subscriptionServiceImpl() @@ -509,7 +516,7 @@ private TaskServiceSecure taskServiceSecure() { return new TaskServiceSecure(taskServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.taskDao(), helperConfig.exceptionHandler(), - helperConfig.parameterConverter(), daoConfig.activityDefinitionDao()); + helperConfig.parameterConverter(), authorizationConfig.taskAuthorizationRule()); } private TaskServiceImpl taskServiceImpl() @@ -530,7 +537,7 @@ private ValueSetServiceSecure valueSetServiceSecure() { return new ValueSetServiceSecure(valueSetServiceImpl(), serverBase, helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.valueSetDao(), helperConfig.exceptionHandler(), - helperConfig.parameterConverter()); + helperConfig.parameterConverter(), authorizationConfig.valueSetAuthorizationRule()); } private ValueSetServiceImpl valueSetServiceImpl() diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/base/AbstractBasicService.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/base/AbstractBasicService.java new file mode 100644 index 000000000..5f989aecb --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/base/AbstractBasicService.java @@ -0,0 +1,42 @@ +package org.highmed.dsf.fhir.webservice.base; + +import java.util.Objects; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.authentication.UserProvider; +import org.springframework.beans.factory.InitializingBean; + +public class AbstractBasicService implements BasicService, InitializingBean +{ + private final String path; + + protected UserProvider userProvider; + + public AbstractBasicService(String path) + { + this.path = path; + } + + @Override + public void afterPropertiesSet() throws Exception + { + Objects.requireNonNull(path, "path"); + } + + @Override + public final void setUserProvider(UserProvider userProvider) + { + this.userProvider = userProvider; + } + + @Override + public final String getPath() + { + return path; + } + + protected final User getCurrentUser() + { + return userProvider.getCurrentUser(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/base/AbstractDelegatingBasicService.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/base/AbstractDelegatingBasicService.java new file mode 100644 index 000000000..53c7e4789 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/base/AbstractDelegatingBasicService.java @@ -0,0 +1,44 @@ +package org.highmed.dsf.fhir.webservice.base; + +import java.util.Objects; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.authentication.UserProvider; +import org.springframework.beans.factory.InitializingBean; + +public class AbstractDelegatingBasicService implements BasicService, InitializingBean +{ + protected final S delegate; + + protected UserProvider userProvider; + + public AbstractDelegatingBasicService(S delegate) + { + this.delegate = delegate; + } + + @Override + public void afterPropertiesSet() throws Exception + { + Objects.requireNonNull(delegate, "delegate"); + } + + @Override + public final void setUserProvider(UserProvider userProvider) + { + delegate.setUserProvider(userProvider); + + this.userProvider = userProvider; + } + + @Override + public final String getPath() + { + return delegate.getPath(); + } + + protected final User getCurrentUser() + { + return userProvider.getCurrentUser(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/specification/BasicService.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/base/BasicService.java similarity index 80% rename from dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/specification/BasicService.java rename to dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/base/BasicService.java index ea6c1bde4..fbfa64a2c 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/specification/BasicService.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/base/BasicService.java @@ -1,4 +1,4 @@ -package org.highmed.dsf.fhir.webservice.specification; +package org.highmed.dsf.fhir.webservice.base; import org.highmed.dsf.fhir.authentication.NeedsAuthentication; import org.highmed.dsf.fhir.authentication.UserProvider; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java index 24bad652d..690541859 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java @@ -42,6 +42,7 @@ import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.service.ResourceReference; import org.highmed.dsf.fhir.service.ResourceValidator; +import org.highmed.dsf.fhir.webservice.base.AbstractBasicService; import org.highmed.dsf.fhir.webservice.specification.BasicResourceService; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.CanonicalType; @@ -71,7 +72,7 @@ import ca.uhn.fhir.validation.ValidationResult; public abstract class AbstractResourceServiceImpl, R extends Resource> - extends AbstractServiceImpl implements BasicResourceService, InitializingBean + extends AbstractBasicService implements BasicResourceService, InitializingBean { private static final Logger logger = LoggerFactory.getLogger(AbstractResourceServiceImpl.class); @@ -89,11 +90,10 @@ public abstract class AbstractResourceServiceImpl, R ex protected final ReferenceExtractor referenceExtractor; protected final ReferenceResolver referenceResolver; - public AbstractResourceServiceImpl(String path, Class resourceType, String serverBase, - int defaultPageCount, D dao, ResourceValidator validator, EventManager eventManager, - ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, - ParameterConverter parameterConverter, ReferenceExtractor referenceExtractor, - ReferenceResolver referenceResolver) + public AbstractResourceServiceImpl(String path, Class resourceType, String serverBase, int defaultPageCount, + D dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, + EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) { super(path); @@ -210,7 +210,8 @@ private boolean resolveReference(Resource resource, Connection connection, Resou case LITERAL_EXTERNAL: return referenceResolver.resolveLiteralExternalReference(resource, resourceReference); case LOGICAL: - return referenceResolver.resolveLogicalReference(resource, resourceReference, connection); + return referenceResolver.resolveLogicalReference(getCurrentUser(), resource, resourceReference, + connection); default: throw new WebApplicationException(responseGenerator.unknownReference(resource, resourceReference)); } @@ -250,7 +251,7 @@ private void checkAlreadyExists(HttpHeaders headers) throws WebApplicationExcept .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); } - SearchQuery query = dao.createSearchQuery(1, 1); + SearchQuery query = dao.createSearchQuery(getCurrentUser(), 1, 1); query.configureParameters(queryParameters); List unsupportedQueryParameters = query @@ -430,78 +431,80 @@ protected Consumer preUpdate(R resource) public Response update(R resource, UriInfo uri, HttpHeaders headers) { throw new UnsupportedOperationException("Implemented and delegated by security layer"); - -// Map> queryParameters = uri.getQueryParameters(); -// if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) -// { -// logger.warn( -// "Query contains parameter not applicable in this conditional update context: '{}', parameters {} will be ignored", -// UriComponentsBuilder.newInstance() -// .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), -// Arrays.toString(SearchQuery.STANDARD_PARAMETERS)); -// -// queryParameters = queryParameters.entrySet().stream() -// .filter(e -> !Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(p -> p.equals(e.getKey()))) -// .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); -// } -// -// SearchQuery query = dao.createSearchQuery(1, 1); -// query.configureParameters(queryParameters); -// -// List unsupportedQueryParameters = query -// .getUnsupportedQueryParameters(queryParameters); -// if (!unsupportedQueryParameters.isEmpty()) -// return responseGenerator.badRequest( -// UriComponentsBuilder.newInstance() -// .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), -// unsupportedQueryParameters); -// -// PartialResult result = exceptionHandler.handleSqlException(() -> dao.search(query)); -// -// // No matches, no id provided: The server creates the resource. -// if (result.getOverallCount() <= 0 && !resource.hasId()) -// return create(resource, uri, headers); -// -// // No matches, id provided: The server treats the interaction as an Update as Create interaction (or rejects it, -// // if it does not support Update as Create) -> reject -// else if (result.getOverallCount() <= 0 && resource.hasId()) -// return responseGenerator.updateAsCreateNotAllowed(resourceTypeName, resource.getId()); -// -// // One Match, no resource id provided OR (resource id provided and it matches the found resource): -// // The server performs the update against the matching resource -// else if (result.getOverallCount() == 1) -// { -// R dbResource = result.getPartialResult().get(0); -// IdType dbResourceId = dbResource.getIdElement(); -// -// // BaseUrl - The server base URL (e.g. "http://example.com/fhir") -// // ResourceType - The resource type (e.g. "Patient") -// // IdPart - The ID (e.g. "123") -// // Version - The version ID ("e.g. "456") -// if (!resource.hasId()) -// { -// resource.setIdElement(dbResourceId); -// return update(resource.getIdElement().getIdPart(), resource, uri, headers); -// } -// else if (resource.hasId() -// && (!resource.getIdElement().hasBaseUrl() -// || serverBase.equals(resource.getIdElement().getBaseUrl())) -// && (!resource.getIdElement().hasResourceType() -// || resourceTypeName.equals(resource.getIdElement().getResourceType())) -// && (dbResourceId.getIdPart().equals(resource.getIdElement().getIdPart()))) -// return update(resource.getIdElement().getIdPart(), resource, uri, headers); -// else -// return responseGenerator.badRequestIdsNotMatching( -// dbResourceId.withServerBase(serverBase, resourceTypeName), -// resource.getIdElement().hasBaseUrl() && resource.getIdElement().hasResourceType() -// ? resource.getIdElement() -// : resource.getIdElement().withServerBase(serverBase, resourceTypeName)); -// } -// // Multiple matches: The server returns a 412 Precondition Failed error indicating the client's criteria were -// // not selective enough preferably with an OperationOutcome -// else // if (result.getOverallCount() > 1) -// throw new WebApplicationException(responseGenerator.multipleExists(resourceTypeName, UriComponentsBuilder -// .newInstance().replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString())); + + // Map> queryParameters = uri.getQueryParameters(); + // if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) + // { + // logger.warn( + // "Query contains parameter not applicable in this conditional update context: '{}', parameters {} will be + // ignored", + // UriComponentsBuilder.newInstance() + // .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), + // Arrays.toString(SearchQuery.STANDARD_PARAMETERS)); + // + // queryParameters = queryParameters.entrySet().stream() + // .filter(e -> !Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(p -> p.equals(e.getKey()))) + // .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + // } + // + // SearchQuery query = dao.createSearchQuery(1, 1); + // query.configureParameters(queryParameters); + // + // List unsupportedQueryParameters = query + // .getUnsupportedQueryParameters(queryParameters); + // if (!unsupportedQueryParameters.isEmpty()) + // return responseGenerator.badRequest( + // UriComponentsBuilder.newInstance() + // .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), + // unsupportedQueryParameters); + // + // PartialResult result = exceptionHandler.handleSqlException(() -> dao.search(query)); + // + // // No matches, no id provided: The server creates the resource. + // if (result.getOverallCount() <= 0 && !resource.hasId()) + // return create(resource, uri, headers); + // + // // No matches, id provided: The server treats the interaction as an Update as Create interaction (or rejects + // it, + // // if it does not support Update as Create) -> reject + // else if (result.getOverallCount() <= 0 && resource.hasId()) + // return responseGenerator.updateAsCreateNotAllowed(resourceTypeName, resource.getId()); + // + // // One Match, no resource id provided OR (resource id provided and it matches the found resource): + // // The server performs the update against the matching resource + // else if (result.getOverallCount() == 1) + // { + // R dbResource = result.getPartialResult().get(0); + // IdType dbResourceId = dbResource.getIdElement(); + // + // // BaseUrl - The server base URL (e.g. "http://example.com/fhir") + // // ResourceType - The resource type (e.g. "Patient") + // // IdPart - The ID (e.g. "123") + // // Version - The version ID ("e.g. "456") + // if (!resource.hasId()) + // { + // resource.setIdElement(dbResourceId); + // return update(resource.getIdElement().getIdPart(), resource, uri, headers); + // } + // else if (resource.hasId() + // && (!resource.getIdElement().hasBaseUrl() + // || serverBase.equals(resource.getIdElement().getBaseUrl())) + // && (!resource.getIdElement().hasResourceType() + // || resourceTypeName.equals(resource.getIdElement().getResourceType())) + // && (dbResourceId.getIdPart().equals(resource.getIdElement().getIdPart()))) + // return update(resource.getIdElement().getIdPart(), resource, uri, headers); + // else + // return responseGenerator.badRequestIdsNotMatching( + // dbResourceId.withServerBase(serverBase, resourceTypeName), + // resource.getIdElement().hasBaseUrl() && resource.getIdElement().hasResourceType() + // ? resource.getIdElement() + // : resource.getIdElement().withServerBase(serverBase, resourceTypeName)); + // } + // // Multiple matches: The server returns a 412 Precondition Failed error indicating the client's criteria were + // // not selective enough preferably with an OperationOutcome + // else // if (result.getOverallCount() > 1) + // throw new WebApplicationException(responseGenerator.multipleExists(resourceTypeName, UriComponentsBuilder + // .newInstance().replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString())); } @Override @@ -543,50 +546,52 @@ protected Consumer preDelete(String id) public Response delete(UriInfo uri, HttpHeaders headers) { throw new UnsupportedOperationException("Implemented and delegated by security layer"); - -// Map> queryParameters = uri.getQueryParameters(); -// if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) -// { -// logger.warn( -// "Query contains parameter not applicable in this conditional delete context: '{}', parameters {} will be ignored", -// UriComponentsBuilder.newInstance() -// .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), -// Arrays.toString(SearchQuery.STANDARD_PARAMETERS)); -// -// queryParameters = queryParameters.entrySet().stream() -// .filter(e -> !Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(p -> p.equals(e.getKey()))) -// .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); -// } -// -// SearchQuery query = dao.createSearchQuery(1, 1); -// query.configureParameters(queryParameters); -// -// List unsupportedQueryParameters = query -// .getUnsupportedQueryParameters(queryParameters); -// if (!unsupportedQueryParameters.isEmpty()) -// return responseGenerator.badRequest( -// UriComponentsBuilder.newInstance() -// .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), -// unsupportedQueryParameters); -// -// PartialResult result = exceptionHandler.handleSqlException(() -> dao.search(query)); -// -// // No matches -// if (result.getOverallCount() <= 0) -// { -// return Response.noContent().build(); // TODO return OperationOutcome -// } -// // One Match: The server performs an ordinary delete on the matching resource -// else if (result.getOverallCount() == 1) -// { -// R resource = result.getPartialResult().get(0); -// return delete(resource.getIdElement().getIdPart(), uri, headers); -// } -// // Multiple matches: A server may choose to delete all the matching resources, or it may choose to return a 412 -// // Precondition Failed error indicating the client's criteria were not selective enough. -// else -// throw new WebApplicationException(responseGenerator.multipleExists(resourceTypeName, UriComponentsBuilder -// .newInstance().replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString())); + + // Map> queryParameters = uri.getQueryParameters(); + // if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) + // { + // logger.warn( + // "Query contains parameter not applicable in this conditional delete context: '{}', parameters {} will be + // ignored", + // UriComponentsBuilder.newInstance() + // .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), + // Arrays.toString(SearchQuery.STANDARD_PARAMETERS)); + // + // queryParameters = queryParameters.entrySet().stream() + // .filter(e -> !Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(p -> p.equals(e.getKey()))) + // .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + // } + // + // SearchQuery query = dao.createSearchQuery(1, 1); + // query.configureParameters(queryParameters); + // + // List unsupportedQueryParameters = query + // .getUnsupportedQueryParameters(queryParameters); + // if (!unsupportedQueryParameters.isEmpty()) + // return responseGenerator.badRequest( + // UriComponentsBuilder.newInstance() + // .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), + // unsupportedQueryParameters); + // + // PartialResult result = exceptionHandler.handleSqlException(() -> dao.search(query)); + // + // // No matches + // if (result.getOverallCount() <= 0) + // { + // return Response.noContent().build(); // TODO return OperationOutcome + // } + // // One Match: The server performs an ordinary delete on the matching resource + // else if (result.getOverallCount() == 1) + // { + // R resource = result.getPartialResult().get(0); + // return delete(resource.getIdElement().getIdPart(), uri, headers); + // } + // // Multiple matches: A server may choose to delete all the matching resources, or it may choose to return a + // 412 + // // Precondition Failed error indicating the client's criteria were not selective enough. + // else + // throw new WebApplicationException(responseGenerator.multipleExists(resourceTypeName, UriComponentsBuilder + // .newInstance().replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString())); } @Override @@ -600,7 +605,7 @@ public Response search(UriInfo uri, HttpHeaders headers) Integer count = parameterConverter.getFirstInt(queryParameters, SearchQuery.PARAMETER_COUNT); int effectiveCount = (count == null || count < 0) ? defaultPageCount : count; - SearchQuery query = dao.createSearchQuery(effectivePage, effectiveCount); + SearchQuery query = dao.createSearchQuery(getCurrentUser(), effectivePage, effectiveCount); query.configureParameters(queryParameters); List errors = query.getUnsupportedQueryParameters(queryParameters); // TODO throw error if strict param handling is configured, include warning else diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractServiceImpl.java deleted file mode 100644 index 6f3348e8d..000000000 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractServiceImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.highmed.dsf.fhir.webservice.impl; - -import java.util.Objects; - -import org.highmed.dsf.fhir.authentication.UserProvider; -import org.highmed.dsf.fhir.webservice.specification.BasicService; -import org.springframework.beans.factory.InitializingBean; - -public abstract class AbstractServiceImpl implements BasicService, InitializingBean -{ - private final String path; - - public AbstractServiceImpl(String path) - { - this.path = path; - } - - @Override - public void afterPropertiesSet() throws Exception - { - Objects.requireNonNull(path, "path"); - } - - @Override - public final String getPath() - { - return path; - } - - @Override - public final void setUserProvider(UserProvider provider) - { - } -} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java index 3a882f6ab..64ac098cf 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java @@ -69,6 +69,7 @@ import org.highmed.dsf.fhir.search.parameters.rev.include.EndpointOrganizationRevInclude; import org.highmed.dsf.fhir.search.parameters.rev.include.OrganizationEndpointRevInclude; import org.highmed.dsf.fhir.search.parameters.rev.include.ResearchStudyEnrollmentRevInclude; +import org.highmed.dsf.fhir.webservice.base.AbstractBasicService; import org.highmed.dsf.fhir.webservice.specification.ConformanceService; import org.highmed.dsf.fhir.websocket.ServerEndpoint; import org.highmed.dsf.tools.build.BuildInfoReader; @@ -124,7 +125,7 @@ import ca.uhn.fhir.model.api.annotation.ResourceDef; import ca.uhn.fhir.rest.api.Constants; -public class ConformanceServiceImpl extends AbstractServiceImpl implements ConformanceService, InitializingBean +public class ConformanceServiceImpl extends AbstractBasicService implements ConformanceService, InitializingBean { private final CapabilityStatement capabilityStatement; private final ParameterConverter parameterConverter; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/RootServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/RootServiceImpl.java index c305a29e3..d2e4569fd 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/RootServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/RootServiceImpl.java @@ -12,6 +12,7 @@ import org.highmed.dsf.fhir.help.ExceptionHandler; import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.webservice.base.AbstractBasicService; import org.highmed.dsf.fhir.webservice.specification.RootService; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.OperationOutcome; @@ -19,7 +20,7 @@ import org.hl7.fhir.r4.model.OperationOutcome.IssueType; import org.springframework.beans.factory.InitializingBean; -public class RootServiceImpl extends AbstractServiceImpl implements RootService, InitializingBean +public class RootServiceImpl extends AbstractBasicService implements RootService, InitializingBean { private final CommandFactory commandFactory; private final ResponseGenerator responseGenerator; @@ -60,7 +61,8 @@ public Response root(UriInfo uri, HttpHeaders headers) @Override public Response handleBundle(Bundle bundle, UriInfo uri, HttpHeaders headers) { - CommandList commands = exceptionHandler.handleBadBundleException(() -> commandFactory.createCommands(bundle)); + CommandList commands = exceptionHandler + .handleBadBundleException(() -> commandFactory.createCommands(bundle, getCurrentUser())); Bundle result = commands.execute(); // throws WebApplicationException diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/StaticResourcesServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/StaticResourcesServiceImpl.java index 61991eaa2..6b1a5f775 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/StaticResourcesServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/StaticResourcesServiceImpl.java @@ -21,11 +21,12 @@ import javax.ws.rs.core.UriInfo; import org.apache.commons.codec.binary.Hex; +import org.highmed.dsf.fhir.webservice.base.AbstractBasicService; import org.highmed.dsf.fhir.webservice.specification.StaticResourcesService; import ca.uhn.fhir.rest.api.Constants; -public class StaticResourcesServiceImpl extends AbstractServiceImpl implements StaticResourcesService +public class StaticResourcesServiceImpl extends AbstractBasicService implements StaticResourcesService { private static final class CacheEntry { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/StructureDefinitionServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/StructureDefinitionServiceImpl.java index 0d211941b..ecd8faff6 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/StructureDefinitionServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/StructureDefinitionServiceImpl.java @@ -230,7 +230,7 @@ else if (urlType == null && resource.isPresent() && resource.get().getResource() private Response getSnapshot(String url, UriInfo uri, HttpHeaders headers) { - SearchQuery query = snapshotDao.createSearchQuery(1, 1); + SearchQuery query = snapshotDao.createSearchQuery(getCurrentUser(), 1, 1); Map> searchParameters = new HashMap<>(); searchParameters.put(StructureDefinitionUrl.PARAMETER_NAME, Collections.singletonList(url)); searchParameters.put(SearchQuery.PARAMETER_SORT, diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/jaxrs/AbstractServiceJaxrs.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/jaxrs/AbstractServiceJaxrs.java index ab9363477..ed3407754 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/jaxrs/AbstractServiceJaxrs.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/jaxrs/AbstractServiceJaxrs.java @@ -7,7 +7,8 @@ import javax.ws.rs.core.MediaType; import org.highmed.dsf.fhir.authentication.UserProvider; -import org.highmed.dsf.fhir.webservice.specification.BasicService; +import org.highmed.dsf.fhir.webservice.base.AbstractDelegatingBasicService; +import org.highmed.dsf.fhir.webservice.base.BasicService; import org.springframework.beans.factory.InitializingBean; import ca.uhn.fhir.rest.api.Constants; @@ -16,33 +17,22 @@ Constants.CT_FHIR_XML_NEW, MediaType.APPLICATION_XML }) @Produces({ MediaType.TEXT_HTML, Constants.CT_FHIR_JSON, Constants.CT_FHIR_JSON_NEW, MediaType.APPLICATION_JSON, Constants.CT_FHIR_XML, Constants.CT_FHIR_XML_NEW, MediaType.APPLICATION_XML }) -public abstract class AbstractServiceJaxrs implements BasicService, InitializingBean +public abstract class AbstractServiceJaxrs extends AbstractDelegatingBasicService + implements BasicService, InitializingBean { @Context private volatile HttpServletRequest httpRequest; - protected final S delegate; - public AbstractServiceJaxrs(S delegate) { - this.delegate = delegate; + super(delegate); } @Override public void afterPropertiesSet() throws Exception { - setUserProvider(new UserProvider(() -> httpRequest)); - } - - @Override - public final String getPath() - { - return delegate.getPath(); - } + super.afterPropertiesSet(); - @Override - public final void setUserProvider(UserProvider provider) - { - delegate.setUserProvider(provider); + setUserProvider(new UserProvider(() -> httpRequest)); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java index 2e103f53d..7c6f93166 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java @@ -3,6 +3,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Map.Entry; import java.util.Optional; import java.util.stream.Collectors; @@ -12,6 +13,7 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; +import org.highmed.dsf.fhir.authorization.AuthorizationRule; import org.highmed.dsf.fhir.dao.ResourceDao; import org.highmed.dsf.fhir.help.ExceptionHandler; import org.highmed.dsf.fhir.help.ParameterConverter; @@ -27,13 +29,14 @@ import org.hl7.fhir.r4.model.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; import org.springframework.util.CollectionUtils; import org.springframework.web.util.UriComponentsBuilder; import ca.uhn.fhir.model.api.annotation.ResourceDef; public abstract class AbstractResourceServiceSecure, R extends Resource, S extends BasicResourceService> - extends AbstractServiceSecure implements BasicResourceService + extends AbstractServiceSecure implements BasicResourceService, InitializingBean { private static final Logger logger = LoggerFactory.getLogger(AbstractResourceServiceSecure.class); @@ -43,10 +46,11 @@ public abstract class AbstractResourceServiceSecure, R protected final D dao; protected final ExceptionHandler exceptionHandler; protected final ParameterConverter parameterConverter; + protected final AuthorizationRule authorizationRule; public AbstractResourceServiceSecure(S delegate, String serverBase, ResponseGenerator responseGenerator, ReferenceResolver referenceResolver, Class resourceType, D dao, ExceptionHandler exceptionHandler, - ParameterConverter parameterConverter) + ParameterConverter parameterConverter, AuthorizationRule authorizationRule) { super(delegate, serverBase, responseGenerator, referenceResolver); @@ -56,6 +60,21 @@ public AbstractResourceServiceSecure(S delegate, String serverBase, ResponseGene this.dao = dao; this.exceptionHandler = exceptionHandler; this.parameterConverter = parameterConverter; + this.authorizationRule = authorizationRule; + } + + @Override + public void afterPropertiesSet() throws Exception + { + super.afterPropertiesSet(); + + Objects.requireNonNull(resourceType, "resourceType"); + Objects.requireNonNull(resourceTypeName, "resourceTypeName"); + Objects.requireNonNull(serverBase, "serverBase"); + Objects.requireNonNull(dao, "dao"); + Objects.requireNonNull(exceptionHandler, "exceptionHandler"); + Objects.requireNonNull(parameterConverter, "parameterConverter"); + Objects.requireNonNull(authorizationRule, "authorizationRule"); } @Override @@ -64,7 +83,7 @@ public Response create(R resource, UriInfo uri, HttpHeaders headers) logger.debug("Current user '{}', role '{}'", userProvider.getCurrentUser().getName(), userProvider.getCurrentUser().getRole()); - Optional reasonCreateAllowed = reasonCreateAllowed(resource); + Optional reasonCreateAllowed = authorizationRule.reasonCreateAllowed(getCurrentUser(), resource); if (reasonCreateAllowed.isEmpty()) { @@ -78,17 +97,6 @@ public Response create(R resource, UriInfo uri, HttpHeaders headers) } } - /** - * Override this method for non default behavior. Default: Not allowed. - * - * @param resource - * @return Reason as String in {@link Optional#of(Object))} if create allowed - */ - protected Optional reasonCreateAllowed(R resource) - { - return Optional.empty(); - } - @Override public Response read(String id, UriInfo uri, HttpHeaders headers) { @@ -100,7 +108,7 @@ public Response read(String id, UriInfo uri, HttpHeaders headers) if (read.hasEntity() && resourceType.isInstance(read.getEntity())) { R entity = resourceType.cast(read.getEntity()); - Optional reasonReadAllowed = reasonReadAllowed(entity); + Optional reasonReadAllowed = authorizationRule.reasonReadAllowed(getCurrentUser(), entity); if (reasonReadAllowed.isEmpty()) { @@ -152,7 +160,7 @@ public Response vread(String id, long version, UriInfo uri, HttpHeaders headers) if (read.hasEntity() && resourceType.isInstance(read.getEntity())) { R entity = resourceType.cast(read.getEntity()); - Optional reasonReadAllowed = reasonReadAllowed(entity); + Optional reasonReadAllowed = authorizationRule.reasonReadAllowed(getCurrentUser(), entity); if (reasonReadAllowed.isEmpty()) { @@ -193,17 +201,6 @@ else if (read.hasEntity()) } } - /** - * Override this method for non default behavior. Default: Not allowed. - * - * @param resource - * @return Reason as String in {@link Optional#of(Object)} if read allowed - */ - protected Optional reasonReadAllowed(R resource) - { - return Optional.empty(); - } - @Override public Response update(String id, R resource, UriInfo uri, HttpHeaders headers) { @@ -225,7 +222,8 @@ public Response update(String id, R resource, UriInfo uri, HttpHeaders headers) private Response update(String id, R newResource, UriInfo uri, HttpHeaders headers, R oldResource) { - Optional reasonUpdateAllowed = reasonUpdateAllowed(oldResource, newResource); + Optional reasonUpdateAllowed = authorizationRule.reasonUpdateAllowed(getCurrentUser(), oldResource, + newResource); if (reasonUpdateAllowed.isEmpty()) { @@ -249,18 +247,6 @@ private Response update(String id, R newResource, UriInfo uri, HttpHeaders heade } } - /** - * Override this method for non default behavior. Default: Not allowed. - * - * @param oldResource - * @param newResource - * @return Reason as String in {@link Optional#of(Object))} if update allowed - */ - protected Optional reasonUpdateAllowed(R oldResource, R newResource) - { - return Optional.empty(); - } - @Override public Response update(R resource, UriInfo uri, HttpHeaders headers) { @@ -348,7 +334,7 @@ private PartialResult getExisting(Map> queryParameters) .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); } - SearchQuery query = dao.createSearchQuery(1, 1); + SearchQuery query = dao.createSearchQuery(getCurrentUser(), 1, 1); query.configureParameters(queryParameters); List unsupportedQueryParameters = query @@ -431,7 +417,7 @@ public Response delete(UriInfo uri, HttpHeaders headers) .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); } - SearchQuery query = dao.createSearchQuery(1, 1); + SearchQuery query = dao.createSearchQuery(getCurrentUser(), 1, 1); query.configureParameters(queryParameters); List unsupportedQueryParameters = query @@ -479,7 +465,7 @@ public Response search(UriInfo uri, HttpHeaders headers) logger.debug("Current user '{}', role '{}'", userProvider.getCurrentUser().getName(), userProvider.getCurrentUser().getRole()); - Optional reasonSearchAllowed = reasonSearchAllowed(); + Optional reasonSearchAllowed = authorizationRule.reasonSearchAllowed(getCurrentUser()); if (reasonSearchAllowed.isEmpty()) { audit.info("Search of resource {} denied for user '{}'", resourceTypeName, getCurrentUser().getName()); @@ -492,17 +478,6 @@ public Response search(UriInfo uri, HttpHeaders headers) } } - /** - * Override this method for non default behavior. Default: Not allowed. - * - * @param uri - * @return Reason as String in {@link Optional#of(Object)} if delete allowed - */ - protected Optional reasonSearchAllowed() - { - return Optional.empty(); - } - @Override public Response postValidateNew(String validate, Parameters parameters, UriInfo uri, HttpHeaders headers) { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractServiceSecure.java index 779f61c4e..4d16e09f7 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractServiceSecure.java @@ -7,13 +7,12 @@ import javax.ws.rs.core.Response; -import org.highmed.dsf.fhir.authentication.User; -import org.highmed.dsf.fhir.authentication.UserProvider; import org.highmed.dsf.fhir.help.ResponseGenerator; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.service.ResourceReference; import org.highmed.dsf.fhir.service.ResourceReference.ReferenceType; -import org.highmed.dsf.fhir.webservice.specification.BasicService; +import org.highmed.dsf.fhir.webservice.base.AbstractDelegatingBasicService; +import org.highmed.dsf.fhir.webservice.base.BasicService; import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.Resource; @@ -21,23 +20,22 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; -public abstract class AbstractServiceSecure implements BasicService, InitializingBean +public abstract class AbstractServiceSecure extends AbstractDelegatingBasicService + implements BasicService, InitializingBean { protected static final Logger audit = LoggerFactory.getLogger("dsf-audit-logger"); private static final Logger logger = LoggerFactory.getLogger(AbstractServiceSecure.class); - protected final S delegate; protected final String serverBase; protected final ResponseGenerator responseGenerator; protected final ReferenceResolver referenceResolver; - protected UserProvider userProvider; - public AbstractServiceSecure(S delegate, String serverBase, ResponseGenerator responseGenerator, ReferenceResolver referenceResolver) { + super(delegate); + this.serverBase = serverBase; - this.delegate = delegate; this.referenceResolver = referenceResolver; this.responseGenerator = responseGenerator; } @@ -45,25 +43,13 @@ public AbstractServiceSecure(S delegate, String serverBase, ResponseGenerator re @Override public void afterPropertiesSet() throws Exception { - Objects.requireNonNull(delegate, "delegate"); + super.afterPropertiesSet(); + Objects.requireNonNull(serverBase, "serverBase"); Objects.requireNonNull(responseGenerator, "responseGenerator"); Objects.requireNonNull(referenceResolver, "referenceResolver"); } - @Override - public final void setUserProvider(UserProvider userProvider) - { - delegate.setUserProvider(userProvider); - - this.userProvider = userProvider; - } - - protected final User getCurrentUser() - { - return userProvider.getCurrentUser(); - } - protected final boolean isCurrentUserPartOfReferencedOrganizations(String referenceLocation, Collection references) { @@ -95,7 +81,7 @@ else if (reference == null) return false; } - Optional resource = referenceResolver.resolveReference(resReference); + Optional resource = referenceResolver.resolveReference(getCurrentUser(), resReference); if (resource.isPresent() && resource.get() instanceof Organization) { boolean sameOrganization = userProvider.getCurrentUser().getOrganization().getIdElement() @@ -116,12 +102,6 @@ else if (reference == null) } } - @Override - public final String getPath() - { - return delegate.getPath(); - } - protected final Response forbidden(String operation) { return responseGenerator.forbiddenNotAllowed(operation, userProvider.getCurrentUser()); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ActivityDefinitionServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ActivityDefinitionServiceSecure.java index 060335f56..445b2fb74 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ActivityDefinitionServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ActivityDefinitionServiceSecure.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.authorization.ActivityDefinitionAuthorizationRule; import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; import org.highmed.dsf.fhir.help.ExceptionHandler; import org.highmed.dsf.fhir.help.ParameterConverter; @@ -12,12 +13,12 @@ public class ActivityDefinitionServiceSecure extends AbstractResourceServiceSecure implements ActivityDefinitionService { - public ActivityDefinitionServiceSecure(ActivityDefinitionService delegate, String serverBase, ResponseGenerator responseGenerator, - ReferenceResolver referenceResolver, ActivityDefinitionDao activityDefinitionDao, ExceptionHandler exceptionHandler, - ParameterConverter parameterConverter) + public ActivityDefinitionServiceSecure(ActivityDefinitionService delegate, String serverBase, + ResponseGenerator responseGenerator, ReferenceResolver referenceResolver, + ActivityDefinitionDao activityDefinitionDao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter, ActivityDefinitionAuthorizationRule authorizationRule) { super(delegate, serverBase, responseGenerator, referenceResolver, ActivityDefinition.class, - activityDefinitionDao, exceptionHandler, - parameterConverter); + activityDefinitionDao, exceptionHandler, parameterConverter, authorizationRule); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/BinaryServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/BinaryServiceSecure.java index 13c674842..7a68df885 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/BinaryServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/BinaryServiceSecure.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.authorization.BinaryAuthorizationRule; import org.highmed.dsf.fhir.dao.BinaryDao; import org.highmed.dsf.fhir.help.ExceptionHandler; import org.highmed.dsf.fhir.help.ParameterConverter; @@ -13,9 +14,9 @@ public class BinaryServiceSecure extends AbstractResourceServiceSecure reasonCreateAllowed(Endpoint resource) - { - // TODO validate unique on Endpoint.address - - return Optional.empty(); - } - - @Override - protected Optional reasonUpdateAllowed(Endpoint oldResource, Endpoint newResource) - { - // TODO validate unique on Endpoint.address - - return Optional.empty(); + parameterConverter, authorizationRule); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/GroupServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/GroupServiceSecure.java index f7d1678df..7f99acdd3 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/GroupServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/GroupServiceSecure.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.authorization.GroupAuthorizationRule; import org.highmed.dsf.fhir.dao.GroupDao; import org.highmed.dsf.fhir.help.ExceptionHandler; import org.highmed.dsf.fhir.help.ParameterConverter; @@ -13,9 +14,9 @@ public class GroupServiceSecure extends AbstractResourceServiceSecure implements LocationService +public class LocationServiceSecure extends AbstractResourceServiceSecure + implements LocationService { public LocationServiceSecure(LocationService delegate, String serverBase, ResponseGenerator responseGenerator, ReferenceResolver referenceResolver, LocationDao locationDao, ExceptionHandler exceptionHandler, - ParameterConverter parameterConverter) + ParameterConverter parameterConverter, LocationAuthorizationRule authorizationRule) { super(delegate, serverBase, responseGenerator, referenceResolver, Location.class, locationDao, exceptionHandler, - parameterConverter); + parameterConverter, authorizationRule); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/NamingSystemServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/NamingSystemServiceSecure.java index 45936d91b..cb06b3c9a 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/NamingSystemServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/NamingSystemServiceSecure.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.authorization.NamingSystemAuthorizationRule; import org.highmed.dsf.fhir.dao.NamingSystemDao; import org.highmed.dsf.fhir.help.ExceptionHandler; import org.highmed.dsf.fhir.help.ParameterConverter; @@ -13,9 +14,10 @@ public class NamingSystemServiceSecure extends { public NamingSystemServiceSecure(NamingSystemService delegate, String serverBase, ResponseGenerator responseGenerator, ReferenceResolver referenceResolver, NamingSystemDao naminngSystemDao, - ExceptionHandler exceptionHandler, ParameterConverter parameterConverter) + ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, + NamingSystemAuthorizationRule authorizationRule) { super(delegate, serverBase, responseGenerator, referenceResolver, NamingSystem.class, naminngSystemDao, - exceptionHandler, parameterConverter); + exceptionHandler, parameterConverter, authorizationRule); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/OrganizationServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/OrganizationServiceSecure.java index ac4c9887c..03492f00d 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/OrganizationServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/OrganizationServiceSecure.java @@ -1,9 +1,6 @@ package org.highmed.dsf.fhir.webservice.secure; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; - +import org.highmed.dsf.fhir.authorization.OrganizationAuthorizationRule; import org.highmed.dsf.fhir.dao.OrganizationDao; import org.highmed.dsf.fhir.help.ExceptionHandler; import org.highmed.dsf.fhir.help.ParameterConverter; @@ -17,38 +14,10 @@ public class OrganizationServiceSecure extends { public OrganizationServiceSecure(OrganizationService delegate, String serverBase, ResponseGenerator responseGenerator, ReferenceResolver referenceResolver, OrganizationDao organizationDao, - ExceptionHandler exceptionHandler, ParameterConverter parameterConverter) + ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, + OrganizationAuthorizationRule authorizationRule) { super(delegate, serverBase, responseGenerator, referenceResolver, Organization.class, organizationDao, - exceptionHandler, parameterConverter); - } - - @Override - public Response create(Organization resource, UriInfo uri, HttpHeaders headers) - { - // check organization not existing if contains identifier with identifier.system (or extension) - // http://highmed.org/fhir/NamingSystem/certificate-thumbprint-hex with same identifier.value - // no two organizations can have the same certificate thumb-print - - // TODO Auto-generated method stub - return super.create(resource, uri, headers); - } - - @Override - public Response update(String id, Organization resource, UriInfo uri, HttpHeaders headers) - { - // see create, no two organizations can have the same certificate thumb-print - - // TODO Auto-generated method stub - return super.update(id, resource, uri, headers); - } - - @Override - public Response update(Organization resource, UriInfo uri, HttpHeaders headers) - { - // see create, no two organizations can have the same certificate thumb-print - - // TODO Auto-generated method stub - return super.update(resource, uri, headers); + exceptionHandler, parameterConverter, authorizationRule); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PatientServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PatientServiceSecure.java index b769a492e..8a8b54ffd 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PatientServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PatientServiceSecure.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.authorization.PatientAuthorizationRule; import org.highmed.dsf.fhir.dao.PatientDao; import org.highmed.dsf.fhir.help.ExceptionHandler; import org.highmed.dsf.fhir.help.ParameterConverter; @@ -13,9 +14,9 @@ public class PatientServiceSecure extends AbstractResourceServiceSecure +public class PractitionerRoleServiceSecure + extends AbstractResourceServiceSecure implements PractitionerRoleService { - public PractitionerRoleServiceSecure(PractitionerRoleService delegate, String serverBase, ResponseGenerator responseGenerator, - ReferenceResolver referenceResolver, PractitionerRoleDao practitionerRoleDao, ExceptionHandler exceptionHandler, - ParameterConverter parameterConverter) + public PractitionerRoleServiceSecure(PractitionerRoleService delegate, String serverBase, + ResponseGenerator responseGenerator, ReferenceResolver referenceResolver, + PractitionerRoleDao practitionerRoleDao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter, PractitionerRoleAuthorizationRule authorizationRule) { - super(delegate, serverBase, responseGenerator, referenceResolver, PractitionerRole.class, practitionerRoleDao, exceptionHandler, - parameterConverter); + super(delegate, serverBase, responseGenerator, referenceResolver, PractitionerRole.class, practitionerRoleDao, + exceptionHandler, parameterConverter, authorizationRule); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PractitionerServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PractitionerServiceSecure.java index 135a11051..cb51416d7 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PractitionerServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/PractitionerServiceSecure.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.authorization.PractitionerAuthorizationRule; import org.highmed.dsf.fhir.dao.PractitionerDao; import org.highmed.dsf.fhir.help.ExceptionHandler; import org.highmed.dsf.fhir.help.ParameterConverter; @@ -13,9 +14,10 @@ public class PractitionerServiceSecure extends { public PractitionerServiceSecure(PractitionerService delegate, String serverBase, ResponseGenerator responseGenerator, ReferenceResolver referenceResolver, PractitionerDao practitionerDao, - ExceptionHandler exceptionHandler, ParameterConverter parameterConverter) + ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, + PractitionerAuthorizationRule authorizationRule) { super(delegate, serverBase, responseGenerator, referenceResolver, Practitioner.class, practitionerDao, - exceptionHandler, parameterConverter); + exceptionHandler, parameterConverter, authorizationRule); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ProvenanceServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ProvenanceServiceSecure.java index fa571da46..30ee79ebc 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ProvenanceServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ProvenanceServiceSecure.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.authorization.ProvenanceAuthorizationRule; import org.highmed.dsf.fhir.dao.ProvenanceDao; import org.highmed.dsf.fhir.help.ExceptionHandler; import org.highmed.dsf.fhir.help.ParameterConverter; @@ -13,9 +14,9 @@ public class ProvenanceServiceSecure extends AbstractResourceServiceSecure implements TaskService { - private final ActivityDefinitionDao activityDefinitionDao; - public TaskServiceSecure(TaskService delegate, String serverBase, ResponseGenerator responseGenerator, ReferenceResolver referenceResolver, TaskDao taskDao, ExceptionHandler exceptionHandler, - ParameterConverter parameterConverter, ActivityDefinitionDao activityDefinitionDao) + ParameterConverter parameterConverter, TaskAuthorizationRule authorizationRule) { super(delegate, serverBase, responseGenerator, referenceResolver, Task.class, taskDao, exceptionHandler, - parameterConverter); - - this.activityDefinitionDao = activityDefinitionDao; - } - - @Override - public void afterPropertiesSet() throws Exception - { - super.afterPropertiesSet(); - - Objects.requireNonNull(activityDefinitionDao, "activityDefinitionDao"); - } - - @Override - protected Optional reasonReadAllowed(Task resource) - { -// if (!resource.hasRestriction() || !resource.getRestriction().hasRecipient() || !resource.hasRequester()) -// return Optional.of("Current user not Task.requester or Task.restriction.recipient"); -// else if (!isCurrentUserPartOfReferencedOrganizations("Task.restriction.recipient", -// resource.getRestriction().getRecipient()) -// && !isCurrentUserPartOfReferencedOrganization("Task.requester", resource.getRequester())) -// return Optional.of("Current user not Task.requester or Task.restriction.recipient"); -// else -// return Optional.of(""); - - return Optional.empty(); - } - - @Override - protected Optional reasonCreateAllowed(Task resource) - { - // FIXME authorization rules - // allowed status draft | requested for all users - // task.requester must be organization of current user - - return Optional.empty(); - } - - @Override - protected Optional reasonUpdateAllowed(Task oldResource, Task newResource) - { - if (TaskStatus.DRAFT.equals(oldResource.getStatus())) - { - return Optional.of("TODO oldResource DRAFT"); - } - else if (TaskStatus.REQUESTED.equals(oldResource.getStatus())) - { - return Optional.of("TODO oldResource REQUESTED"); - } - else if (TaskStatus.COMPLETED.equals(oldResource.getStatus())) - { - return Optional.of("TODO oldResource REQUESTED"); - } - else if (TaskStatus.FAILED.equals(oldResource.getStatus())) - { - return Optional.of("TODO oldResource REQUESTED"); - } - // FIXME authorization rules - // allowed status change from draft to requested for remote users - // update only allowed at status draft for remote users - // task.requester must be organization of current user or local user - // only update of tasks with requester = current user allowed for remote users - - return Optional.empty(); - } - - @Override - protected Optional reasonDeleteAllowed(Task oldResource) - { - // TODO authorization rules - // allowed if oldResouce created by current user and status draft - - return Optional.empty(); - } - - @Override - protected Optional reasonSearchAllowed() - { - // TODO authorization rules - - return Optional.empty(); + parameterConverter, authorizationRule); } } \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ValueSetServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ValueSetServiceSecure.java index f6c1d0cdb..52cd7f298 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ValueSetServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/ValueSetServiceSecure.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.secure; +import org.highmed.dsf.fhir.authorization.ValueSetAuthorizationRule; import org.highmed.dsf.fhir.dao.ValueSetDao; import org.highmed.dsf.fhir.help.ExceptionHandler; import org.highmed.dsf.fhir.help.ParameterConverter; @@ -13,9 +14,9 @@ public class ValueSetServiceSecure extends AbstractResourceServiceSecure + + + + + + + + + + + <status value="active"/> + <experimental value="false"/> + <date value="2020-02-18T11:00:00+02:00"/> + <publisher value="HiGHmed"/> + <description value="CodeSystem with authorization roles"/> + <caseSensitive value="true"/> + <hierarchyMeaning value="grouped-by"/> + <versionNeeded value="false"/> + <content value="complete"/> + <concept> + <code value="REMOTE"/> + <display value="REMOTE"/> + <definition value="Remote and local use"/> + </concept> + <concept> + <code value="LOCAL"/> + <display value="LOCAL"/> + <definition value="Local use only"/> + </concept> +</CodeSystem> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-0.1.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-0.1.0.xml.put new file mode 100644 index 000000000..c4772abb3 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-0.1.0.xml.put @@ -0,0 +1 @@ +CodeSystem?url=http://highmed.org/fhir/CodeSystem/authorization&version=0.1.0 \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/bpmn-message-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/bpmn-message-0.1.0.xml index 33f58d2f5..e1b417007 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/bpmn-message-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/bpmn-message-0.1.0.xml @@ -1,5 +1,11 @@ <CodeSystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://hl7.org/fhir" xsi:schemaLocation="http://hl7.org/fhir http://www.hl7.org/fhir/fhir-base.xsd"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/CodeSystem/bpmn-message"/> <version value="0.1.0"/> <name value="HiGHmed_Bpmn_Message_Values"/> diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/AbstractResourceDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/AbstractResourceDaoTest.java index 86012d029..8a54d1f80 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/AbstractResourceDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/AbstractResourceDaoTest.java @@ -6,10 +6,12 @@ import static org.junit.Assert.assertTrue; import java.sql.Connection; +import java.sql.SQLException; import java.util.Optional; import java.util.UUID; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.exception.ResourceDeletedException; import org.highmed.dsf.fhir.dao.exception.ResourceNotFoundException; import org.highmed.dsf.fhir.dao.exception.ResourceVersionNoMatchException; @@ -36,7 +38,7 @@ public abstract class AbstractResourceDaoTest<D extends Resource, C extends Reso protected final Class<D> resouceClass; protected final FhirContext fhirContext = FhirContext.forR4(); - protected C dao; + protected C ttpDao, medicDao; protected AbstractResourceDaoTest(Class<D> resouceClass) { @@ -46,20 +48,33 @@ protected AbstractResourceDaoTest(Class<D> resouceClass) @Before public void before() throws Exception { - dao = createDao(database.getDataSource(), fhirContext); + ttpDao = createDao(database.getDataSource(), fhirContext, OrganizationType.TTP); + medicDao = createDao(database.getDataSource(), fhirContext, OrganizationType.MeDIC); } - protected abstract C createDao(BasicDataSource dataSource, FhirContext fhirContext); + protected abstract C createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType); @Test - public void testEmpty() throws Exception + public void testEmptyForTtp() throws Exception { - Optional<D> read = dao.read(UUID.randomUUID()); + Optional<D> read = ttpDao.read(UUID.randomUUID()); assertTrue(read.isEmpty()); } + @Test + public void testEmptyForMedic() throws Exception + { + testEmpty(medicDao); + } + @Test public void testEmptyWithVersion() throws Exception + { + testEmpty(ttpDao); + } + + private void testEmpty(C dao) throws SQLException { Optional<D> read = dao.readVersion(UUID.randomUUID(), 1L); assertTrue(read.isEmpty()); @@ -68,7 +83,18 @@ public void testEmptyWithVersion() throws Exception protected abstract D createResource(); @Test - public void testCreate() throws Exception + public void testCreateForTtp() throws Exception + { + testCreate(ttpDao); + } + + @Test + public void testCreateForMedic() throws Exception + { + testCreate(medicDao); + } + + private void testCreate(C dao) throws SQLException, ResourceDeletedException { D newResource = createResource(); assertNull(newResource.getId()); @@ -99,7 +125,18 @@ public void testCreate() throws Exception protected abstract D updateResource(D resource); @Test - public void testUpdate() throws Exception + public void testUpdateForTtp() throws Exception + { + testUpdate(ttpDao); + } + + @Test + public void testUpdateForMedic() throws Exception + { + testUpdate(medicDao); + } + + private void testUpdate(C dao) throws SQLException, ResourceNotFoundException, ResourceVersionNoMatchException { D newResource = createResource(); assertNull(newResource.getId()); @@ -117,12 +154,24 @@ public void testUpdate() throws Exception D updatedResource = dao.update(updateResource(createdResource), null); assertNotNull(updatedResource); - + checkUpdates(updatedResource); } @Test(expected = ResourceNotFoundException.class) - public void testUpdateNonExisting() throws Exception + public void testUpdateNonExistingForTtp() throws Exception + { + testUpdateNonExisting(ttpDao); + } + + @Test(expected = ResourceNotFoundException.class) + public void testUpdateNonExistingForMedic() throws Exception + { + testUpdateNonExisting(medicDao); + } + + private void testUpdateNonExisting(C dao) + throws SQLException, ResourceNotFoundException, ResourceVersionNoMatchException { D newResource = createResource(); assertNull(newResource.getId()); @@ -132,7 +181,19 @@ public void testUpdateNonExisting() throws Exception } @Test(expected = ResourceVersionNoMatchException.class) - public void testUpdateNotLatest() throws Exception + public void testUpdateNotLatestForTtp() throws Exception + { + testUpdateNotLatest(ttpDao); + } + + @Test(expected = ResourceVersionNoMatchException.class) + public void testUpdateNotLatestForMedic() throws Exception + { + testUpdateNotLatest(medicDao); + } + + private void testUpdateNotLatest(C dao) + throws SQLException, ResourceNotFoundException, ResourceVersionNoMatchException { D newResource = createResource(); assertNull(newResource.getId()); @@ -152,7 +213,18 @@ public void testUpdateNotLatest() throws Exception } @Test - public void testUpdateLatest() throws Exception + public void testUpdateLatestForTtp() throws Exception + { + testUpdateLatest(ttpDao); + } + + @Test + public void testUpdateLatestForMedic() throws Exception + { + testUpdateLatest(medicDao); + } + + private void testUpdateLatest(C dao) throws SQLException, ResourceNotFoundException, ResourceVersionNoMatchException { D newResource = createResource(); assertNull(newResource.getId()); @@ -175,7 +247,18 @@ public void testUpdateLatest() throws Exception protected abstract void checkUpdates(D resource); @Test(expected = ResourceDeletedException.class) - public void testDelete() throws Exception + public void testDeleteForTtp() throws Exception + { + testDelete(ttpDao); + } + + @Test(expected = ResourceDeletedException.class) + public void testDeleteForMedic() throws Exception + { + testDelete(medicDao); + } + + private void testDelete(C dao) throws SQLException, ResourceDeletedException, ResourceNotFoundException { D newResource = createResource(); assertNull(newResource.getId()); @@ -200,7 +283,18 @@ public void testDelete() throws Exception } @Test - public void testReadWithVersion() throws Exception + public void testReadWithVersionForTtp() throws Exception + { + testReadWithVersion(ttpDao); + } + + @Test + public void testReadWithVersionFotMedic() throws Exception + { + testReadWithVersion(medicDao); + } + + private void testReadWithVersion(C dao) throws SQLException { D newResource = createResource(); assertNull(newResource.getId()); @@ -224,7 +318,18 @@ public void testReadWithVersion() throws Exception } @Test - public void testRead() throws Exception + public void testReadForTtp() throws Exception + { + testRead(ttpDao); + } + + @Test + public void testReadForMedic() throws Exception + { + testRead(medicDao); + } + + private void testRead(C dao) throws SQLException, ResourceDeletedException { D newResource = createResource(); assertNull(newResource.getId()); @@ -249,7 +354,19 @@ public void testRead() throws Exception } @Test - public void testReadLatest() throws Exception + public void testReadLatestForTtp() throws Exception + { + testReadLatest(ttpDao); + } + + @Test + public void testReadLatestForMedic() throws Exception + { + testReadLatest(medicDao); + } + + private void testReadLatest(C dao) + throws SQLException, ResourceNotFoundException, ResourceVersionNoMatchException, ResourceDeletedException { D newResource = createResource(); assertNull(newResource.getId()); @@ -288,7 +405,18 @@ public void testReadLatest() throws Exception } @Test - public void testUpdateSameRow() throws Exception + public void testUpdateSameRowForTtp() throws Exception + { + testUpdateSameRow(ttpDao); + } + + @Test + public void testUpdateSameRowForMedic() throws Exception + { + testUpdateSameRow(medicDao); + } + + private void testUpdateSameRow(C dao) throws SQLException, ResourceNotFoundException, ResourceDeletedException { D newResource = createResource(); assertNull(newResource.getId()); diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDaoTest.java index ef93df470..69fee17a8 100644 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDaoTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.ActivityDefinitionDaoJdbc; import org.hl7.fhir.r4.model.ActivityDefinition; @@ -19,9 +20,10 @@ public ActivityDefinitionDaoTest() } @Override - protected ActivityDefinitionDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected ActivityDefinitionDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new ActivityDefinitionDaoJdbc(dataSource, fhirContext); + return new ActivityDefinitionDaoJdbc(dataSource, fhirContext, organizationType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/BinaryDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/BinaryDaoTest.java index 9645368ac..8d11229e5 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/BinaryDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/BinaryDaoTest.java @@ -12,6 +12,7 @@ import java.util.Arrays; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.BinaryDaoJdbc; import org.hl7.fhir.r4.model.Binary; import org.junit.Test; @@ -31,9 +32,10 @@ public BinaryDaoTest() } @Override - protected BinaryDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected BinaryDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new BinaryDaoJdbc(dataSource, fhirContext); + return new BinaryDaoJdbc(dataSource, fhirContext, organizationType); } @Override @@ -75,7 +77,7 @@ public void testCreateCheckDataNullInJsonColumn() throws Exception assertNull(newResource.getId()); assertNull(newResource.getMeta().getVersionId()); - Binary createdResource = dao.create(newResource); + Binary createdResource = ttpDao.create(newResource); assertNotNull(createdResource); assertNotNull(createdResource.getId()); assertNotNull(createdResource.getMeta().getVersionId()); diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/BundleDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/BundleDaoTest.java index 48618a1b2..36f04d112 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/BundleDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/BundleDaoTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.BundleDaoJdbc; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleType; @@ -20,9 +21,10 @@ public BundleDaoTest() } @Override - protected BundleDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected BundleDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new BundleDaoJdbc(dataSource, fhirContext); + return new BundleDaoJdbc(dataSource, fhirContext, organizationType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/CodeSystemDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/CodeSystemDaoTest.java index 69bae42f0..fb6fbebd7 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/CodeSystemDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/CodeSystemDaoTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.CodeSystemDaoJdbc; import org.hl7.fhir.r4.model.CodeSystem; @@ -19,9 +20,10 @@ public CodeSystemDaoTest() } @Override - protected CodeSystemDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected CodeSystemDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new CodeSystemDaoJdbc(dataSource, fhirContext); + return new CodeSystemDaoJdbc(dataSource, fhirContext, organizationType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/EndpointDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/EndpointDaoTest.java index e96f9b966..a729d527b 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/EndpointDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/EndpointDaoTest.java @@ -8,6 +8,7 @@ import java.util.UUID; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.EndpointDaoJdbc; import org.hl7.fhir.r4.model.Endpoint; import org.hl7.fhir.r4.model.Endpoint.EndpointStatus; @@ -26,9 +27,10 @@ public EndpointDaoTest() } @Override - protected EndpointDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected EndpointDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new EndpointDaoJdbc(dataSource, fhirContext); + return new EndpointDaoJdbc(dataSource, fhirContext, organizationType); } @Override @@ -67,10 +69,10 @@ public void testExistsActiveNotDeletedByAddress() throws Exception e.setStatus(EndpointStatus.ACTIVE); e.setAddress(address); - Endpoint created = dao.create(e); + Endpoint created = ttpDao.create(e); assertNotNull(created); - assertTrue(dao.existsActiveNotDeletedByAddress(address)); + assertTrue(ttpDao.existsActiveNotDeletedByAddress(address)); } @Test @@ -82,10 +84,10 @@ public void testExistsActiveNotDeletedByAddressNotActive() throws Exception e.setStatus(EndpointStatus.OFF); e.setAddress(address); - Endpoint created = dao.create(e); + Endpoint created = ttpDao.create(e); assertNotNull(created); - assertFalse(dao.existsActiveNotDeletedByAddress(address)); + assertFalse(ttpDao.existsActiveNotDeletedByAddress(address)); } @Test @@ -97,10 +99,10 @@ public void testExistsActiveNotDeletedByAddressDeleted() throws Exception e.setStatus(EndpointStatus.ACTIVE); e.setAddress(address); - Endpoint created = dao.create(e); + Endpoint created = ttpDao.create(e); assertNotNull(created); - dao.delete(UUID.fromString(created.getIdElement().getIdPart())); + ttpDao.delete(UUID.fromString(created.getIdElement().getIdPart())); - assertFalse(dao.existsActiveNotDeletedByAddress(address)); + assertFalse(ttpDao.existsActiveNotDeletedByAddress(address)); } } diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/GroupDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/GroupDaoTest.java index efd56e622..8ea8fc9cf 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/GroupDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/GroupDaoTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.GroupDaoJdbc; import org.hl7.fhir.r4.model.Group; @@ -20,9 +21,9 @@ public GroupDaoTest() } @Override - protected GroupDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected GroupDao createDao(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) { - return new GroupDaoJdbc(dataSource, fhirContext); + return new GroupDaoJdbc(dataSource, fhirContext, organizationType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/HealthcareServiceDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/HealthcareServiceDaoTest.java index bc7b1c522..b29fdddaf 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/HealthcareServiceDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/HealthcareServiceDaoTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.HealthcareServiceDaoJdbc; import org.hl7.fhir.r4.model.HealthcareService; @@ -19,9 +20,10 @@ public HealthcareServiceDaoTest() } @Override - protected HealthcareServiceDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected HealthcareServiceDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new HealthcareServiceDaoJdbc(dataSource, fhirContext); + return new HealthcareServiceDaoJdbc(dataSource, fhirContext, organizationType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/LocationDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/LocationDaoTest.java index 9b3f5894b..52e029919 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/LocationDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/LocationDaoTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.LocationDaoJdbc; import org.hl7.fhir.r4.model.Location; @@ -19,9 +20,10 @@ public LocationDaoTest() } @Override - protected LocationDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected LocationDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new LocationDaoJdbc(dataSource, fhirContext); + return new LocationDaoJdbc(dataSource, fhirContext, organizationType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/NamingSystemDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/NamingSystemDaoTest.java index 3407cab63..bd2a7fc8a 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/NamingSystemDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/NamingSystemDaoTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.NamingSystemDaoJdbc; import org.hl7.fhir.r4.model.NamingSystem; @@ -19,9 +20,10 @@ public NamingSystemDaoTest() } @Override - protected NamingSystemDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected NamingSystemDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new NamingSystemDaoJdbc(dataSource, fhirContext); + return new NamingSystemDaoJdbc(dataSource, fhirContext, organizationType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/OrganizationDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/OrganizationDaoTest.java index 5fa6231f0..340783405 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/OrganizationDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/OrganizationDaoTest.java @@ -1,6 +1,8 @@ package org.highmed.dsf.fhir.dao; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import java.nio.charset.StandardCharsets; import java.util.Optional; @@ -8,6 +10,7 @@ import org.apache.commons.codec.binary.Hex; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.OrganizationDaoJdbc; import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.StringType; @@ -26,9 +29,10 @@ public OrganizationDaoTest() } @Override - protected OrganizationDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected OrganizationDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new OrganizationDaoJdbc(dataSource, fhirContext); + return new OrganizationDaoJdbc(dataSource, fhirContext, organizationType); } @Override @@ -69,10 +73,10 @@ public void testReadActiveNotDeletedByThumbprint() throws Exception org.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/certificate-thumbprint") .setValue(new StringType(certHex)); - Organization created = dao.create(org); + Organization created = ttpDao.create(org); assertNotNull(created); - Optional<Organization> read = dao.readActiveNotDeletedByThumbprint(certHex); + Optional<Organization> read = ttpDao.readActiveNotDeletedByThumbprint(certHex); assertNotNull(read); assertTrue(read.isPresent()); assertNotNull( @@ -97,14 +101,14 @@ public void testReadActiveNotDeletedByThumbprintNotActive() throws Exception org.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/certificate-thumbprint") .setValue(new StringType(certHex)); - Organization created = dao.create(org); + Organization created = ttpDao.create(org); assertNotNull(created); - Optional<Organization> read = dao.readActiveNotDeletedByThumbprint(certHex); + Optional<Organization> read = ttpDao.readActiveNotDeletedByThumbprint(certHex); assertNotNull(read); assertTrue(read.isEmpty()); - Optional<Organization> read2 = dao.read(UUID.fromString(created.getIdElement().getIdPart())); + Optional<Organization> read2 = ttpDao.read(UUID.fromString(created.getIdElement().getIdPart())); assertNotNull(read2); assertTrue(read2.isPresent()); } @@ -120,11 +124,11 @@ public void testReadActiveNotDeletedByThumbprintDeleted() throws Exception org.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/certificate-thumbprint") .setValue(new StringType(certHex)); - Organization created = dao.create(org); + Organization created = ttpDao.create(org); assertNotNull(created); - dao.delete(UUID.fromString(created.getIdElement().getIdPart())); + ttpDao.delete(UUID.fromString(created.getIdElement().getIdPart())); - Optional<Organization> read = dao.readActiveNotDeletedByThumbprint(certHex); + Optional<Organization> read = ttpDao.readActiveNotDeletedByThumbprint(certHex); assertNotNull(read); assertTrue(read.isEmpty()); } @@ -134,7 +138,7 @@ public void testReadActiveNotDeletedByThumbprintNotExisting() throws Exception { final String certHex = Hex.encodeHexString("FooBarBaz".getBytes(StandardCharsets.UTF_8)); - Optional<Organization> read = dao.readActiveNotDeletedByThumbprint(certHex); + Optional<Organization> read = ttpDao.readActiveNotDeletedByThumbprint(certHex); assertNotNull(read); assertTrue(read.isEmpty()); } @@ -142,7 +146,7 @@ public void testReadActiveNotDeletedByThumbprintNotExisting() throws Exception @Test public void testReadActiveNotDeletedByThumbprintNull() throws Exception { - Optional<Organization> read = dao.readActiveNotDeletedByThumbprint(null); + Optional<Organization> read = ttpDao.readActiveNotDeletedByThumbprint(null); assertNotNull(read); assertTrue(read.isEmpty()); } @@ -150,7 +154,7 @@ public void testReadActiveNotDeletedByThumbprintNull() throws Exception @Test public void testReadActiveNotDeletedByThumbprintBlank() throws Exception { - Optional<Organization> read = dao.readActiveNotDeletedByThumbprint(" "); + Optional<Organization> read = ttpDao.readActiveNotDeletedByThumbprint(" "); assertNotNull(read); assertTrue(read.isEmpty()); } diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PatientDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PatientDaoTest.java index e7271444b..b72a10d9a 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PatientDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PatientDaoTest.java @@ -6,6 +6,7 @@ import java.util.GregorianCalendar; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.PatientDaoJdbc; import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender; import org.hl7.fhir.r4.model.Patient; @@ -23,9 +24,10 @@ public PatientDaoTest() } @Override - protected PatientDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected PatientDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new PatientDaoJdbc(dataSource, fhirContext); + return new PatientDaoJdbc(dataSource, fhirContext, organizationType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PractitionerDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PractitionerDaoTest.java index 3edbda4c0..12b8b5c80 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PractitionerDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PractitionerDaoTest.java @@ -6,6 +6,7 @@ import java.util.GregorianCalendar; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.PractitionerDaoJdbc; import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender; import org.hl7.fhir.r4.model.Practitioner; @@ -23,9 +24,10 @@ public PractitionerDaoTest() } @Override - protected PractitionerDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected PractitionerDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new PractitionerDaoJdbc(dataSource, fhirContext); + return new PractitionerDaoJdbc(dataSource, fhirContext, organizationType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PractitionerRoleDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PractitionerRoleDaoTest.java index 855b07d01..51a4d1d05 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PractitionerRoleDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PractitionerRoleDaoTest.java @@ -6,6 +6,7 @@ import java.util.GregorianCalendar; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.PractitionerRoleDaoJdbc; import org.hl7.fhir.r4.model.Period; import org.hl7.fhir.r4.model.PractitionerRole; @@ -24,9 +25,10 @@ public PractitionerRoleDaoTest() } @Override - protected PractitionerRoleDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected PractitionerRoleDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new PractitionerRoleDaoJdbc(dataSource, fhirContext); + return new PractitionerRoleDaoJdbc(dataSource, fhirContext, organizationType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ProvenanceDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ProvenanceDaoTest.java index 464910b07..0c0a807a0 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ProvenanceDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ProvenanceDaoTest.java @@ -9,6 +9,7 @@ import java.util.GregorianCalendar; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.ProvenanceDaoJdbc; import org.hl7.fhir.r4.model.Provenance; import org.hl7.fhir.r4.model.Signature; @@ -26,9 +27,10 @@ public ProvenanceDaoTest() } @Override - protected ProvenanceDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected ProvenanceDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new ProvenanceDaoJdbc(dataSource, fhirContext); + return new ProvenanceDaoJdbc(dataSource, fhirContext, organizationType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ResearchStudyDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ResearchStudyDaoTest.java index 6a8ca974a..a4c2b1646 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ResearchStudyDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ResearchStudyDaoTest.java @@ -6,6 +6,7 @@ import java.util.GregorianCalendar; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.ResearchStudyDaoJdbc; import org.hl7.fhir.r4.model.Period; import org.hl7.fhir.r4.model.ResearchStudy; @@ -24,9 +25,10 @@ public ResearchStudyDaoTest() } @Override - protected ResearchStudyDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected ResearchStudyDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new ResearchStudyDaoJdbc(dataSource, fhirContext); + return new ResearchStudyDaoJdbc(dataSource, fhirContext, organizationType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/StructureDefinitionDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/StructureDefinitionDaoTest.java index a2c3f5296..249e7b3f0 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/StructureDefinitionDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/StructureDefinitionDaoTest.java @@ -3,13 +3,13 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.StructureDefinitionDaoJdbc; import org.hl7.fhir.r4.model.StructureDefinition; import ca.uhn.fhir.context.FhirContext; -public class StructureDefinitionDaoTest - extends AbstractResourceDaoTest<StructureDefinition, StructureDefinitionDao> +public class StructureDefinitionDaoTest extends AbstractResourceDaoTest<StructureDefinition, StructureDefinitionDao> { private static final String name = "StructureDefinition"; private static final String title = "Demo Structure Definition"; @@ -20,9 +20,10 @@ public StructureDefinitionDaoTest() } @Override - protected StructureDefinitionDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected StructureDefinitionDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new StructureDefinitionDaoJdbc(dataSource, fhirContext); + return new StructureDefinitionDaoJdbc(dataSource, fhirContext, organizationType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/StructureDefinitionSnapshotDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/StructureDefinitionSnapshotDaoTest.java index 5e9793228..00eace7a9 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/StructureDefinitionSnapshotDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/StructureDefinitionSnapshotDaoTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.converter.SnapshotInfoConverter; import org.highmed.dsf.fhir.dao.jdbc.StructureDefinitionSnapshotDaoJdbc; import org.highmed.dsf.fhir.spring.config.JsonConfig; @@ -26,9 +27,11 @@ public StructureDefinitionSnapshotDaoTest() } @Override - protected StructureDefinitionSnapshotDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected StructureDefinitionSnapshotDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new StructureDefinitionSnapshotDaoJdbc(dataSource, fhirContext, new SnapshotInfoConverter(objectMapper)); + return new StructureDefinitionSnapshotDaoJdbc(dataSource, fhirContext, organizationType, + new SnapshotInfoConverter(objectMapper)); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/SubscriptionDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/SubscriptionDaoTest.java index f54001c38..2f2d38c76 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/SubscriptionDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/SubscriptionDaoTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.SubscriptionDaoJdbc; import org.hl7.fhir.r4.model.Subscription; import org.hl7.fhir.r4.model.Subscription.SubscriptionStatus; @@ -20,9 +21,10 @@ public SubscriptionDaoTest() } @Override - protected SubscriptionDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected SubscriptionDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new SubscriptionDaoJdbc(dataSource, fhirContext); + return new SubscriptionDaoJdbc(dataSource, fhirContext, organizationType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/TaskDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/TaskDaoTest.java index d9ac33820..ae3f8499d 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/TaskDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/TaskDaoTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.TaskDaoJdbc; import org.hl7.fhir.r4.model.Task; import org.hl7.fhir.r4.model.Task.TaskStatus; @@ -20,9 +21,9 @@ public TaskDaoTest() } @Override - protected TaskDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected TaskDao createDao(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) { - return new TaskDaoJdbc(dataSource, fhirContext); + return new TaskDaoJdbc(dataSource, fhirContext, organizationType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ValueSetDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ValueSetDaoTest.java index ceafc4e5c..d53f379fe 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ValueSetDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ValueSetDaoTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.ValueSetDaoJdbc; import org.hl7.fhir.r4.model.ValueSet; @@ -19,9 +20,10 @@ public ValueSetDaoTest() } @Override - protected ValueSetDao createDao(BasicDataSource dataSource, FhirContext fhirContext) + protected ValueSetDao createDao(BasicDataSource dataSource, FhirContext fhirContext, + OrganizationType organizationType) { - return new ValueSetDaoJdbc(dataSource, fhirContext); + return new ValueSetDaoJdbc(dataSource, fhirContext, organizationType); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/MetaTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/MetaTest.java new file mode 100644 index 000000000..467dae634 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/MetaTest.java @@ -0,0 +1,33 @@ +package org.highmed.dsf.fhir.hapi; + +import static org.junit.Assert.*; + +import org.hl7.fhir.r4.model.CodeSystem; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ca.uhn.fhir.context.FhirContext; + +public class MetaTest +{ + private static final Logger logger = LoggerFactory.getLogger(MetaTest.class); + + @Test + public void testMetaTag() throws Exception + { + CodeSystem c = new CodeSystem(); + c.getMeta().addTag().setSystem("http://system.com/foo").setCode("TAG_CODE"); + + FhirContext context = FhirContext.forR4(); + String string = context.newJsonParser().encodeResourceToString(c); + + logger.info(string); + + CodeSystem c2 = context.newJsonParser().parseResource(CodeSystem.class, string); + assertTrue(c2.hasMeta()); + assertTrue(c2.getMeta().hasTag()); + assertEquals(1, c2.getMeta().getTag().size()); + assertEquals(c.getMeta().getTagFirstRep().getSystem(), c2.getMeta().getTagFirstRep().getSystem()); + } +} diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/java-test-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/java-test-fhir-config.properties index 7faeeab6f..a3781c0e1 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/java-test-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/java-test-fhir-config.properties @@ -7,6 +7,7 @@ org.highmed.dsf.fhir.db.server_users_group=fhir_users org.highmed.dsf.fhir.db.server_user=fhir_server_user org.highmed.dsf.fhir.db.server_user_password=gv7UJQEPPx3Yq87TWzYj +org.highmed.dsf.fhir.organizationType=MeDIC org.highmed.dsf.fhir.serverBase=https://localhost:8001/fhir org.highmed.dsf.fhir.defaultPageCount=20 From 57ee56572bf33cce000eb92546c833925090a6dd Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Wed, 19 Feb 2020 02:17:41 +0100 Subject: [PATCH 05/55] new config parameter to distinguish between MeDIC and TTP --- .../src/test/resources/integration/config.properties | 1 + .../config-templates/docker-test-fhir-config.properties | 1 + .../config-templates/docker-test-medic1-fhir-config.properties | 1 + .../config-templates/docker-test-medic2-fhir-config.properties | 1 + .../config-templates/docker-test-medic3-fhir-config.properties | 1 + .../config-templates/docker-test-ttp-fhir-config.properties | 1 + 6 files changed, 6 insertions(+) diff --git a/dsf-fhir/dsf-fhir-server/src/test/resources/integration/config.properties b/dsf-fhir/dsf-fhir-server/src/test/resources/integration/config.properties index 3319b092a..80a236e55 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/resources/integration/config.properties +++ b/dsf-fhir/dsf-fhir-server/src/test/resources/integration/config.properties @@ -3,6 +3,7 @@ org.highmed.dsf.fhir.db.url= org.highmed.dsf.fhir.db.server_user= org.highmed.dsf.fhir.db.server_user_password= +org.highmed.dsf.fhir.organizationType=MeDIC org.highmed.dsf.fhir.serverBase=https://localhost:8001/fhir org.highmed.dsf.fhir.defaultPageCount=20 diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-fhir-config.properties index 796fdb0c9..3c9f3f63c 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-fhir-config.properties @@ -7,6 +7,7 @@ org.highmed.dsf.fhir.db.server_users_group=fhir_users org.highmed.dsf.fhir.db.server_user=fhir_server_user org.highmed.dsf.fhir.db.server_user_password=xTZkzduUjYw3Bk7XQ4hYi2cRbunDAdNT +org.highmed.dsf.fhir.organizationType=MeDIC org.highmed.dsf.fhir.serverBase=https://localhost/fhir org.highmed.dsf.fhir.defaultPageCount=20 diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic1-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic1-fhir-config.properties index 4659e0938..ea2118577 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic1-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic1-fhir-config.properties @@ -7,6 +7,7 @@ org.highmed.dsf.fhir.db.server_users_group=fhir_users org.highmed.dsf.fhir.db.server_user=fhir_server_user org.highmed.dsf.fhir.db.server_user_password=jnZkystPHM52FG3ryr7YHSTsWC9wu7KW +org.highmed.dsf.fhir.organizationType=MeDIC org.highmed.dsf.fhir.serverBase=https://medic1/fhir org.highmed.dsf.fhir.defaultPageCount=20 diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic2-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic2-fhir-config.properties index b1679aba7..4e972d39e 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic2-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic2-fhir-config.properties @@ -7,6 +7,7 @@ org.highmed.dsf.fhir.db.server_users_group=fhir_users org.highmed.dsf.fhir.db.server_user=fhir_server_user org.highmed.dsf.fhir.db.server_user_password=uBtGUqB2sk3wgSbJEaxcyq3tCEjbUG6W +org.highmed.dsf.fhir.organizationType=MeDIC org.highmed.dsf.fhir.serverBase=https://medic2/fhir org.highmed.dsf.fhir.defaultPageCount=20 diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic3-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic3-fhir-config.properties index 1a67e8040..32d0e0d6b 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic3-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic3-fhir-config.properties @@ -7,6 +7,7 @@ org.highmed.dsf.fhir.db.server_users_group=fhir_users org.highmed.dsf.fhir.db.server_user=fhir_server_user org.highmed.dsf.fhir.db.server_user_password=jzrMLm6sKjkwCemEuwn98cjH2X3dV2LY +org.highmed.dsf.fhir.organizationType=MeDIC org.highmed.dsf.fhir.serverBase=https://medic3/fhir org.highmed.dsf.fhir.defaultPageCount=20 diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-ttp-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-ttp-fhir-config.properties index 633712956..83ba9f2ff 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-ttp-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-ttp-fhir-config.properties @@ -7,6 +7,7 @@ org.highmed.dsf.fhir.db.server_users_group=fhir_users org.highmed.dsf.fhir.db.server_user=fhir_server_user org.highmed.dsf.fhir.db.server_user_password=2xbELSVbMpPw7Dns9UQrmrvy9T3yzhS2 +org.highmed.dsf.fhir.organizationType=TTP org.highmed.dsf.fhir.serverBase=https://ttp/fhir org.highmed.dsf.fhir.defaultPageCount=20 From 1c2d284272b79aa06be34075b28a07d636da5d56 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Thu, 20 Feb 2020 02:14:55 +0100 Subject: [PATCH 06/55] more work on authorization rules and user filters --- .../AbstractAuthorizationRule.java | 82 +++++- .../ActivityDefinitionAuthorizationRule.java | 7 +- .../AuthorizationRuleProvider.java | 50 ++++ .../AuthorizationRuleProviderImpl.java | 244 ++++++++++++++++++ .../BinaryAuthorizationRule.java | 195 +++++++++++++- .../BundleAuthorizationRule.java | 6 +- .../CodeSystemAuthorizationRule.java | 10 +- .../EndpointAuthorizationRule.java | 6 +- .../authorization/GroupAuthorizationRule.java | 6 +- .../HealthcareServiceAuthorizationRule.java | 10 +- .../LocationAuthorizationRule.java | 6 +- .../NamingSystemAuthorizationRule.java | 7 +- .../OrganizationAuthorizationRule.java | 11 +- .../PatientAuthorizationRule.java | 6 +- .../PractitionerAuthorizationRule.java | 7 +- .../PractitionerRoleAuthorizationRule.java | 7 +- .../ProvenanceAuthorizationRule.java | 6 +- .../ResearchStudyAuthorizationRule.java | 7 +- .../StructureDefinitionAuthorizationRule.java | 7 +- .../SubscriptionAuthorizationRule.java | 9 +- .../authorization/TaskAuthorizationRule.java | 6 +- .../ValueSetAuthorizationRule.java | 10 +- .../fhir/dao/provider/DaoProviderImpl.java | 2 +- .../parameters/user/BinaryUserFilter.java | 17 +- .../fhir/service/ReferenceResolverImpl.java | 9 +- .../spring/config/AuthorizationConfig.java | 56 ++-- .../dsf/fhir/spring/config/ClientConfig.java | 4 +- .../dsf/fhir/spring/config/CommandConfig.java | 26 +- .../fhir/spring/config/ReferenceConfig.java | 38 +++ .../fhir/spring/config/WebserviceConfig.java | 109 ++++---- .../secure/AbstractServiceSecure.java | 61 ----- .../dsf/fhir/hapi/ReferenceTypTest.java | 34 ++- .../integration/BinaryIntegrationTest.java | 21 ++ 33 files changed, 852 insertions(+), 230 deletions(-) create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProvider.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProviderImpl.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/ReferenceConfig.java diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java index 703719fb1..af75af301 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java @@ -1,28 +1,55 @@ package org.highmed.dsf.fhir.authorization; +import java.util.Collection; +import java.util.EnumSet; import java.util.Objects; +import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.authentication.UserRole; import org.highmed.dsf.fhir.dao.ResourceDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.search.SearchQueryUserFilter; +import org.highmed.dsf.fhir.service.ReferenceResolver; +import org.highmed.dsf.fhir.service.ResourceReference; +import org.highmed.dsf.fhir.service.ResourceReference.ReferenceType; +import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; public abstract class AbstractAuthorizationRule<R extends Resource, D extends ResourceDao<R>> implements AuthorizationRule<R>, InitializingBean { - protected final D dao; + private static final Logger logger = LoggerFactory.getLogger(AbstractAuthorizationRule.class); - public AbstractAuthorizationRule(D dao) + protected final Class<R> resourceType; + protected final DaoProvider daoProvider; + protected final String serverBase; + protected final ReferenceResolver referenceResolver; + + public AbstractAuthorizationRule(Class<R> resourceType, DaoProvider daoProvider, String serverBase, + ReferenceResolver referenceResolver) + { + this.resourceType = resourceType; + this.daoProvider = daoProvider; + this.serverBase = serverBase; + this.referenceResolver = referenceResolver; + } + + @SuppressWarnings("unchecked") + protected final D getDao() { - this.dao = dao; + return (D) daoProvider.getDao(resourceType).orElseThrow(); } @Override public void afterPropertiesSet() throws Exception { - Objects.requireNonNull(dao, "dao"); + Objects.requireNonNull(resourceType, "resourceType"); + Objects.requireNonNull(daoProvider, "daoProvider"); } protected final boolean isLocalUser(User user) @@ -58,4 +85,51 @@ private boolean hasAuthorizationRole(Resource resource, String role) return resource.hasMeta() && resource.getMeta().getTag().stream().anyMatch( c -> SearchQueryUserFilter.AUTHORIZATION_ROLE_SYSTEM.equals(c.getSystem()) && role.equals(c.getCode())); } + + protected final boolean isCurrentUserPartOfReferencedOrganizations(User user, String referenceLocation, + Collection<? extends Reference> references) + { + return references.stream().anyMatch(r -> isCurrentUserPartOfReferencedOrganization(user, referenceLocation, r)); + } + + protected final boolean isCurrentUserPartOfReferencedOrganization(User user, String referenceLocation, + Reference reference) + { + if (reference == null) + { + logger.warn("Null reference while checking if user part of referenced organization"); + return false; + } + else + { + ResourceReference resReference = new ResourceReference(referenceLocation, reference, Organization.class); + + if (!EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL) + .contains(resReference.getType(serverBase))) + { + logger.warn("Reference of type {} not supported while checking if user part of referenced organization", + resReference.getType(serverBase)); + return false; + } + + Optional<Resource> resource = referenceResolver.resolveReference(user, resReference); + if (resource.isPresent() && resource.get() instanceof Organization) + { + boolean sameOrganization = user.getOrganization().getIdElement().equals(resource.get().getIdElement()); + if (!sameOrganization) + logger.warn( + "Current user not part organization {} while checking if user part of referenced organization", + resource.get().getIdElement().getValue()); + + return sameOrganization; + } + else + { + logger.warn( + "Reference to organization could not be resolved while checking if user part of referenced organization"); + return false; + } + } + } + } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java index d0c928b13..e49b42f89 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java @@ -4,14 +4,17 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.ActivityDefinition; public class ActivityDefinitionAuthorizationRule extends AbstractAuthorizationRule<ActivityDefinition, ActivityDefinitionDao> { - public ActivityDefinitionAuthorizationRule(ActivityDefinitionDao dao) + public ActivityDefinitionAuthorizationRule(DaoProvider daoProvider, String serverBase, + ReferenceResolver referenceResolver) { - super(dao); + super(ActivityDefinition.class, daoProvider, serverBase, referenceResolver); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProvider.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProvider.java new file mode 100644 index 000000000..be1c95114 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProvider.java @@ -0,0 +1,50 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.hl7.fhir.r4.model.Resource; + +public interface AuthorizationRuleProvider +{ + ActivityDefinitionAuthorizationRule getActivityDefinitionAuthorizationRule(); + + BinaryAuthorizationRule getBinaryAuthorizationRule(); + + BundleAuthorizationRule getBundleAuthorizationRule(); + + CodeSystemAuthorizationRule getCodeSystemAuthorizationRule(); + + EndpointAuthorizationRule getEndpointAuthorizationRule(); + + GroupAuthorizationRule getGroupAuthorizationRule(); + + HealthcareServiceAuthorizationRule getHealthcareServiceAuthorizationRule(); + + LocationAuthorizationRule getLocationAuthorizationRule(); + + NamingSystemAuthorizationRule getNamingSystemAuthorizationRule(); + + OrganizationAuthorizationRule getOrganizationAuthorizationRule(); + + PatientAuthorizationRule getPatientAuthorizationRule(); + + PractitionerAuthorizationRule getPractitionerAuthorizationRule(); + + PractitionerRoleAuthorizationRule getPractitionerRoleAuthorizationRule(); + + ProvenanceAuthorizationRule getpProvenanceAuthorizationRule(); + + ResearchStudyAuthorizationRule getResearchStudyAuthorizationRule(); + + StructureDefinitionAuthorizationRule getStructureDefinitionAuthorizationRule(); + + SubscriptionAuthorizationRule getSubscriptionAuthorizationRule(); + + TaskAuthorizationRule getTaskAuthorizationRule(); + + ValueSetAuthorizationRule getValueSetAuthorizationRule(); + + <R extends Resource> Optional<? extends AuthorizationRule<R>> getAuthorizationRule(Class<R> resourceClass); + + Optional<AuthorizationRule<?>> getAuthorizationRule(String resourceTypeName); +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProviderImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProviderImpl.java new file mode 100644 index 000000000..e86da5097 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProviderImpl.java @@ -0,0 +1,244 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import org.hl7.fhir.r4.model.ActivityDefinition; +import org.hl7.fhir.r4.model.Binary; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.CodeSystem; +import org.hl7.fhir.r4.model.Endpoint; +import org.hl7.fhir.r4.model.Group; +import org.hl7.fhir.r4.model.HealthcareService; +import org.hl7.fhir.r4.model.Location; +import org.hl7.fhir.r4.model.NamingSystem; +import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.Practitioner; +import org.hl7.fhir.r4.model.PractitionerRole; +import org.hl7.fhir.r4.model.Provenance; +import org.hl7.fhir.r4.model.ResearchStudy; +import org.hl7.fhir.r4.model.Resource; +import org.hl7.fhir.r4.model.StructureDefinition; +import org.hl7.fhir.r4.model.Subscription; +import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.ValueSet; + +import ca.uhn.fhir.model.api.annotation.ResourceDef; + +public class AuthorizationRuleProviderImpl implements AuthorizationRuleProvider +{ + private final ActivityDefinitionAuthorizationRule activityDefinitionAuthorizationRule; + private final BinaryAuthorizationRule binaryAuthorizationRule; + private final BundleAuthorizationRule bundleAuthorizationRule; + private final CodeSystemAuthorizationRule codeSystemAuthorizationRule; + private final EndpointAuthorizationRule endpointAuthorizationRule; + private final GroupAuthorizationRule groupAuthorizationRule; + private final HealthcareServiceAuthorizationRule healthcareServiceAuthorizationRule; + private final LocationAuthorizationRule locationAuthorizationRule; + private final NamingSystemAuthorizationRule namingSystemAuthorizationRule; + private final OrganizationAuthorizationRule organizationAuthorizationRule; + private final PatientAuthorizationRule patientAuthorizationRule; + private final PractitionerAuthorizationRule practitionerAuthorizationRule; + private final PractitionerRoleAuthorizationRule practitionerRoleAuthorizationRule; + private final ProvenanceAuthorizationRule provenanceAuthorizationRule; + private final ResearchStudyAuthorizationRule researchStudyAuthorizationRule; + private final StructureDefinitionAuthorizationRule structureDefinitionAuthorizationRule; + private final SubscriptionAuthorizationRule subscriptionAuthorizationRule; + private final TaskAuthorizationRule taskAuthorizationRule; + private final ValueSetAuthorizationRule valueSetAuthorizationRule; + + private final Map<Class<? extends Resource>, AuthorizationRule<?>> authorizationRulesByResourecClass = new HashMap<>(); + private final Map<String, AuthorizationRule<?>> authorizationRulesByResourceTypeName = new HashMap<>(); + + public AuthorizationRuleProviderImpl(ActivityDefinitionAuthorizationRule activityDefinitionAuthorizationRule, + BinaryAuthorizationRule binaryAuthorizationRule, BundleAuthorizationRule bundleAuthorizationRule, + CodeSystemAuthorizationRule codeSystemAuthorizationRule, + EndpointAuthorizationRule endpointAuthorizationRule, GroupAuthorizationRule groupAuthorizationRule, + HealthcareServiceAuthorizationRule healthcareServiceAuthorizationRule, + LocationAuthorizationRule locationAuthorizationRule, + NamingSystemAuthorizationRule namingSystemAuthorizationRule, + OrganizationAuthorizationRule organizationAuthorizationRule, + PatientAuthorizationRule patientAuthorizationRule, + PractitionerAuthorizationRule practitionerAuthorizationRule, + PractitionerRoleAuthorizationRule practitionerRoleAuthorizationRule, + ProvenanceAuthorizationRule provenanceAuthorizationRule, + ResearchStudyAuthorizationRule researchStudyAuthorizationRule, + StructureDefinitionAuthorizationRule structureDefinitionAuthorizationRule, + SubscriptionAuthorizationRule subscriptionAuthorizationRule, TaskAuthorizationRule taskAuthorizationRule, + ValueSetAuthorizationRule valueSetAuthorizationRule) + { + this.activityDefinitionAuthorizationRule = activityDefinitionAuthorizationRule; + this.binaryAuthorizationRule = binaryAuthorizationRule; + this.bundleAuthorizationRule = bundleAuthorizationRule; + this.codeSystemAuthorizationRule = codeSystemAuthorizationRule; + this.endpointAuthorizationRule = endpointAuthorizationRule; + this.groupAuthorizationRule = groupAuthorizationRule; + this.healthcareServiceAuthorizationRule = healthcareServiceAuthorizationRule; + this.locationAuthorizationRule = locationAuthorizationRule; + this.namingSystemAuthorizationRule = namingSystemAuthorizationRule; + this.organizationAuthorizationRule = organizationAuthorizationRule; + this.patientAuthorizationRule = patientAuthorizationRule; + this.practitionerAuthorizationRule = practitionerAuthorizationRule; + this.practitionerRoleAuthorizationRule = practitionerRoleAuthorizationRule; + this.provenanceAuthorizationRule = provenanceAuthorizationRule; + this.researchStudyAuthorizationRule = researchStudyAuthorizationRule; + this.structureDefinitionAuthorizationRule = structureDefinitionAuthorizationRule; + this.subscriptionAuthorizationRule = subscriptionAuthorizationRule; + this.taskAuthorizationRule = taskAuthorizationRule; + this.valueSetAuthorizationRule = valueSetAuthorizationRule; + + authorizationRulesByResourecClass.put(ActivityDefinition.class, activityDefinitionAuthorizationRule); + authorizationRulesByResourecClass.put(Binary.class, binaryAuthorizationRule); + authorizationRulesByResourecClass.put(Bundle.class, bundleAuthorizationRule); + authorizationRulesByResourecClass.put(CodeSystem.class, codeSystemAuthorizationRule); + authorizationRulesByResourecClass.put(Endpoint.class, endpointAuthorizationRule); + authorizationRulesByResourecClass.put(Group.class, groupAuthorizationRule); + authorizationRulesByResourecClass.put(HealthcareService.class, healthcareServiceAuthorizationRule); + authorizationRulesByResourecClass.put(Location.class, locationAuthorizationRule); + authorizationRulesByResourecClass.put(NamingSystem.class, namingSystemAuthorizationRule); + authorizationRulesByResourecClass.put(Organization.class, organizationAuthorizationRule); + authorizationRulesByResourecClass.put(Patient.class, patientAuthorizationRule); + authorizationRulesByResourecClass.put(Practitioner.class, practitionerAuthorizationRule); + authorizationRulesByResourecClass.put(PractitionerRole.class, practitionerRoleAuthorizationRule); + authorizationRulesByResourecClass.put(Provenance.class, provenanceAuthorizationRule); + authorizationRulesByResourecClass.put(ResearchStudy.class, researchStudyAuthorizationRule); + authorizationRulesByResourecClass.put(StructureDefinition.class, structureDefinitionAuthorizationRule); + authorizationRulesByResourecClass.put(Subscription.class, subscriptionAuthorizationRule); + authorizationRulesByResourecClass.put(Task.class, taskAuthorizationRule); + authorizationRulesByResourecClass.put(ValueSet.class, valueSetAuthorizationRule); + + authorizationRulesByResourecClass.forEach((k, v) -> authorizationRulesByResourceTypeName.put(k.getAnnotation(ResourceDef.class).name(), v)); + } + + @Override + public ActivityDefinitionAuthorizationRule getActivityDefinitionAuthorizationRule() + { + return activityDefinitionAuthorizationRule; + } + + @Override + public BinaryAuthorizationRule getBinaryAuthorizationRule() + { + return binaryAuthorizationRule; + } + + @Override + public BundleAuthorizationRule getBundleAuthorizationRule() + { + return bundleAuthorizationRule; + } + + @Override + public CodeSystemAuthorizationRule getCodeSystemAuthorizationRule() + { + return codeSystemAuthorizationRule; + } + + @Override + public EndpointAuthorizationRule getEndpointAuthorizationRule() + { + return endpointAuthorizationRule; + } + + @Override + public GroupAuthorizationRule getGroupAuthorizationRule() + { + return groupAuthorizationRule; + } + + @Override + public HealthcareServiceAuthorizationRule getHealthcareServiceAuthorizationRule() + { + return healthcareServiceAuthorizationRule; + } + + @Override + public LocationAuthorizationRule getLocationAuthorizationRule() + { + return locationAuthorizationRule; + } + + @Override + public NamingSystemAuthorizationRule getNamingSystemAuthorizationRule() + { + return namingSystemAuthorizationRule; + } + + @Override + public OrganizationAuthorizationRule getOrganizationAuthorizationRule() + { + return organizationAuthorizationRule; + } + + @Override + public PatientAuthorizationRule getPatientAuthorizationRule() + { + return patientAuthorizationRule; + } + + @Override + public PractitionerAuthorizationRule getPractitionerAuthorizationRule() + { + return practitionerAuthorizationRule; + } + + @Override + public PractitionerRoleAuthorizationRule getPractitionerRoleAuthorizationRule() + { + return practitionerRoleAuthorizationRule; + } + + @Override + public ProvenanceAuthorizationRule getpProvenanceAuthorizationRule() + { + return provenanceAuthorizationRule; + } + + @Override + public ResearchStudyAuthorizationRule getResearchStudyAuthorizationRule() + { + return researchStudyAuthorizationRule; + } + + @Override + public StructureDefinitionAuthorizationRule getStructureDefinitionAuthorizationRule() + { + return structureDefinitionAuthorizationRule; + } + + @Override + public SubscriptionAuthorizationRule getSubscriptionAuthorizationRule() + { + return subscriptionAuthorizationRule; + } + + @Override + public TaskAuthorizationRule getTaskAuthorizationRule() + { + return taskAuthorizationRule; + } + + @Override + public ValueSetAuthorizationRule getValueSetAuthorizationRule() + { + return valueSetAuthorizationRule; + } + + @Override + public <R extends Resource> Optional<? extends AuthorizationRule<R>> getAuthorizationRule(Class<R> resourceClass) + { + @SuppressWarnings("unchecked") + AuthorizationRule<R> authorizationRule = (AuthorizationRule<R>) authorizationRulesByResourecClass + .get(resourceClass); + return Optional.ofNullable(authorizationRule); + } + + @Override + public Optional<AuthorizationRule<?>> getAuthorizationRule(String resourceTypeName) + { + AuthorizationRule<?> authorizationRule = authorizationRulesByResourceTypeName.get(resourceTypeName); + return Optional.ofNullable(authorizationRule); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java index 62a552451..1246c4f40 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java @@ -1,50 +1,221 @@ package org.highmed.dsf.fhir.authorization; +import java.util.EnumSet; import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.BinaryDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; +import org.highmed.dsf.fhir.service.ResourceReference; +import org.highmed.dsf.fhir.service.ResourceReference.ReferenceType; +import org.hl7.fhir.r4.model.ActivityDefinition; import org.hl7.fhir.r4.model.Binary; +import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.ResearchStudy; +import org.hl7.fhir.r4.model.Resource; +import org.hl7.fhir.r4.model.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class BinaryAuthorizationRule extends AbstractAuthorizationRule<Binary, BinaryDao> { - public BinaryAuthorizationRule(BinaryDao dao) + private static final Logger logger = LoggerFactory.getLogger(BinaryAuthorizationRule.class); + + public BinaryAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { - super(dao); + super(Binary.class, daoProvider, serverBase, referenceResolver); } @Override public Optional<String> reasonCreateAllowed(User user, Binary newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + if (newResource.hasData() && newResource.hasContentType() && newResource.hasSecurityContext()) + { + ResourceReference reference = new ResourceReference("Binary.SecurityContext", + newResource.getSecurityContext(), ActivityDefinition.class, Organization.class, + ResearchStudy.class, Task.class); + if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL) + .contains(reference.getType(serverBase))) + { + Optional<Resource> securityContext = referenceResolver.resolveReference(user, reference); + if (securityContext.isPresent()) + { + logger.info("Create of Binary authorized for local user '{}', Binary.SecurityContext resolved", + user.getName()); + return Optional.of("local user, Binary.SecurityContext resolved"); + } + else + { + logger.warn("Create of Binary unauthorized, securityContext reference could not be resolved"); + return Optional.empty(); + } + } + else + { + logger.warn( + "Create of Binary unauthorized, securityContext not a literal internal or logical reference"); + return Optional.empty(); + } + } + else + { + logger.warn("Create of Binary unauthorized, missing data or contentType or securityContext"); + return Optional.empty(); + } + } + else + { + logger.warn("Create of Binary unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonReadAllowed(User user, Binary existingResource) { - // TODO Auto-generated method stub - return Optional.empty(); + ResourceReference reference = new ResourceReference("Binary.SecurityContext", + existingResource.getSecurityContext(), ActivityDefinition.class, Organization.class, + ResearchStudy.class, Task.class); + if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL).contains(reference.getType(serverBase))) + { + Optional<Resource> securityContext = referenceResolver.resolveReference(user, reference); + if (securityContext.isPresent()) + { + logger.info( + "Read of Binary authorized, Binary.SecurityContext reference could be resolved for user '{}'", + user.getName()); + return Optional.of("Binary.SecurityContext resolved"); + } + else + { + logger.warn( + "Read of Binary unauthorized, securityContext reference could not be resolved for user '{}'", + user.getName()); + return Optional.empty(); + } + } + else + { + logger.warn("Read of Binary unauthorized, securityContext not a literal internal or logical reference"); + return Optional.empty(); + } } @Override public Optional<String> reasonUpdateAllowed(User user, Binary oldResource, Binary newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + if (newResource.hasData() && newResource.hasContentType() && newResource.hasSecurityContext()) + { + ResourceReference oldReference = new ResourceReference("Binary.SecurityContext", + oldResource.getSecurityContext(), ActivityDefinition.class, Organization.class, + ResearchStudy.class, Task.class); + ResourceReference newReference = new ResourceReference("Binary.SecurityContext", + newResource.getSecurityContext(), ActivityDefinition.class, Organization.class, + ResearchStudy.class, Task.class); + if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL) + .contains(oldReference.getType(serverBase)) + && EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL) + .contains(newReference.getType(serverBase))) + { + Optional<Resource> oldSecurityContext = referenceResolver.resolveReference(user, oldReference); + Optional<Resource> newSecurityContext = referenceResolver.resolveReference(user, newReference); + if (oldSecurityContext.isPresent() && newSecurityContext.isPresent()) + { + logger.info( + "Update of Binary authorized for local user '{}', Binary.SecurityContext could be resolved (old and new)", + user.getName()); + return Optional.of("local user, Binary.SecurityContext resolved"); + } + else + { + logger.warn( + "Update of Binary unauthorized, securityContext reference could not be resolved (old or new)"); + return Optional.empty(); + } + } + else + { + logger.warn( + "Update of Binary unauthorized, securityContext not a literal internal or logical reference (old or new)"); + return Optional.empty(); + } + } + else + { + logger.warn("Update of Binary unauthorized, missing data or contentType or securityContext"); + return Optional.empty(); + } + } + else + { + logger.warn("Update of Binary unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonDeleteAllowed(User user, Binary oldResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + if (oldResource.hasData() && oldResource.hasContentType() && oldResource.hasSecurityContext()) + { + ResourceReference reference = new ResourceReference("Binary.SecurityContext", + oldResource.getSecurityContext(), ActivityDefinition.class, Organization.class, + ResearchStudy.class, Task.class); + if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL) + .contains(reference.getType(serverBase))) + { + Optional<Resource> securityContext = referenceResolver.resolveReference(user, reference); + if (securityContext.isPresent()) + { + logger.info("Delete of Binary authorized for local user '{}', Binary.SecurityContext resolved", + user.getName()); + return Optional.of("local user, Binary.SecurityContext resolved"); + } + else + { + logger.warn("Delete of Binary unauthorized, securityContext reference could not be resolved"); + return Optional.empty(); + } + } + else + { + logger.warn( + "Delete of Binary unauthorized, securityContext not a literal internal or logical reference"); + return Optional.empty(); + } + } + else + { + logger.warn("Delete of Binary unauthorized, missing data or contentType or securityContext"); + return Optional.empty(); + } + } + else + { + logger.warn("Delete of Binary unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonSearchAllowed(User user) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Search of Binary authorized for {} user '{}'", user.getRole(), user.getName()); + return Optional.of("Allowed for local users"); + } + else + { + logger.warn("Search of Binary unauthorized, not a local user"); + return Optional.empty(); + } } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java index 683e49ba5..8c06f650b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java @@ -4,13 +4,15 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.BundleDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Bundle; public class BundleAuthorizationRule extends AbstractAuthorizationRule<Bundle, BundleDao> { - public BundleAuthorizationRule(BundleDao dao) + public BundleAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { - super(dao); + super(Bundle.class, daoProvider, serverBase, referenceResolver); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java index ed922ca95..db8d5d0df 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java @@ -5,6 +5,8 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.CodeSystemDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.CodeSystem; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,9 +15,9 @@ public class CodeSystemAuthorizationRule extends AbstractAuthorizationRule<CodeS { private static final Logger logger = LoggerFactory.getLogger(CodeSystemAuthorizationRule.class); - public CodeSystemAuthorizationRule(CodeSystemDao dao) + public CodeSystemAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { - super(dao); + super(CodeSystem.class, daoProvider, serverBase, referenceResolver); } @Override @@ -23,12 +25,12 @@ public Optional<String> reasonCreateAllowed(User user, CodeSystem newResource) { if (isLocalUser(user)) { + // TODO move check for url, version, authorization tag, to validation layer if (newResource.hasUrl() && newResource.hasVersion() && hasLocalOrRemoteAuthorizationRole(newResource)) { try { - // TODO move check for url, version, authorization tag, to validation layer - Optional<CodeSystem> existing = dao.readByUrlAndVersion(newResource.getUrl(), + Optional<CodeSystem> existing = getDao().readByUrlAndVersion(newResource.getUrl(), newResource.getVersion()); if (existing.isEmpty()) { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java index 55fe3d9db..5b5845389 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java @@ -4,13 +4,15 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.EndpointDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Endpoint; public class EndpointAuthorizationRule extends AbstractAuthorizationRule<Endpoint, EndpointDao> { - public EndpointAuthorizationRule(EndpointDao dao) + public EndpointAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { - super(dao); + super(Endpoint.class, daoProvider, serverBase, referenceResolver); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java index 195a04fa1..a8d2dd64e 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java @@ -4,13 +4,15 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.GroupDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Group; public class GroupAuthorizationRule extends AbstractAuthorizationRule<Group, GroupDao> { - public GroupAuthorizationRule(GroupDao dao) + public GroupAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { - super(dao); + super(Group.class, daoProvider, serverBase, referenceResolver); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java index 20c480dd9..b47ec3e4a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java @@ -4,13 +4,17 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.HealthcareServiceDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.HealthcareService; -public class HealthcareServiceAuthorizationRule extends AbstractAuthorizationRule<HealthcareService, HealthcareServiceDao> +public class HealthcareServiceAuthorizationRule + extends AbstractAuthorizationRule<HealthcareService, HealthcareServiceDao> { - public HealthcareServiceAuthorizationRule(HealthcareServiceDao dao) + public HealthcareServiceAuthorizationRule(DaoProvider daoProvider, String serverBase, + ReferenceResolver referenceResolver) { - super(dao); + super(HealthcareService.class, daoProvider, serverBase, referenceResolver); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java index ccb07d514..9925c0383 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java @@ -4,13 +4,15 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.LocationDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Location; public class LocationAuthorizationRule extends AbstractAuthorizationRule<Location, LocationDao> { - public LocationAuthorizationRule(LocationDao dao) + public LocationAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { - super(dao); + super(Location.class, daoProvider, serverBase, referenceResolver); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java index e2356fa51..7258c203b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java @@ -4,13 +4,16 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.NamingSystemDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.NamingSystem; public class NamingSystemAuthorizationRule extends AbstractAuthorizationRule<NamingSystem, NamingSystemDao> { - public NamingSystemAuthorizationRule(NamingSystemDao dao) + public NamingSystemAuthorizationRule(DaoProvider daoProvider, String serverBase, + ReferenceResolver referenceResolver) { - super(dao); + super(NamingSystem.class, daoProvider, serverBase, referenceResolver); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java index a733baa7f..d800309cf 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java @@ -4,13 +4,16 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.OrganizationDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Organization; public class OrganizationAuthorizationRule extends AbstractAuthorizationRule<Organization, OrganizationDao> { - public OrganizationAuthorizationRule(OrganizationDao dao) + public OrganizationAuthorizationRule(DaoProvider daoProvider, String serverBase, + ReferenceResolver referenceResolver) { - super(dao); + super(Organization.class, daoProvider, serverBase, referenceResolver); } @Override @@ -19,7 +22,7 @@ public Optional<String> reasonCreateAllowed(User user, Organization newResource) // check organization not existing if contains identifier with identifier.system (or extension) // http://highmed.org/fhir/NamingSystem/certificate-thumbprint-hex with same identifier.value // no two organizations can have the same certificate thumb-print - + // TODO Auto-generated method stub return Optional.empty(); } @@ -28,7 +31,7 @@ public Optional<String> reasonCreateAllowed(User user, Organization newResource) public Optional<String> reasonReadAllowed(User user, Organization existingResource) { // see create, no two organizations can have the same certificate thumb-print - + // TODO Auto-generated method stub return Optional.empty(); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java index 57f1e435f..e0860438b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java @@ -4,13 +4,15 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.PatientDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Patient; public class PatientAuthorizationRule extends AbstractAuthorizationRule<Patient, PatientDao> { - public PatientAuthorizationRule(PatientDao dao) + public PatientAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { - super(dao); + super(Patient.class, daoProvider, serverBase, referenceResolver); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java index 9e0291537..a49d7a97a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java @@ -4,13 +4,16 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.PractitionerDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Practitioner; public class PractitionerAuthorizationRule extends AbstractAuthorizationRule<Practitioner, PractitionerDao> { - public PractitionerAuthorizationRule(PractitionerDao dao) + public PractitionerAuthorizationRule(DaoProvider daoProvider, String serverBase, + ReferenceResolver referenceResolver) { - super(dao); + super(Practitioner.class, daoProvider, serverBase, referenceResolver); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java index 162384968..bf9d1de08 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java @@ -4,13 +4,16 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.PractitionerRoleDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.PractitionerRole; public class PractitionerRoleAuthorizationRule extends AbstractAuthorizationRule<PractitionerRole, PractitionerRoleDao> { - public PractitionerRoleAuthorizationRule(PractitionerRoleDao dao) + public PractitionerRoleAuthorizationRule(DaoProvider daoProvider, String serverBase, + ReferenceResolver referenceResolver) { - super(dao); + super(PractitionerRole.class, daoProvider, serverBase, referenceResolver); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java index 3fe5c090a..f04deaad6 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java @@ -4,13 +4,15 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ProvenanceDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Provenance; public class ProvenanceAuthorizationRule extends AbstractAuthorizationRule<Provenance, ProvenanceDao> { - public ProvenanceAuthorizationRule(ProvenanceDao dao) + public ProvenanceAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { - super(dao); + super(Provenance.class, daoProvider, serverBase, referenceResolver); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java index 30c4e753c..55a73ae5f 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java @@ -4,13 +4,16 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ResearchStudyDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.ResearchStudy; public class ResearchStudyAuthorizationRule extends AbstractAuthorizationRule<ResearchStudy, ResearchStudyDao> { - public ResearchStudyAuthorizationRule(ResearchStudyDao dao) + public ResearchStudyAuthorizationRule(DaoProvider daoProvider, String serverBase, + ReferenceResolver referenceResolver) { - super(dao); + super(ResearchStudy.class, daoProvider, serverBase, referenceResolver); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java index 40461b8e9..f58aa4ffc 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java @@ -4,14 +4,17 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.StructureDefinitionDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.StructureDefinition; public class StructureDefinitionAuthorizationRule extends AbstractAuthorizationRule<StructureDefinition, StructureDefinitionDao> { - public StructureDefinitionAuthorizationRule(StructureDefinitionDao dao) + public StructureDefinitionAuthorizationRule(DaoProvider daoProvider, String serverBase, + ReferenceResolver referenceResolver) { - super(dao); + super(StructureDefinition.class, daoProvider, serverBase, referenceResolver); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java index fc5e2261d..c8c5941ba 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java @@ -4,13 +4,16 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.SubscriptionDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Subscription; public class SubscriptionAuthorizationRule extends AbstractAuthorizationRule<Subscription, SubscriptionDao> { - public SubscriptionAuthorizationRule(SubscriptionDao dao) + public SubscriptionAuthorizationRule(DaoProvider daoProvider, String serverBase, + ReferenceResolver referenceResolver) { - super(dao); + super(Subscription.class, daoProvider, serverBase, referenceResolver); } @Override @@ -20,7 +23,7 @@ public Optional<String> reasonCreateAllowed(User user, Subscription newResource) // check subscription.channel.type = websocket // check subscription.criteria is implemented as search query // check if subscription.channel.type = websocket, Task unique on subscription.criteria - + // TODO Auto-generated method stub return Optional.empty(); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java index ead057701..d904eeb88 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java @@ -4,13 +4,15 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.TaskDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Task; public class TaskAuthorizationRule extends AbstractAuthorizationRule<Task, TaskDao> { - public TaskAuthorizationRule(TaskDao dao) + public TaskAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { - super(dao); + super(Task.class, daoProvider, serverBase, referenceResolver); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ValueSetAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ValueSetAuthorizationRule.java index f8d567e62..44d00fafd 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ValueSetAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ValueSetAuthorizationRule.java @@ -5,6 +5,8 @@ import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ValueSetDao; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.ValueSet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,9 +15,9 @@ public class ValueSetAuthorizationRule extends AbstractAuthorizationRule<ValueSe { private static final Logger logger = LoggerFactory.getLogger(ValueSetAuthorizationRule.class); - public ValueSetAuthorizationRule(ValueSetDao dao) + public ValueSetAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { - super(dao); + super(ValueSet.class, daoProvider, serverBase, referenceResolver); } @Override @@ -23,12 +25,12 @@ public Optional<String> reasonCreateAllowed(User user, ValueSet newResource) { if (isLocalUser(user)) { + // TODO move check for url, version, authorization tag, to validation layer if (newResource.hasUrl() && newResource.hasVersion() && hasLocalOrRemoteAuthorizationRole(newResource)) { try { - // TODO move check for url, version, authorization tag, to validation layer - Optional<ValueSet> existing = dao.readByUrlAndVersion(newResource.getUrl(), + Optional<ValueSet> existing = getDao().readByUrlAndVersion(newResource.getUrl(), newResource.getVersion()); if (existing.isEmpty()) { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProviderImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProviderImpl.java index 867e81c7f..343a403c6 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProviderImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProviderImpl.java @@ -275,9 +275,9 @@ public ValueSetDao getValueSetDao() } @Override - @SuppressWarnings("unchecked") public <R extends Resource> Optional<? extends ResourceDao<R>> getDao(Class<R> resourceClass) { + @SuppressWarnings("unchecked") ResourceDao<R> value = (ResourceDao<R>) daosByResourecClass.get(resourceClass); return Optional.ofNullable(value); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java index 07f5b5452..e0611788a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java @@ -5,6 +5,7 @@ import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.authentication.UserRole; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,24 +21,24 @@ public BinaryUserFilter(OrganizationType organizationType, User user) @Override public String getFilterQuery() { - // TODO implement - - logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); - return "false"; + if (UserRole.LOCAL.equals(user.getRole())) + return ""; + else + { + logger.warn("Filter query for non local user -> 'false'"); + return "false"; + } } @Override public int getSqlParameterCount() { - logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); return 0; } @Override public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException { - // TODO implement - - logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + // nothing to do } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolverImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolverImpl.java index 5543a3e95..8a477a74a 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolverImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolverImpl.java @@ -75,7 +75,7 @@ public Optional<Resource> resolveReference(User user, String referenceLocation, { Objects.requireNonNull(user, "user"); Objects.requireNonNull(reference, "reference"); - + return resolveReference(user, new ResourceReference(referenceLocation, reference, referenceTypes)); } @@ -84,7 +84,7 @@ public Optional<Resource> resolveReference(User user, ResourceReference referenc { Objects.requireNonNull(user, "user"); Objects.requireNonNull(reference, "reference"); - + switch (reference.getType(serverBase)) { case LITERAL_INTERNAL: @@ -102,7 +102,8 @@ public Optional<Resource> resolveReference(User user, ResourceReference referenc } @Override - public boolean resolveReference(User user, Resource resource, ResourceReference resourceReference, Connection connection) + public boolean resolveReference(User user, Resource resource, ResourceReference resourceReference, + Connection connection) { return resolveReference(user, resource, null, resourceReference, connection); } @@ -160,7 +161,7 @@ private Optional<Resource> resolveLiteralInternalReference(ResourceReference res Optional<UUID> uuid = parameterConverter.toUuid(id.getIdPart()); - if (id.hasVersionIdPart()) + if (!id.hasVersionIdPart()) return uuid.flatMap(i -> exceptionHandler.catchAndLogSqlAndResourceDeletedExceptionAndIfReturn( () -> d.read(i), Optional::empty, Optional::empty)); else diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthorizationConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthorizationConfig.java index 56bc4fe85..9324270cd 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthorizationConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthorizationConfig.java @@ -20,126 +20,144 @@ import org.highmed.dsf.fhir.authorization.TaskAuthorizationRule; import org.highmed.dsf.fhir.authorization.ValueSetAuthorizationRule; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AuthorizationConfig { + @Value("${org.highmed.dsf.fhir.serverBase}") + private String serverBase; + @Autowired private DaoConfig daoConfig; + @Autowired + private ReferenceConfig referenceConfig; + @Bean public ActivityDefinitionAuthorizationRule activityDefinitionAuthorizationRule() { - return new ActivityDefinitionAuthorizationRule(daoConfig.activityDefinitionDao()); + return new ActivityDefinitionAuthorizationRule(daoConfig.daoProvider(), serverBase, + referenceConfig.referenceResolver()); } @Bean public BinaryAuthorizationRule binaryAuthorizationRule() { - return new BinaryAuthorizationRule(daoConfig.binaryDao()); + return new BinaryAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); } @Bean public BundleAuthorizationRule bundleAuthorizationRule() { - return new BundleAuthorizationRule(daoConfig.bundleDao()); + return new BundleAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); } @Bean public CodeSystemAuthorizationRule codeSystemAuthorizationRule() { - return new CodeSystemAuthorizationRule(daoConfig.codeSystemDao()); + return new CodeSystemAuthorizationRule(daoConfig.daoProvider(), serverBase, + referenceConfig.referenceResolver()); } @Bean public EndpointAuthorizationRule endpointAuthorizationRule() { - return new EndpointAuthorizationRule(daoConfig.endpointDao()); + return new EndpointAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); } @Bean public GroupAuthorizationRule groupAuthorizationRule() { - return new GroupAuthorizationRule(daoConfig.groupDao()); + return new GroupAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); } @Bean public HealthcareServiceAuthorizationRule healthcareServiceAuthorizationRule() { - return new HealthcareServiceAuthorizationRule(daoConfig.healthcareServiceDao()); + return new HealthcareServiceAuthorizationRule(daoConfig.daoProvider(), serverBase, + referenceConfig.referenceResolver()); } @Bean public LocationAuthorizationRule locationAuthorizationRule() { - return new LocationAuthorizationRule(daoConfig.locationDao()); + return new LocationAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); } @Bean public NamingSystemAuthorizationRule namingSystemAuthorizationRule() { - return new NamingSystemAuthorizationRule(daoConfig.namingSystemDao()); + return new NamingSystemAuthorizationRule(daoConfig.daoProvider(), serverBase, + referenceConfig.referenceResolver()); } @Bean public OrganizationAuthorizationRule organizationAuthorizationRule() { - return new OrganizationAuthorizationRule(daoConfig.organizationDao()); + return new OrganizationAuthorizationRule(daoConfig.daoProvider(), serverBase, + referenceConfig.referenceResolver()); } @Bean public PatientAuthorizationRule patientAuthorizationRule() { - return new PatientAuthorizationRule(daoConfig.patientDao()); + return new PatientAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); } @Bean public PractitionerAuthorizationRule practitionerAuthorizationRule() { - return new PractitionerAuthorizationRule(daoConfig.practitionerDao()); + return new PractitionerAuthorizationRule(daoConfig.daoProvider(), serverBase, + referenceConfig.referenceResolver()); } @Bean public PractitionerRoleAuthorizationRule practitionerRoleAuthorizationRule() { - return new PractitionerRoleAuthorizationRule(daoConfig.practitionerRoleDao()); + return new PractitionerRoleAuthorizationRule(daoConfig.daoProvider(), serverBase, + referenceConfig.referenceResolver()); } @Bean public ProvenanceAuthorizationRule provenanceAuthorizationRule() { - return new ProvenanceAuthorizationRule(daoConfig.provenanceDao()); + return new ProvenanceAuthorizationRule(daoConfig.daoProvider(), serverBase, + referenceConfig.referenceResolver()); } @Bean public ResearchStudyAuthorizationRule researchStudyAuthorizationRule() { - return new ResearchStudyAuthorizationRule(daoConfig.researchStudyDao()); + return new ResearchStudyAuthorizationRule(daoConfig.daoProvider(), serverBase, + referenceConfig.referenceResolver()); } @Bean public StructureDefinitionAuthorizationRule structureDefinitionAuthorizationRule() { - return new StructureDefinitionAuthorizationRule(daoConfig.structureDefinitionDao()); + return new StructureDefinitionAuthorizationRule(daoConfig.daoProvider(), serverBase, + referenceConfig.referenceResolver()); } @Bean public SubscriptionAuthorizationRule subscriptionAuthorizationRule() { - return new SubscriptionAuthorizationRule(daoConfig.subscriptionDao()); + return new SubscriptionAuthorizationRule(daoConfig.daoProvider(), serverBase, + referenceConfig.referenceResolver()); } @Bean public TaskAuthorizationRule taskAuthorizationRule() { - return new TaskAuthorizationRule(daoConfig.taskDao()); + return new TaskAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); } @Bean public ValueSetAuthorizationRule valueSetAuthorizationRule() { - return new ValueSetAuthorizationRule(daoConfig.valueSetDao()); + return new ValueSetAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/ClientConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/ClientConfig.java index 077ea2dfd..63f43091d 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/ClientConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/ClientConfig.java @@ -53,7 +53,7 @@ public class ClientConfig private HelperConfig helperConfig; @Autowired - private CommandConfig commandConfig; + private ReferenceConfig referenceConfig; @Bean public ClientProvider clientProvider() @@ -70,7 +70,7 @@ public ClientProvider clientProvider() return new ClientProviderImpl(webserviceTrustStore, webserviceKeyStore, webserviceKeyStorePassword, remoteReadTimeout, remoteConnectTimeout, remoteProxyPassword, remoteProxyUsername, - remoteProxySchemeHostPort, fhirConfig.fhirContext(), commandConfig.referenceExtractor(), + remoteProxySchemeHostPort, fhirConfig.fhirContext(), referenceConfig.referenceExtractor(), daoConfig.endpointDao(), helperConfig.exceptionHandler()); } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException e) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/CommandConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/CommandConfig.java index 919aab13b..1a7c9a7f9 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/CommandConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/CommandConfig.java @@ -2,9 +2,6 @@ import org.highmed.dsf.fhir.dao.command.CommandFactory; import org.highmed.dsf.fhir.dao.command.CommandFactoryImpl; -import org.highmed.dsf.fhir.service.ReferenceExtractorImpl; -import org.highmed.dsf.fhir.service.ReferenceResolver; -import org.highmed.dsf.fhir.service.ReferenceResolverImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -32,28 +29,15 @@ public class CommandConfig private EventConfig eventConfig; @Autowired - private ClientConfig clientConfig; - - @Bean - public ReferenceExtractorImpl referenceExtractor() - { - return new ReferenceExtractorImpl(); - } - - @Bean - public ReferenceResolver referenceResolver() - { - return new ReferenceResolverImpl(serverBase, daoConfig.daoProvider(), helperConfig.responseGenerator(), - helperConfig.exceptionHandler(), clientConfig.clientProvider(), helperConfig.parameterConverter()); - } + private ReferenceConfig referenceConfig; @Bean public CommandFactory commandFactory() { return new CommandFactoryImpl(serverBase, defaultPageCount, daoConfig.dataSource(), daoConfig.daoProvider(), - referenceExtractor(), referenceResolver(), helperConfig.responseGenerator(), - helperConfig.exceptionHandler(), eventConfig.eventManager(), eventConfig.eventGenerator(), - snapshotConfig.snapshotGenerator(), snapshotConfig.snapshotDependencyAnalyzer(), - helperConfig.parameterConverter()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver(), + helperConfig.responseGenerator(), helperConfig.exceptionHandler(), eventConfig.eventManager(), + eventConfig.eventGenerator(), snapshotConfig.snapshotGenerator(), + snapshotConfig.snapshotDependencyAnalyzer(), helperConfig.parameterConverter()); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/ReferenceConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/ReferenceConfig.java new file mode 100644 index 000000000..49893430c --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/ReferenceConfig.java @@ -0,0 +1,38 @@ +package org.highmed.dsf.fhir.spring.config; + +import org.highmed.dsf.fhir.service.ReferenceExtractorImpl; +import org.highmed.dsf.fhir.service.ReferenceResolver; +import org.highmed.dsf.fhir.service.ReferenceResolverImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ReferenceConfig +{ + @Value("${org.highmed.dsf.fhir.serverBase}") + private String serverBase; + + @Autowired + private HelperConfig helperConfig; + + @Autowired + private DaoConfig daoConfig; + + @Autowired + private ClientConfig clientConfig; + + @Bean + public ReferenceExtractorImpl referenceExtractor() + { + return new ReferenceExtractorImpl(); + } + + @Bean + public ReferenceResolver referenceResolver() + { + return new ReferenceResolverImpl(serverBase, daoConfig.daoProvider(), helperConfig.responseGenerator(), + helperConfig.exceptionHandler(), clientConfig.clientProvider(), helperConfig.parameterConverter()); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java index 5bcdf52ce..71aaa1ce5 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java @@ -127,6 +127,9 @@ public class WebserviceConfig @Autowired private AuthorizationConfig authorizationConfig; + @Autowired + private ReferenceConfig referenceConfig; + @Bean public ServerBaseProvider serverBaseProvider() { @@ -142,8 +145,8 @@ public ActivityDefinitionService activityDefinitionService() private ActivityDefinitionServiceSecure activityDefinitionServiceSecure() { return new ActivityDefinitionServiceSecure(activityDefinitionServiceImpl(), serverBase, - helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.activityDefinitionDao(), - helperConfig.exceptionHandler(), helperConfig.parameterConverter(), + helperConfig.responseGenerator(), referenceConfig.referenceResolver(), + daoConfig.activityDefinitionDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.activityDefinitionAuthorizationRule()); } @@ -152,8 +155,8 @@ private ActivityDefinitionServiceImpl activityDefinitionServiceImpl() return new ActivityDefinitionServiceImpl(ActivityDefinitionServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.activityDefinitionDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), - helperConfig.parameterConverter(), commandConfig.referenceExtractor(), - commandConfig.referenceResolver()); + helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), + referenceConfig.referenceResolver()); } @Bean @@ -165,7 +168,7 @@ public CodeSystemService codeSystemService() private CodeSystemServiceSecure codeSystemServiceSecure() { return new CodeSystemServiceSecure(codeSystemServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver(), daoConfig.codeSystemDao(), helperConfig.exceptionHandler(), + referenceConfig.referenceResolver(), daoConfig.codeSystemDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.codeSystemAuthorizationRule()); } @@ -174,8 +177,8 @@ private CodeSystemServiceImpl codeSystemServiceImpl() return new CodeSystemServiceImpl(CodeSystemServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.codeSystemDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), - helperConfig.parameterConverter(), commandConfig.referenceExtractor(), - commandConfig.referenceResolver()); + helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), + referenceConfig.referenceResolver()); } @Bean @@ -187,7 +190,7 @@ public BinaryService binaryService() private BinaryServiceSecure binaryServiceSecure() { return new BinaryServiceSecure(binaryServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver(), daoConfig.binaryDao(), helperConfig.exceptionHandler(), + referenceConfig.referenceResolver(), daoConfig.binaryDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.binaryAuthorizationRule()); } @@ -196,7 +199,7 @@ private BinaryService binaryServiceImpl() return new BinaryServiceImpl(BinaryServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.binaryDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), - commandConfig.referenceExtractor(), commandConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); } @Bean @@ -208,7 +211,7 @@ public BundleService bundleService() private BundleServiceSecure bundleServiceSecure() { return new BundleServiceSecure(bundleServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver(), daoConfig.bundleDao(), helperConfig.exceptionHandler(), + referenceConfig.referenceResolver(), daoConfig.bundleDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.bundleAuthorizationRule()); } @@ -217,7 +220,7 @@ private BundleService bundleServiceImpl() return new BundleServiceImpl(BundleServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.bundleDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), - commandConfig.referenceExtractor(), commandConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); } @Bean @@ -229,7 +232,7 @@ public EndpointService endpointService() private EndpointServiceSecure endpointServiceSecure() { return new EndpointServiceSecure(endpointServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver(), daoConfig.endpointDao(), helperConfig.exceptionHandler(), + referenceConfig.referenceResolver(), daoConfig.endpointDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.endpointAuthorizationRule()); } @@ -238,7 +241,7 @@ private EndpointServiceImpl endpointServiceImpl() return new EndpointServiceImpl(EndpointServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.endpointDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), - commandConfig.referenceExtractor(), commandConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); } @Bean @@ -250,7 +253,7 @@ public GroupService groupService() private GroupServiceSecure groupServiceSecure() { return new GroupServiceSecure(groupServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver(), daoConfig.groupDao(), helperConfig.exceptionHandler(), + referenceConfig.referenceResolver(), daoConfig.groupDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.groupAuthorizationRule()); } @@ -259,7 +262,7 @@ private GroupServiceImpl groupServiceImpl() return new GroupServiceImpl(GroupServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.groupDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), - commandConfig.referenceExtractor(), commandConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); } @Bean @@ -271,7 +274,7 @@ public HealthcareServiceService healthcareServiceService() private HealthcareServiceServiceSecure healthcareServiceServiceSecure() { return new HealthcareServiceServiceSecure(healthcareServiceServiceImpl(), serverBase, - helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.healthcareServiceDao(), + helperConfig.responseGenerator(), referenceConfig.referenceResolver(), daoConfig.healthcareServiceDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.healthcareServiceAuthorizationRule()); } @@ -281,8 +284,8 @@ private HealthcareServiceServiceImpl healthcareServiceServiceImpl() return new HealthcareServiceServiceImpl(HealthcareServiceServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.healthcareServiceDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), - helperConfig.parameterConverter(), commandConfig.referenceExtractor(), - commandConfig.referenceResolver()); + helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), + referenceConfig.referenceResolver()); } @Bean @@ -294,7 +297,7 @@ public LocationService locationService() private LocationServiceSecure locationServiceSecure() { return new LocationServiceSecure(locationServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver(), daoConfig.locationDao(), helperConfig.exceptionHandler(), + referenceConfig.referenceResolver(), daoConfig.locationDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.locationAuthorizationRule()); } @@ -303,7 +306,7 @@ private LocationServiceImpl locationServiceImpl() return new LocationServiceImpl(LocationServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.locationDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), - commandConfig.referenceExtractor(), commandConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); } @Bean @@ -315,7 +318,7 @@ public NamingSystemService namingSystemService() private NamingSystemServiceSecure namingSystemServiceSecure() { return new NamingSystemServiceSecure(namingSystemServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver(), daoConfig.namingSystemDao(), helperConfig.exceptionHandler(), + referenceConfig.referenceResolver(), daoConfig.namingSystemDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.namingSystemAuthorizationRule()); } @@ -324,8 +327,8 @@ private NamingSystemService namingSystemServiceImpl() return new NamingSystemServiceImpl(LocationServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.namingSystemDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), - helperConfig.parameterConverter(), commandConfig.referenceExtractor(), - commandConfig.referenceResolver()); + helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), + referenceConfig.referenceResolver()); } @Bean @@ -337,7 +340,7 @@ public OrganizationService organizationService() private OrganizationServiceSecure organizationServiceSecure() { return new OrganizationServiceSecure(organizationServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver(), daoConfig.organizationDao(), helperConfig.exceptionHandler(), + referenceConfig.referenceResolver(), daoConfig.organizationDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.organizationAuthorizationRule()); } @@ -346,8 +349,8 @@ private OrganizationServiceImpl organizationServiceImpl() return new OrganizationServiceImpl(OrganizationServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.organizationDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), - helperConfig.parameterConverter(), commandConfig.referenceExtractor(), - commandConfig.referenceResolver()); + helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), + referenceConfig.referenceResolver()); } @Bean @@ -359,7 +362,7 @@ public PatientService patientService() private PatientServiceSecure patientServiceSecure() { return new PatientServiceSecure(patientServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver(), daoConfig.patientDao(), helperConfig.exceptionHandler(), + referenceConfig.referenceResolver(), daoConfig.patientDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.patientAuthorizationRule()); } @@ -368,7 +371,7 @@ private PatientServiceImpl patientServiceImpl() return new PatientServiceImpl(PatientServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.patientDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), - commandConfig.referenceExtractor(), commandConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); } @Bean @@ -380,7 +383,7 @@ public PractitionerRoleService practitionerRoleService() private PractitionerRoleServiceSecure practitionerRoleServiceSecure() { return new PractitionerRoleServiceSecure(practitionerRoleServiceImpl(), serverBase, - helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.practitionerRoleDao(), + helperConfig.responseGenerator(), referenceConfig.referenceResolver(), daoConfig.practitionerRoleDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.practitionerRoleAuthorizationRule()); } @@ -390,8 +393,8 @@ private PractitionerRoleServiceImpl practitionerRoleServiceImpl() return new PractitionerRoleServiceImpl(PractitionerRoleServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.practitionerRoleDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), - helperConfig.parameterConverter(), commandConfig.referenceExtractor(), - commandConfig.referenceResolver()); + helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), + referenceConfig.referenceResolver()); } @Bean @@ -403,7 +406,7 @@ public PractitionerService practitionerService() private PractitionerServiceSecure practitionerServiceSecure() { return new PractitionerServiceSecure(practitionerServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver(), daoConfig.practitionerDao(), helperConfig.exceptionHandler(), + referenceConfig.referenceResolver(), daoConfig.practitionerDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.practitionerAuthorizationRule()); } @@ -412,8 +415,8 @@ private PractitionerServiceImpl practitionerServiceImpl() return new PractitionerServiceImpl(PractitionerServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.practitionerDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), - helperConfig.parameterConverter(), commandConfig.referenceExtractor(), - commandConfig.referenceResolver()); + helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), + referenceConfig.referenceResolver()); } @Bean @@ -425,7 +428,7 @@ public ProvenanceService provenanceService() private ProvenanceServiceSecure provenanceServiceSecure() { return new ProvenanceServiceSecure(provenanceServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver(), daoConfig.provenanceDao(), helperConfig.exceptionHandler(), + referenceConfig.referenceResolver(), daoConfig.provenanceDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.provenanceAuthorizationRule()); } @@ -434,8 +437,8 @@ private ProvenanceServiceImpl provenanceServiceImpl() return new ProvenanceServiceImpl(ProvenanceServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.provenanceDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), - helperConfig.parameterConverter(), commandConfig.referenceExtractor(), - commandConfig.referenceResolver()); + helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), + referenceConfig.referenceResolver()); } @Bean @@ -447,7 +450,7 @@ public ResearchStudyService researchStudyService() private ResearchStudyServiceSecure researchStudyServiceSecure() { return new ResearchStudyServiceSecure(researchStudyServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver(), daoConfig.researchStudyDao(), helperConfig.exceptionHandler(), + referenceConfig.referenceResolver(), daoConfig.researchStudyDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.researchStudyAuthorizationRule()); } @@ -456,8 +459,8 @@ private ResearchStudyServiceImpl researchStudyServiceImpl() return new ResearchStudyServiceImpl(ResearchStudyServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.researchStudyDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), - helperConfig.parameterConverter(), commandConfig.referenceExtractor(), - commandConfig.referenceResolver()); + helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), + referenceConfig.referenceResolver()); } @Bean @@ -469,8 +472,8 @@ public StructureDefinitionService structureDefinitionService() private StructureDefinitionServiceSecure structureDefinitionServiceSecure() { return new StructureDefinitionServiceSecure(structureDefinitionServiceImpl(), serverBase, - helperConfig.responseGenerator(), commandConfig.referenceResolver(), daoConfig.structureDefinitionDao(), - helperConfig.exceptionHandler(), helperConfig.parameterConverter(), + helperConfig.responseGenerator(), referenceConfig.referenceResolver(), + daoConfig.structureDefinitionDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.structureDefinitionAuthorizationRule()); } @@ -481,7 +484,7 @@ private StructureDefinitionServiceImpl structureDefinitionServiceImpl() helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), daoConfig.structureDefinitionSnapshotDao(), snapshotConfig.snapshotGenerator(), snapshotConfig.snapshotDependencyAnalyzer(), - commandConfig.referenceExtractor(), commandConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); } @Bean @@ -493,7 +496,7 @@ public SubscriptionService subscriptionService() private SubscriptionServiceSecure subscriptionServiceSecure() { return new SubscriptionServiceSecure(subscriptionServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver(), daoConfig.subscriptionDao(), helperConfig.exceptionHandler(), + referenceConfig.referenceResolver(), daoConfig.subscriptionDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.subscriptionAuthorizationRule()); } @@ -502,8 +505,8 @@ private SubscriptionServiceImpl subscriptionServiceImpl() return new SubscriptionServiceImpl(SubscriptionServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.subscriptionDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), - helperConfig.parameterConverter(), commandConfig.referenceExtractor(), - commandConfig.referenceResolver()); + helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), + referenceConfig.referenceResolver()); } @Bean @@ -515,7 +518,7 @@ public TaskService taskService() private TaskServiceSecure taskServiceSecure() { return new TaskServiceSecure(taskServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver(), daoConfig.taskDao(), helperConfig.exceptionHandler(), + referenceConfig.referenceResolver(), daoConfig.taskDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.taskAuthorizationRule()); } @@ -524,7 +527,7 @@ private TaskServiceImpl taskServiceImpl() return new TaskServiceImpl(TaskServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.taskDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), - commandConfig.referenceExtractor(), commandConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); } @Bean @@ -536,7 +539,7 @@ public ValueSetService valueSetService() private ValueSetServiceSecure valueSetServiceSecure() { return new ValueSetServiceSecure(valueSetServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver(), daoConfig.valueSetDao(), helperConfig.exceptionHandler(), + referenceConfig.referenceResolver(), daoConfig.valueSetDao(), helperConfig.exceptionHandler(), helperConfig.parameterConverter(), authorizationConfig.valueSetAuthorizationRule()); } @@ -545,7 +548,7 @@ private ValueSetServiceImpl valueSetServiceImpl() return new ValueSetServiceImpl(ValueSetServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.valueSetDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), - commandConfig.referenceExtractor(), commandConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); } @Bean @@ -557,7 +560,7 @@ public RootService rootService() private RootServiceSecure rootServiceSecure() { return new RootServiceSecure(rootServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver()); + referenceConfig.referenceResolver()); } private RootServiceImpl rootServiceImpl() @@ -575,7 +578,7 @@ public ConformanceService conformanceService() private ConformanceServiceSecure conformanceServiceSecure() { return new ConformanceServiceSecure(conformanceServiceImpl(), serverBase, helperConfig.responseGenerator(), - commandConfig.referenceResolver()); + referenceConfig.referenceResolver()); } private ConformanceServiceImpl conformanceServiceImpl() @@ -593,7 +596,7 @@ public StaticResourcesService staticResourcesService() private StaticResourcesServiceSecure staticResourcesServiceSecure() { return new StaticResourcesServiceSecure(staticResourcesServiceImpl(), serverBase, - helperConfig.responseGenerator(), commandConfig.referenceResolver()); + helperConfig.responseGenerator(), referenceConfig.referenceResolver()); } private StaticResourcesServiceImpl staticResourcesServiceImpl() diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractServiceSecure.java index 4d16e09f7..d0a4a5548 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractServiceSecure.java @@ -1,21 +1,13 @@ package org.highmed.dsf.fhir.webservice.secure; -import java.util.Collection; -import java.util.EnumSet; import java.util.Objects; -import java.util.Optional; import javax.ws.rs.core.Response; import org.highmed.dsf.fhir.help.ResponseGenerator; import org.highmed.dsf.fhir.service.ReferenceResolver; -import org.highmed.dsf.fhir.service.ResourceReference; -import org.highmed.dsf.fhir.service.ResourceReference.ReferenceType; import org.highmed.dsf.fhir.webservice.base.AbstractDelegatingBasicService; import org.highmed.dsf.fhir.webservice.base.BasicService; -import org.hl7.fhir.r4.model.Organization; -import org.hl7.fhir.r4.model.Reference; -import org.hl7.fhir.r4.model.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; @@ -24,7 +16,6 @@ public abstract class AbstractServiceSecure<S extends BasicService> extends Abst implements BasicService, InitializingBean { protected static final Logger audit = LoggerFactory.getLogger("dsf-audit-logger"); - private static final Logger logger = LoggerFactory.getLogger(AbstractServiceSecure.class); protected final String serverBase; protected final ResponseGenerator responseGenerator; @@ -50,58 +41,6 @@ public void afterPropertiesSet() throws Exception Objects.requireNonNull(referenceResolver, "referenceResolver"); } - protected final boolean isCurrentUserPartOfReferencedOrganizations(String referenceLocation, - Collection<? extends Reference> references) - { - return references.stream().anyMatch(r -> isCurrentUserPartOfReferencedOrganization(referenceLocation, r)); - } - - protected final boolean isCurrentUserPartOfReferencedOrganization(String referenceLocation, Reference reference) - { - if (userProvider.getCurrentUser() == null || userProvider.getCurrentUser().getOrganization() == null) - { - logger.warn( - "No current user or current user without organization while checking if user part of referenced organization"); - return false; - } - else if (reference == null) - { - logger.warn("Null reference while checking if user part of referenced organization"); - return false; - } - else - { - ResourceReference resReference = new ResourceReference(referenceLocation, reference, Organization.class); - - if (!EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL) - .contains(resReference.getType(serverBase))) - { - logger.warn("Reference of type {} not supported while checking if user part of referenced organization", - resReference.getType(serverBase)); - return false; - } - - Optional<Resource> resource = referenceResolver.resolveReference(getCurrentUser(), resReference); - if (resource.isPresent() && resource.get() instanceof Organization) - { - boolean sameOrganization = userProvider.getCurrentUser().getOrganization().getIdElement() - .equals(resource.get().getIdElement()); - if (!sameOrganization) - logger.warn( - "Current user not part organization {} while checking if user part of referenced organization", - resource.get().getIdElement().getValue()); - - return sameOrganization; - } - else - { - logger.warn( - "Reference to organization could not be resolved while checking if user part of referenced organization"); - return false; - } - } - } - protected final Response forbidden(String operation) { return responseGenerator.forbiddenNotAllowed(operation, userProvider.getCurrentUser()); diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/ReferenceTypTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/ReferenceTypTest.java index 03e3336e8..d154830fc 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/ReferenceTypTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/ReferenceTypTest.java @@ -1,15 +1,26 @@ package org.highmed.dsf.fhir.hapi; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import java.util.UUID; import java.util.regex.Pattern; +import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.Reference; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ca.uhn.fhir.context.FhirContext; public class ReferenceTypTest { + private static final Logger logger = LoggerFactory.getLogger(ReferenceTypTest.class); + private static final Pattern ID_PATTERN = Pattern .compile("(?<base>(http|https):\\/\\/([A-Za-z0-9\\-\\\\\\.\\:\\%\\$]*\\/)+)?" + "(?<resource>Account|ActivityDefinition|AdverseEvent|AllergyIntolerance|Appointment|AppointmentResponse" @@ -168,4 +179,25 @@ public void testIdType() throws Exception assertFalse(id5.isUrn()); assertFalse(id5.isAbsolute()); } + + @Test + public void testType() throws Exception + { +// Reference ref = new Reference(); +// ref.setType("Organization"); +// ref.setReferenceElement(new IdType().setParts(null, "Organization", UUID.randomUUID().toString(), null)); + + Organization org = new Organization(); + org.setIdElement(new IdType(UUID.randomUUID().toString())); + + Binary b = new Binary(); + Reference ref = new Reference(org); + b.setSecurityContext(ref); + b.getSecurityContext().setType("Organization"); + + FhirContext context = FhirContext.forR4(); + String string = context.newXmlParser().encodeResourceToString(b); + + logger.debug(string); + } } diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/BinaryIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/BinaryIntegrationTest.java index 292bde993..f631de2d1 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/BinaryIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/BinaryIntegrationTest.java @@ -9,9 +9,12 @@ import java.util.Collections; import org.highmed.dsf.fhir.dao.BinaryDao; +import org.highmed.dsf.fhir.dao.ResearchStudyDao; import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.SearchEntryMode; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ResearchStudy; import org.junit.Test; public class BinaryIntegrationTest extends AbstractIntegrationTest @@ -19,12 +22,16 @@ public class BinaryIntegrationTest extends AbstractIntegrationTest @Test public void testCreate() throws Exception { + ResearchStudyDao researchStudyDao = getSpringWebApplicationContext().getBean(ResearchStudyDao.class); + ResearchStudy createdRS = researchStudyDao.create(new ResearchStudy()); + final String contentType = "text/plain"; final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); Binary binary = new Binary(); binary.setContentType(contentType); binary.setData(data); + binary.setSecurityContext(new Reference(createdRS.getIdElement().toVersionless())); Binary created = getWebserviceClient().create(binary); @@ -36,11 +43,17 @@ public void testCreate() throws Exception assertNotNull(created.getContentType()); assertEquals(contentType, created.getContentType()); assertTrue(Arrays.equals(data, created.getData())); + + assertNotNull(created.getSecurityContext()); + assertEquals(createdRS.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); } @Test public void testUpdate() throws Exception { + ResearchStudyDao researchStudyDao = getSpringWebApplicationContext().getBean(ResearchStudyDao.class); + ResearchStudy createdRS = researchStudyDao.create(new ResearchStudy()); + final String contentType = "text/plain"; final byte[] data1 = "Hello World".getBytes(StandardCharsets.UTF_8); final byte[] data2 = "Hello World and goodbye".getBytes(StandardCharsets.UTF_8); @@ -48,6 +61,7 @@ public void testUpdate() throws Exception Binary binary = new Binary(); binary.setContentType(contentType); binary.setData(data1); + binary.setSecurityContext(new Reference(createdRS.getIdElement().toVersionless())); BinaryDao binaryDao = getSpringWebApplicationContext().getBean(BinaryDao.class); Binary created = binaryDao.create(binary); @@ -60,8 +74,15 @@ public void testUpdate() throws Exception assertNotNull(created.getContentType()); assertEquals(contentType, created.getContentType()); assertTrue(Arrays.equals(data1, created.getData())); + + assertNotNull(created.getSecurityContext()); + assertEquals(createdRS.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); created.setData(data2); + + assertNotNull(created.getSecurityContext()); + assertEquals(createdRS.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + Binary updated = getWebserviceClient().update(created); assertNotNull(updated); From d796bcec8108b8ba3fc21f701c33a04f3d188e2b Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Sun, 23 Feb 2020 16:48:15 +0100 Subject: [PATCH 07/55] work on binary rules, integration tests, fhir client error handling --- .../BinaryAuthorizationRule.java | 29 ++--- .../EndpointAuthorizationRule.java | 9 +- .../dao/jdbc/AbstractResourceDaoJdbc.java | 9 +- .../highmed/dsf/fhir/search/SearchQuery.java | 4 +- .../integration/AbstractIntegrationTest.java | 26 +++- .../integration/BinaryIntegrationTest.java | 115 +++++++++++++++--- .../client/FhirWebserviceClientJersey.java | 68 ++++++++--- 7 files changed, 197 insertions(+), 63 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java index 1246c4f40..b5fe4807d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java @@ -9,12 +9,9 @@ import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.service.ResourceReference; import org.highmed.dsf.fhir.service.ResourceReference.ReferenceType; -import org.hl7.fhir.r4.model.ActivityDefinition; import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.Organization; -import org.hl7.fhir.r4.model.ResearchStudy; import org.hl7.fhir.r4.model.Resource; -import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,8 +32,7 @@ public Optional<String> reasonCreateAllowed(User user, Binary newResource) if (newResource.hasData() && newResource.hasContentType() && newResource.hasSecurityContext()) { ResourceReference reference = new ResourceReference("Binary.SecurityContext", - newResource.getSecurityContext(), ActivityDefinition.class, Organization.class, - ResearchStudy.class, Task.class); + newResource.getSecurityContext(), Organization.class); if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL) .contains(reference.getType(serverBase))) { @@ -77,24 +73,24 @@ public Optional<String> reasonCreateAllowed(User user, Binary newResource) public Optional<String> reasonReadAllowed(User user, Binary existingResource) { ResourceReference reference = new ResourceReference("Binary.SecurityContext", - existingResource.getSecurityContext(), ActivityDefinition.class, Organization.class, - ResearchStudy.class, Task.class); + existingResource.getSecurityContext(), Organization.class); if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL).contains(reference.getType(serverBase))) { - Optional<Resource> securityContext = referenceResolver.resolveReference(user, reference); - if (securityContext.isPresent()) + if (isCurrentUserPartOfReferencedOrganization(user, "Binary.SecurityContext", + existingResource.getSecurityContext())) { logger.info( - "Read of Binary authorized, Binary.SecurityContext reference could be resolved for user '{}'", + "Read of Binary authorized, Binary.SecurityContext reference could be resolved and user '{}' is part of referenced organization", user.getName()); - return Optional.of("Binary.SecurityContext resolved"); + return Optional.of("Binary.SecurityContext resolved and user part of referenced organization"); } else { logger.warn( - "Read of Binary unauthorized, securityContext reference could not be resolved for user '{}'", + "Read of Binary unauthorized, securityContext reference could not be resolved or user '{}' not part of referenced organization", user.getName()); return Optional.empty(); + } } else @@ -112,11 +108,9 @@ public Optional<String> reasonUpdateAllowed(User user, Binary oldResource, Binar if (newResource.hasData() && newResource.hasContentType() && newResource.hasSecurityContext()) { ResourceReference oldReference = new ResourceReference("Binary.SecurityContext", - oldResource.getSecurityContext(), ActivityDefinition.class, Organization.class, - ResearchStudy.class, Task.class); + oldResource.getSecurityContext(), Organization.class); ResourceReference newReference = new ResourceReference("Binary.SecurityContext", - newResource.getSecurityContext(), ActivityDefinition.class, Organization.class, - ResearchStudy.class, Task.class); + newResource.getSecurityContext(), Organization.class); if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL) .contains(oldReference.getType(serverBase)) && EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL) @@ -166,8 +160,7 @@ public Optional<String> reasonDeleteAllowed(User user, Binary oldResource) if (oldResource.hasData() && oldResource.hasContentType() && oldResource.hasSecurityContext()) { ResourceReference reference = new ResourceReference("Binary.SecurityContext", - oldResource.getSecurityContext(), ActivityDefinition.class, Organization.class, - ResearchStudy.class, Task.class); + oldResource.getSecurityContext(), Organization.class); if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL) .contains(reference.getType(serverBase))) { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java index 5b5845389..aa8a1dd35 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java @@ -7,9 +7,13 @@ import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Endpoint; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class EndpointAuthorizationRule extends AbstractAuthorizationRule<Endpoint, EndpointDao> { + private static final Logger logger = LoggerFactory.getLogger(EndpointAuthorizationRule.class); + public EndpointAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { super(Endpoint.class, daoProvider, serverBase, referenceResolver); @@ -48,7 +52,8 @@ public Optional<String> reasonDeleteAllowed(User user, Endpoint oldResource) @Override public Optional<String> reasonSearchAllowed(User user) { - // TODO Auto-generated method stub - return Optional.empty(); + logger.info("Search of Endpoint authorized for {} user '{}', will be fitered by user role", user.getRole(), + user.getName()); + return Optional.of("Allowed for all, filtered by user role"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java index 8d90e4ff5..94eb81aab 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java @@ -940,9 +940,14 @@ public final SearchQuery<R> createSearchQuery(User user, int page, int count) } @Override + @SuppressWarnings({ "unchecked", "rawtypes" }) public SearchQuery<R> createSearchQueryWithoutUserFilter(int page, int count) { - // TODO Auto-generated method stub - return null; + return SearchQueryBuilder.create(resourceType, getResourceTable(), getResourceColumn(), page, count) + .with(new ResourceId(getResourceIdColumn()), new ResourceLastUpdated(getResourceColumn())) + .with(searchParameterFactories.stream().map(Supplier::get).toArray(SearchQueryParameter[]::new)) + .withRevInclude(searchRevIncludeParameterFactories.stream().map(Supplier::get) + .toArray(SearchQueryRevIncludeParameterFactory[]::new)) + .build(); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQuery.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQuery.java index 91c759709..d67760d8c 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQuery.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQuery.java @@ -152,7 +152,7 @@ public SearchQuery<R> build() this.revIncludeParameterFactories.addAll(revIncludeParameters); } - public void configureParameters(Map<String, List<String>> queryParameters) + public SearchQuery<R> configureParameters(Map<String, List<String>> queryParameters) { searchParameters.forEach(p -> p.configure(queryParameters)); @@ -166,6 +166,8 @@ public void configureParameters(Map<String, List<String>> queryParameters) filterQuery = createFilterQuery(); sortSql = createSortSql(getFirst(queryParameters, PARAMETER_SORT)); + + return this; } private String createFilterQuery() diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java index eb9ccb913..52621e3e4 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java @@ -24,6 +24,9 @@ import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -122,7 +125,7 @@ public static void beforeClass() throws Exception private static FhirWebserviceClient createWebserviceClient(KeyStore trustStore, KeyStore keyStore, String keyStorePassword, FhirContext fhirContext, ReferenceExtractor referenceExtractor) { - return new FhirWebserviceClientJersey(BASE_URL, trustStore, keyStore, keyStorePassword, null, null, null, 0, 0, + return new FhirWebserviceClientJersey(BASE_URL, trustStore, keyStore, keyStorePassword, null, null, null, 500, 5000, null, fhirContext, referenceExtractor); } @@ -328,11 +331,22 @@ protected AnnotationConfigWebApplicationContext getSpringWebApplicationContext() @Before public void before() throws Exception { - logger.info("Loading initial FHIR data bundles ..."); - InitialDataLoaderConfig initialDataLoadConfig = getSpringWebApplicationContext() - .getBean(InitialDataLoaderConfig.class); - assertNotNull(initialDataLoadConfig); - initialDataLoadConfig.onContextRefreshedEvent(null); + try (Connection connection = database.getDataSource().getConnection(); + PreparedStatement statement = connection.prepareStatement("SELECT count(*) FROM current_organizations"); + ResultSet result = statement.executeQuery()) + { + assertTrue(result.next()); + if (result.getInt(1) <= 0) + { + logger.info("Loading initial FHIR data bundles for next test case ..."); + InitialDataLoaderConfig initialDataLoadConfig = getSpringWebApplicationContext() + .getBean(InitialDataLoaderConfig.class); + assertNotNull(initialDataLoadConfig); + initialDataLoadConfig.onContextRefreshedEvent(null); + } + else + logger.info("Not loading initial FHIR data bundles for first test case"); + } } protected static FhirWebserviceClient getWebserviceClient() diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/BinaryIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/BinaryIntegrationTest.java index f631de2d1..725ebf518 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/BinaryIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/BinaryIntegrationTest.java @@ -7,31 +7,92 @@ import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collections; +import java.util.UUID; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response.Status; import org.highmed.dsf.fhir.dao.BinaryDao; -import org.highmed.dsf.fhir.dao.ResearchStudyDao; +import org.highmed.dsf.fhir.dao.OrganizationDao; +import org.highmed.dsf.fhir.search.PartialResult; import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.SearchEntryMode; +import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Reference; -import org.hl7.fhir.r4.model.ResearchStudy; import org.junit.Test; public class BinaryIntegrationTest extends AbstractIntegrationTest { + @Test + public void testReadAllowed() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + PartialResult<Organization> result = orgDao + .search(orgDao.createSearchQueryWithoutUserFilter(1, 1).configureParameters(Collections.emptyMap())); + assertNotNull(result); + assertEquals(1, result.getOverallCount()); + assertNotNull(result.getPartialResult()); + assertEquals(1, result.getPartialResult().size()); + assertNotNull(result.getPartialResult().get(0)); + + Organization org = result.getPartialResult().get(0); + + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference(org.getIdElement().toVersionless())); + + BinaryDao binDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binDao.create(binary); + + getWebserviceClient().read(Binary.class, created.getIdElement().getIdPart()); + } + + @Test(expected = WebApplicationException.class) + public void testReadNotAllowed() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); + + BinaryDao binDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binDao.create(binary); + + try + { + getWebserviceClient().read(Binary.class, created.getIdElement().getIdPart()); + } + catch (WebApplicationException e) + { + assertEquals(Status.FORBIDDEN.getStatusCode(), e.getResponse().getStatus()); + throw e; + } + } + @Test public void testCreate() throws Exception { - ResearchStudyDao researchStudyDao = getSpringWebApplicationContext().getBean(ResearchStudyDao.class); - ResearchStudy createdRS = researchStudyDao.create(new ResearchStudy()); - + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + final String contentType = "text/plain"; final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); Binary binary = new Binary(); binary.setContentType(contentType); binary.setData(data); - binary.setSecurityContext(new Reference(createdRS.getIdElement().toVersionless())); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); Binary created = getWebserviceClient().create(binary); @@ -43,17 +104,39 @@ public void testCreate() throws Exception assertNotNull(created.getContentType()); assertEquals(contentType, created.getContentType()); assertTrue(Arrays.equals(data, created.getData())); - + assertNotNull(created.getSecurityContext()); - assertEquals(createdRS.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + } + + @Test(expected = WebApplicationException.class) + public void testCreateSecurityContextOrgNotExisting() throws Exception + { + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference("Organization/" + UUID.randomUUID().toString())); + + try + { + getWebserviceClient().create(binary); + } + catch (WebApplicationException e) + { + assertEquals(Status.FORBIDDEN.getStatusCode(), e.getResponse().getStatus()); + throw e; + } } @Test public void testUpdate() throws Exception { - ResearchStudyDao researchStudyDao = getSpringWebApplicationContext().getBean(ResearchStudyDao.class); - ResearchStudy createdRS = researchStudyDao.create(new ResearchStudy()); - + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + final String contentType = "text/plain"; final byte[] data1 = "Hello World".getBytes(StandardCharsets.UTF_8); final byte[] data2 = "Hello World and goodbye".getBytes(StandardCharsets.UTF_8); @@ -61,7 +144,7 @@ public void testUpdate() throws Exception Binary binary = new Binary(); binary.setContentType(contentType); binary.setData(data1); - binary.setSecurityContext(new Reference(createdRS.getIdElement().toVersionless())); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); BinaryDao binaryDao = getSpringWebApplicationContext().getBean(BinaryDao.class); Binary created = binaryDao.create(binary); @@ -74,15 +157,15 @@ public void testUpdate() throws Exception assertNotNull(created.getContentType()); assertEquals(contentType, created.getContentType()); assertTrue(Arrays.equals(data1, created.getData())); - + assertNotNull(created.getSecurityContext()); - assertEquals(createdRS.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); created.setData(data2); assertNotNull(created.getSecurityContext()); - assertEquals(createdRS.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); - + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + Binary updated = getWebserviceClient().update(created); assertNotNull(updated); diff --git a/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java b/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java index 37efe748d..2c540bdad 100755 --- a/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java +++ b/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java @@ -7,8 +7,10 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Objects; +import java.util.stream.Collectors; import java.util.stream.Stream; +import javax.ws.rs.ProcessingException; import javax.ws.rs.WebApplicationException; import javax.ws.rs.client.Entity; import javax.ws.rs.client.Invocation.Builder; @@ -68,6 +70,8 @@ import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.CapabilityStatement; import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.OperationOutcome; +import org.hl7.fhir.r4.model.OperationOutcome.OperationOutcomeIssueComponent; import org.hl7.fhir.r4.model.Parameters; import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.StructureDefinition; @@ -128,6 +132,24 @@ public static List<AbstractFhirAdapter<?>> components(FhirContext fhirContext) new ValueSetXmlFhirAdapter(fhirContext)); } + private WebApplicationException handleError(Response response) + { + try + { + OperationOutcome outcome = response.readEntity(OperationOutcome.class); + String message = toString(outcome); + + logger.warn("OperationOutcome: {}", message); + return new WebApplicationException(message, response.getStatus()); + } + catch (ProcessingException e) + { + response.close(); + logger.warn("{}: {}", e.getClass().getName(), e.getMessage()); + return new WebApplicationException(e, response.getStatus()); + } + } + @Override public <R extends Resource> R create(R resource) { @@ -149,7 +171,7 @@ public <R extends Resource> R create(R resource) return read; } else - throw new WebApplicationException(response); + throw handleError(response); } @Override @@ -175,7 +197,7 @@ public <R extends Resource> R createConditionaly(R resource, String ifNoneExistC return read; } else - throw new WebApplicationException(response); + throw handleError(response); } @Override @@ -203,7 +225,7 @@ public <R extends Resource> R update(R resource) return read; } else - throw new WebApplicationException(response); + throw handleError(response); } @Override @@ -238,7 +260,7 @@ public <R extends Resource> R updateConditionaly(R resource, Map<String, List<St return read; } else - throw new WebApplicationException(response); + throw handleError(response); } @Override @@ -257,7 +279,7 @@ public void delete(Class<? extends Resource> resourceClass, String id) if (Status.OK.getStatusCode() != response.getStatus() && Status.NO_CONTENT.getStatusCode() != response.getStatus()) - throw new WebApplicationException(response); + throw handleError(response); } @Override @@ -282,7 +304,7 @@ public void deleteConditionaly(Class<? extends Resource> resourceClass, Map<Stri if (Status.OK.getStatusCode() != response.getStatus() && Status.NO_CONTENT.getStatusCode() != response.getStatus()) - throw new WebApplicationException(response); + throw handleError(response); } @Override @@ -297,7 +319,7 @@ public CapabilityStatement getConformance() if (Status.OK.getStatusCode() == response.getStatus()) return response.readEntity(CapabilityStatement.class); else - throw new WebApplicationException(response); + throw handleError(response); } @Override @@ -317,7 +339,7 @@ public StructureDefinition generateSnapshot(String url) if (Status.OK.getStatusCode() == response.getStatus()) return response.readEntity(StructureDefinition.class); else - throw new WebApplicationException(response); + throw handleError(response); } @Override @@ -337,7 +359,7 @@ public StructureDefinition generateSnapshot(StructureDefinition differential) if (Status.OK.getStatusCode() == response.getStatus()) return response.readEntity(StructureDefinition.class); else - throw new WebApplicationException(response); + throw handleError(response); } @Override @@ -355,7 +377,7 @@ public <R extends Resource> R read(Class<R> resourceType, String id) // TODO remove workaround if HAPI bug fixed return fixBundle(response.readEntity(resourceType)); else - throw new WebApplicationException(response); + throw handleError(response); } @Override @@ -374,7 +396,7 @@ public <R extends Resource> R read(Class<R> resourceType, String id, String vers // TODO remove workaround if HAPI bug fixed return fixBundle(response.readEntity(resourceType)); else - throw new WebApplicationException(response); + throw handleError(response); } @Override @@ -394,7 +416,7 @@ public Resource read(String resourceTypeName, String id) // TODO remove workaround if HAPI bug fixed return fixBundle((Resource) response.readEntity(resourceTypeByNames.get(resourceTypeName))); else - throw new WebApplicationException(response); + throw handleError(response); } @@ -416,7 +438,7 @@ public Resource read(String resourceTypeName, String id, String version) // TODO remove workaround if HAPI bug fixed return fixBundle((Resource) response.readEntity(resourceTypeByNames.get(resourceTypeName))); else - throw new WebApplicationException(response); + throw handleError(response); } @Override @@ -435,7 +457,7 @@ public <R extends Resource> boolean exists(Class<R> resourceType, String id) else if (Status.NOT_FOUND.getStatusCode() == response.getStatus()) return false; else - throw new WebApplicationException(response); + throw handleError(response); } @Override @@ -461,7 +483,7 @@ public boolean exists(IdType resourceTypeIdVersion) else if (Status.NOT_FOUND.getStatusCode() == response.getStatus()) return false; else - throw new WebApplicationException(response); + throw handleError(response); } // FIXME bug in HAPI framework @@ -499,7 +521,7 @@ public <R extends Resource> boolean exists(Class<R> resourceType, String id, Str else if (Status.NOT_FOUND.getStatusCode() == response.getStatus()) return false; else - throw new WebApplicationException(response); + throw handleError(response); } @Override @@ -521,7 +543,7 @@ public <R extends Resource> Bundle search(Class<R> resourceType, Map<String, Lis if (Status.OK.getStatusCode() == response.getStatus()) return response.readEntity(Bundle.class); else - throw new WebApplicationException(response); + throw handleError(response); } // private <R extends DomainResource> List<R> bundleToList(Class<R> resourceType, Bundle bundle) @@ -547,6 +569,16 @@ public Bundle postBundle(Bundle bundle) if (Status.OK.getStatusCode() == response.getStatus()) return response.readEntity(Bundle.class); else - throw new WebApplicationException(response); + throw handleError(response); + } + + private String toString(OperationOutcome outcome) + { + return outcome.getIssue().stream().map(i -> toString(i)).collect(Collectors.joining("\n")); + } + + private String toString(OperationOutcomeIssueComponent issue) + { + return issue == null ? "" : issue.getSeverity() + " " + issue.getCode() + " " + issue.getDiagnostics(); } } From d032fef9c971e6c04458340c826a297c6e63aa1b Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Sun, 23 Feb 2020 22:08:15 +0100 Subject: [PATCH 08/55] work on binary auth rules, user filter and integration test --- .../BinaryAuthorizationRule.java | 81 ++--- .../parameters/user/BinaryUserFilter.java | 19 +- .../secure/AbstractResourceServiceSecure.java | 13 +- .../integration/AbstractIntegrationTest.java | 27 +- .../integration/BinaryIntegrationTest.java | 308 ++++++++++++++++-- .../dsf/fhir/test/X509Certificates.java | 76 ++++- .../resources/integration/test-bundle.xml | 44 +++ 7 files changed, 443 insertions(+), 125 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java index b5fe4807d..35ae2aa08 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java @@ -72,30 +72,24 @@ public Optional<String> reasonCreateAllowed(User user, Binary newResource) @Override public Optional<String> reasonReadAllowed(User user, Binary existingResource) { - ResourceReference reference = new ResourceReference("Binary.SecurityContext", - existingResource.getSecurityContext(), Organization.class); - if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL).contains(reference.getType(serverBase))) + if (isLocalUser(user)) { - if (isCurrentUserPartOfReferencedOrganization(user, "Binary.SecurityContext", - existingResource.getSecurityContext())) - { - logger.info( - "Read of Binary authorized, Binary.SecurityContext reference could be resolved and user '{}' is part of referenced organization", - user.getName()); - return Optional.of("Binary.SecurityContext resolved and user part of referenced organization"); - } - else - { - logger.warn( - "Read of Binary unauthorized, securityContext reference could not be resolved or user '{}' not part of referenced organization", - user.getName()); - return Optional.empty(); - - } + logger.info("Read of Binary authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else if (isCurrentUserPartOfReferencedOrganization(user, "Binary.SecurityContext", + existingResource.getSecurityContext())) + { + logger.info( + "Read of Binary authorized, Binary.SecurityContext reference could be resolved and user '{}' is part of referenced organization", + user.getName()); + return Optional.of("Binary.SecurityContext resolved and user part of referenced organization"); } else { - logger.warn("Read of Binary unauthorized, securityContext not a literal internal or logical reference"); + logger.warn( + "Read of Binary unauthorized, securityContext reference could not be resolved or user '{}' not part of referenced organization", + user.getName()); return Optional.empty(); } } @@ -157,38 +151,8 @@ public Optional<String> reasonDeleteAllowed(User user, Binary oldResource) { if (isLocalUser(user)) { - if (oldResource.hasData() && oldResource.hasContentType() && oldResource.hasSecurityContext()) - { - ResourceReference reference = new ResourceReference("Binary.SecurityContext", - oldResource.getSecurityContext(), Organization.class); - if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL) - .contains(reference.getType(serverBase))) - { - Optional<Resource> securityContext = referenceResolver.resolveReference(user, reference); - if (securityContext.isPresent()) - { - logger.info("Delete of Binary authorized for local user '{}', Binary.SecurityContext resolved", - user.getName()); - return Optional.of("local user, Binary.SecurityContext resolved"); - } - else - { - logger.warn("Delete of Binary unauthorized, securityContext reference could not be resolved"); - return Optional.empty(); - } - } - else - { - logger.warn( - "Delete of Binary unauthorized, securityContext not a literal internal or logical reference"); - return Optional.empty(); - } - } - else - { - logger.warn("Delete of Binary unauthorized, missing data or contentType or securityContext"); - return Optional.empty(); - } + logger.info("Delete of Binary authorized for local user '{}'", user.getName()); + return Optional.of("local user"); } else { @@ -200,15 +164,8 @@ public Optional<String> reasonDeleteAllowed(User user, Binary oldResource) @Override public Optional<String> reasonSearchAllowed(User user) { - if (isLocalUser(user)) - { - logger.info("Search of Binary authorized for {} user '{}'", user.getRole(), user.getName()); - return Optional.of("Allowed for local users"); - } - else - { - logger.warn("Search of Binary unauthorized, not a local user"); - return Optional.empty(); - } + logger.info("Search of Binary authorized for {} user '{}', will be fitered by users organization {}", + user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString()); + return Optional.of("Allowed for all, filtered by users organization"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java index e0611788a..2982e10ba 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java @@ -6,13 +6,9 @@ import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.authentication.UserRole; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class BinaryUserFilter extends AbstractUserFilter { - private static final Logger logger = LoggerFactory.getLogger(BinaryUserFilter.class); - public BinaryUserFilter(OrganizationType organizationType, User user) { super(organizationType, user); @@ -24,21 +20,24 @@ public String getFilterQuery() if (UserRole.LOCAL.equals(user.getRole())) return ""; else - { - logger.warn("Filter query for non local user -> 'false'"); - return "false"; - } + return "(binary_json->'securityContext'->>'reference' = ? OR binary_json->'securityContext'->>'reference' = ?)"; } @Override public int getSqlParameterCount() { - return 0; + return UserRole.LOCAL.equals(user.getRole()) ? 0 : 2; } @Override public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException { - // nothing to do + if (!UserRole.LOCAL.equals(user.getRole())) + { + if (parameterIndex == 1) + statement.setString(1, user.getOrganization().getIdElement().getValue()); + else if (parameterIndex == 2) + statement.setString(2, user.getOrganization().getIdElement().toVersionless().getValue()); + } } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java index 7c6f93166..97ef6fe0a 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java @@ -364,7 +364,7 @@ public Response delete(String id, UriInfo uri, HttpHeaders headers) { R oldResource = dbResource.get(); - Optional<String> reasonDeleteAllowed = reasonDeleteAllowed(oldResource); + Optional<String> reasonDeleteAllowed = authorizationRule.reasonDeleteAllowed(getCurrentUser(), oldResource); if (reasonDeleteAllowed.isEmpty()) { audit.info("Delete of resource {} denied for user '{}'", oldResource.getIdElement().getValue(), @@ -386,17 +386,6 @@ public Response delete(String id, UriInfo uri, HttpHeaders headers) } } - /** - * Override this method for non default behavior. Default: Not allowed. - * - * @param oldResource - * @return Reason as String in {@link Optional#of(Object)} if delete allowed - */ - protected Optional<String> reasonDeleteAllowed(R oldResource) - { - return Optional.empty(); - } - @Override public Response delete(UriInfo uri, HttpHeaders headers) { diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java index 52621e3e4..705028fbe 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java @@ -103,6 +103,7 @@ public abstract class AbstractIntegrationTest private static JettyServer fhirServer; private static FhirWebserviceClient webserviceClient; + private static FhirWebserviceClient externalWebserviceClient; @BeforeClass public static void beforeClass() throws Exception @@ -111,13 +112,19 @@ public static void beforeClass() throws Exception template.createSchema(); logger.info("Creating Bundle ..."); - createTestBundle(certificates.getClientCertificate().getCertificate()); + createTestBundle(certificates.getClientCertificate().getCertificate(), + certificates.getExternalClientCertificate().getCertificate()); logger.info("Creating webservice client ..."); webserviceClient = createWebserviceClient(certificates.getClientCertificate().getTrustStore(), certificates.getClientCertificate().getKeyStore(), certificates.getClientCertificate().getKeyStorePassword(), fhirContext, extractor); + logger.info("Creating external webservice client ..."); + externalWebserviceClient = createWebserviceClient(certificates.getExternalClientCertificate().getTrustStore(), + certificates.getExternalClientCertificate().getKeyStore(), + certificates.getExternalClientCertificate().getKeyStorePassword(), fhirContext, extractor); + logger.info("Starting FHIR Server ..."); fhirServer = startFhirServer(); } @@ -125,8 +132,8 @@ public static void beforeClass() throws Exception private static FhirWebserviceClient createWebserviceClient(KeyStore trustStore, KeyStore keyStore, String keyStorePassword, FhirContext fhirContext, ReferenceExtractor referenceExtractor) { - return new FhirWebserviceClientJersey(BASE_URL, trustStore, keyStore, keyStorePassword, null, null, null, 500, 5000, - null, fhirContext, referenceExtractor); + return new FhirWebserviceClientJersey(BASE_URL, trustStore, keyStore, keyStorePassword, null, null, null, 500, + 5000, null, fhirContext, referenceExtractor); } private static WebsocketClient createWebsocketClient(KeyStore trustStore, KeyStore keyStore, @@ -247,7 +254,7 @@ protected static IParser newJsonParser() return parser; } - private static void createTestBundle(X509Certificate certificate) + private static void createTestBundle(X509Certificate certificate, X509Certificate externalCertificate) { Path testBundleTemplateFile = Paths.get("src/test/resources/integration/test-bundle.xml"); @@ -260,6 +267,13 @@ private static void createTestBundle(X509Certificate certificate) String clientCertHashHex = calculateSha512CertificateThumbprintHex(certificate); thumbprintExtension.setValue(new StringType(clientCertHashHex)); + Organization externalOrganization = (Organization) testBundle.getEntry().get(2).getResource(); + Extension externalThumbprintExtension = externalOrganization + .getExtensionByUrl("http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"); + + String externalClientCertHashHex = calculateSha512CertificateThumbprintHex(externalCertificate); + externalThumbprintExtension.setValue(new StringType(externalClientCertHashHex)); + removeReferenceEmbeddedResources(testBundle); writeBundle(FHIR_BUNDLE_FILE, testBundle); @@ -354,6 +368,11 @@ protected static FhirWebserviceClient getWebserviceClient() return webserviceClient; } + protected static FhirWebserviceClient getExternalWebserviceClient() + { + return externalWebserviceClient; + } + protected static WebsocketClient getWebsocketClient() { Bundle bundle = getWebserviceClient().search(Subscription.class, diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/BinaryIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/BinaryIntegrationTest.java index 725ebf518..455c516a7 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/BinaryIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/BinaryIntegrationTest.java @@ -7,17 +7,20 @@ import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.UUID; +import java.util.stream.Collectors; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response.Status; import org.highmed.dsf.fhir.dao.BinaryDao; import org.highmed.dsf.fhir.dao.OrganizationDao; +import org.highmed.dsf.fhir.dao.exception.ResourceDeletedException; import org.highmed.dsf.fhir.search.PartialResult; import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.Bundle; -import org.hl7.fhir.r4.model.Bundle.SearchEntryMode; import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Reference; import org.junit.Test; @@ -25,11 +28,11 @@ public class BinaryIntegrationTest extends AbstractIntegrationTest { @Test - public void testReadAllowed() throws Exception + public void testReadAllowedLocalUser() throws Exception { OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); - PartialResult<Organization> result = orgDao - .search(orgDao.createSearchQueryWithoutUserFilter(1, 1).configureParameters(Collections.emptyMap())); + PartialResult<Organization> result = orgDao.search(orgDao.createSearchQueryWithoutUserFilter(1, 1) + .configureParameters(Map.of("name", Arrays.asList("Test Organization")))); assertNotNull(result); assertEquals(1, result.getOverallCount()); assertNotNull(result.getPartialResult()); @@ -52,11 +55,47 @@ public void testReadAllowed() throws Exception getWebserviceClient().read(Binary.class, created.getIdElement().getIdPart()); } + @Test + public void testReadAllowedExternalUser() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + PartialResult<Organization> result = orgDao.search(orgDao.createSearchQueryWithoutUserFilter(1, 1) + .configureParameters(Map.of("name", Arrays.asList("External Test Organization")))); + assertNotNull(result); + assertEquals(1, result.getOverallCount()); + assertNotNull(result.getPartialResult()); + assertEquals(1, result.getPartialResult().size()); + assertNotNull(result.getPartialResult().get(0)); + + Organization org = result.getPartialResult().get(0); + + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference(org.getIdElement().toVersionless())); + + BinaryDao binDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binDao.create(binary); + + getExternalWebserviceClient().read(Binary.class, created.getIdElement().getIdPart()); + } + @Test(expected = WebApplicationException.class) - public void testReadNotAllowed() throws Exception + public void testReadNotAllowedExternalUser() throws Exception { OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); - Organization createdOrg = orgDao.create(new Organization()); + PartialResult<Organization> result = orgDao.search(orgDao.createSearchQueryWithoutUserFilter(1, 1) + .configureParameters(Map.of("name", Arrays.asList("Test Organization")))); + assertNotNull(result); + assertEquals(1, result.getOverallCount()); + assertNotNull(result.getPartialResult()); + assertEquals(1, result.getPartialResult().size()); + assertNotNull(result.getPartialResult().get(0)); + + Organization org = result.getPartialResult().get(0); final String contentType = "text/plain"; final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); @@ -64,14 +103,14 @@ public void testReadNotAllowed() throws Exception Binary binary = new Binary(); binary.setContentType(contentType); binary.setData(data); - binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); + binary.setSecurityContext(new Reference(org.getIdElement().toVersionless())); BinaryDao binDao = getSpringWebApplicationContext().getBean(BinaryDao.class); Binary created = binDao.create(binary); try { - getWebserviceClient().read(Binary.class, created.getIdElement().getIdPart()); + getExternalWebserviceClient().read(Binary.class, created.getIdElement().getIdPart()); } catch (WebApplicationException e) { @@ -109,6 +148,31 @@ public void testCreate() throws Exception assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); } + @Test(expected = WebApplicationException.class) + public void testCreateNotAllowedExternalUser() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); + + try + { + getExternalWebserviceClient().create(binary); + } + catch (WebApplicationException e) + { + assertEquals(Status.FORBIDDEN.getStatusCode(), e.getResponse().getStatus()); + throw e; + } + } + @Test(expected = WebApplicationException.class) public void testCreateSecurityContextOrgNotExisting() throws Exception { @@ -178,15 +242,179 @@ public void testUpdate() throws Exception assertTrue(Arrays.equals(data2, updated.getData())); } + @Test(expected = WebApplicationException.class) + public void testUpdateNotAllowedExternalUser() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + + final String contentType = "text/plain"; + final byte[] data1 = "Hello World".getBytes(StandardCharsets.UTF_8); + final byte[] data2 = "Hello World and goodbye".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data1); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); + + BinaryDao binaryDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binaryDao.create(binary); + + assertNotNull(created); + assertNotNull(created.getIdElement().toString()); + assertEquals("1", created.getMeta().getVersionId()); + assertNotNull(created.getMeta().getLastUpdated()); + + assertNotNull(created.getContentType()); + assertEquals(contentType, created.getContentType()); + assertTrue(Arrays.equals(data1, created.getData())); + + assertNotNull(created.getSecurityContext()); + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + + created.setData(data2); + + assertNotNull(created.getSecurityContext()); + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + + try + { + getExternalWebserviceClient().update(created); + } + catch (WebApplicationException e) + { + assertEquals(Status.FORBIDDEN.getStatusCode(), e.getResponse().getStatus()); + throw e; + } + } + @Test public void testSearchAll() throws Exception { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + PartialResult<Organization> result = orgDao + .search(orgDao.createSearchQueryWithoutUserFilter(1, 2).configureParameters(Collections.emptyMap())); + assertNotNull(result); + assertEquals(2, result.getOverallCount()); + assertNotNull(result.getPartialResult()); + assertEquals(2, result.getPartialResult().size()); + assertNotNull(result.getPartialResult().get(0)); + assertNotNull(result.getPartialResult().get(1)); + + Organization org1 = result.getPartialResult().get(0); + Organization org2 = result.getPartialResult().get(1); + + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary b1 = new Binary(); + b1.setContentType(contentType); + b1.setData(data); + b1.setSecurityContext(new Reference(org1.getIdElement())); + Binary b2 = new Binary(); + b2.setContentType(contentType); + b2.setData(data); + b2.setSecurityContext(new Reference(org1.getIdElement().toVersionless())); + Binary b3 = new Binary(); + b3.setContentType(contentType); + b3.setData(data); + b3.setSecurityContext(new Reference(org2.getIdElement())); + Binary b4 = new Binary(); + b4.setContentType(contentType); + b4.setData(data); + b4.setSecurityContext(new Reference(org2.getIdElement().toVersionless())); + + BinaryDao binaryDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + b1 = binaryDao.create(b1); + b2 = binaryDao.create(b2); + b3 = binaryDao.create(b3); + b4 = binaryDao.create(b4); + + Bundle searchBundle = getWebserviceClient().search(Binary.class, Collections.emptyMap()); + assertNotNull(searchBundle); + assertEquals(4, searchBundle.getTotal()); + assertTrue(searchBundle.getEntry().stream() + .allMatch(c -> c.getResource() != null && c.getResource() instanceof Binary)); + + String actualIds = searchBundle.getEntry().stream().map(c -> c.getResource()) + .map(r -> "Binary/" + r.getIdElement().getIdPart() + "/_history/" + r.getMeta().getVersionId()).sorted() + .collect(Collectors.joining(", ")); + String expectedIds = Arrays.asList(b1, b2, b3, b4).stream().map(b -> b.getIdElement().getValueAsString()) + .sorted().collect(Collectors.joining(", ")); + assertEquals(expectedIds, actualIds); + } + + @Test + public void testSearchAllExternalUser() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + PartialResult<Organization> result = orgDao + .search(orgDao.createSearchQueryWithoutUserFilter(1, 2).configureParameters(Collections.emptyMap())); + assertNotNull(result); + assertEquals(2, result.getOverallCount()); + assertNotNull(result.getPartialResult()); + assertEquals(2, result.getPartialResult().size()); + assertNotNull(result.getPartialResult().get(0)); + assertNotNull(result.getPartialResult().get(1)); + + Organization org1 = result.getPartialResult().get(0); + Organization org2 = result.getPartialResult().get(1); + final String contentType = "text/plain"; final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + Binary b1 = new Binary(); + b1.setContentType(contentType); + b1.setData(data); + b1.setSecurityContext(new Reference(org1.getIdElement())); + Binary b2 = new Binary(); + b2.setContentType(contentType); + b2.setData(data); + b2.setSecurityContext(new Reference(org1.getIdElement().toVersionless())); + Binary b3 = new Binary(); + b3.setContentType(contentType); + b3.setData(data); + b3.setSecurityContext(new Reference(org2.getIdElement())); + Binary b4 = new Binary(); + b4.setContentType(contentType); + b4.setData(data); + b4.setSecurityContext(new Reference(org2.getIdElement().toVersionless())); + + BinaryDao binaryDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + b1 = binaryDao.create(b1); + b2 = binaryDao.create(b2); + b3 = binaryDao.create(b3); + b4 = binaryDao.create(b4); + + Bundle searchBundle = getExternalWebserviceClient().search(Binary.class, Collections.emptyMap()); + assertNotNull(searchBundle); + assertEquals(2, searchBundle.getTotal()); + assertTrue(searchBundle.getEntry().stream() + .allMatch(c -> c.getResource() != null && c.getResource() instanceof Binary)); + + String actualIds = searchBundle.getEntry().stream().map(c -> c.getResource()) + .map(r -> "Binary/" + r.getIdElement().getIdPart() + "/_history/" + r.getMeta().getVersionId()).sorted() + .collect(Collectors.joining(", ")); + List<Binary> binaries = "External Test Organization".equals(org1.getName()) ? Arrays.asList(b1, b2) + : Arrays.asList(b3, b4); + String expectedIds = binaries.stream().map(b -> b.getIdElement().getValueAsString()).sorted() + .collect(Collectors.joining(", ")); + assertEquals(expectedIds, actualIds); + } + + @Test(expected = ResourceDeletedException.class) + public void testDelete() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + + final String contentType = "text/plain"; + final byte[] data1 = "Hello World".getBytes(StandardCharsets.UTF_8); + Binary binary = new Binary(); binary.setContentType(contentType); - binary.setData(data); + binary.setData(data1); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); BinaryDao binaryDao = getSpringWebApplicationContext().getBean(BinaryDao.class); Binary created = binaryDao.create(binary); @@ -198,21 +426,53 @@ public void testSearchAll() throws Exception assertNotNull(created.getContentType()); assertEquals(contentType, created.getContentType()); - assertTrue(Arrays.equals(data, created.getData())); + assertTrue(Arrays.equals(data1, created.getData())); - Bundle searchBundle = getWebserviceClient().search(Binary.class, Collections.emptyMap()); - assertNotNull(searchBundle); - assertEquals(1, searchBundle.getTotal()); - assertNotNull(searchBundle.getEntry().get(0)); - assertNotNull(searchBundle.getEntry().get(0).getSearch()); - assertEquals(SearchEntryMode.MATCH, searchBundle.getEntry().get(0).getSearch().getMode()); - assertNotNull(searchBundle.getEntry().get(0).getResource()); - assertTrue(searchBundle.getEntry().get(0).getResource() instanceof Binary); - - Binary found = (Binary) searchBundle.getEntry().get(0).getResource(); - assertNotNull(found.getContentType()); - assertEquals(contentType, found.getContentType()); - assertNotNull(found.getData()); - assertTrue(Arrays.equals(data, found.getData())); + assertNotNull(created.getSecurityContext()); + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + + getWebserviceClient().delete(Binary.class, created.getIdElement().getIdPart()); + + binaryDao.read(UUID.fromString(created.getIdElement().getIdPart())); + } + + @Test(expected = WebApplicationException.class) + public void testDeleteNotAllowedExternalUser() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + + final String contentType = "text/plain"; + final byte[] data1 = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data1); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); + + BinaryDao binaryDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binaryDao.create(binary); + + assertNotNull(created); + assertNotNull(created.getIdElement().toString()); + assertEquals("1", created.getMeta().getVersionId()); + assertNotNull(created.getMeta().getLastUpdated()); + + assertNotNull(created.getContentType()); + assertEquals(contentType, created.getContentType()); + assertTrue(Arrays.equals(data1, created.getData())); + + assertNotNull(created.getSecurityContext()); + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + + try + { + getExternalWebserviceClient().delete(Binary.class, created.getIdElement().getIdPart()); + } + catch (WebApplicationException e) + { + assertEquals(Status.FORBIDDEN.getStatusCode(), e.getResponse().getStatus()); + throw e; + } } } diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/test/X509Certificates.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/test/X509Certificates.java index 18dc956b4..6aacc0cf3 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/test/X509Certificates.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/test/X509Certificates.java @@ -75,11 +75,14 @@ public String getKeyStorePassword() private final X509Certificates parent; private ClientCertificate clientCertificate; - private Path caCertificateFile = Paths.get("target", UUID.randomUUID().toString() + ".pem"); - private Path serverCertificateFile = Paths.get("target", UUID.randomUUID().toString() + ".p12"); - private Path clientCertificateFile = Paths.get("target", UUID.randomUUID().toString() + ".p12"); + private ClientCertificate externalClientCertificate; - private List<Path> filesToDelete = Arrays.asList(caCertificateFile, serverCertificateFile, clientCertificateFile); + private Path caCertificateFile; + private Path serverCertificateFile; + private Path clientCertificateFile; + private Path externalClientCertificateFile; + + private List<Path> filesToDelete; public X509Certificates() { @@ -124,6 +127,14 @@ public ClientCertificate getClientCertificate() return clientCertificate; } + public ClientCertificate getExternalClientCertificate() + { + if (parentBeforeRan()) + return parent.getExternalClientCertificate(); + else + return externalClientCertificate; + } + public Path getCaCertificateFile() { if (parentBeforeRan()) @@ -148,14 +159,23 @@ public Path getClientCertificateFile() return clientCertificateFile; } + public Path getExternalClientCertificateFile() + { + if (parentBeforeRan()) + return parent.getExternalClientCertificateFile(); + + return externalClientCertificateFile; + } + private void createX509Certificates() throws InvalidKeyException, NoSuchAlgorithmException, KeyStoreException, CertificateException, OperatorCreationException, IllegalStateException, IOException, InvalidKeySpecException { logger.info("Creating certificates ..."); - caCertificateFile = Paths.get("target", UUID.randomUUID().toString() + ".pem"); - serverCertificateFile = Paths.get("target", UUID.randomUUID().toString() + ".p12"); - clientCertificateFile = Paths.get("target", UUID.randomUUID().toString() + ".p12"); + Path caCertificateFile = Paths.get("target", UUID.randomUUID().toString() + ".pem"); + Path serverCertificateFile = Paths.get("target", UUID.randomUUID().toString() + ".p12"); + Path clientCertificateFile = Paths.get("target", UUID.randomUUID().toString() + ".p12"); + Path externalClientCertificateFile = Paths.get("target", UUID.randomUUID().toString() + ".p12"); CertificateAuthority.registerBouncyCastleProvider(); @@ -165,6 +185,7 @@ private void createX509Certificates() throws InvalidKeyException, NoSuchAlgorith PemIo.writeX509CertificateToPem(caCertificate, caCertificateFile); + // -- server X500Name serverSubject = CertificationRequestBuilder.createSubject("DE", null, null, null, null, "test-server"); KeyPair serverRsaKeyPair = CertificationRequestBuilder.createRsaKeyPair4096Bit(); JcaPKCS10CertificationRequest serverRequest = CertificationRequestBuilder @@ -174,7 +195,9 @@ private void createX509Certificates() throws InvalidKeyException, NoSuchAlgorith CertificateWriter.toPkcs12(serverCertificateFile, serverRsaKeyPair.getPrivate(), "password", serverCertificate, caCertificate, "test-server"); + // server -- + // -- client X500Name clientSubject = CertificationRequestBuilder.createSubject("DE", null, null, null, null, "test-client"); KeyPair clientRsaKeyPair = CertificationRequestBuilder.createRsaKeyPair4096Bit(); JcaPKCS10CertificationRequest clientRequest = CertificationRequestBuilder @@ -188,12 +211,39 @@ private void createX509Certificates() throws InvalidKeyException, NoSuchAlgorith CertificateWriter.toPkcs12(clientCertificateFile, clientRsaKeyPair.getPrivate(), "password", clientCertificate, caCertificate, "client"); - - KeyStore clientTrustStore = CertificateHelper.extractTrust(clientKeyStore); - - this.clientCertificate = new ClientCertificate(clientCertificate, clientTrustStore, clientKeyStore, - clientKeyStorePassword); - this.filesToDelete = Arrays.asList(caCertificateFile, serverCertificateFile, clientCertificateFile); + // client -- + + // -- external client + X500Name externalClientSubject = CertificationRequestBuilder.createSubject("DE", null, null, null, null, + "external-client"); + KeyPair externalClientRsaKeyPair = CertificationRequestBuilder.createRsaKeyPair4096Bit(); + JcaPKCS10CertificationRequest externalClientRequest = CertificationRequestBuilder + .createClientCertificationRequest(externalClientSubject, externalClientRsaKeyPair); + + X509Certificate externalClientCertificate = ca.signWebClientCertificate(externalClientRequest); + + String externalClientKeyStorePassword = "password"; + KeyStore externalClientKeyStore = CertificateHelper.toPkcs12KeyStore(externalClientRsaKeyPair.getPrivate(), + new Certificate[] { externalClientCertificate, caCertificate }, "external-client", + externalClientKeyStorePassword); + + CertificateWriter.toPkcs12(externalClientCertificateFile, externalClientRsaKeyPair.getPrivate(), "password", + externalClientCertificate, caCertificate, "client"); + // external client -- + + this.clientCertificate = new ClientCertificate(clientCertificate, + CertificateHelper.extractTrust(clientKeyStore), clientKeyStore, clientKeyStorePassword); + this.externalClientCertificate = new ClientCertificate(externalClientCertificate, + CertificateHelper.extractTrust(externalClientKeyStore), externalClientKeyStore, + externalClientKeyStorePassword); + + this.caCertificateFile = caCertificateFile; + this.serverCertificateFile = serverCertificateFile; + this.clientCertificateFile = clientCertificateFile; + this.externalClientCertificateFile = externalClientCertificateFile; + + this.filesToDelete = Arrays.asList(caCertificateFile, serverCertificateFile, clientCertificateFile, + externalClientCertificateFile); } private void deleteX509Certificates() diff --git a/dsf-fhir/dsf-fhir-server/src/test/resources/integration/test-bundle.xml b/dsf-fhir/dsf-fhir-server/src/test/resources/integration/test-bundle.xml index 321750f71..4db0fbedf 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/resources/integration/test-bundle.xml +++ b/dsf-fhir/dsf-fhir-server/src/test/resources/integration/test-bundle.xml @@ -4,6 +4,12 @@ <fullUrl value="urn:uuid:bb73165c-c7b9-4342-8e28-531f07fa7735"/> <resource> <Organization xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization"/> + <code value="REMOTE"/> + </tag> + </meta> <extension url="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"> <valueString value="TODO"/> </extension> @@ -34,6 +40,12 @@ <fullUrl value="urn:uuid:b879e904-d666-45de-a995-accdd4429b79"/> <resource> <Endpoint xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization"/> + <code value="REMOTE"/> + </tag> + </meta> <identifier> <system value="http://highmed.org/fhir/CodeSystem/endpoint"/> <value value="Test_Endpoint"/> @@ -64,4 +76,36 @@ <url value="Endpoint?identifier=http://highmed.org/fhir/CodeSystem/endpoint|Test_Endpoint"/> </request> </entry> + <entry> + <fullUrl value="urn:uuid:ddd4e309-e41b-4427-9657-8a58a89f01a9"/> + <resource> + <Organization xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization"/> + <code value="REMOTE"/> + </tag> + </meta> + <extension url="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"> + <valueString value="TODO"/> + </extension> + <identifier> + <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <value value="External_Test_Organization"/> + </identifier> + <active value="true"/> + <type> + <coding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type"/> + <code value="MeDIC"/> + </coding> + </type> + <name value="External Test Organization"/> + </Organization> + </resource> + <request> + <method value="PUT"/> + <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|External_Test_Organization"/> + </request> + </entry> </Bundle> \ No newline at end of file From 1d45b10b03de594a7434355be242d7871c4ef07d Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Mon, 24 Feb 2020 02:06:19 +0100 Subject: [PATCH 09/55] organization/endpoint id-systems to NamingSystem, work on auth rules --- .../java/org/highmed/dsf/bpe/Constants.java | 4 +- ...lityFromMedicsViaMedic1ExampleStarter.java | 12 +- .../simple-feasibility-bundle.example.json | 10 +- .../Ping3MedicFromTtpExampleStarter.java | 4 +- .../resources/start-process-task.example.json | 4 +- .../test/resources/parent-task.example.json | 4 +- ...UpdateResource3MedicTtpExampleStarter.java | 6 +- ...request-update-resources-task.example.json | 6 +- ...pdateWhiteList3MedicTtpExampleStarter.java | 4 +- .../update-whitelist-task.example.json | 4 +- .../dsf/bpe/client/TestBpeJerseyClient.java | 4 +- .../OrganizationProviderWithDbBackend.java | 27 +++- .../authorization/TaskAuthorizationRule.java | 9 +- .../parameters/user/BinaryUserFilter.java | 4 +- .../parameters/user/TaskUserFilter.java | 26 ++-- .../spring/config/AuthenticationConfig.java | 5 +- .../fhir/NamingSystem/highmed-endpoint.xml | 4 +- .../NamingSystem/highmed-endpoint.xml.put | 2 +- .../NamingSystem/highmed-organization.xml | 4 +- .../NamingSystem/highmed-organization.xml.put | 2 +- .../highmed-endpoint-0.1.0.xml | 88 ++++++------ .../highmed-organization-0.1.0.xml | 130 ++++++++---------- .../org/highmed/dsf/fhir/hapi/BundleTest.java | 8 +- .../org/highmed/dsf/fhir/hapi/TaskTest.java | 44 ++++++ .../src/test/resources/bundle.xml | 30 ++-- .../resources/integration/test-bundle.xml | 12 +- .../fhir/client/TestFhirJerseyClient.java | 18 +-- .../bundle-templates/medic1-bundle.xml | 14 +- .../bundle-templates/medic2-bundle.xml | 14 +- .../bundle-templates/medic3-bundle.xml | 14 +- .../bundle-templates/test-bundle.xml | 8 +- .../resources/bundle-templates/ttp-bundle.xml | 40 +++--- .../docker-test-fhir-config.properties | 1 + .../docker-test-medic1-fhir-config.properties | 1 + .../docker-test-medic2-fhir-config.properties | 1 + .../docker-test-medic3-fhir-config.properties | 1 + .../docker-test-ttp-fhir-config.properties | 1 + .../java-test-fhir-config.properties | 1 + 38 files changed, 318 insertions(+), 253 deletions(-) create mode 100644 dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/TaskTest.java diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/bpe/Constants.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/bpe/Constants.java index e76546a7d..a723033c2 100755 --- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/bpe/Constants.java +++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/bpe/Constants.java @@ -64,9 +64,9 @@ public interface Constants String PROCESS_URI_BASE = "http://highmed.org/bpe/Process/"; - String ORGANIZATION_IDENTIFIER_SYSTEM = "http://highmed.org/fhir/CodeSystem/organization"; + String ORGANIZATION_IDENTIFIER_SYSTEM = "http://highmed.org/fhir/NamingSystem/organization-identifier"; String ORGANIZATION_TYPE_SYSTEM = "http://highmed.org/fhir/CodeSystem/organization-type"; - String ENDPOINT_IDENTIFIER_SYSTEM = "http://highmed.org/fhir/CodeSystem/endpoint"; + String ENDPOINT_IDENTIFIER_SYSTEM = "http://highmed.org/fhir/NamingSystem/endpoint-identifier"; String EXTENSION_PARTICIPATING_MEDIC_URI = "http://highmed.org/fhir/StructureDefinition/participating-medic"; String EXTENSION_QUERY_URI = "http://highmed.org/fhir/StructureDefinition/query"; diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java b/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java index 68f36a124..ab1f7143a 100644 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java @@ -134,8 +134,8 @@ private static PractitionerRole createPractitionerRole(Practitioner practitioner practitionerRole.getPractitioner().setReference(practitioner.getIdElement().getIdPart()) .setType("Practitioner"); practitionerRole.getOrganization().setType("Organization").getIdentifier() - .setSystem("http://highmed.org/fhir/CodeSystem/organization").setValue("Test_MeDIC_1"); - + .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_MeDIC_1"); + return practitionerRole; } @@ -156,13 +156,13 @@ private static ResearchStudy createResearchStudy(Group group1, Group group2, Pra researchStudy.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-medic") .setValue(new Reference().setType("Organization").setIdentifier(new Identifier() - .setSystem("http://highmed.org/fhir/CodeSystem/organization").setValue("Test_MeDIC_1"))); + .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_MeDIC_1"))); researchStudy.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-medic") .setValue(new Reference().setType("Organization").setIdentifier(new Identifier() - .setSystem("http://highmed.org/fhir/CodeSystem/organization").setValue("Test_MeDIC_2"))); + .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_MeDIC_2"))); researchStudy.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-medic") .setValue(new Reference().setType("Organization").setIdentifier(new Identifier() - .setSystem("http://highmed.org/fhir/CodeSystem/organization").setValue("Test_MeDIC_3"))); + .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_MeDIC_3"))); return researchStudy; } @@ -180,7 +180,7 @@ private static Task createTask(Practitioner practitioner, ResearchStudy research task.setAuthoredOn(new Date()); task.getRequester().setType("Practitioner").setReference(practitioner.getIdElement().getIdPart()); task.getRestriction().addRecipient().setType("Organization").getIdentifier() - .setSystem("http://highmed.org/fhir/CodeSystem/organization").setValue("Test_MeDIC_1"); + .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_MeDIC_1"); task.addInput().setValue(new StringType("requestSimpleFeasibilityMessage")).getType().addCoding() .setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message").setCode("message-name"); diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/test/resources/simple-feasibility-bundle.example.json b/dsf-bpe/dsf-bpe-process-feasibility/src/test/resources/simple-feasibility-bundle.example.json index 2310de132..23f982674 100755 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/test/resources/simple-feasibility-bundle.example.json +++ b/dsf-bpe/dsf-bpe-process-feasibility/src/test/resources/simple-feasibility-bundle.example.json @@ -115,7 +115,7 @@ }, "organization":{ "identifier":{ - "system":"http://highmed.org/fhir/CodeSystem/organization", + "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", "value":"Test_Organization" }, "type":"Organization" @@ -152,7 +152,7 @@ "url":"http://highmed.org/fhir/StructureDefinition/participating-medic", "valueReference":{ "identifier":{ - "system":"http://highmed.org/fhir/CodeSystem/organization", + "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", "value":"Test_Organization" }, "type":"Organization" @@ -162,7 +162,7 @@ "url":"http://highmed.org/fhir/StructureDefinition/participating-medic", "valueReference":{ "identifier":{ - "system":"http://highmed.org/fhir/CodeSystem/organization", + "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", "value":"Test_Organization_2" }, "type":"Organization" @@ -172,7 +172,7 @@ "url":"http://highmed.org/fhir/StructureDefinition/participating-medic", "valueReference":{ "identifier":{ - "system":"http://highmed.org/fhir/CodeSystem/organization", + "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", "value":"Test_Organization_3" }, "type":"Organization" @@ -203,7 +203,7 @@ "recipient":[ { "identifier":{ - "system":"http://highmed.org/fhir/CodeSystem/organization", + "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", "value":"Test_Organization" }, "type":"Organization" diff --git a/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java b/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java index 41d63b53f..7c06527ef 100644 --- a/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java @@ -44,9 +44,9 @@ public static void main(String[] args) task.setIntent(TaskIntent.ORDER); task.setAuthoredOn(new Date()); task.getRequester().setType("Organization").getIdentifier() - .setSystem("http://highmed.org/fhir/CodeSystem/organization").setValue("Test_TTP"); + .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_TTP"); task.getRestriction().addRecipient().setType("Organization").getIdentifier() - .setSystem("http://highmed.org/fhir/CodeSystem/organization").setValue("Test_TTP"); + .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_TTP"); task.addInput().setValue(new StringType("startProcessMessage")).getType().addCoding() .setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message").setCode("message-name"); diff --git a/dsf-bpe/dsf-bpe-process-ping/src/test/resources/start-process-task.example.json b/dsf-bpe/dsf-bpe-process-ping/src/test/resources/start-process-task.example.json index 2e44a9425..9e7a896e7 100755 --- a/dsf-bpe/dsf-bpe-process-ping/src/test/resources/start-process-task.example.json +++ b/dsf-bpe/dsf-bpe-process-ping/src/test/resources/start-process-task.example.json @@ -9,7 +9,7 @@ "authoredOn":"2019-10-21", "requester":{ "identifier":{ - "system":"http://highmed.org/fhir/CodeSystem/organization", + "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", "value":"Test_Organization" }, "type":"Organization" @@ -18,7 +18,7 @@ "recipient":[ { "identifier":{ - "system":"http://highmed.org/fhir/CodeSystem/organization", + "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", "value":"Test_Organization_2" }, "type":"Organization" diff --git a/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-parent/src/test/resources/parent-task.example.json b/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-parent/src/test/resources/parent-task.example.json index 260f1644f..3cdb96f68 100644 --- a/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-parent/src/test/resources/parent-task.example.json +++ b/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-parent/src/test/resources/parent-task.example.json @@ -9,7 +9,7 @@ "authoredOn":"2019-10-21", "requester":{ "identifier":{ - "system":"http://highmed.org/fhir/CodeSystem/organization", + "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", "value":"Test_Organization" }, "type":"Organization" @@ -18,7 +18,7 @@ "recipient":[ { "identifier":{ - "system":"http://highmed.org/fhir/CodeSystem/organization", + "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", "value":"Test_Organization" }, "type":"Organization" diff --git a/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java b/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java index 17d12d6cb..21bc3c580 100644 --- a/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java @@ -54,9 +54,9 @@ public static void main(String[] args) task.setIntent(TaskIntent.ORDER); task.setAuthoredOn(new Date()); task.getRequester().setType("Organization").getIdentifier() - .setSystem("http://highmed.org/fhir/CodeSystem/organization").setValue("Test_TTP"); + .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_TTP"); task.getRestriction().addRecipient().setType("Organization").getIdentifier() - .setSystem("http://highmed.org/fhir/CodeSystem/organization").setValue("Test_TTP"); + .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_TTP"); task.addInput().setValue(new StringType("requestUpdateResourcesMessage")).getType().addCoding() .setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message").setCode("message-name"); @@ -64,7 +64,7 @@ public static void main(String[] args) task.addInput().setValue(new Reference("Bundle/" + whiteList.getIdElement().getIdPart())).getType().addCoding() .setSystem("http://highmed.org/fhir/CodeSystem/update-resources").setCode("bundle-reference"); - task.addInput().setValue(new StringType("http://highmed.org/fhir/CodeSystem/organization|")).getType() + task.addInput().setValue(new StringType("http://highmed.org/fhir/NamingSystem/organization-identifier|")).getType() .addCoding().setSystem("http://highmed.org/fhir/CodeSystem/update-resources") .setCode("organization-identifier-search-parameter"); diff --git a/dsf-bpe/dsf-bpe-process-update-resources/src/test/resources/request-update-resources-task.example.json b/dsf-bpe/dsf-bpe-process-update-resources/src/test/resources/request-update-resources-task.example.json index d9c018635..d86cc4ef1 100755 --- a/dsf-bpe/dsf-bpe-process-update-resources/src/test/resources/request-update-resources-task.example.json +++ b/dsf-bpe/dsf-bpe-process-update-resources/src/test/resources/request-update-resources-task.example.json @@ -8,7 +8,7 @@ "intent":"order", "requester":{ "identifier":{ - "system":"http://highmed.org/fhir/CodeSystem/organization", + "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", "value":"Test_Organization" }, "type":"Organization" @@ -17,7 +17,7 @@ "recipient":[ { "identifier":{ - "system":"http://highmed.org/fhir/CodeSystem/organization", + "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", "value":"Test_Organization" }, "type":"Organization" @@ -58,7 +58,7 @@ } ] }, - "valueString":"http://highmed.org/fhir/CodeSystem/organization|" + "valueString":"http://highmed.org/fhir/NamingSystem/organization-identifier|" } ] } \ No newline at end of file diff --git a/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java b/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java index 3231a0e46..70428f79d 100644 --- a/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java @@ -44,9 +44,9 @@ public static void main(String[] args) task.setIntent(TaskIntent.ORDER); task.setAuthoredOn(new Date()); task.getRequester().setType("Organization").getIdentifier() - .setSystem("http://highmed.org/fhir/CodeSystem/organization").setValue("Test_TTP"); + .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_TTP"); task.getRestriction().addRecipient().setType("Organization").getIdentifier() - .setSystem("http://highmed.org/fhir/CodeSystem/organization").setValue("Test_TTP"); + .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_TTP"); task.addInput().setValue(new StringType("updateWhiteListMessage")).getType().addCoding() .setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message").setCode("message-name"); diff --git a/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/resources/update-whitelist-task.example.json b/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/resources/update-whitelist-task.example.json index b5c3ba0a6..c7a54d9d2 100755 --- a/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/resources/update-whitelist-task.example.json +++ b/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/resources/update-whitelist-task.example.json @@ -9,7 +9,7 @@ "authoredOn":"2019-10-21", "requester":{ "identifier":{ - "system":"http://highmed.org/fhir/CodeSystem/organization", + "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", "value":"Test_Organization" }, "type":"Organization" @@ -18,7 +18,7 @@ "recipient":[ { "identifier":{ - "system":"http://highmed.org/fhir/CodeSystem/organization", + "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", "value":"Test_Organization" }, "type":"Organization" diff --git a/dsf-bpe/dsf-bpe-webservice-client/src/test/java/org/highmed/dsf/bpe/client/TestBpeJerseyClient.java b/dsf-bpe/dsf-bpe-webservice-client/src/test/java/org/highmed/dsf/bpe/client/TestBpeJerseyClient.java index 609cfa2c2..fa87f0b32 100755 --- a/dsf-bpe/dsf-bpe-webservice-client/src/test/java/org/highmed/dsf/bpe/client/TestBpeJerseyClient.java +++ b/dsf-bpe/dsf-bpe-webservice-client/src/test/java/org/highmed/dsf/bpe/client/TestBpeJerseyClient.java @@ -36,11 +36,11 @@ public static void main(String[] args) // client.startProcessWithVersion("updateWhiteList", "1.0.0"); client.startProcessWithVersion("requestUpdateResources", "1.0.0", Map.of("target-identifier", - Collections.singletonList("http://highmed.org/fhir/CodeSystem/organization|"), "bundle-id", + Collections.singletonList("http://highmed.org/fhir/NamingSystem/organization-identifier|"), "bundle-id", Arrays.asList("Bundle/2548395d-83d3-488a-859e-a844e62ce3fd"))); // client.startProcessWithVersion("requestUpdateResources", "1.0.0", Map.of("target-identifier", -// Collections.singletonList("http://highmed.org/fhir/CodeSystem/organization|"), "bundle-id", +// Collections.singletonList("http://highmed.org/fhir/NamingSystem/organization-identifier|"), "bundle-id", // Arrays.asList("Bundle/30a376fa-f3ba-4f68-8e04-c5b9c0c4f5c9"))); // client.startProcessWithVersion("requestSimpleCohortSizeQuery", "1.0.0"); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/OrganizationProviderWithDbBackend.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/OrganizationProviderWithDbBackend.java index 08970ddb4..57a5ac782 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/OrganizationProviderWithDbBackend.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/OrganizationProviderWithDbBackend.java @@ -5,7 +5,9 @@ import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -15,6 +17,8 @@ import org.apache.commons.codec.binary.Hex; import org.highmed.dsf.fhir.dao.OrganizationDao; import org.highmed.dsf.fhir.help.ExceptionHandler; +import org.highmed.dsf.fhir.search.PartialResult; +import org.highmed.dsf.fhir.search.SearchQuery; import org.hl7.fhir.r4.model.Organization; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,15 +31,17 @@ public class OrganizationProviderWithDbBackend implements OrganizationProvider, private final OrganizationDao dao; private final ExceptionHandler exceptionHandler; private final List<String> localUserThumbprints = new ArrayList<String>(); + private final String localSystemAndIdentifier; public OrganizationProviderWithDbBackend(OrganizationDao dao, ExceptionHandler exceptionHandler, - List<String> localUserThumbprints) + List<String> localUserThumbprints, String localSystemAndIdentifier) { this.dao = dao; this.exceptionHandler = exceptionHandler; if (localUserThumbprints != null) localUserThumbprints.stream().map(t -> t.toLowerCase()).forEach(this.localUserThumbprints::add); + this.localSystemAndIdentifier = localSystemAndIdentifier; } @Override @@ -50,6 +56,9 @@ public void afterPropertiesSet() throws Exception logger.info("{} local user{} configured with tumbprint{}: {}", localUserThumbprints.size(), localUserThumbprints.size() != 1 ? "s" : "", localUserThumbprints.size() != 1 ? "s" : "", localUserThumbprints.stream().collect(Collectors.joining(", ", "[", "]"))); + + if (getLocalOrganization().isEmpty()) + logger.warn("Local organization not found by identifier: {}", localSystemAndIdentifier); } @Override @@ -69,11 +78,25 @@ public Optional<User> getOrganization(X509Certificate certificate) () -> dao.readActiveNotDeletedByThumbprint(loginThumbprintHex), Optional::empty); if (optOrg.isEmpty() && UserRole.LOCAL.equals(userRole)) - return Optional.of(new User(new Organization().setName("Local Admin User"), userRole)); + return getLocalOrganization().map(org -> new User(org, userRole)); return optOrg.map(org -> new User(org, userRole)); } + private Optional<Organization> getLocalOrganization() + { + SearchQuery<Organization> query = dao.createSearchQueryWithoutUserFilter(1, 1) + .configureParameters(Map.of("identifier", Arrays.asList(localSystemAndIdentifier))); + + PartialResult<Organization> result = exceptionHandler + .catchAndLogSqlExceptionAndIfReturn(() -> dao.search(query), null); + + if (result != null && result.getOverallCount() == 1) + return Optional.of(result.getPartialResult().get(0)); + else + return Optional.empty(); + } + private byte[] getThumbprint(X509Certificate certificate) { try diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java index d904eeb88..b6e5ed7ba 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java @@ -7,9 +7,13 @@ import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Task; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class TaskAuthorizationRule extends AbstractAuthorizationRule<Task, TaskDao> { + private static final Logger logger = LoggerFactory.getLogger(TaskAuthorizationRule.class); + public TaskAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { super(Task.class, daoProvider, serverBase, referenceResolver); @@ -56,7 +60,8 @@ public Optional<String> reasonDeleteAllowed(User user, Task oldResource) @Override public Optional<String> reasonSearchAllowed(User user) { - // TODO Auto-generated method stub - return Optional.empty(); + logger.info("Search of Task authorized for {} user '{}', will be fitered by users organization {}", + user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString()); + return Optional.of("Allowed for all, filtered by users organization"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java index 2982e10ba..cfdd9cae2 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java @@ -35,9 +35,9 @@ public void modifyStatement(int parameterIndex, PreparedStatement statement) thr if (!UserRole.LOCAL.equals(user.getRole())) { if (parameterIndex == 1) - statement.setString(1, user.getOrganization().getIdElement().getValue()); + statement.setString(parameterIndex, user.getOrganization().getIdElement().getValue()); else if (parameterIndex == 2) - statement.setString(2, user.getOrganization().getIdElement().toVersionless().getValue()); + statement.setString(parameterIndex, user.getOrganization().getIdElement().toVersionless().getValue()); } } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/TaskUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/TaskUserFilter.java index 51217a853..c87c7386a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/TaskUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/TaskUserFilter.java @@ -5,13 +5,9 @@ import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; public class TaskUserFilter extends AbstractUserFilter { - private static final Logger logger = LoggerFactory.getLogger(TaskUserFilter.class); - public TaskUserFilter(OrganizationType organizationType, User user) { super(organizationType, user); @@ -20,24 +16,28 @@ public TaskUserFilter(OrganizationType organizationType, User user) @Override public String getFilterQuery() { - // TODO implement - - logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); - return "false"; + return "(task->'requester'->>'reference' = ? OR task->'requester'->>'reference' = ? OR" + + " task->'restriction'->'recipient' @> ?::jsonb OR task->'restriction'->'recipient' @> ?::jsonb)"; } @Override public int getSqlParameterCount() { - logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); - return 0; + return 4; } @Override public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException { - // TODO implement - - logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + if (parameterIndex == 1) + statement.setString(parameterIndex, user.getOrganization().getIdElement().getValue()); + else if (parameterIndex == 2) + statement.setString(parameterIndex, user.getOrganization().getIdElement().toVersionless().getValue()); + else if (parameterIndex == 3) + statement.setString(parameterIndex, + "[{\"reference\": \"" + user.getOrganization().getIdElement().getValue() + "\"}]"); + else if (parameterIndex == 4) + statement.setString(parameterIndex, + "[{\"reference\": \"" + user.getOrganization().getIdElement().toVersionless().getValue() + "\"}]"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthenticationConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthenticationConfig.java index 096ccf772..20c287889 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthenticationConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthenticationConfig.java @@ -27,6 +27,9 @@ public class AuthenticationConfig @Value("#{'${org.highmed.dsf.fhir.local-user.thumbprints}'.split(',')}") private List<String> localUserThumbprints; + @Value("${org.highmed.dsf.fhir.local-organization.systemAndIdentifier}") + private String localSystemAndIdentifier; + @Bean public AuthenticationFilterConfig authenticationFilterConfig() { @@ -37,6 +40,6 @@ public AuthenticationFilterConfig authenticationFilterConfig() public OrganizationProvider organizationProvider() { return new OrganizationProviderWithDbBackend(daoConfig.organizationDao(), helperConfig.exceptionHandler(), - localUserThumbprints); + localUserThumbprints, localSystemAndIdentifier); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-endpoint.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-endpoint.xml index b894e1073..4034eefbe 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-endpoint.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-endpoint.xml @@ -1,6 +1,6 @@ <NamingSystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://hl7.org/fhir" xsi:schemaLocation="http://hl7.org/fhir http://www.hl7.org/fhir/fhir-base.xsd"> - <name value="HiGHmed_Endpoint_Identifiers"/> + <name value="HiGHmed_Endpoint_Identifier"/> <status value="active"/> <kind value="identifier"/> <date value="2019-09-23"/> @@ -10,6 +10,6 @@ <usage value="Used withing HiGHmed to identify endpoints"/> <uniqueId> <type value="uri"/> - <value value="http://highmed.org/fhir/NamingSystem/endpoint-identifiers"/> + <value value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> </uniqueId> </NamingSystem> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-endpoint.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-endpoint.xml.put index 1e1315df7..b5facfc23 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-endpoint.xml.put +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-endpoint.xml.put @@ -1 +1 @@ -NamingSystem?name=HiGHmed_Endpoint_Identifiers \ No newline at end of file +NamingSystem?name=HiGHmed_Endpoint_Identifier \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-organization.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-organization.xml index 5dd83e933..22217f478 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-organization.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-organization.xml @@ -1,6 +1,6 @@ <NamingSystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://hl7.org/fhir" xsi:schemaLocation="http://hl7.org/fhir http://www.hl7.org/fhir/fhir-base.xsd"> - <name value="HiGHmed_Organization_Identifiers"/> + <name value="HiGHmed_Organization_Identifier"/> <status value="active"/> <kind value="identifier"/> <date value="2015-08-31"/> @@ -11,6 +11,6 @@ <usage value="Used withing HiGHmed to identify organizations"/> <uniqueId> <type value="uri"/> - <value value="http://highmed.org/fhir/NamingSystem/organization-identifiers"/> + <value value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> </uniqueId> </NamingSystem> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-organization.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-organization.xml.put index 284f978d2..9aa46c1c8 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-organization.xml.put +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-organization.xml.put @@ -1 +1 @@ -NamingSystem?name=HiGHmed_Organization_Identifiers \ No newline at end of file +NamingSystem?name=HiGHmed_Organization_Identifier \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-endpoint-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-endpoint-0.1.0.xml index 76c6fafd0..e5e1f468a 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-endpoint-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-endpoint-0.1.0.xml @@ -1,50 +1,44 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> - <url value="http://highmed.org/fhir/StructureDefinition/highmed-endpoint"/> - <version value="0.1.0"/> - <name value="Endpoint"/> - <status value="active"/> - <date value="2019-05-21"/> - <fhirVersion value="4.0.0"/> - <kind value="resource"/> - <abstract value="false"/> - <type value="Endpoint"/> - <baseDefinition value="http://hl7.org/fhir/StructureDefinition/Endpoint"/> - <derivation value="constraint"/> - <differential> - <element id="Endpoint.identifier"> - <path value="Endpoint.identifier"/> - <slicing> - <discriminator> - <type value="value"/> - <path value="system"/> - </discriminator> - <rules value="open"/> - </slicing> - <min value="1"/> - </element> - <element id="Endpoint.identifier:sliceIdentifier"> - <path value="Endpoint.identifier"/> - <sliceName value="sliceIdentifier"/> - </element> - <element id="Endpoint.identifier:sliceIdentifier.system"> - <path value="Endpoint.identifier.system"/> - <fixedUri value="http://highmed.org/fhir/CodeSystem/highmed-endpoint"/> - </element> - <element id="Endpoint.identifier:sliceIdentifier.value"> - <path value="Endpoint.identifier.value"/> - <binding> - <strength value="required"/> - <valueSet value="http://highmed.org/fhir/ValueSet/highmed-endpoint"/> - </binding> - </element> - <element id="Endpoint.managingOrganization"> - <path value="Endpoint.managingOrganization"/> - <min value="1"/> - <type> - <code value="Reference"/> - <targetProfile value="http://highmed.org/fhir/StructureDefinition/highmed-organization"/> - </type> - </element> - </differential> + <url value="http://highmed.org/fhir/StructureDefinition/highmed-endpoint" /> + <version value="0.1.0" /> + <name value="Endpoint" /> + <status value="active" /> + <date value="2019-05-21" /> + <fhirVersion value="4.0.0" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="Endpoint" /> + <baseDefinition value="http://hl7.org/fhir/StructureDefinition/Endpoint" /> + <derivation value="constraint" /> + <differential> + <element id="Endpoint.identifier"> + <path value="Endpoint.identifier" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="system" /> + </discriminator> + <rules value="open" /> + </slicing> + <min value="1" /> + </element> + <element id="Endpoint.identifier:sliceIdentifier"> + <path value="Endpoint.identifier" /> + <sliceName value="sliceIdentifier" /> + </element> + <element id="Endpoint.identifier:sliceIdentifier.system"> + <path value="Endpoint.identifier.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/NamingSystem/endpoint-identifier" /> + </element> + <element id="Endpoint.managingOrganization"> + <path value="Endpoint.managingOrganization" /> + <min value="1" /> + <type> + <code value="Reference" /> + <targetProfile value="http://highmed.org/fhir/StructureDefinition/highmed-organization" /> + </type> + </element> + </differential> </StructureDefinition> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-organization-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-organization-0.1.0.xml index e50815078..eebcd083b 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-organization-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-organization-0.1.0.xml @@ -1,73 +1,63 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> - <url value="http://highmed.org/fhir/StructureDefinition/highmed-organization"/> - <version value="0.1.0"/> - <name value="Organization"/> - <status value="active"/> - <date value="2019-05-21"/> - <fhirVersion value="4.0.0"/> - <kind value="resource"/> - <abstract value="false"/> - <type value="Organization"/> - <baseDefinition value="http://hl7.org/fhir/StructureDefinition/Organization"/> - <derivation value="constraint"/> - <differential> - <element id="Organization.extension"> - <path value="Organization.extension"/> - <slicing> - <discriminator> - <type value="value"/> - <path value="url"/> - </discriminator> - <rules value="open"/> - </slicing> - </element> - <element id="Organization.extension:certificateThumbprint"> - <path value="Organization.extension"/> - <sliceName value="certificateThumbprint"/> - <min value="1"/> - <type> - <code value="Extension"/> - <profile value="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"/> - </type> - </element> - <element id="Organization.identifier"> - <path value="Organization.identifier"/> - <slicing> - <discriminator> - <type value="value"/> - <path value="system"/> - </discriminator> - <rules value="open"/> - </slicing> - <min value="1"/> - </element> - <element id="Organization.identifier:HiGHmed"> - <path value="Organization.identifier"/> - <sliceName value="HiGHmed"/> - <min value="1"/> - <max value="1"/> - </element> - <element id="Organization.identifier:HiGHmed.system"> - <path value="Organization.identifier.system"/> - <min value="1"/> - <fixedUri value="http://highmed.org/fhir/CodeSystem/organization"/> - </element> - <element id="Organization.identifier:HiGHmed.value"> - <path value="Organization.identifier.value"/> - <min value="1"/> - <binding> - <strength value="required"/> - <valueSet value="http://highmed.org/fhir/ValueSet/organization"/> - </binding> - </element> - <element id="Organization.endpoint"> - <path value="Organization.endpoint"/> - <min value="1"/> - <type> - <code value="Reference"/> - <targetProfile value="http://highmed.org/fhir/StructureDefinition/highmed-endpoint"/> - </type> - </element> - </differential> + <url value="http://highmed.org/fhir/StructureDefinition/highmed-organization" /> + <version value="0.1.0" /> + <name value="Organization" /> + <status value="active" /> + <date value="2019-05-21" /> + <fhirVersion value="4.0.0" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="Organization" /> + <baseDefinition value="http://hl7.org/fhir/StructureDefinition/Organization" /> + <derivation value="constraint" /> + <differential> + <element id="Organization.extension"> + <path value="Organization.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> + </element> + <element id="Organization.extension:certificateThumbprint"> + <path value="Organization.extension" /> + <sliceName value="certificateThumbprint" /> + <min value="1" /> + <type> + <code value="Extension" /> + <profile value="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint" /> + </type> + </element> + <element id="Organization.identifier"> + <path value="Organization.identifier" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="system" /> + </discriminator> + <rules value="open" /> + </slicing> + <min value="1" /> + </element> + <element id="Organization.identifier:sliceIdentifier"> + <path value="Organization.identifier" /> + <sliceName value="sliceIdentifier" /> + </element> + <element id="Organization.identifier:sliceIdentifier.system"> + <path value="Organization.identifier.system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/NamingSystem/organization-identifier" /> + </element> + <element id="Organization.endpoint"> + <path value="Organization.endpoint" /> + <min value="1" /> + <type> + <code value="Reference" /> + <targetProfile value="http://highmed.org/fhir/StructureDefinition/highmed-endpoint" /> + </type> + </element> + </differential> </StructureDefinition> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/BundleTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/BundleTest.java index 38bca057b..5a1477fa9 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/BundleTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/BundleTest.java @@ -66,10 +66,10 @@ private void testBundleWithParser(IParser parser) String eptTempId = "urn:uuid:" + UUID.randomUUID().toString(); Organization org = new Organization(); - org.addIdentifier().setSystem("http://highmed.org/fhir/CodeSystem/organization").setValue("Test_Organization"); + org.addIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_Organization"); Endpoint ept = new Endpoint(); - ept.addIdentifier().setSystem("http://highmed.org/fhir/CodeSystem/endpoint").setValue("Test_Endpoint"); + ept.addIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/endpoint-identifier").setValue("Test_Endpoint"); org.getEndpointFirstRep().setType("Endpoint").setReference(eptTempId); ept.getManagingOrganization().setType("Organization").setReference(orgTempId); @@ -78,13 +78,13 @@ private void testBundleWithParser(IParser parser) orgEntry.setFullUrl(orgTempId); orgEntry.setResource(org); orgEntry.getRequest().setMethod(HTTPVerb.PUT) - .setUrl("Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_Organization"); + .setUrl("Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_Organization"); BundleEntryComponent eptEntry = bundle1.addEntry(); eptEntry.setFullUrl(eptTempId); eptEntry.setResource(ept); eptEntry.getRequest().setMethod(HTTPVerb.PUT) - .setUrl("Endpoint?identifier=http://highmed.org/fhir/CodeSystem/endpoint|Test_Endpoint"); + .setUrl("Endpoint?identifier=http://highmed.org/fhir/NamingSystem/endpoint-identifier|Test_Endpoint"); String bundle1String = parser.encodeResourceToString(bundle1); logger.debug("Bundle1: {}", bundle1String); diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/TaskTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/TaskTest.java new file mode 100644 index 000000000..32e837059 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/TaskTest.java @@ -0,0 +1,44 @@ +package org.highmed.dsf.fhir.hapi; + +import static org.junit.Assert.*; + +import java.util.UUID; + +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.Task; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ca.uhn.fhir.context.FhirContext; + +public class TaskTest +{ + private static final Logger logger = LoggerFactory.getLogger(TaskTest.class); + + @Test + public void testRequester() throws Exception + { + Task t = new Task(); + t.setRequester(new Reference("Organization/" + UUID.randomUUID().toString())); + + FhirContext context = FhirContext.forR4(); + + String txt = context.newJsonParser().setPrettyPrint(true).encodeResourceToString(t); + assertNotNull(txt); + logger.debug(txt); + } + + @Test + public void testRestrictionRecipient() throws Exception + { + Task t = new Task(); + t.getRestriction().addRecipient(new Reference("Organization/" + UUID.randomUUID().toString())); + + FhirContext context = FhirContext.forR4(); + + String txt = context.newJsonParser().setPrettyPrint(true).encodeResourceToString(t); + assertNotNull(txt); + logger.debug(txt); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/test/resources/bundle.xml b/dsf-fhir/dsf-fhir-server/src/test/resources/bundle.xml index f420b9ef0..f961571a8 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/resources/bundle.xml +++ b/dsf-fhir/dsf-fhir-server/src/test/resources/bundle.xml @@ -37,7 +37,7 @@ </resource> <request> <method value="PUT"></method> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_MeDIC_3"></url> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_MeDIC_3"></url> </request> </entry> <entry> @@ -45,7 +45,7 @@ <resource> <Endpoint xmlns="http://hl7.org/fhir"> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/endpoint"></system> + <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"></system> <value value="Test_MeDIC_3_Endpoint"></value> </identifier> <status value="active"></status> @@ -71,7 +71,7 @@ </resource> <request> <method value="PUT"></method> - <url value="Endpoint?identifier=http://highmed.org/fhir/CodeSystem/endpoint|Test_MeDIC_3_Endpoint"></url> + <url value="Endpoint?identifier=http://highmed.org/fhir/NamingSystem/endpoint-identifier|Test_MeDIC_3_Endpoint"></url> </request> </entry> <entry> @@ -83,7 +83,7 @@ value="532a7736fd2187c4895765fa211cd076e70d0e9405c466b650ca3c2e89b9cd796a063f1840f26b6422b08aafdaff677fb53bec14916185355ae1b6ee1b0afc5f"></valueString> </extension> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"></system> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"></system> <value value="Test_TTP"></value> </identifier> <active value="true"></active> @@ -102,7 +102,7 @@ </resource> <request> <method value="PUT"></method> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_TTP"></url> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_TTP"></url> </request> </entry> <entry> @@ -110,7 +110,7 @@ <resource> <Endpoint xmlns="http://hl7.org/fhir"> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/endpoint"></system> + <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"></system> <value value="Test_TTP_Endpoint"></value> </identifier> <status value="active"></status> @@ -136,7 +136,7 @@ </resource> <request> <method value="PUT"></method> - <url value="Endpoint?identifier=http://highmed.org/fhir/CodeSystem/endpoint|Test_TTP_Endpoint"></url> + <url value="Endpoint?identifier=http://highmed.org/fhir/NamingSystem/endpoint-identifier|Test_TTP_Endpoint"></url> </request> </entry> <entry> @@ -148,7 +148,7 @@ value="f143826e22f1a95830ab32dde7b388c154039ed0633c9b0d1526078a9ee7f403540e3cd3459331a3c2caf72e006daff2f71ab7cd2136272e5e022ef392c32246"></valueString> </extension> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"></system> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"></system> <value value="Test_MeDIC_1"></value> </identifier> <active value="true"></active> @@ -167,7 +167,7 @@ </resource> <request> <method value="PUT"></method> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_MeDIC_1"></url> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_MeDIC_1"></url> </request> </entry> <entry> @@ -175,7 +175,7 @@ <resource> <Endpoint xmlns="http://hl7.org/fhir"> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/endpoint"></system> + <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"></system> <value value="Test_MeDIC_1_Endpoint"></value> </identifier> <status value="active"></status> @@ -201,7 +201,7 @@ </resource> <request> <method value="PUT"></method> - <url value="Endpoint?identifier=http://highmed.org/fhir/CodeSystem/endpoint|Test_MeDIC_1_Endpoint"></url> + <url value="Endpoint?identifier=http://highmed.org/fhir/NamingSystem/endpoint-identifier|Test_MeDIC_1_Endpoint"></url> </request> </entry> <entry> @@ -213,7 +213,7 @@ value="e4af921e6cbc35032ddb21b8a36f366ff7605bdb20bddddcbca6bcc437239b58e9189dfea3a66c584a9bb0a6006c243031c6c5504a43d059afa629d24f8b55bb"></valueString> </extension> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"></system> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"></system> <value value="Test_MeDIC_2"></value> </identifier> <active value="true"></active> @@ -232,7 +232,7 @@ </resource> <request> <method value="PUT"></method> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_MeDIC_2"></url> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_MeDIC_2"></url> </request> </entry> <entry> @@ -240,7 +240,7 @@ <resource> <Endpoint xmlns="http://hl7.org/fhir"> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/endpoint"></system> + <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"></system> <value value="Test_MeDIC_2_Endpoint"></value> </identifier> <status value="active"></status> @@ -266,7 +266,7 @@ </resource> <request> <method value="PUT"></method> - <url value="Endpoint?identifier=http://highmed.org/fhir/CodeSystem/endpoint|Test_MeDIC_2_Endpoint"></url> + <url value="Endpoint?identifier=http://highmed.org/fhir/NamingSystem/endpoint-identifier|Test_MeDIC_2_Endpoint"></url> </request> </entry> </Bundle> diff --git a/dsf-fhir/dsf-fhir-server/src/test/resources/integration/test-bundle.xml b/dsf-fhir/dsf-fhir-server/src/test/resources/integration/test-bundle.xml index 4db0fbedf..e4eeb8a7b 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/resources/integration/test-bundle.xml +++ b/dsf-fhir/dsf-fhir-server/src/test/resources/integration/test-bundle.xml @@ -14,7 +14,7 @@ <valueString value="TODO"/> </extension> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_Organization"/> </identifier> <active value="true"/> @@ -33,7 +33,7 @@ </resource> <request> <method value="PUT"/> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_Organization"/> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_Organization"/> </request> </entry> <entry> @@ -47,7 +47,7 @@ </tag> </meta> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/endpoint"/> + <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_Endpoint"/> </identifier> <status value="active"/> @@ -73,7 +73,7 @@ </resource> <request> <method value="PUT"/> - <url value="Endpoint?identifier=http://highmed.org/fhir/CodeSystem/endpoint|Test_Endpoint"/> + <url value="Endpoint?identifier=http://highmed.org/fhir/NamingSystem/endpoint-identifier|Test_Endpoint"/> </request> </entry> <entry> @@ -90,7 +90,7 @@ <valueString value="TODO"/> </extension> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="External_Test_Organization"/> </identifier> <active value="true"/> @@ -105,7 +105,7 @@ </resource> <request> <method value="PUT"/> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|External_Test_Organization"/> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|External_Test_Organization"/> </request> </entry> </Bundle> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-webservice-client/src/test/java/org/highmed/fhir/client/TestFhirJerseyClient.java b/dsf-fhir/dsf-fhir-webservice-client/src/test/java/org/highmed/fhir/client/TestFhirJerseyClient.java index 012189332..ce3f02e1b 100755 --- a/dsf-fhir/dsf-fhir-webservice-client/src/test/java/org/highmed/fhir/client/TestFhirJerseyClient.java +++ b/dsf-fhir/dsf-fhir-webservice-client/src/test/java/org/highmed/fhir/client/TestFhirJerseyClient.java @@ -175,20 +175,20 @@ public static void main(String[] args) // client.update(org); // // Organization org = client.read(Organization.class, "e8aa9c06-9789-4c2b-8292-1c2a9601c2cc"); - // org.addIdentifier().setSystem("http://highmed.org/fhir/CodeSystem/organizations").setValue("Hochschule + // org.addIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Hochschule // Heilbronn"); // // client.update(org); // Organization org = new Organization(); - // org.addIdentifier().setSystem("http://highmed.org/fhir/CodeSystem/organization") + // org.addIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier") // .setValue("Test Organization"); // org.setActive(true); // org.setName("Test Organization"); // org = client.create(org); // // Endpoint endpoint1 = new Endpoint(); - // endpoint1.addIdentifier().setSystem("http://highmed.org/fhir/CodeSystem/endpoint").setValue("Endpoint1"); + // endpoint1.addIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/endpoint-identifier").setValue("Endpoint1"); // endpoint1.setStatus(EndpointStatus.ACTIVE); // endpoint1.setConnectionType(new Coding("http://terminology.hl7.org/CodeSystem/endpoint-connection-type", // "hl7-fhir-rest", "HL7 FHIR")); @@ -202,7 +202,7 @@ public static void main(String[] args) // endpoint1 = client.create(endpoint1); // // Endpoint endpoint2 = new Endpoint(); - // endpoint2.addIdentifier().setSystem("http://highmed.org/fhir/CodeSystem/endpoint").setValue("Endpoint2"); + // endpoint2.addIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/endpoint-identifier").setValue("Endpoint2"); // endpoint2.setStatus(EndpointStatus.ACTIVE); // endpoint2.setConnectionType(new Coding("http://terminology.hl7.org/CodeSystem/endpoint-connection-type", // "hl7-fhir-rest", "HL7 FHIR")); @@ -223,7 +223,7 @@ public static void main(String[] args) // client.update(org); // Organization org = new Organization(); - // client.create(org, "identifier=http://highmed.org/fhir/CodeSystem/organization|Test + // client.create(org, "identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test // Organization&_format=json"); // Organization org = new Organization(); @@ -340,9 +340,9 @@ private static void deleteCreateBundleTest(FhirContext context, FhirWebserviceCl private static Bundle deleteCreateBundle() { - final String orgIdentifierSystem = "http://highmed.org/fhir/CodeSystem/organization"; + final String orgIdentifierSystem = "http://highmed.org/fhir/NamingSystem/organization-identifier"; final String orgIdentifierValue = "Transaction Test Organization"; - final String eptIdentifierSystem = "http://highmed.org/fhir/CodeSystem/endpoint"; + final String eptIdentifierSystem = "http://highmed.org/fhir/NamingSystem/endpoint-identifier"; final String eptIdentifierValue = "Transaction Test Endpoint"; var bundle = new Bundle(); @@ -392,9 +392,9 @@ private static Bundle deleteCreateBundle() private static void updateBundleTest(FhirContext context, FhirWebserviceClient client) { - final String orgIdentifierSystem = "http://highmed.org/fhir/CodeSystem/organization"; + final String orgIdentifierSystem = "http://highmed.org/fhir/NamingSystem/organization-identifier"; final String orgIdentifierValue = "Transaction Test Organization"; - final String eptIdentifierSystem = "http://highmed.org/fhir/CodeSystem/endpoint"; + final String eptIdentifierSystem = "http://highmed.org/fhir/NamingSystem/endpoint-identifier"; final String eptIdentifierValue = "Transaction Test Endpoint"; var bundle = new Bundle(); diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic1-bundle.xml b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic1-bundle.xml index b850698e3..d422e7e18 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic1-bundle.xml +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic1-bundle.xml @@ -8,7 +8,7 @@ <valueString value="TODO"/> </extension> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_TTP"/> </identifier> <active value="true"/> @@ -27,7 +27,7 @@ </resource> <request> <method value="PUT"/> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_TTP"/> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_TTP"/> </request> </entry> <entry> @@ -38,7 +38,7 @@ <valueString value="TODO"/> </extension> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_MeDIC_1"/> </identifier> <active value="true"/> @@ -53,7 +53,7 @@ </resource> <request> <method value="PUT"/> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_MeDIC_1"/> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_MeDIC_1"/> </request> </entry> <entry> @@ -61,7 +61,7 @@ <resource> <Endpoint xmlns="http://hl7.org/fhir"> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/endpoint"/> + <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_TTP_Endpoint"/> </identifier> <status value="active"/> @@ -73,7 +73,7 @@ <managingOrganization> <type value="Organization"/> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_TTP"/> </identifier> </managingOrganization> @@ -90,7 +90,7 @@ </resource> <request> <method value="PUT"/> - <url value="Endpoint?identifier=http://highmed.org/fhir/CodeSystem/endpoint|Test_TTP_Endpoint"/> + <url value="Endpoint?identifier=http://highmed.org/fhir/NamingSystem/endpoint-identifier|Test_TTP_Endpoint"/> </request> </entry> </Bundle> \ No newline at end of file diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic2-bundle.xml b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic2-bundle.xml index 4a4a091ac..ce04e26f7 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic2-bundle.xml +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic2-bundle.xml @@ -8,7 +8,7 @@ <valueString value="TODO"/> </extension> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_TTP"/> </identifier> <active value="true"/> @@ -27,7 +27,7 @@ </resource> <request> <method value="PUT"/> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_TTP"/> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_TTP"/> </request> </entry> <entry> @@ -38,7 +38,7 @@ <valueString value="TODO"/> </extension> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_MeDIC_2"/> </identifier> <active value="true"/> @@ -53,7 +53,7 @@ </resource> <request> <method value="PUT"/> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_MeDIC_2"/> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_MeDIC_2"/> </request> </entry> <entry> @@ -61,7 +61,7 @@ <resource> <Endpoint xmlns="http://hl7.org/fhir"> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/endpoint"/> + <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_TTP_Endpoint"/> </identifier> <status value="active"/> @@ -73,7 +73,7 @@ <managingOrganization> <type value="Organization"/> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_TTP"/> </identifier> </managingOrganization> @@ -90,7 +90,7 @@ </resource> <request> <method value="PUT"/> - <url value="Endpoint?identifier=http://highmed.org/fhir/CodeSystem/endpoint|Test_TTP_Endpoint"/> + <url value="Endpoint?identifier=http://highmed.org/fhir/NamingSystem/endpoint-identifier|Test_TTP_Endpoint"/> </request> </entry> </Bundle> \ No newline at end of file diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic3-bundle.xml b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic3-bundle.xml index 88e7d94a5..3fe68cb49 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic3-bundle.xml +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic3-bundle.xml @@ -8,7 +8,7 @@ <valueString value="TODO"/> </extension> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_TTP"/> </identifier> <active value="true"/> @@ -27,7 +27,7 @@ </resource> <request> <method value="PUT"/> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_TTP"/> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_TTP"/> </request> </entry> <entry> @@ -38,7 +38,7 @@ <valueString value="TODO"/> </extension> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_MeDIC_3"/> </identifier> <active value="true"/> @@ -53,7 +53,7 @@ </resource> <request> <method value="PUT"/> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_MeDIC_3"/> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_MeDIC_3"/> </request> </entry> <entry> @@ -61,7 +61,7 @@ <resource> <Endpoint xmlns="http://hl7.org/fhir"> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/endpoint"/> + <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_TTP_Endpoint"/> </identifier> <status value="active"/> @@ -73,7 +73,7 @@ <managingOrganization> <type value="Organization"/> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_TTP"/> </identifier> </managingOrganization> @@ -90,7 +90,7 @@ </resource> <request> <method value="PUT"/> - <url value="Endpoint?identifier=http://highmed.org/fhir/CodeSystem/endpoint|Test_TTP_Endpoint"/> + <url value="Endpoint?identifier=http://highmed.org/fhir/NamingSystem/endpoint-identifier|Test_TTP_Endpoint"/> </request> </entry> </Bundle> \ No newline at end of file diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/test-bundle.xml b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/test-bundle.xml index cdd77c13b..3e52a50e3 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/test-bundle.xml +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/test-bundle.xml @@ -8,7 +8,7 @@ <valueString value="TODO"/> </extension> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_Organization"/> </identifier> <active value="true"/> @@ -27,7 +27,7 @@ </resource> <request> <method value="PUT"/> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_Organization"/> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_Organization"/> </request> </entry> <entry> @@ -35,7 +35,7 @@ <resource> <Endpoint xmlns="http://hl7.org/fhir"> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/endpoint"/> + <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_Endpoint"/> </identifier> <status value="active"/> @@ -61,7 +61,7 @@ </resource> <request> <method value="PUT"/> - <url value="Endpoint?identifier=http://highmed.org/fhir/CodeSystem/endpoint|Test_Endpoint"/> + <url value="Endpoint?identifier=http://highmed.org/fhir/NamingSystem/endpoint-identifier|Test_Endpoint"/> </request> </entry> </Bundle> \ No newline at end of file diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/ttp-bundle.xml b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/ttp-bundle.xml index 053e788ba..c4c8fb4ab 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/ttp-bundle.xml +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/ttp-bundle.xml @@ -8,7 +8,7 @@ <valueString value="TODO"/> </extension> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_TTP"/> </identifier> <active value="true"/> @@ -27,7 +27,7 @@ </resource> <request> <method value="PUT"/> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_TTP"/> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_TTP"/> </request> </entry> <entry> @@ -38,7 +38,7 @@ <valueString value="TODO"/> </extension> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_MeDIC_1"/> </identifier> <active value="true"/> @@ -57,7 +57,7 @@ </resource> <request> <method value="PUT"/> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_MeDIC_1"/> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_MeDIC_1"/> </request> </entry> <entry> @@ -68,7 +68,7 @@ <valueString value="TODO"/> </extension> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_MeDIC_2"/> </identifier> <active value="true"/> @@ -87,7 +87,7 @@ </resource> <request> <method value="PUT"/> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_MeDIC_2"/> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_MeDIC_2"/> </request> </entry> <entry> @@ -98,7 +98,7 @@ <valueString value="TODO"/> </extension> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_MeDIC_3"/> </identifier> <active value="true"/> @@ -117,7 +117,7 @@ </resource> <request> <method value="PUT"/> - <url value="Organization?identifier=http://highmed.org/fhir/CodeSystem/organization|Test_MeDIC_3"/> + <url value="Organization?identifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_MeDIC_3"/> </request> </entry> <entry> @@ -125,7 +125,7 @@ <resource> <Endpoint xmlns="http://hl7.org/fhir"> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/endpoint"/> + <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_TTP_Endpoint"/> </identifier> <status value="active"/> @@ -137,7 +137,7 @@ <managingOrganization> <type value="Organization"/> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_TTP"/> </identifier> </managingOrganization> @@ -154,7 +154,7 @@ </resource> <request> <method value="PUT"/> - <url value="Endpoint?identifier=http://highmed.org/fhir/CodeSystem/endpoint|Test_TTP_Endpoint"/> + <url value="Endpoint?identifier=http://highmed.org/fhir/NamingSystem/endpoint-identifier|Test_TTP_Endpoint"/> </request> </entry> <entry> @@ -162,7 +162,7 @@ <resource> <Endpoint xmlns="http://hl7.org/fhir"> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/endpoint"/> + <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_MeDIC_1_Endpoint"/> </identifier> <status value="active"/> @@ -174,7 +174,7 @@ <managingOrganization> <type value="Organization"/> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_MeDIC_1"/> </identifier> </managingOrganization> @@ -191,7 +191,7 @@ </resource> <request> <method value="PUT"/> - <url value="Endpoint?identifier=http://highmed.org/fhir/CodeSystem/endpoint|Test_MeDIC_1_Endpoint"/> + <url value="Endpoint?identifier=http://highmed.org/fhir/NamingSystem/endpoint-identifier|Test_MeDIC_1_Endpoint"/> </request> </entry> <entry> @@ -199,7 +199,7 @@ <resource> <Endpoint xmlns="http://hl7.org/fhir"> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/endpoint"/> + <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_MeDIC_2_Endpoint"/> </identifier> <status value="active"/> @@ -211,7 +211,7 @@ <managingOrganization> <type value="Organization"/> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_MeDIC_2"/> </identifier> </managingOrganization> @@ -228,7 +228,7 @@ </resource> <request> <method value="PUT"/> - <url value="Endpoint?identifier=http://highmed.org/fhir/CodeSystem/endpoint|Test_MeDIC_2_Endpoint"/> + <url value="Endpoint?identifier=http://highmed.org/fhir/NamingSystem/endpoint-identifier|Test_MeDIC_2_Endpoint"/> </request> </entry> <entry> @@ -236,7 +236,7 @@ <resource> <Endpoint xmlns="http://hl7.org/fhir"> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/endpoint"/> + <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_MeDIC_3_Endpoint"/> </identifier> <status value="active"/> @@ -248,7 +248,7 @@ <managingOrganization> <type value="Organization"/> <identifier> - <system value="http://highmed.org/fhir/CodeSystem/organization"/> + <system value="http://highmed.org/fhir/NamingSystem/organization-identifier"/> <value value="Test_MeDIC_3"/> </identifier> </managingOrganization> @@ -265,7 +265,7 @@ </resource> <request> <method value="PUT"/> - <url value="Endpoint?identifier=http://highmed.org/fhir/CodeSystem/endpoint|Test_MeDIC_3_Endpoint"/> + <url value="Endpoint?identifier=http://highmed.org/fhir/NamingSystem/endpoint-identifier|Test_MeDIC_3_Endpoint"/> </request> </entry> </Bundle> \ No newline at end of file diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-fhir-config.properties index 3c9f3f63c..9682007fa 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-fhir-config.properties @@ -12,6 +12,7 @@ org.highmed.dsf.fhir.serverBase=https://localhost/fhir org.highmed.dsf.fhir.defaultPageCount=20 org.highmed.dsf.fhir.local-user.thumbprints= +org.highmed.dsf.fhir.local-organization.systemAndIdentifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_Organization org.highmed.dsf.fhir.init.bundle.file=conf/bundle.xml diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic1-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic1-fhir-config.properties index ea2118577..ac1eda5a7 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic1-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic1-fhir-config.properties @@ -12,6 +12,7 @@ org.highmed.dsf.fhir.serverBase=https://medic1/fhir org.highmed.dsf.fhir.defaultPageCount=20 org.highmed.dsf.fhir.local-user.thumbprints= +org.highmed.dsf.fhir.local-organization.systemAndIdentifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_MeDIC_1 org.highmed.dsf.fhir.init.bundle.file=conf/bundle.xml diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic2-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic2-fhir-config.properties index 4e972d39e..943d6ca5a 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic2-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic2-fhir-config.properties @@ -12,6 +12,7 @@ org.highmed.dsf.fhir.serverBase=https://medic2/fhir org.highmed.dsf.fhir.defaultPageCount=20 org.highmed.dsf.fhir.local-user.thumbprints= +org.highmed.dsf.fhir.local-organization.systemAndIdentifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_MeDIC_2 org.highmed.dsf.fhir.init.bundle.file=conf/bundle.xml diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic3-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic3-fhir-config.properties index 32d0e0d6b..a52f9db20 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic3-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic3-fhir-config.properties @@ -12,6 +12,7 @@ org.highmed.dsf.fhir.serverBase=https://medic3/fhir org.highmed.dsf.fhir.defaultPageCount=20 org.highmed.dsf.fhir.local-user.thumbprints= +org.highmed.dsf.fhir.local-organization.systemAndIdentifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_MeDIC_3 org.highmed.dsf.fhir.init.bundle.file=conf/bundle.xml diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-ttp-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-ttp-fhir-config.properties index 83ba9f2ff..a9db4d8a5 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-ttp-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-ttp-fhir-config.properties @@ -12,6 +12,7 @@ org.highmed.dsf.fhir.serverBase=https://ttp/fhir org.highmed.dsf.fhir.defaultPageCount=20 org.highmed.dsf.fhir.local-user.thumbprints= +org.highmed.dsf.fhir.local-organization.systemAndIdentifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_TTP org.highmed.dsf.fhir.init.bundle.file=conf/bundle.xml diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/java-test-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/java-test-fhir-config.properties index a3781c0e1..d988728fb 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/java-test-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/java-test-fhir-config.properties @@ -12,6 +12,7 @@ org.highmed.dsf.fhir.serverBase=https://localhost:8001/fhir org.highmed.dsf.fhir.defaultPageCount=20 org.highmed.dsf.fhir.local-user.thumbprints= +org.highmed.dsf.fhir.local-organization.systemAndIdentifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_Organization org.highmed.dsf.fhir.init.bundle.file=conf/bundle.xml From 59f77ee03a7f59471bb1bc99e771e508507fc19e Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 25 Feb 2020 16:03:47 +0100 Subject: [PATCH 10/55] work on authorization, passwords as char[], dependency version upgrades --- ...lityFromMedicsViaMedic1ExampleStarter.java | 2 +- .../Ping3MedicFromTtpExampleStarter.java | 2 +- ...UpdateResource3MedicTtpExampleStarter.java | 2 +- ...pdateWhiteList3MedicTtpExampleStarter.java | 2 +- .../dsf/bpe/spring/config/FhirConfig.java | 6 +- .../fhir/client/FhirClientProviderImpl.java | 12 +-- .../dsf/bpe/client/AbstractJerseyClient.java | 8 +- .../bpe/client/WebserviceClientJersey.java | 2 +- .../dsf/bpe/client/TestBpeJerseyClient.java | 2 +- .../OrganizationProviderWithDbBackend.java | 47 ++++---- .../BinaryAuthorizationRule.java | 34 ++++-- .../OrganizationAuthorizationRule.java | 9 +- .../dsf/fhir/client/ClientProviderImpl.java | 8 +- .../highmed/dsf/fhir/dao/OrganizationDao.java | 2 + .../fhir/dao/jdbc/OrganizationDaoJdbc.java | 66 ++++++++++-- .../dsf/fhir/help/ResponseGenerator.java | 3 +- .../fhir/search/SearchQueryUserFilter.java | 2 +- .../spring/config/AuthenticationConfig.java | 6 +- .../dsf/fhir/spring/config/ClientConfig.java | 4 +- .../CodeSystem/authorization-0.1.0.xml.put | 1 - ...0.1.0.xml => authorization-role-0.1.0.xml} | 4 +- .../authorization-role-0.1.0.xml.put | 1 + .../fhir/CodeSystem/bpmn-message-0.1.0.xml | 2 +- .../fhir/CodeSystem/feasibility-0.1.0.xml | 6 ++ .../CodeSystem/organization-type-0.1.0.xml | 6 ++ .../fhir/CodeSystem/query-type-0.1.0.xml | 6 ++ .../fhir/CodeSystem/update-resource-0.1.0.xml | 6 ++ .../CodeSystem/update-whitelist-0.1.0.xml | 6 ++ .../fhir/NamingSystem/highmed-endpoint.xml | 6 ++ .../NamingSystem/highmed-organization.xml | 6 ++ ...-extension-process-authorization-0.1.0.xml | 100 ++++++++++++++++++ ...ension-process-authorization-0.1.0.xml.put | 1 + .../fhir/ValueSet/query-type-0.1.0.xml | 6 ++ .../dsf/fhir/client/ClientProviderTest.java | 4 +- .../integration/AbstractIntegrationTest.java | 4 +- .../dsf/fhir/test/X509Certificates.java | 22 ++-- .../fhir/client/AbstractJerseyClient.java | 12 +-- .../client/FhirWebserviceClientJersey.java | 38 ++----- .../fhir/client/TestFhirJerseyClient.java | 2 +- .../fhir/client/WebsocketClientTyrus.java | 2 +- .../fhir/client/TestFhirWebsocketClient.java | 2 +- .../org/highmed/dsf/tools/db/DbMigrator.java | 23 ++-- .../highmed/dsf/tools/proxy/ProxyTest.java | 2 +- .../highmed/dsf/tools/proxy/TestClient.java | 4 +- .../tools/generator/CertificateGenerator.java | 2 +- .../bundle-templates/test-bundle.xml | 12 +++ .../docker-test-fhir-config.properties | 2 +- .../docker-test-medic1-fhir-config.properties | 2 +- .../docker-test-medic2-fhir-config.properties | 2 +- .../docker-test-medic3-fhir-config.properties | 2 +- .../docker-test-ttp-fhir-config.properties | 2 +- .../java-test-fhir-config.properties | 2 +- pom.xml | 26 ++--- 53 files changed, 388 insertions(+), 155 deletions(-) delete mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-0.1.0.xml.put rename dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/{authorization-0.1.0.xml => authorization-role-0.1.0.xml} (92%) create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-role-0.1.0.xml.put create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml.put diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java b/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java index ab1f7143a..59099dc20 100644 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java @@ -46,7 +46,7 @@ public class RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter public static void main(String[] args) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { - String keyStorePassword = "password"; + char[] keyStorePassword = "password".toCharArray(); KeyStore keyStore = CertificateReader.fromPkcs12(Paths.get( "../../dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12"), keyStorePassword); diff --git a/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java b/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java index 7c06527ef..2e6c37da5 100644 --- a/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java @@ -26,7 +26,7 @@ public class Ping3MedicFromTtpExampleStarter public static void main(String[] args) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { - String keyStorePassword = "password"; + char[] keyStorePassword = "password".toCharArray(); KeyStore keyStore = CertificateReader.fromPkcs12(Paths.get( "../../dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12"), keyStorePassword); diff --git a/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java b/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java index 21bc3c580..ed6327ae1 100644 --- a/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java @@ -30,7 +30,7 @@ public class UpdateResource3MedicTtpExampleStarter public static void main(String[] args) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { - String keyStorePassword = "password"; + char[] keyStorePassword = "password".toCharArray(); KeyStore keyStore = CertificateReader.fromPkcs12(Paths.get( "../../dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12"), keyStorePassword); diff --git a/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java b/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java index 70428f79d..de3234cac 100644 --- a/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java @@ -26,7 +26,7 @@ public class UpdateWhiteList3MedicTtpExampleStarter public static void main(String[] args) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { - String keyStorePassword = "password"; + char[] keyStorePassword = "password".toCharArray(); KeyStore keyStore = CertificateReader.fromPkcs12(Paths.get( "../../dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12"), keyStorePassword); diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/FhirConfig.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/FhirConfig.java index 754ecbdcc..b65238bf9 100755 --- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/FhirConfig.java +++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/FhirConfig.java @@ -61,7 +61,7 @@ public class FhirConfig private String webserviceKeyStoreFile; @Value("${org.highmed.dsf.bpe.fhir.local.webservice.keystore.password}") - private String webserviceKeyStorePassword; + private char[] webserviceKeyStorePassword; @Value("${org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout}") private int remoteReadTimeout; @@ -70,7 +70,7 @@ public class FhirConfig private int remoteConnectTimeout; @Value("${org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password:#{null}}") - private String remoteProxyPassword; + private char[] remoteProxyPassword; @Value("${org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username:#{null}}") private String remoteProxyUsername; @@ -94,7 +94,7 @@ public class FhirConfig private String localWebsocketKeyStoreFile; @Value("${org.highmed.dsf.bpe.fhir.local.websocket.keystore.password}") - private String localWebsocketKeyStorePassword; + private char[] localWebsocketKeyStorePassword; @Value("${org.highmed.dsf.bpe.fhir.task.subscription.searchParameter}") private String subscriptionSearchParameter; diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirClientProviderImpl.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirClientProviderImpl.java index 8d64a0097..35a10d9b4 100755 --- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirClientProviderImpl.java +++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirClientProviderImpl.java @@ -40,25 +40,25 @@ public class FhirClientProviderImpl private final KeyStore webserviceTrustStore; private final KeyStore webserviceKeyStore; - private final String webserviceKeyStorePassword; + private final char[] webserviceKeyStorePassword; private final int remoteReadTimeout; private final int remoteConnectTimeout; - private final String remoteProxyPassword; + private final char[] remoteProxyPassword; private final String remoteProxyUsername; private final String remoteProxySchemeHostPort; private final String localWebsocketUrl; private final KeyStore localWebsocketTrustStore; private final KeyStore localWebsocketKeyStore; - private final String localWebsocketKeyStorePassword; + private final char[] localWebsocketKeyStorePassword; public FhirClientProviderImpl(FhirContext fhirContext, ReferenceExtractor referenceExtractor, String localBaseUrl, int localReadTimeout, int localConnectTimeout, KeyStore webserviceTrustStore, KeyStore webserviceKeyStore, - String webserviceKeyStorePassword, int remoteReadTimeout, int remoteConnectTimeout, - String remoteProxyPassword, String remoteProxyUsername, String remoteProxySchemeHostPort, + char[] webserviceKeyStorePassword, int remoteReadTimeout, int remoteConnectTimeout, + char[] remoteProxyPassword, String remoteProxyUsername, String remoteProxySchemeHostPort, String localWebsocketUrl, KeyStore localWebsocketTrustStore, KeyStore localWebsocketKeyStore, - String localWebsocketKeyStorePassword) + char[] localWebsocketKeyStorePassword) { this.fhirContext = fhirContext; this.referenceExtractor = referenceExtractor; diff --git a/dsf-bpe/dsf-bpe-webservice-client/src/main/java/org/highmed/dsf/bpe/client/AbstractJerseyClient.java b/dsf-bpe/dsf-bpe-webservice-client/src/main/java/org/highmed/dsf/bpe/client/AbstractJerseyClient.java index 1dce07bdb..66d81d454 100755 --- a/dsf-bpe/dsf-bpe-webservice-client/src/main/java/org/highmed/dsf/bpe/client/AbstractJerseyClient.java +++ b/dsf-bpe/dsf-bpe-webservice-client/src/main/java/org/highmed/dsf/bpe/client/AbstractJerseyClient.java @@ -22,15 +22,15 @@ public class AbstractJerseyClient private final Client client; private final String baseUrl; - public AbstractJerseyClient(String baseUrl, KeyStore trustStore, KeyStore keyStore, String keyStorePassword, + public AbstractJerseyClient(String baseUrl, KeyStore trustStore, KeyStore keyStore, char[] keyStorePassword, ObjectMapper objectMapper, List<?> componentsToRegister) { this(baseUrl, trustStore, keyStore, keyStorePassword, null, null, null, 0, 0, objectMapper, componentsToRegister); } - public AbstractJerseyClient(String baseUrl, KeyStore trustStore, KeyStore keyStore, String keyStorePassword, - String proxySchemeHostPort, String proxyUserName, String proxyPassword, int connectTimeout, int readTimeout, + public AbstractJerseyClient(String baseUrl, KeyStore trustStore, KeyStore keyStore, char[] keyStorePassword, + String proxySchemeHostPort, String proxyUserName, char[] proxyPassword, int connectTimeout, int readTimeout, ObjectMapper objectMapper, List<?> componentsToRegister) { SSLContext sslContext = null; @@ -47,7 +47,7 @@ else if (trustStore != null && keyStore != null && keyStorePassword != null) builder = builder.property(ClientProperties.PROXY_URI, proxySchemeHostPort) .property(ClientProperties.PROXY_USERNAME, proxyUserName) - .property(ClientProperties.PROXY_PASSWORD, proxyPassword); + .property(ClientProperties.PROXY_PASSWORD, String.valueOf(proxyPassword)); builder = builder.readTimeout(readTimeout, TimeUnit.MILLISECONDS).connectTimeout(connectTimeout, TimeUnit.MILLISECONDS); diff --git a/dsf-bpe/dsf-bpe-webservice-client/src/main/java/org/highmed/dsf/bpe/client/WebserviceClientJersey.java b/dsf-bpe/dsf-bpe-webservice-client/src/main/java/org/highmed/dsf/bpe/client/WebserviceClientJersey.java index 45b679bd0..948bdbe27 100755 --- a/dsf-bpe/dsf-bpe-webservice-client/src/main/java/org/highmed/dsf/bpe/client/WebserviceClientJersey.java +++ b/dsf-bpe/dsf-bpe-webservice-client/src/main/java/org/highmed/dsf/bpe/client/WebserviceClientJersey.java @@ -22,7 +22,7 @@ public class WebserviceClientJersey extends AbstractJerseyClient implements Webs private static final Logger logger = LoggerFactory.getLogger(WebserviceClientJersey.class); public WebserviceClientJersey(String schemaHostPort, KeyStore trustStore, KeyStore keyStore, - String keyStorePassword, String proxySchemeHostPort, String proxyUserName, String proxyPassword, + char[] keyStorePassword, String proxySchemeHostPort, String proxyUserName, char[] proxyPassword, int connectTimeout, int readTimeout, ObjectMapper objectMapper) { super(schemaHostPort, trustStore, keyStore, keyStorePassword, proxySchemeHostPort, proxyUserName, proxyPassword, diff --git a/dsf-bpe/dsf-bpe-webservice-client/src/test/java/org/highmed/dsf/bpe/client/TestBpeJerseyClient.java b/dsf-bpe/dsf-bpe-webservice-client/src/test/java/org/highmed/dsf/bpe/client/TestBpeJerseyClient.java index fa87f0b32..cef0220e3 100755 --- a/dsf-bpe/dsf-bpe-webservice-client/src/test/java/org/highmed/dsf/bpe/client/TestBpeJerseyClient.java +++ b/dsf-bpe/dsf-bpe-webservice-client/src/test/java/org/highmed/dsf/bpe/client/TestBpeJerseyClient.java @@ -21,7 +21,7 @@ public class TestBpeJerseyClient public static void main(String[] args) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { - String keyStorePassword = "password"; + char[] keyStorePassword = "password".toCharArray(); KeyStore keyStore = CertificateReader .fromPkcs12(Paths.get("dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12"), keyStorePassword); KeyStore trustStore = CertificateHelper.extractTrust(keyStore); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/OrganizationProviderWithDbBackend.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/OrganizationProviderWithDbBackend.java index 57a5ac782..4a15443c8 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/OrganizationProviderWithDbBackend.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/OrganizationProviderWithDbBackend.java @@ -5,9 +5,7 @@ import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -17,8 +15,6 @@ import org.apache.commons.codec.binary.Hex; import org.highmed.dsf.fhir.dao.OrganizationDao; import org.highmed.dsf.fhir.help.ExceptionHandler; -import org.highmed.dsf.fhir.search.PartialResult; -import org.highmed.dsf.fhir.search.SearchQuery; import org.hl7.fhir.r4.model.Organization; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,17 +27,17 @@ public class OrganizationProviderWithDbBackend implements OrganizationProvider, private final OrganizationDao dao; private final ExceptionHandler exceptionHandler; private final List<String> localUserThumbprints = new ArrayList<String>(); - private final String localSystemAndIdentifier; + private final String localIdentifierValue; public OrganizationProviderWithDbBackend(OrganizationDao dao, ExceptionHandler exceptionHandler, - List<String> localUserThumbprints, String localSystemAndIdentifier) + List<String> localUserThumbprints, String localIdentifier) { this.dao = dao; this.exceptionHandler = exceptionHandler; if (localUserThumbprints != null) localUserThumbprints.stream().map(t -> t.toLowerCase()).forEach(this.localUserThumbprints::add); - this.localSystemAndIdentifier = localSystemAndIdentifier; + this.localIdentifierValue = localIdentifier; } @Override @@ -57,8 +53,9 @@ public void afterPropertiesSet() throws Exception localUserThumbprints.size() != 1 ? "s" : "", localUserThumbprints.size() != 1 ? "s" : "", localUserThumbprints.stream().collect(Collectors.joining(", ", "[", "]"))); + Objects.requireNonNull(localIdentifierValue, "localIdentifierValue"); if (getLocalOrganization().isEmpty()) - logger.warn("Local organization not found by identifier: {}", localSystemAndIdentifier); + logger.warn("Local organization not found by identifier: {}", localIdentifierValue); } @Override @@ -74,27 +71,31 @@ public Optional<User> getOrganization(X509Certificate certificate) UserRole userRole = localUserThumbprints.contains(loginThumbprintHex.toLowerCase()) ? UserRole.LOCAL : UserRole.REMOTE; - Optional<Organization> optOrg = exceptionHandler.catchAndLogSqlExceptionAndIfReturn( - () -> dao.readActiveNotDeletedByThumbprint(loginThumbprintHex), Optional::empty); - - if (optOrg.isEmpty() && UserRole.LOCAL.equals(userRole)) + if (UserRole.LOCAL.equals(userRole)) + { return getLocalOrganization().map(org -> new User(org, userRole)); + } + else if (UserRole.REMOTE.equals(userRole)) + { + return getOrganization(loginThumbprintHex).map(org -> new User(org, userRole)); + } + else + { + logger.warn("UserRole {} not supported", userRole); + return Optional.empty(); + } + } - return optOrg.map(org -> new User(org, userRole)); + private Optional<Organization> getOrganization(String loginThumbprintHex) + { + return exceptionHandler.catchAndLogSqlExceptionAndIfReturn( + () -> dao.readActiveNotDeletedByThumbprint(loginThumbprintHex), Optional::empty); } private Optional<Organization> getLocalOrganization() { - SearchQuery<Organization> query = dao.createSearchQueryWithoutUserFilter(1, 1) - .configureParameters(Map.of("identifier", Arrays.asList(localSystemAndIdentifier))); - - PartialResult<Organization> result = exceptionHandler - .catchAndLogSqlExceptionAndIfReturn(() -> dao.search(query), null); - - if (result != null && result.getOverallCount() == 1) - return Optional.of(result.getPartialResult().get(0)); - else - return Optional.empty(); + return exceptionHandler.catchAndLogSqlExceptionAndIfReturn( + () -> dao.readActiveNotDeletedByIdentifier(localIdentifierValue), Optional::empty); } private byte[] getThumbprint(X509Certificate certificate) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java index 35ae2aa08..29ab99399 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java @@ -39,9 +39,19 @@ public Optional<String> reasonCreateAllowed(User user, Binary newResource) Optional<Resource> securityContext = referenceResolver.resolveReference(user, reference); if (securityContext.isPresent()) { - logger.info("Create of Binary authorized for local user '{}', Binary.SecurityContext resolved", - user.getName()); - return Optional.of("local user, Binary.SecurityContext resolved"); + if (securityContext.get() instanceof Organization) + { + logger.info( + "Create of Binary authorized for local user '{}', Binary.SecurityContext resolved and instance of Organization", + user.getName()); + return Optional.of("local user, Binary.SecurityContext(Organization) resolved"); + } + else + { + logger.warn( + "Create of Binary unauthorized, securityContext reference could be resolved but not instance of Organization"); + return Optional.empty(); + } } else { @@ -114,10 +124,20 @@ public Optional<String> reasonUpdateAllowed(User user, Binary oldResource, Binar Optional<Resource> newSecurityContext = referenceResolver.resolveReference(user, newReference); if (oldSecurityContext.isPresent() && newSecurityContext.isPresent()) { - logger.info( - "Update of Binary authorized for local user '{}', Binary.SecurityContext could be resolved (old and new)", - user.getName()); - return Optional.of("local user, Binary.SecurityContext resolved"); + if (oldSecurityContext.get() instanceof Organization + && newSecurityContext.get() instanceof Organization) + { + logger.info( + "Create of Binary authorized for local user '{}', Binary.SecurityContext resolved and instance of Organization (old and new)", + user.getName()); + return Optional.of("local user, Binary.SecurityContext(Organization) resolved"); + } + else + { + logger.warn( + "Create of Binary unauthorized, securityContext reference could be resolved (old and new) but not instance of Organization (old or new)"); + return Optional.empty(); + } } else { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java index d800309cf..1f1d3bbf5 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java @@ -7,9 +7,13 @@ import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Organization; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class OrganizationAuthorizationRule extends AbstractAuthorizationRule<Organization, OrganizationDao> { + private static final Logger logger = LoggerFactory.getLogger(OrganizationAuthorizationRule.class); + public OrganizationAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { @@ -53,7 +57,8 @@ public Optional<String> reasonDeleteAllowed(User user, Organization oldResource) @Override public Optional<String> reasonSearchAllowed(User user) { - // TODO Auto-generated method stub - return Optional.empty(); + logger.info("Search of Organization authorized for {} user '{}', will be fitered by user role", user.getRole(), + user.getName()); + return Optional.of("Allowed for all, filtered by user role"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/client/ClientProviderImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/client/ClientProviderImpl.java index 858e78294..6f9e2aee8 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/client/ClientProviderImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/client/ClientProviderImpl.java @@ -21,11 +21,11 @@ public class ClientProviderImpl implements ClientProvider, InitializingBean private final KeyStore webserviceTrustStore; private final KeyStore webserviceKeyStore; - private final String webserviceKeyStorePassword; + private final char[] webserviceKeyStorePassword; private final int remoteReadTimeout; private final int remoteConnectTimeout; - private final String remoteProxyPassword; + private final char[] remoteProxyPassword; private final String remoteProxyUsername; private final String remoteProxySchemeHostPort; private final FhirContext fhirContext; @@ -34,8 +34,8 @@ public class ClientProviderImpl implements ClientProvider, InitializingBean private final ExceptionHandler exceptionHandler; public ClientProviderImpl(KeyStore webserviceTrustStore, KeyStore webserviceKeyStore, - String webserviceKeyStorePassword, int remoteReadTimeout, int remoteConnectTimeout, - String remoteProxyPassword, String remoteProxyUsername, String remoteProxySchemeHostPort, + char[] webserviceKeyStorePassword, int remoteReadTimeout, int remoteConnectTimeout, + char[] remoteProxyPassword, String remoteProxyUsername, String remoteProxySchemeHostPort, FhirContext fhirContext, ReferenceExtractor referenceExtractor, EndpointDao endpointDao, ExceptionHandler exceptionHandler) { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/OrganizationDao.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/OrganizationDao.java index 94440afa9..7b8f52aaa 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/OrganizationDao.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/OrganizationDao.java @@ -8,4 +8,6 @@ public interface OrganizationDao extends ResourceDao<Organization> { Optional<Organization> readActiveNotDeletedByThumbprint(String thumbprintHex) throws SQLException; + + Optional<Organization> readActiveNotDeletedByIdentifier(String identifierValue) throws SQLException; } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java index 459f18804..9bfa7af76 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java @@ -47,9 +47,8 @@ public Optional<Organization> readActiveNotDeletedByThumbprint(String thumbprint return Optional.empty(); try (Connection connection = getDataSource().getConnection(); - PreparedStatement statement = connection.prepareStatement("SELECT " + getResourceColumn() + " FROM " - + getResourceTable() + " WHERE " + getResourceColumn() + "->'extension' @> ?::jsonb AND " - + getResourceColumn() + "->>'active' = 'true' AND NOT deleted ORDER BY version LIMIT 1")) + PreparedStatement statement = connection.prepareStatement( + "SELECT organization FROM current_organizations WHERE organization->'extension' @> ?::jsonb AND organization->>'active' = 'true'")) { String search = "[{\"url\": \"http://highmed.org/fhir/StructureDefinition/certificate-thumbprint\", \"valueString\": \"" @@ -62,12 +61,67 @@ public Optional<Organization> readActiveNotDeletedByThumbprint(String thumbprint if (result.next()) { Organization organization = getResource(result, 1); - logger.debug("{} with thumprint {}, IdPart {} found.", getResourceTypeName(), getResourceTypeName(), - thumbprintHex, organization.getIdElement().getIdPart()); - return Optional.of(organization); + if (result.next()) + { + logger.warn("Found multiple Organizations with thumprint {}", thumbprintHex); + throw new SQLException("Found multiple Organizations with thumprint " + thumbprintHex + + ", single result expected"); + } + else + { + logger.debug("Organization with thumprint {}, IdPart {} found", thumbprintHex, + organization.getIdElement().getIdPart()); + return Optional.of(organization); + } } else + { + logger.warn("Organization with thumprint {} not found", thumbprintHex); + return Optional.empty(); + } + } + } + } + + @Override + public Optional<Organization> readActiveNotDeletedByIdentifier(String identifierValue) throws SQLException + { + if (identifierValue == null || identifierValue.isBlank()) + return Optional.empty(); + + try (Connection connection = getDataSource().getConnection(); + PreparedStatement statement = connection.prepareStatement( + "SELECT organization FROM current_organizations WHERE organization->'identifier' @> ?::jsonb AND organization->>'active' = 'true'")) + { + + String search = "[{\"system\": \"http://highmed.org/fhir/NamingSystem/organization-identifier\", \"value\": \"" + + identifierValue + "\"}]"; + statement.setString(1, search); + + logger.trace("Executing query '{}'", statement); + try (ResultSet result = statement.executeQuery()) + { + if (result.next()) + { + Organization organization = getResource(result, 1); + if (result.next()) + { + logger.warn("Found multiple Organizations with identifier {}", identifierValue); + throw new SQLException("Found multiple Organizations with identifier " + identifierValue + + ", single result expected"); + } + else + { + logger.debug("Organization with identifier {}, IdPart {} found", identifierValue, + organization.getIdElement().getIdPart()); + return Optional.of(organization); + } + } + else + { + logger.warn("Organization with identifier {} not found", identifierValue); return Optional.empty(); + } } } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ResponseGenerator.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ResponseGenerator.java index d3fa59112..e03998668 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ResponseGenerator.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ResponseGenerator.java @@ -1,6 +1,7 @@ package org.highmed.dsf.fhir.help; import java.net.URI; +import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.List; import java.util.Objects; @@ -66,7 +67,7 @@ public ResponseBuilder response(Status status, Resource resource, MediaType medi ResponseBuilder b = Response.status(status).entity(resource); if (mediaType != null) - b = b.type(mediaType); + b = b.type(mediaType.withCharset(StandardCharsets.UTF_8.displayName())); if (resource.getMeta() != null && resource.getMeta().getLastUpdated() != null && resource.getMeta().getVersionId() != null) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQueryUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQueryUserFilter.java index 90fe31913..cefe3d02c 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQueryUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQueryUserFilter.java @@ -5,7 +5,7 @@ public interface SearchQueryUserFilter { - String AUTHORIZATION_ROLE_SYSTEM = "http://highmed.org/fhir/CodeSystem/authorization"; + String AUTHORIZATION_ROLE_SYSTEM = "http://highmed.org/fhir/CodeSystem/authorization-role"; String AUTHORIZATION_ROLE_VALUE_REMOTE = "REMOTE"; String AUTHORIZATION_ROLE_VALUE_LOCAL = "LOCAL"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthenticationConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthenticationConfig.java index 20c287889..910da3081 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthenticationConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthenticationConfig.java @@ -27,8 +27,8 @@ public class AuthenticationConfig @Value("#{'${org.highmed.dsf.fhir.local-user.thumbprints}'.split(',')}") private List<String> localUserThumbprints; - @Value("${org.highmed.dsf.fhir.local-organization.systemAndIdentifier}") - private String localSystemAndIdentifier; + @Value("${org.highmed.dsf.fhir.local-organization.identifier}") + private String localIdentifierValue; @Bean public AuthenticationFilterConfig authenticationFilterConfig() @@ -40,6 +40,6 @@ public AuthenticationFilterConfig authenticationFilterConfig() public OrganizationProvider organizationProvider() { return new OrganizationProviderWithDbBackend(daoConfig.organizationDao(), helperConfig.exceptionHandler(), - localUserThumbprints, localSystemAndIdentifier); + localUserThumbprints, localIdentifierValue); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/ClientConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/ClientConfig.java index 63f43091d..8b3161c99 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/ClientConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/ClientConfig.java @@ -26,7 +26,7 @@ public class ClientConfig private String webserviceKeyStoreFile; @Value("${org.highmed.dsf.fhir.webservice.keystore.password}") - private String webserviceKeyStorePassword; + private char[] webserviceKeyStorePassword; @Value("${org.highmed.dsf.fhir.remote.webservice.readTimeout}") private int remoteReadTimeout; @@ -35,7 +35,7 @@ public class ClientConfig private int remoteConnectTimeout; @Value("${org.highmed.dsf.fhir.remote.webservice.proxy.password:#{null}}") - private String remoteProxyPassword; + private char[] remoteProxyPassword; @Value("${org.highmed.dsf.fhir.remote.webservice.proxy.username:#{null}}") private String remoteProxyUsername; diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-0.1.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-0.1.0.xml.put deleted file mode 100644 index c4772abb3..000000000 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-0.1.0.xml.put +++ /dev/null @@ -1 +0,0 @@ -CodeSystem?url=http://highmed.org/fhir/CodeSystem/authorization&version=0.1.0 \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-role-0.1.0.xml similarity index 92% rename from dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-0.1.0.xml rename to dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-role-0.1.0.xml index ce63a995d..b206e96c7 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-role-0.1.0.xml @@ -2,11 +2,11 @@ xsi:schemaLocation="http://hl7.org/fhir http://www.hl7.org/fhir/fhir-base.xsd"> <meta> <tag> - <system value="http://highmed.org/fhir/CodeSystem/authorization"/> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> <code value="REMOTE"/> </tag> </meta> - <url value="http://highmed.org/fhir/CodeSystem/authorization"/> + <url value="http://highmed.org/fhir/CodeSystem/authorization-role"/> <version value="0.1.0"/> <name value="HiGHmed_Authorization_Values"/> <title value="HiGHmed authorization values"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-role-0.1.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-role-0.1.0.xml.put new file mode 100644 index 000000000..a1c148e79 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/authorization-role-0.1.0.xml.put @@ -0,0 +1 @@ +CodeSystem?url=http://highmed.org/fhir/CodeSystem/authorization-role&version=0.1.0 \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/bpmn-message-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/bpmn-message-0.1.0.xml index e1b417007..b941c7a77 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/bpmn-message-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/bpmn-message-0.1.0.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://hl7.org/fhir http://www.hl7.org/fhir/fhir-base.xsd"> <meta> <tag> - <system value="http://highmed.org/fhir/CodeSystem/authorization"/> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> <code value="REMOTE"/> </tag> </meta> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/feasibility-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/feasibility-0.1.0.xml index 1a5e6e8e5..8fc7d5265 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/feasibility-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/feasibility-0.1.0.xml @@ -1,5 +1,11 @@ <CodeSystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://hl7.org/fhir" xsi:schemaLocation="http://hl7.org/fhir http://www.hl7.org/fhir/fhir-base.xsd"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/CodeSystem/feasibility"/> <version value="0.1.0"/> <name value="HiGHmed_Feasibility_Values"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/organization-type-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/organization-type-0.1.0.xml index f95b401bf..39a7fd579 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/organization-type-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/organization-type-0.1.0.xml @@ -1,5 +1,11 @@ <CodeSystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://hl7.org/fhir" xsi:schemaLocation="http://hl7.org/fhir http://www.hl7.org/fhir/fhir-base.xsd"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/CodeSystem/organization-type"/> <version value="0.1.0"/> <name value="HiGHmed_Organization_Type"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/query-type-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/query-type-0.1.0.xml index c2b47c5b4..0509bd121 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/query-type-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/query-type-0.1.0.xml @@ -1,5 +1,11 @@ <CodeSystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://hl7.org/fhir" xsi:schemaLocation="http://hl7.org/fhir http://www.hl7.org/fhir/fhir-base.xsd"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/CodeSystem/query-type"/> <version value="0.1.0"/> <name value="HiGHmed_Query_Type"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/update-resource-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/update-resource-0.1.0.xml index 35a067d76..5277112b8 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/update-resource-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/update-resource-0.1.0.xml @@ -1,5 +1,11 @@ <CodeSystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://hl7.org/fhir" xsi:schemaLocation="http://hl7.org/fhir http://www.hl7.org/fhir/fhir-base.xsd"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/CodeSystem/update-resources"/> <version value="0.1.0"/> <name value="HiGHmed_Update_Resource"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/update-whitelist-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/update-whitelist-0.1.0.xml index 51f09f565..7ee34e513 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/update-whitelist-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/CodeSystem/update-whitelist-0.1.0.xml @@ -1,5 +1,11 @@ <CodeSystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://hl7.org/fhir" xsi:schemaLocation="http://hl7.org/fhir http://www.hl7.org/fhir/fhir-base.xsd"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/CodeSystem/update-whitelist"/> <version value="0.1.0"/> <name value="HiGHmed_Update_Whitelist_Values"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-endpoint.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-endpoint.xml index 4034eefbe..f05c170e5 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-endpoint.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-endpoint.xml @@ -1,5 +1,11 @@ <NamingSystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://hl7.org/fhir" xsi:schemaLocation="http://hl7.org/fhir http://www.hl7.org/fhir/fhir-base.xsd"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <name value="HiGHmed_Endpoint_Identifier"/> <status value="active"/> <kind value="identifier"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-organization.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-organization.xml index 22217f478..14902dbb0 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-organization.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-organization.xml @@ -1,5 +1,11 @@ <NamingSystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://hl7.org/fhir" xsi:schemaLocation="http://hl7.org/fhir http://www.hl7.org/fhir/fhir-base.xsd"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <name value="HiGHmed_Organization_Identifier"/> <status value="active"/> <kind value="identifier"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml new file mode 100644 index 000000000..34d6ee228 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml @@ -0,0 +1,100 @@ +<?xml version="1.0" encoding="utf-8"?> +<StructureDefinition xmlns="http://hl7.org/fhir"> + <url value="http://highmed.org/fhir/StructureDefinition/process-authorization" /> + <version value="0.1.0" /> + <name value="ProcessAuthorization" /> + <status value="active" /> + <experimental value="false" /> + <date value="2020-02-24" /> + <fhirVersion value="4.0.0" /> + <kind value="complex-type" /> + <abstract value="false" /> + <context> + <type value="element" /> + <expression value="ActivityDefinition" /> + </context> + <type value="Extension" /> + <baseDefinition value="http://hl7.org/fhir/StructureDefinition/Extension" /> + <derivation value="constraint" /> + <differential> + <element id="Extension.extension"> + <path value="Extension.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> + </element> + <element id="Extension.extension:message-name"> + <path value="Extension.extension" /> + <sliceName value="message-name" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Extension.extension:message-name.url"> + <path value="Extension.extension.url" /> + <fixedUri value="message-name" /> + </element> + <element id="Extension.extension:message-name.value[x]"> + <path value="Extension.extension.value[x]" /> + <min value="1" /> + <type> + <code value="string" /> + </type> + </element> + <element id="Extension.extension:authorization-role"> + <path value="Extension.extension" /> + <sliceName value="authorization-role" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Extension.extension:authorization-role.url"> + <path value="Extension.extension.url" /> + <fixedUri value="authorization-role" /> + </element> + <element id="Extension.extension:authorization-role.value[x]"> + <path value="Extension.extension.value[x]" /> + <min value="1" /> + <type> + <code value="Coding" /> + </type> + </element> + <element id="Extension.extension:authorization-role.value[x].system"> + <path value="Extension.extension.value[x].system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + </element> + <element id="Extension.extension:organization-type"> + <path value="Extension.extension" /> + <sliceName value="organization-type" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Extension.extension:organization-type.url"> + <path value="Extension.extension.url" /> + <fixedUri value="organization-type" /> + </element> + <element id="Extension.extension:organization-type.value[x]"> + <path value="Extension.extension.value[x]" /> + <min value="1" /> + <type> + <code value="Coding" /> + </type> + </element> + <element id="Extension.extension:organization-type.value[x].system"> + <path value="Extension.extension.value[x].system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/organization-type" /> + </element> + <element id="Extension.url"> + <path value="Extension.url" /> + <fixedUri value="http://highmed.org/fhir/StructureDefinition/process-authorization" /> + </element> + <element id="Extension.value[x]"> + <path value="Extension.value[x]" /> + <max value="0" /> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml.put new file mode 100644 index 000000000..885afab45 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml.put @@ -0,0 +1 @@ +StructureDefinition?url=http://highmed.org/fhir/StructureDefinition/process-authorization&version=0.1.0 \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ValueSet/query-type-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ValueSet/query-type-0.1.0.xml index be2a3e29d..7f1a0b28a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ValueSet/query-type-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ValueSet/query-type-0.1.0.xml @@ -1,4 +1,10 @@ <ValueSet xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/ValueSet/query-type"/> <version value="0.1.0"/> <name value="HiGHmed_Query_Type"/> diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/client/ClientProviderTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/client/ClientProviderTest.java index 4ddd93ce9..2391255be 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/client/ClientProviderTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/client/ClientProviderTest.java @@ -38,10 +38,10 @@ public void before() throws Exception KeyStore webserviceTrustStore = KeyStore.getInstance(KeyStore.getDefaultType()); webserviceTrustStore.load(null); - String webserviceKeyStorePassword = "password"; + char[] webserviceKeyStorePassword = "password".toCharArray(); int remoteReadTimeout = 0; int remoteConnectTimeout = 0; - String remoteProxyPassword = null; + char[] remoteProxyPassword = null; String remoteProxyUsername = null; String remoteProxySchemeHostPort = null; FhirContext fhirContext = mock(FhirContext.class); diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java index 705028fbe..2439e7f42 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java @@ -130,14 +130,14 @@ public static void beforeClass() throws Exception } private static FhirWebserviceClient createWebserviceClient(KeyStore trustStore, KeyStore keyStore, - String keyStorePassword, FhirContext fhirContext, ReferenceExtractor referenceExtractor) + char[] keyStorePassword, FhirContext fhirContext, ReferenceExtractor referenceExtractor) { return new FhirWebserviceClientJersey(BASE_URL, trustStore, keyStore, keyStorePassword, null, null, null, 500, 5000, null, fhirContext, referenceExtractor); } private static WebsocketClient createWebsocketClient(KeyStore trustStore, KeyStore keyStore, - String keyStorePassword, FhirContext fhirContext, String subscriptionIdPart) + char[] keyStorePassword, FhirContext fhirContext, String subscriptionIdPart) { return new WebsocketClientTyrus(fhirContext, URI.create(WEBSOCKET_URL), trustStore, keyStore, keyStorePassword, subscriptionIdPart); diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/test/X509Certificates.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/test/X509Certificates.java index 6aacc0cf3..174a5f5dd 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/test/X509Certificates.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/test/X509Certificates.java @@ -37,9 +37,9 @@ public static final class ClientCertificate private final X509Certificate certificate; private final KeyStore trustStore; private final KeyStore keyStore; - private final String keyStorePassword; + private final char[] keyStorePassword; - ClientCertificate(X509Certificate certificate, KeyStore trustStore, KeyStore keyStore, String keyStorePassword) + ClientCertificate(X509Certificate certificate, KeyStore trustStore, KeyStore keyStore, char[] keyStorePassword) { this.certificate = certificate; this.trustStore = trustStore; @@ -62,7 +62,7 @@ public KeyStore getKeyStore() return keyStore; } - public String getKeyStorePassword() + public char[] getKeyStorePassword() { return keyStorePassword; } @@ -193,8 +193,8 @@ private void createX509Certificates() throws InvalidKeyException, NoSuchAlgorith X509Certificate serverCertificate = ca.signWebServerCertificate(serverRequest); - CertificateWriter.toPkcs12(serverCertificateFile, serverRsaKeyPair.getPrivate(), "password", serverCertificate, - caCertificate, "test-server"); + CertificateWriter.toPkcs12(serverCertificateFile, serverRsaKeyPair.getPrivate(), "password".toCharArray(), + serverCertificate, caCertificate, "test-server"); // server -- // -- client @@ -205,12 +205,12 @@ private void createX509Certificates() throws InvalidKeyException, NoSuchAlgorith X509Certificate clientCertificate = ca.signWebClientCertificate(clientRequest); - String clientKeyStorePassword = "password"; + char[] clientKeyStorePassword = "password".toCharArray(); KeyStore clientKeyStore = CertificateHelper.toPkcs12KeyStore(clientRsaKeyPair.getPrivate(), new Certificate[] { clientCertificate, caCertificate }, "test-client", clientKeyStorePassword); - CertificateWriter.toPkcs12(clientCertificateFile, clientRsaKeyPair.getPrivate(), "password", clientCertificate, - caCertificate, "client"); + CertificateWriter.toPkcs12(clientCertificateFile, clientRsaKeyPair.getPrivate(), "password".toCharArray(), + clientCertificate, caCertificate, "client"); // client -- // -- external client @@ -222,13 +222,13 @@ private void createX509Certificates() throws InvalidKeyException, NoSuchAlgorith X509Certificate externalClientCertificate = ca.signWebClientCertificate(externalClientRequest); - String externalClientKeyStorePassword = "password"; + char[] externalClientKeyStorePassword = "password".toCharArray(); KeyStore externalClientKeyStore = CertificateHelper.toPkcs12KeyStore(externalClientRsaKeyPair.getPrivate(), new Certificate[] { externalClientCertificate, caCertificate }, "external-client", externalClientKeyStorePassword); - CertificateWriter.toPkcs12(externalClientCertificateFile, externalClientRsaKeyPair.getPrivate(), "password", - externalClientCertificate, caCertificate, "client"); + CertificateWriter.toPkcs12(externalClientCertificateFile, externalClientRsaKeyPair.getPrivate(), + "password".toCharArray(), externalClientCertificate, caCertificate, "client"); // external client -- this.clientCertificate = new ClientCertificate(clientCertificate, diff --git a/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/AbstractJerseyClient.java b/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/AbstractJerseyClient.java index 9383bc186..e1960db07 100644 --- a/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/AbstractJerseyClient.java +++ b/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/AbstractJerseyClient.java @@ -22,18 +22,18 @@ public class AbstractJerseyClient { private final Client client; private final String baseUrl; - + protected final List<?> registeredComponents; - public AbstractJerseyClient(String baseUrl, KeyStore trustStore, KeyStore keyStore, String keyStorePassword, + public AbstractJerseyClient(String baseUrl, KeyStore trustStore, KeyStore keyStore, char[] keyStorePassword, ObjectMapper objectMapper, List<?> componentsToRegister) { this(baseUrl, trustStore, keyStore, keyStorePassword, null, null, null, 0, 0, objectMapper, componentsToRegister); } - public AbstractJerseyClient(String baseUrl, KeyStore trustStore, KeyStore keyStore, String keyStorePassword, - String proxySchemeHostPort, String proxyUserName, String proxyPassword, int connectTimeout, int readTimeout, + public AbstractJerseyClient(String baseUrl, KeyStore trustStore, KeyStore keyStore, char[] keyStorePassword, + String proxySchemeHostPort, String proxyUserName, char[] proxyPassword, int connectTimeout, int readTimeout, ObjectMapper objectMapper, List<?> componentsToRegister) { SSLContext sslContext = null; @@ -52,7 +52,7 @@ else if (trustStore != null && keyStore != null && keyStorePassword != null) config.connectorProvider(new ApacheConnectorProvider()); config.property(ClientProperties.PROXY_URI, proxySchemeHostPort); config.property(ClientProperties.PROXY_USERNAME, proxyUserName); - config.property(ClientProperties.PROXY_PASSWORD, proxyPassword); + config.property(ClientProperties.PROXY_PASSWORD, proxyPassword == null ? null : String.valueOf(proxyPassword)); builder = builder.withConfig(config); builder = builder.readTimeout(readTimeout, TimeUnit.MILLISECONDS).connectTimeout(connectTimeout, @@ -72,7 +72,7 @@ else if (trustStore != null && keyStore != null && keyStorePassword != null) this.baseUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/"; // making sure the root url works, this might be a workaround for a jersey client bug - + this.registeredComponents = componentsToRegister; } diff --git a/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java b/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java index 2c540bdad..10c6f715c 100755 --- a/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java +++ b/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java @@ -92,8 +92,8 @@ public class FhirWebserviceClientJersey extends AbstractJerseyClient implements private final ReferenceExtractor referenceExtractor; private final Map<String, Class<?>> resourceTypeByNames = new HashMap<>(); - public FhirWebserviceClientJersey(String baseUrl, KeyStore trustStore, KeyStore keyStore, String keyStorePassword, - String proxySchemeHostPort, String proxyUserName, String proxyPassword, int connectTimeout, int readTimeout, + public FhirWebserviceClientJersey(String baseUrl, KeyStore trustStore, KeyStore keyStore, char[] keyStorePassword, + String proxySchemeHostPort, String proxyUserName, char[] proxyPassword, int connectTimeout, int readTimeout, ObjectMapper objectMapper, FhirContext fhirContext, ReferenceExtractor referenceExtractor) { super(baseUrl, trustStore, keyStore, keyStorePassword, proxySchemeHostPort, proxyUserName, proxyPassword, @@ -151,6 +151,7 @@ private WebApplicationException handleError(Response response) } @Override + @SuppressWarnings("unchecked") public <R extends Resource> R create(R resource) { Objects.requireNonNull(resource, "resource"); @@ -165,16 +166,13 @@ public <R extends Resource> R create(R resource) logger.debug("HTTP header Last-Modified: {}", response.getHeaderString(HttpHeaders.LAST_MODIFIED)); if (Status.CREATED.getStatusCode() == response.getStatus()) - { - @SuppressWarnings("unchecked") - R read = (R) response.readEntity(resource.getClass()); - return read; - } + return (R) response.readEntity(resource.getClass()); else throw handleError(response); } @Override + @SuppressWarnings("unchecked") public <R extends Resource> R createConditionaly(R resource, String ifNoneExistCriteria) { Objects.requireNonNull(resource, "resource"); @@ -191,16 +189,13 @@ public <R extends Resource> R createConditionaly(R resource, String ifNoneExistC logger.debug("HTTP header Last-Modified: {}", response.getHeaderString(HttpHeaders.LAST_MODIFIED)); if (Status.CREATED.getStatusCode() == response.getStatus()) - { - @SuppressWarnings("unchecked") - R read = (R) response.readEntity(resource.getClass()); - return read; - } + return (R) response.readEntity(resource.getClass()); else throw handleError(response); } @Override + @SuppressWarnings("unchecked") public <R extends Resource> R update(R resource) { Objects.requireNonNull(resource, "resource"); @@ -219,16 +214,13 @@ public <R extends Resource> R update(R resource) logger.debug("HTTP header Last-Modified: {}", response.getHeaderString(HttpHeaders.LAST_MODIFIED)); if (Status.OK.getStatusCode() == response.getStatus()) - { - @SuppressWarnings("unchecked") - R read = (R) response.readEntity(resource.getClass()); - return read; - } + return (R) response.readEntity(resource.getClass()); else throw handleError(response); } @Override + @SuppressWarnings("unchecked") public <R extends Resource> R updateConditionaly(R resource, Map<String, List<String>> criteria) { Objects.requireNonNull(resource, "resource"); @@ -254,11 +246,7 @@ public <R extends Resource> R updateConditionaly(R resource, Map<String, List<St logger.debug("HTTP header Last-Modified: {}", response.getHeaderString(HttpHeaders.LAST_MODIFIED)); if (Status.CREATED.getStatusCode() == response.getStatus() || Status.OK.getStatusCode() == response.getStatus()) - { - @SuppressWarnings("unchecked") - R read = (R) response.readEntity(resource.getClass()); - return read; - } + return (R) response.readEntity(resource.getClass()); else throw handleError(response); } @@ -546,12 +534,6 @@ public <R extends Resource> Bundle search(Class<R> resourceType, Map<String, Lis throw handleError(response); } - // private <R extends DomainResource> List<R> bundleToList(Class<R> resourceType, Bundle bundle) - // { - // return bundle.getEntry().stream().filter(c -> resourceType.isInstance(c.getResource())) - // .map(c -> resourceType.cast(c.getResource())).collect(Collectors.toList()); - // } - @Override public Bundle postBundle(Bundle bundle) { diff --git a/dsf-fhir/dsf-fhir-webservice-client/src/test/java/org/highmed/fhir/client/TestFhirJerseyClient.java b/dsf-fhir/dsf-fhir-webservice-client/src/test/java/org/highmed/fhir/client/TestFhirJerseyClient.java index ce3f02e1b..df1e1b8af 100755 --- a/dsf-fhir/dsf-fhir-webservice-client/src/test/java/org/highmed/fhir/client/TestFhirJerseyClient.java +++ b/dsf-fhir/dsf-fhir-webservice-client/src/test/java/org/highmed/fhir/client/TestFhirJerseyClient.java @@ -34,7 +34,7 @@ public class TestFhirJerseyClient public static void main(String[] args) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { - String keyStorePassword = "password"; + char[] keyStorePassword = "password".toCharArray(); KeyStore keyStore = CertificateReader.fromPkcs12( Paths.get("../../dsf-tools/dsf-tools-test-data-generator/cert/Webbrowser_Test_User/Webbrowser_Test_User_certificate.p12"), keyStorePassword); KeyStore trustStore = CertificateHelper.extractTrust(keyStore); diff --git a/dsf-fhir/dsf-fhir-websocket-client/src/main/java/org/highmed/fhir/client/WebsocketClientTyrus.java b/dsf-fhir/dsf-fhir-websocket-client/src/main/java/org/highmed/fhir/client/WebsocketClientTyrus.java index 7e80c27c3..d99f9f059 100755 --- a/dsf-fhir/dsf-fhir-websocket-client/src/main/java/org/highmed/fhir/client/WebsocketClientTyrus.java +++ b/dsf-fhir/dsf-fhir-websocket-client/src/main/java/org/highmed/fhir/client/WebsocketClientTyrus.java @@ -54,7 +54,7 @@ public boolean onDisconnect(CloseReason closeReason) private volatile boolean closed; public WebsocketClientTyrus(FhirContext fhirContext, URI wsUri, KeyStore trustStore, KeyStore keyStore, - String keyStorePassword, String subscriptionIdPart) + char[] keyStorePassword, String subscriptionIdPart) { this.wsUri = wsUri; diff --git a/dsf-fhir/dsf-fhir-websocket-client/src/test/java/org/highmed/fhir/client/TestFhirWebsocketClient.java b/dsf-fhir/dsf-fhir-websocket-client/src/test/java/org/highmed/fhir/client/TestFhirWebsocketClient.java index 7d4c7868f..46ac66b3a 100755 --- a/dsf-fhir/dsf-fhir-websocket-client/src/test/java/org/highmed/fhir/client/TestFhirWebsocketClient.java +++ b/dsf-fhir/dsf-fhir-websocket-client/src/test/java/org/highmed/fhir/client/TestFhirWebsocketClient.java @@ -23,7 +23,7 @@ public class TestFhirWebsocketClient public static void main(String[] args) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, InterruptedException { - String keyStorePassword = "password"; + char[] keyStorePassword = "password".toCharArray(); KeyStore keyStore = CertificateReader.fromPkcs12( Paths.get("../fhir-demo-cert-generator/cert/test-client_certificate.p12"), keyStorePassword); KeyStore trustStore = CertificateHelper.extractTrust(keyStore); diff --git a/dsf-tools/dsf-tools-db-migration/src/main/java/org/highmed/dsf/tools/db/DbMigrator.java b/dsf-tools/dsf-tools-db-migration/src/main/java/org/highmed/dsf/tools/db/DbMigrator.java index 7b61d3f4b..97f54fe95 100755 --- a/dsf-tools/dsf-tools-db-migration/src/main/java/org/highmed/dsf/tools/db/DbMigrator.java +++ b/dsf-tools/dsf-tools-db-migration/src/main/java/org/highmed/dsf/tools/db/DbMigrator.java @@ -96,15 +96,17 @@ public void migrate() { Database database = DatabaseFactory.getInstance() .findCorrectDatabaseImplementation(new JdbcConnection(connection)); - Liquibase liquibase = new Liquibase("db/db.changelog.xml", new ClassLoaderResourceAccessor(), database); - - ChangeLogParameters changeLogParameters = liquibase.getChangeLogParameters(); - changeLogParameterNames.forEach(parameterName -> changeLogParameters.set(parameterName, - properties.getProperty(prefix + parameterName))); + try (Liquibase liquibase = new Liquibase("db/db.changelog.xml", new ClassLoaderResourceAccessor(), + database)) + { + ChangeLogParameters changeLogParameters = liquibase.getChangeLogParameters(); + changeLogParameterNames.forEach(parameterName -> changeLogParameters.set(parameterName, + properties.getProperty(prefix + parameterName))); - logger.info("Executing DB migration ..."); - liquibase.update(new Contexts()); - logger.info("Executing DB migration [Done]"); + logger.info("Executing DB migration ..."); + liquibase.update(new Contexts()); + logger.info("Executing DB migration [Done]"); + } } } catch (SQLException e) @@ -117,6 +119,11 @@ public void migrate() logger.error("Error while running liquibase", e); throw new RuntimeException(e); } + catch (Exception e) + { + logger.error("Error while running liquibase", e); + throw new RuntimeException(e); + } } public static void retryOnConnectException(int times, Runnable run) diff --git a/dsf-tools/dsf-tools-proxy-test/src/main/java/org/highmed/dsf/tools/proxy/ProxyTest.java b/dsf-tools/dsf-tools-proxy-test/src/main/java/org/highmed/dsf/tools/proxy/ProxyTest.java index b90005b01..cd00dca69 100755 --- a/dsf-tools/dsf-tools-proxy-test/src/main/java/org/highmed/dsf/tools/proxy/ProxyTest.java +++ b/dsf-tools/dsf-tools-proxy-test/src/main/java/org/highmed/dsf/tools/proxy/ProxyTest.java @@ -19,7 +19,7 @@ public static void main(String[] args) if ((cons = System.console()) != null && (passwd = cons.readPassword("[%s]", "Password:")) != null) { TestClient client = new TestClient(args[0], args.length > 1 ? args[1] : null, - args.length > 2 ? args[2] : null, passwd != null ? String.valueOf(passwd) : null); + args.length > 2 ? args[2] : null, passwd); client.testBaseUrl(); java.util.Arrays.fill(passwd, ' '); diff --git a/dsf-tools/dsf-tools-proxy-test/src/main/java/org/highmed/dsf/tools/proxy/TestClient.java b/dsf-tools/dsf-tools-proxy-test/src/main/java/org/highmed/dsf/tools/proxy/TestClient.java index da7363eef..d6e8f24fe 100755 --- a/dsf-tools/dsf-tools-proxy-test/src/main/java/org/highmed/dsf/tools/proxy/TestClient.java +++ b/dsf-tools/dsf-tools-proxy-test/src/main/java/org/highmed/dsf/tools/proxy/TestClient.java @@ -13,14 +13,14 @@ public class TestClient extends AbstractJerseyClient { private static final Logger logger = LoggerFactory.getLogger(TestClient.class); - public TestClient(String baseUrl, String proxySchemeHostPort, String proxyUserName, String proxyPassword) + public TestClient(String baseUrl, String proxySchemeHostPort, String proxyUserName, char[] proxyPassword) { super(baseUrl, null, null, null, proxySchemeHostPort, proxyUserName, proxyPassword, 5_000, 5_000, null, null); logger.info("baseUrl: {}", baseUrl); logger.info("proxySchemeHostPort: {}", proxySchemeHostPort); logger.info("proxyUserName: {}", proxyUserName); - logger.info("proxyPassword: {}", IntStream.range(0, proxyPassword != null ? proxyPassword.length() : 0) + logger.info("proxyPassword: {}", IntStream.range(0, proxyPassword != null ? proxyPassword.length : 0) .mapToObj(i -> "*").collect(Collectors.joining())); } diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/java/org/highmed/dsf/tools/generator/CertificateGenerator.java b/dsf-tools/dsf-tools-test-data-generator/src/main/java/org/highmed/dsf/tools/generator/CertificateGenerator.java index 81e9bc217..a48b1ab4a 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/java/org/highmed/dsf/tools/generator/CertificateGenerator.java +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/java/org/highmed/dsf/tools/generator/CertificateGenerator.java @@ -52,7 +52,7 @@ public class CertificateGenerator private static final Logger logger = LoggerFactory.getLogger(CertificateGenerator.class); private static final String SERVER_DNS_ALTERNATIVE_NAME = "fhir"; - private static final String CERT_PASSWORD = "password"; + private static final char[] CERT_PASSWORD = "password".toCharArray(); private static final String[] SERVER_COMMON_NAMES = { "ttp", "medic1", "medic2", "medic3", "localhost" }; private static final String[] CLIENT_COMMON_NAMES = { "ttp-client", "medic1-client", "medic2-client", diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/test-bundle.xml b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/test-bundle.xml index 3e52a50e3..bb257b0b1 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/test-bundle.xml +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/test-bundle.xml @@ -4,6 +4,12 @@ <fullUrl value="urn:uuid:bb73165c-c7b9-4342-8e28-531f07fa7735"/> <resource> <Organization xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <extension url="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"> <valueString value="TODO"/> </extension> @@ -34,6 +40,12 @@ <fullUrl value="urn:uuid:b879e904-d666-45de-a995-accdd4429b79"/> <resource> <Endpoint xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <identifier> <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_Endpoint"/> diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-fhir-config.properties index 9682007fa..294c10ae0 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-fhir-config.properties @@ -12,7 +12,7 @@ org.highmed.dsf.fhir.serverBase=https://localhost/fhir org.highmed.dsf.fhir.defaultPageCount=20 org.highmed.dsf.fhir.local-user.thumbprints= -org.highmed.dsf.fhir.local-organization.systemAndIdentifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_Organization +org.highmed.dsf.fhir.local-organization.identifier=Test_Organization org.highmed.dsf.fhir.init.bundle.file=conf/bundle.xml diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic1-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic1-fhir-config.properties index ac1eda5a7..4f7b4fb6a 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic1-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic1-fhir-config.properties @@ -12,7 +12,7 @@ org.highmed.dsf.fhir.serverBase=https://medic1/fhir org.highmed.dsf.fhir.defaultPageCount=20 org.highmed.dsf.fhir.local-user.thumbprints= -org.highmed.dsf.fhir.local-organization.systemAndIdentifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_MeDIC_1 +org.highmed.dsf.fhir.local-organization.identifier=Test_MeDIC_1 org.highmed.dsf.fhir.init.bundle.file=conf/bundle.xml diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic2-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic2-fhir-config.properties index 943d6ca5a..47e74e931 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic2-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic2-fhir-config.properties @@ -12,7 +12,7 @@ org.highmed.dsf.fhir.serverBase=https://medic2/fhir org.highmed.dsf.fhir.defaultPageCount=20 org.highmed.dsf.fhir.local-user.thumbprints= -org.highmed.dsf.fhir.local-organization.systemAndIdentifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_MeDIC_2 +org.highmed.dsf.fhir.local-organization.identifier=Test_MeDIC_2 org.highmed.dsf.fhir.init.bundle.file=conf/bundle.xml diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic3-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic3-fhir-config.properties index a52f9db20..28b26bdb8 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic3-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic3-fhir-config.properties @@ -12,7 +12,7 @@ org.highmed.dsf.fhir.serverBase=https://medic3/fhir org.highmed.dsf.fhir.defaultPageCount=20 org.highmed.dsf.fhir.local-user.thumbprints= -org.highmed.dsf.fhir.local-organization.systemAndIdentifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_MeDIC_3 +org.highmed.dsf.fhir.local-organization.identifier=Test_MeDIC_3 org.highmed.dsf.fhir.init.bundle.file=conf/bundle.xml diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-ttp-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-ttp-fhir-config.properties index a9db4d8a5..034998645 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-ttp-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-ttp-fhir-config.properties @@ -12,7 +12,7 @@ org.highmed.dsf.fhir.serverBase=https://ttp/fhir org.highmed.dsf.fhir.defaultPageCount=20 org.highmed.dsf.fhir.local-user.thumbprints= -org.highmed.dsf.fhir.local-organization.systemAndIdentifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_TTP +org.highmed.dsf.fhir.local-organization.identifier=Test_TTP org.highmed.dsf.fhir.init.bundle.file=conf/bundle.xml diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/java-test-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/java-test-fhir-config.properties index d988728fb..22c563232 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/java-test-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/java-test-fhir-config.properties @@ -12,7 +12,7 @@ org.highmed.dsf.fhir.serverBase=https://localhost:8001/fhir org.highmed.dsf.fhir.defaultPageCount=20 org.highmed.dsf.fhir.local-user.thumbprints= -org.highmed.dsf.fhir.local-organization.systemAndIdentifier=http://highmed.org/fhir/NamingSystem/organization-identifier|Test_Organization +org.highmed.dsf.fhir.local-organization.identifier=Test_Organization org.highmed.dsf.fhir.init.bundle.file=conf/bundle.xml diff --git a/pom.xml b/pom.xml index 150ae5bb0..cac644a45 100755 --- a/pom.xml +++ b/pom.xml @@ -20,12 +20,12 @@ <compileTarget>11</compileTarget> <slf4j.version>1.8.0-beta4</slf4j.version> - <log4j.version>2.12.1</log4j.version> + <log4j.version>2.13.0</log4j.version> - <jetty.version>9.4.22.v20191022</jetty.version> - <jersey.version>2.29.1</jersey.version> + <jetty.version>9.4.26.v20200117</jetty.version> + <jersey.version>2.30.1</jersey.version> <tyrus.version>1.15</tyrus.version> - <spring.version>5.2.1.RELEASE</spring.version> + <spring.version>5.2.3.RELEASE</spring.version> <hapi.version>4.1.0</hapi.version> </properties> @@ -86,7 +86,7 @@ <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> - <version>4.12</version> + <version>4.13</version> </dependency> <dependency> <groupId>org.mockito</groupId> @@ -103,34 +103,34 @@ <dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> - <version>3.8.1</version> + <version>3.8.7</version> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> - <version>42.2.8</version> + <version>42.2.10</version> </dependency> <!-- hhn rwh --> <dependency> <groupId>de.hs-heilbronn.mi</groupId> <artifactId>jetty-utils</artifactId> - <version>0.5.0</version> + <version>0.6.0</version> </dependency> <dependency> <groupId>de.hs-heilbronn.mi</groupId> <artifactId>crypto-utils</artifactId> - <version>2.3.0</version> + <version>2.4.0</version> </dependency> <dependency> <groupId>de.hs-heilbronn.mi</groupId> <artifactId>log4j2-utils</artifactId> - <version>0.4.0</version> + <version>0.5.0</version> </dependency> <dependency> <groupId>de.hs-heilbronn.mi</groupId> <artifactId>db-test-utils</artifactId> - <version>0.4.0</version> + <version>0.5.0</version> </dependency> <dependency> @@ -337,12 +337,12 @@ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>3.0.0-M3</version> + <version>3.0.0-M4</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> - <version>3.2.1</version> + <version>3.2.2</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> From b2ca06226b5e3e5ac4aa7dda029fd638d74f5382 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Wed, 26 Feb 2020 00:53:54 +0100 Subject: [PATCH 11/55] hapi version upgrade to 4.2.0, ..DaoJdbc, ...UserFilter cleanup --- .../org/highmed/dsf/fhir/dao/ResourceDao.java | 9 +- .../AbstractPreparedStatementFactory.java | 6 +- .../dao/jdbc/AbstractResourceDaoJdbc.java | 83 ++------- .../AbstractStructureDefinitionDaoJdbc.java | 10 +- .../dao/jdbc/ActivityDefinitionDaoJdbc.java | 6 +- .../dsf/fhir/dao/jdbc/BinaryDaoJdbc.java | 16 +- .../dsf/fhir/dao/jdbc/BundleDaoJdbc.java | 7 +- .../dsf/fhir/dao/jdbc/CodeSystemDaoJdbc.java | 5 +- .../dsf/fhir/dao/jdbc/EndpointDaoJdbc.java | 6 +- .../dsf/fhir/dao/jdbc/GroupDaoJdbc.java | 7 +- .../dao/jdbc/HealthcareServiceDaoJdbc.java | 6 +- .../dsf/fhir/dao/jdbc/LocationDaoJdbc.java | 7 +- .../fhir/dao/jdbc/NamingSystemDaoJdbc.java | 5 +- .../fhir/dao/jdbc/OrganizationDaoJdbc.java | 5 +- .../dsf/fhir/dao/jdbc/PatientDaoJdbc.java | 7 +- .../fhir/dao/jdbc/PractitionerDaoJdbc.java | 6 +- .../dao/jdbc/PractitionerRoleDaoJdbc.java | 6 +- .../dao/jdbc/PreparedStatementFactory.java | 6 + .../dsf/fhir/dao/jdbc/ProvenanceDaoJdbc.java | 5 +- .../fhir/dao/jdbc/ResearchStudyDaoJdbc.java | 6 +- .../dao/jdbc/StructureDefinitionDaoJdbc.java | 8 +- .../StructureDefinitionSnapshotDaoJdbc.java | 16 +- .../fhir/dao/jdbc/SubscriptionDaoJdbc.java | 5 +- .../dsf/fhir/dao/jdbc/TaskDaoJdbc.java | 5 +- .../dsf/fhir/dao/jdbc/ValueSetDaoJdbc.java | 5 +- ...actMetaTagAuthorizationRoleUserFilter.java | 6 +- .../parameters/user/AbstractUserFilter.java | 5 +- .../user/ActivityDefinitionUserFilter.java | 5 +- .../parameters/user/BinaryUserFilter.java | 5 +- .../parameters/user/BundleUserFilter.java | 5 +- .../parameters/user/CodeSystemUserFilter.java | 5 +- .../parameters/user/EndpointUserFilter.java | 5 +- .../parameters/user/GroupUserFilter.java | 5 +- .../user/HealthcareServiceUserFilter.java | 5 +- .../parameters/user/LocationUserFilter.java | 5 +- .../user/NamingSystemUserFilter.java | 5 +- .../user/OrganizationUserFilter.java | 5 +- .../parameters/user/PatientUserFilter.java | 5 +- .../user/PractitionerRoleUserFilter.java | 5 +- .../user/PractitionerUserFilter.java | 5 +- .../parameters/user/ProvenanceUserFilter.java | 5 +- .../user/ResearchStudyUserFilter.java | 5 +- ...StructureDefinitionSnapshotUserFilter.java | 5 +- .../user/StructureDefinitionUserFilter.java | 5 +- .../user/SubscriptionUserFilter.java | 5 +- .../parameters/user/TaskUserFilter.java | 5 +- .../parameters/user/ValueSetUserFilter.java | 5 +- .../dsf/fhir/spring/config/DaoConfig.java | 41 +++-- .../impl/AbstractResourceServiceImpl.java | 4 +- .../dsf/fhir/dao/AbstractResourceDaoTest.java | 169 +++--------------- .../fhir/dao/ActivityDefinitionDaoTest.java | 6 +- .../highmed/dsf/fhir/dao/BinaryDaoTest.java | 8 +- .../highmed/dsf/fhir/dao/BundleDaoTest.java | 6 +- .../dsf/fhir/dao/CodeSystemDaoTest.java | 6 +- .../highmed/dsf/fhir/dao/EndpointDaoTest.java | 20 +-- .../highmed/dsf/fhir/dao/GroupDaoTest.java | 5 +- .../fhir/dao/HealthcareServiceDaoTest.java | 6 +- .../highmed/dsf/fhir/dao/LocationDaoTest.java | 6 +- .../dsf/fhir/dao/NamingSystemDaoTest.java | 6 +- .../dsf/fhir/dao/OrganizationDaoTest.java | 28 ++- .../highmed/dsf/fhir/dao/PatientDaoTest.java | 6 +- .../dsf/fhir/dao/PractitionerDaoTest.java | 6 +- .../dsf/fhir/dao/PractitionerRoleDaoTest.java | 6 +- .../dsf/fhir/dao/ProvenanceDaoTest.java | 6 +- .../dsf/fhir/dao/ResearchStudyDaoTest.java | 6 +- .../fhir/dao/StructureDefinitionDaoTest.java | 6 +- .../StructureDefinitionSnapshotDaoTest.java | 7 +- .../dsf/fhir/dao/SubscriptionDaoTest.java | 6 +- .../org/highmed/dsf/fhir/dao/TaskDaoTest.java | 5 +- .../highmed/dsf/fhir/dao/ValueSetDaoTest.java | 6 +- .../SnapshotDependencyAnalyzerTest.java | 27 ++- .../resources/integration/config.properties | 1 + pom.xml | 4 +- 73 files changed, 271 insertions(+), 496 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResourceDao.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResourceDao.java index 8bdf8d4f4..453f8b6c0 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResourceDao.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResourceDao.java @@ -24,13 +24,8 @@ public interface ResourceDao<R extends Resource> Class<R> getResourceType(); - /** - * @return new connection (read-only <code>false</code>, auto-commit <code>false</code>, isolation-level - * {@link Connection#TRANSACTION_REPEATABLE_READ}) - * @throws SQLException - */ - Connection getNewTransaction() throws SQLException; - + Connection newReadWriteTransaction() throws SQLException; + /** * @param resource * not <code>null</code> diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractPreparedStatementFactory.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractPreparedStatementFactory.java index fff563f74..1ffab4333 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractPreparedStatementFactory.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractPreparedStatementFactory.java @@ -36,7 +36,8 @@ protected AbstractPreparedStatementFactory(FhirContext fhirContext, Class<R> res this.updateSameRowSql = Objects.requireNonNull(updateSameRowSql, "updateSameRowSql"); } - private IParser getJsonParser() + @Override + public IParser getJsonParser() { IParser p = fhirContext.newJsonParser(); p.setStripVersionsFromReferences(false); @@ -58,7 +59,8 @@ protected final R jsonToResource(String json) return resource; } - protected final PGobject resourceToPgObject(R resource) + @Override + public final PGobject resourceToPgObject(R resource) { if (resource == null) return null; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java index 94eb81aab..6fdfb4c0f 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java @@ -13,13 +13,12 @@ import java.util.Objects; import java.util.Optional; import java.util.UUID; -import java.util.function.BiFunction; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import javax.sql.DataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ResourceDao; import org.highmed.dsf.fhir.dao.exception.ResourceDeletedException; @@ -38,7 +37,6 @@ import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.Resource; -import org.postgresql.util.PGobject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; @@ -49,8 +47,6 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.api.annotation.ResourceDef; -import ca.uhn.fhir.parser.DataFormatException; -import ca.uhn.fhir.parser.IParser; abstract class AbstractResourceDaoJdbc<R extends Resource> implements ResourceDao<R>, InitializingBean { @@ -103,7 +99,6 @@ public Resource getResource() } private final DataSource dataSource; - private final FhirContext fhirContext; private final Class<R> resourceType; private final String resourceTypeName; @@ -112,8 +107,7 @@ public Resource getResource() private final String resourceIdColumn; private final PreparedStatementFactory<R> preparedStatementFactory; - private final OrganizationType organizationType; - private final BiFunction<OrganizationType, User, SearchQueryUserFilter> userFilter; + private final Function<User, SearchQueryUserFilter> userFilter; private final List<Supplier<SearchQueryParameter<R>>> searchParameterFactories = new ArrayList<>(); private final List<Supplier<SearchQueryRevIncludeParameterFactory>> searchRevIncludeParameterFactories = new ArrayList<>(); @@ -128,15 +122,14 @@ protected static <T> List<T> with(T... t) * created on a request basis */ AbstractResourceDaoJdbc(DataSource dataSource, FhirContext fhirContext, Class<R> resourceType, String resourceTable, - String resourceColumn, String resourceIdColumn, OrganizationType organizationType, - BiFunction<OrganizationType, User, SearchQueryUserFilter> userFilter, + String resourceColumn, String resourceIdColumn, Function<User, SearchQueryUserFilter> userFilter, List<Supplier<SearchQueryParameter<R>>> searchParameterFactories, List<Supplier<SearchQueryRevIncludeParameterFactory>> searchRevIncludeParameterFactories) { this(dataSource, fhirContext, resourceType, resourceTable, resourceColumn, resourceIdColumn, new PreparedStatementFactoryDefault<>(fhirContext, resourceType, resourceTable, resourceIdColumn, resourceColumn), - organizationType, userFilter, searchParameterFactories, searchRevIncludeParameterFactories); + userFilter, searchParameterFactories, searchRevIncludeParameterFactories); } /* @@ -145,12 +138,11 @@ protected static <T> List<T> with(T... t) */ AbstractResourceDaoJdbc(DataSource dataSource, FhirContext fhirContext, Class<R> resourceType, String resourceTable, String resourceColumn, String resourceIdColumn, PreparedStatementFactory<R> preparedStatementFactory, - OrganizationType organizationType, BiFunction<OrganizationType, User, SearchQueryUserFilter> userFilter, + Function<User, SearchQueryUserFilter> userFilter, List<Supplier<SearchQueryParameter<R>>> searchParameterFactories, List<Supplier<SearchQueryRevIncludeParameterFactory>> searchRevIncludeParameterFactories) { this.dataSource = dataSource; - this.fhirContext = fhirContext; this.resourceType = resourceType; resourceTypeName = Objects.requireNonNull(resourceType, "resourceType").getAnnotation(ResourceDef.class).name(); @@ -160,7 +152,6 @@ protected static <T> List<T> with(T... t) this.preparedStatementFactory = preparedStatementFactory; - this.organizationType = organizationType; this.userFilter = userFilter; if (searchParameterFactories != null) @@ -200,6 +191,11 @@ protected String getResourceColumn() return resourceColumn; } + protected PreparedStatementFactory<R> getPreparedStatementFactory() + { + return preparedStatementFactory; + } + @Override public String getResourceTypeName() { @@ -213,7 +209,7 @@ public Class<R> getResourceType() } @Override - public Connection getNewTransaction() throws SQLException + public Connection newReadWriteTransaction() throws SQLException { Connection connection = dataSource.getConnection(); connection.setReadOnly(false); @@ -279,53 +275,10 @@ private R create(Connection connection, R resource, UUID uuid) throws SQLExcepti protected abstract R copy(R resource); - protected final Object resourceToPgObject(R resource) - { - if (resource == null) - return null; - - try - { - PGobject o = new PGobject(); - o.setType("JSONB"); - o.setValue(getJsonParser().encodeResourceToString(resource)); - return o; - } - catch (DataFormatException | SQLException e) - { - throw new RuntimeException(e); - } - } - - protected final PGobject uuidToPgObject(UUID uuid) - { - if (uuid == null) - return null; - - try - { - PGobject o = new PGobject(); - o.setType("UUID"); - o.setValue(uuid.toString()); - return o; - } - catch (DataFormatException | SQLException e) - { - throw new RuntimeException(e); - } - } - - private IParser getJsonParser() - { - IParser p = Objects.requireNonNull(fhirContext, "fhirContext").newJsonParser(); - p.setStripVersionsFromReferences(false); - return p; - } - protected R getResource(ResultSet result, int index) throws SQLException { String json = result.getString(index); - return getJsonParser().parseResource(resourceType, json); + return preparedStatementFactory.getJsonParser().parseResource(resourceType, json); } /* caution: only works because we set all versions as deleted or not deleted in method markDeleted */ @@ -338,7 +291,7 @@ public final boolean hasNonDeletedResource(UUID uuid) throws SQLException PreparedStatement statement = connection.prepareStatement("SELECT count(*) FROM " + resourceTable + " WHERE " + resourceIdColumn + " = ? AND NOT deleted")) { - statement.setObject(1, uuidToPgObject(uuid)); + statement.setObject(1, preparedStatementFactory.uuidToPgObject(uuid)); logger.trace("Executing query '{}'", statement); try (ResultSet result = statement.executeQuery()) @@ -510,7 +463,7 @@ public boolean existsNotDeletedWithTransaction(Connection connection, String idS try (PreparedStatement statement = connection.prepareStatement("SELECT count(*) FROM " + resourceTable + " WHERE " + resourceIdColumn + " = ? AND version = ? AND NOT deleted")) { - statement.setObject(1, uuidToPgObject(uuid)); + statement.setObject(1, preparedStatementFactory.uuidToPgObject(uuid)); statement.setLong(2, version); logger.trace("Executing query '{}'", statement); @@ -743,7 +696,7 @@ protected final Optional<LatestVersion> getLatestVersionIfExists(UUID uuid, Conn try (PreparedStatement statement = connection.prepareStatement("SELECT version, deleted FROM " + resourceTable + " WHERE " + resourceIdColumn + " = ? ORDER BY version DESC LIMIT 1")) { - statement.setObject(1, uuidToPgObject(uuid)); + statement.setObject(1, preparedStatementFactory.uuidToPgObject(uuid)); logger.trace("Executing query '{}'", statement); try (ResultSet result = statement.executeQuery()) @@ -812,7 +765,7 @@ protected final boolean markDeleted(Connection connection, UUID uuid, boolean de .prepareStatement("UPDATE " + resourceTable + " SET deleted = ? WHERE " + resourceIdColumn + " = ?")) { statement.setBoolean(1, deleted); - statement.setObject(2, uuidToPgObject(uuid)); + statement.setObject(2, preparedStatementFactory.uuidToPgObject(uuid)); logger.trace("Executing query '{}'", statement); statement.execute(); @@ -914,7 +867,7 @@ private void getResources(ResultSet result, int columnIndex, List<? super Resour while (it.hasNext()) { JsonElement jsonElement = it.next(); - IBaseResource resource = getJsonParser().parseResource(jsonElement.toString()); + IBaseResource resource = preparedStatementFactory.getJsonParser().parseResource(jsonElement.toString()); if (resource instanceof Resource) { query.modifyIncludeResource((Resource) resource, columnIndex, connection); @@ -931,7 +884,7 @@ private void getResources(ResultSet result, int columnIndex, List<? super Resour public final SearchQuery<R> createSearchQuery(User user, int page, int count) { return SearchQueryBuilder.create(resourceType, getResourceTable(), getResourceColumn(), page, count) - .with(userFilter.apply(organizationType, user)) + .with(userFilter.apply(user)) .with(new ResourceId(getResourceIdColumn()), new ResourceLastUpdated(getResourceColumn())) .with(searchParameterFactories.stream().map(Supplier::get).toArray(SearchQueryParameter[]::new)) .withRevInclude(searchRevIncludeParameterFactories.stream().map(Supplier::get) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractStructureDefinitionDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractStructureDefinitionDaoJdbc.java index 26918b4ea..4bc5a2dac 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractStructureDefinitionDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractStructureDefinitionDaoJdbc.java @@ -7,10 +7,9 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.function.BiFunction; +import java.util.function.Function; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.StructureDefinitionDaoBase; import org.highmed.dsf.fhir.search.SearchQueryUserFilter; @@ -30,12 +29,11 @@ abstract class AbstractStructureDefinitionDaoJdbc extends AbstractResourceDaoJdb private final ReadByUrlDaoJdbc<StructureDefinition> readByUrl; - public AbstractStructureDefinitionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType, String resourceTable, String resourceColumn, String resourceIdColumn, - BiFunction<OrganizationType, User, SearchQueryUserFilter> userFilter) + public AbstractStructureDefinitionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, String resourceTable, + String resourceColumn, String resourceIdColumn, Function<User, SearchQueryUserFilter> userFilter) { super(dataSource, fhirContext, StructureDefinition.class, resourceTable, resourceColumn, resourceIdColumn, - organizationType, userFilter, + userFilter, with(() -> new StructureDefinitionIdentifier(resourceColumn), () -> new StructureDefinitionUrl(resourceColumn), () -> new StructureDefinitionVersion(resourceColumn)), diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java index ee6c4dc40..b9c20dc03 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java @@ -1,7 +1,6 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionIdentifier; import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionName; @@ -16,11 +15,10 @@ public class ActivityDefinitionDaoJdbc extends AbstractResourceDaoJdbc<ActivityDefinition> implements ActivityDefinitionDao { - public ActivityDefinitionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + public ActivityDefinitionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, ActivityDefinition.class, "activity_definitions", "activity_definition", - "activity_definition_id", organizationType, ActivityDefinitionUserFilter::new, + "activity_definition_id", ActivityDefinitionUserFilter::new, with(ActivityDefinitionIdentifier::new, ActivityDefinitionName::new, ActivityDefinitionStatus::new, ActivityDefinitionUrl::new, ActivityDefinitionVersion::new), with()); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/BinaryDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/BinaryDaoJdbc.java index d6e7a611b..96dc8ae52 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/BinaryDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/BinaryDaoJdbc.java @@ -6,22 +6,22 @@ import java.sql.SQLException; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.BinaryDao; import org.highmed.dsf.fhir.search.parameters.BinaryContentType; import org.highmed.dsf.fhir.search.parameters.user.BinaryUserFilter; import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.IdType; +import org.postgresql.util.PGobject; import ca.uhn.fhir.context.FhirContext; public class BinaryDaoJdbc extends AbstractResourceDaoJdbc<Binary> implements BinaryDao { - public BinaryDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) + public BinaryDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, Binary.class, "binaries", "binary_json", "binary_id", - new PreparedStatementFactoryBinary(fhirContext), organizationType, BinaryUserFilter::new, - with(BinaryContentType::new), with()); + new PreparedStatementFactoryBinary(fhirContext), BinaryUserFilter::new, with(BinaryContentType::new), + with()); } @Override @@ -47,8 +47,12 @@ protected void modifySearchResultResource(Binary resource, Connection connection try (PreparedStatement statement = connection .prepareStatement("SELECT binary_data FROM binaries WHERE binary_id = ? AND version = ?")) { - statement.setObject(1, uuidToPgObject(toUuid(resource.getIdElement().getIdPart()))); - statement.setLong(2, resource.getMeta().getVersionIdElement().getIdPartAsLong()); + PGobject uuidObject = getPreparedStatementFactory() + .uuidToPgObject(toUuid(resource.getIdElement().getIdPart())); + Long version = resource.getMeta().getVersionIdElement().getIdPartAsLong(); + + statement.setObject(1, uuidObject); + statement.setLong(2, version); try (ResultSet result = statement.executeQuery()) { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/BundleDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/BundleDaoJdbc.java index c8dda87c5..71886ae76 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/BundleDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/BundleDaoJdbc.java @@ -4,7 +4,6 @@ import java.sql.SQLException; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.BundleDao; import org.highmed.dsf.fhir.search.parameters.BundleIdentifier; import org.highmed.dsf.fhir.search.parameters.user.BundleUserFilter; @@ -15,10 +14,10 @@ public class BundleDaoJdbc extends AbstractResourceDaoJdbc<Bundle> implements BundleDao { - public BundleDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) + public BundleDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { - super(dataSource, fhirContext, Bundle.class, "bundles", "bundle", "bundle_id", organizationType, - BundleUserFilter::new, with(BundleIdentifier::new), with()); + super(dataSource, fhirContext, Bundle.class, "bundles", "bundle", "bundle_id", BundleUserFilter::new, + with(BundleIdentifier::new), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/CodeSystemDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/CodeSystemDaoJdbc.java index 1799f60f7..d6b78552d 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/CodeSystemDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/CodeSystemDaoJdbc.java @@ -5,7 +5,6 @@ import java.util.Optional; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.CodeSystemDao; import org.highmed.dsf.fhir.search.parameters.CodeSystemIdentifier; import org.highmed.dsf.fhir.search.parameters.CodeSystemStatus; @@ -20,10 +19,10 @@ public class CodeSystemDaoJdbc extends AbstractResourceDaoJdbc<CodeSystem> imple { private final ReadByUrlDaoJdbc<CodeSystem> readByUrl; - public CodeSystemDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) + public CodeSystemDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, CodeSystem.class, "code_systems", "code_system", "code_system_id", - organizationType, CodeSystemUserFilter::new, + CodeSystemUserFilter::new, with(CodeSystemIdentifier::new, CodeSystemStatus::new, CodeSystemUrl::new, CodeSystemVersion::new), with()); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/EndpointDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/EndpointDaoJdbc.java index 1f231e301..377e077f6 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/EndpointDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/EndpointDaoJdbc.java @@ -6,7 +6,6 @@ import java.sql.SQLException; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.EndpointDao; import org.highmed.dsf.fhir.search.parameters.EndpointIdentifier; import org.highmed.dsf.fhir.search.parameters.EndpointName; @@ -24,10 +23,9 @@ public class EndpointDaoJdbc extends AbstractResourceDaoJdbc<Endpoint> implement { private static final Logger logger = LoggerFactory.getLogger(EndpointDaoJdbc.class); - public EndpointDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) + public EndpointDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { - super(dataSource, fhirContext, Endpoint.class, "endpoints", "endpoint", "endpoint_id", organizationType, - EndpointUserFilter::new, + super(dataSource, fhirContext, Endpoint.class, "endpoints", "endpoint", "endpoint_id", EndpointUserFilter::new, with(EndpointOrganization::new, EndpointIdentifier::new, EndpointName::new, EndpointStatus::new), with(OrganizationEndpointRevInclude::new)); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/GroupDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/GroupDaoJdbc.java index 2e1e3a221..0c2fb9199 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/GroupDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/GroupDaoJdbc.java @@ -1,7 +1,6 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.GroupDao; import org.highmed.dsf.fhir.search.parameters.rev.include.ResearchStudyEnrollmentRevInclude; import org.highmed.dsf.fhir.search.parameters.user.GroupUserFilter; @@ -11,10 +10,10 @@ public class GroupDaoJdbc extends AbstractResourceDaoJdbc<Group> implements GroupDao { - public GroupDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) + public GroupDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { - super(dataSource, fhirContext, Group.class, "groups", "group_json", "group_id", organizationType, - GroupUserFilter::new, with(), with(ResearchStudyEnrollmentRevInclude::new)); + super(dataSource, fhirContext, Group.class, "groups", "group_json", "group_id", GroupUserFilter::new, with(), + with(ResearchStudyEnrollmentRevInclude::new)); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/HealthcareServiceDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/HealthcareServiceDaoJdbc.java index 3fb1546dd..22305c237 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/HealthcareServiceDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/HealthcareServiceDaoJdbc.java @@ -1,7 +1,6 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.HealthcareServiceDao; import org.highmed.dsf.fhir.search.parameters.HealthcareServiceActive; import org.highmed.dsf.fhir.search.parameters.HealthcareServiceIdentifier; @@ -12,11 +11,10 @@ public class HealthcareServiceDaoJdbc extends AbstractResourceDaoJdbc<HealthcareService> implements HealthcareServiceDao { - public HealthcareServiceDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + public HealthcareServiceDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, HealthcareService.class, "healthcare_services", "healthcare_service", - "healthcare_service_id", organizationType, HealthcareServiceUserFilter::new, + "healthcare_service_id", HealthcareServiceUserFilter::new, with(HealthcareServiceIdentifier::new, HealthcareServiceActive::new), with()); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/LocationDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/LocationDaoJdbc.java index 2f718d0dd..b1fbafe37 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/LocationDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/LocationDaoJdbc.java @@ -1,7 +1,6 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.LocationDao; import org.highmed.dsf.fhir.search.parameters.LocationIdentifier; import org.highmed.dsf.fhir.search.parameters.user.LocationUserFilter; @@ -11,10 +10,10 @@ public class LocationDaoJdbc extends AbstractResourceDaoJdbc<Location> implements LocationDao { - public LocationDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) + public LocationDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { - super(dataSource, fhirContext, Location.class, "locations", "location", "location_id", organizationType, - LocationUserFilter::new, with(LocationIdentifier::new), with()); + super(dataSource, fhirContext, Location.class, "locations", "location", "location_id", LocationUserFilter::new, + with(LocationIdentifier::new), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/NamingSystemDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/NamingSystemDaoJdbc.java index cf82203b4..908a03519 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/NamingSystemDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/NamingSystemDaoJdbc.java @@ -1,7 +1,6 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.NamingSystemDao; import org.highmed.dsf.fhir.search.parameters.NamingSystemName; import org.highmed.dsf.fhir.search.parameters.user.NamingSystemUserFilter; @@ -11,10 +10,10 @@ public class NamingSystemDaoJdbc extends AbstractResourceDaoJdbc<NamingSystem> implements NamingSystemDao { - public NamingSystemDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) + public NamingSystemDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, NamingSystem.class, "naming_systems", "naming_system", "naming_system_id", - organizationType, NamingSystemUserFilter::new, with(NamingSystemName::new), with()); + NamingSystemUserFilter::new, with(NamingSystemName::new), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java index 9bfa7af76..c2846d5c5 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java @@ -25,11 +25,10 @@ public class OrganizationDaoJdbc extends AbstractResourceDaoJdbc<Organization> i { private static final Logger logger = LoggerFactory.getLogger(OrganizationDaoJdbc.class); - public OrganizationDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, - org.highmed.dsf.fhir.OrganizationType organizationType) + public OrganizationDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, Organization.class, "organizations", "organization", "organization_id", - organizationType, OrganizationUserFilter::new, with(OrganizationName::new, OrganizationEndpoint::new, + OrganizationUserFilter::new, with(OrganizationName::new, OrganizationEndpoint::new, OrganizationIdentifier::new, OrganizationActive::new, OrganizationType::new), with(EndpointOrganizationRevInclude::new)); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PatientDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PatientDaoJdbc.java index 0e76d4b8d..da5c7318f 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PatientDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PatientDaoJdbc.java @@ -1,7 +1,6 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.PatientDao; import org.highmed.dsf.fhir.search.parameters.PatientActive; import org.highmed.dsf.fhir.search.parameters.PatientIdentifier; @@ -12,10 +11,10 @@ public class PatientDaoJdbc extends AbstractResourceDaoJdbc<Patient> implements PatientDao { - public PatientDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) + public PatientDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { - super(dataSource, fhirContext, Patient.class, "patients", "patient", "patient_id", organizationType, - PatientUserFilter::new, with(PatientIdentifier::new, PatientActive::new), with()); + super(dataSource, fhirContext, Patient.class, "patients", "patient", "patient_id", PatientUserFilter::new, + with(PatientIdentifier::new, PatientActive::new), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerDaoJdbc.java index 046831412..a1f515860 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerDaoJdbc.java @@ -1,7 +1,6 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.PractitionerDao; import org.highmed.dsf.fhir.search.parameters.PractitionerActive; import org.highmed.dsf.fhir.search.parameters.PractitionerIdentifier; @@ -12,11 +11,10 @@ public class PractitionerDaoJdbc extends AbstractResourceDaoJdbc<Practitioner> implements PractitionerDao { - public PractitionerDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) + public PractitionerDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, Practitioner.class, "practitioners", "practitioner", "practitioner_id", - organizationType, PractitionerUserFilter::new, - with(PractitionerIdentifier::new, PractitionerActive::new), with()); + PractitionerUserFilter::new, with(PractitionerIdentifier::new, PractitionerActive::new), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerRoleDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerRoleDaoJdbc.java index 8d42bcc01..d5a056297 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerRoleDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerRoleDaoJdbc.java @@ -1,7 +1,6 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.PractitionerRoleDao; import org.highmed.dsf.fhir.search.parameters.PractitionerRoleActive; import org.highmed.dsf.fhir.search.parameters.PractitionerRoleIdentifier; @@ -12,11 +11,10 @@ public class PractitionerRoleDaoJdbc extends AbstractResourceDaoJdbc<PractitionerRole> implements PractitionerRoleDao { - public PractitionerRoleDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + public PractitionerRoleDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, PractitionerRole.class, "practitioner_roles", "practitioner_role", - "practitioner_role_id", organizationType, PractitionerRoleUserFilter::new, + "practitioner_role_id", PractitionerRoleUserFilter::new, with(PractitionerRoleIdentifier::new, PractitionerRoleActive::new), with()); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PreparedStatementFactory.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PreparedStatementFactory.java index eaa18c1ec..851185e73 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PreparedStatementFactory.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PreparedStatementFactory.java @@ -8,8 +8,14 @@ import org.hl7.fhir.r4.model.Resource; import org.postgresql.util.PGobject; +import ca.uhn.fhir.parser.IParser; + interface PreparedStatementFactory<R extends Resource> { + IParser getJsonParser(); + + PGobject resourceToPgObject(R resource); + PGobject uuidToPgObject(UUID uuid); String getCreateSql(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ProvenanceDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ProvenanceDaoJdbc.java index aef539f5e..07f6d36c2 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ProvenanceDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ProvenanceDaoJdbc.java @@ -1,7 +1,6 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.ProvenanceDao; import org.highmed.dsf.fhir.search.parameters.user.PatientUserFilter; import org.hl7.fhir.r4.model.Provenance; @@ -10,9 +9,9 @@ public class ProvenanceDaoJdbc extends AbstractResourceDaoJdbc<Provenance> implements ProvenanceDao { - public ProvenanceDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) + public ProvenanceDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { - super(dataSource, fhirContext, Provenance.class, "provenances", "provenance", "provenance_id", organizationType, + super(dataSource, fhirContext, Provenance.class, "provenances", "provenance", "provenance_id", PatientUserFilter::new, with(), with()); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java index 60e50f126..bbe888f09 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java @@ -1,7 +1,6 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.ResearchStudyDao; import org.highmed.dsf.fhir.search.parameters.ResearchStudyEnrollment; import org.highmed.dsf.fhir.search.parameters.ResearchStudyIdentifier; @@ -12,11 +11,10 @@ public class ResearchStudyDaoJdbc extends AbstractResourceDaoJdbc<ResearchStudy> implements ResearchStudyDao { - public ResearchStudyDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) + public ResearchStudyDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, ResearchStudy.class, "research_studies", "research_study", "research_study_id", - organizationType, ResearchStudyUserFilter::new, - with(ResearchStudyIdentifier::new, ResearchStudyEnrollment::new), with()); + ResearchStudyUserFilter::new, with(ResearchStudyIdentifier::new, ResearchStudyEnrollment::new), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/StructureDefinitionDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/StructureDefinitionDaoJdbc.java index 76b0686c5..b3db5b0ba 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/StructureDefinitionDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/StructureDefinitionDaoJdbc.java @@ -1,7 +1,6 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.StructureDefinitionDao; import org.highmed.dsf.fhir.search.parameters.user.StructureDefinitionUserFilter; import org.hl7.fhir.r4.model.StructureDefinition; @@ -10,11 +9,10 @@ public class StructureDefinitionDaoJdbc extends AbstractStructureDefinitionDaoJdbc implements StructureDefinitionDao { - public StructureDefinitionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + public StructureDefinitionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { - super(dataSource, fhirContext, organizationType, "structure_definitions", "structure_definition", - "structure_definition_id", StructureDefinitionUserFilter::new); + super(dataSource, fhirContext, "structure_definitions", "structure_definition", "structure_definition_id", + StructureDefinitionUserFilter::new); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/StructureDefinitionSnapshotDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/StructureDefinitionSnapshotDaoJdbc.java index d3402e76f..7492c5482 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/StructureDefinitionSnapshotDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/StructureDefinitionSnapshotDaoJdbc.java @@ -8,7 +8,6 @@ import java.util.UUID; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.StructureDefinitionSnapshotDao; import org.highmed.dsf.fhir.dao.converter.SnapshotInfoConverter; import org.highmed.dsf.fhir.dao.exception.ResourceNotFoundException; @@ -29,11 +28,10 @@ public class StructureDefinitionSnapshotDaoJdbc extends AbstractStructureDefinit private final SnapshotInfoConverter converter; public StructureDefinitionSnapshotDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType, SnapshotInfoConverter converter) + SnapshotInfoConverter converter) { - super(dataSource, fhirContext, organizationType, "structure_definition_snapshots", - "structure_definition_snapshot", "structure_definition_snapshot_id", - StructureDefinitionSnapshotUserFilter::new); + super(dataSource, fhirContext, "structure_definition_snapshots", "structure_definition_snapshot", + "structure_definition_snapshot_id", StructureDefinitionSnapshotUserFilter::new); this.converter = converter; } @@ -89,8 +87,8 @@ public StructureDefinition createWithTransaction(Connection connection, UUID uui .prepareStatement("INSERT INTO " + getResourceTable() + " (" + getResourceIdColumn() + ", " + getResourceColumn() + ", structure_definition_snapshot_info) VALUES (?, ?, ?)")) { - statement.setObject(1, uuidToPgObject(uuid)); - statement.setObject(2, resourceToPgObject(resource)); + statement.setObject(1, getPreparedStatementFactory().uuidToPgObject(uuid)); + statement.setObject(2, getPreparedStatementFactory().resourceToPgObject(resource)); statement.setObject(3, converter.toDb(info)); logger.trace("Executing query '{}'", statement); @@ -168,9 +166,9 @@ private StructureDefinition update(Connection connection, StructureDefinition re .prepareStatement("INSERT INTO " + getResourceTable() + " (" + getResourceIdColumn() + ", version, " + getResourceColumn() + ", structure_definition_snapshot_info) VALUES (?, ?, ?, ?)")) { - statement.setObject(1, uuidToPgObject(uuid)); + statement.setObject(1, getPreparedStatementFactory().uuidToPgObject(uuid)); statement.setLong(2, newVersion); - statement.setObject(3, resourceToPgObject(resource)); + statement.setObject(3, getPreparedStatementFactory().resourceToPgObject(resource)); statement.setObject(4, converter.toDb(info)); logger.trace("Executing query '{}'", statement); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/SubscriptionDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/SubscriptionDaoJdbc.java index 1b2b6ae19..46c4d6137 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/SubscriptionDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/SubscriptionDaoJdbc.java @@ -9,7 +9,6 @@ import java.util.List; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.SubscriptionDao; import org.highmed.dsf.fhir.search.parameters.SubscriptionChannelPayload; import org.highmed.dsf.fhir.search.parameters.SubscriptionChannelType; @@ -26,10 +25,10 @@ public class SubscriptionDaoJdbc extends AbstractResourceDaoJdbc<Subscription> i { private static final Logger logger = LoggerFactory.getLogger(SubscriptionDaoJdbc.class); - public SubscriptionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) + public SubscriptionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, Subscription.class, "subscriptions", "subscription", "subscription_id", - organizationType, SubscriptionUserFilter::new, with(SubscriptionCriteria::new, SubscriptionStatus::new, + SubscriptionUserFilter::new, with(SubscriptionCriteria::new, SubscriptionStatus::new, SubscriptionChannelType::new, SubscriptionChannelPayload::new), with()); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/TaskDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/TaskDaoJdbc.java index f961ec66f..09aeee935 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/TaskDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/TaskDaoJdbc.java @@ -1,7 +1,6 @@ package org.highmed.dsf.fhir.dao.jdbc; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.TaskDao; import org.highmed.dsf.fhir.search.parameters.TaskIdentifier; import org.highmed.dsf.fhir.search.parameters.TaskRequester; @@ -13,9 +12,9 @@ public class TaskDaoJdbc extends AbstractResourceDaoJdbc<Task> implements TaskDao { - public TaskDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) + public TaskDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { - super(dataSource, fhirContext, Task.class, "tasks", "task", "task_id", organizationType, TaskUserFilter::new, + super(dataSource, fhirContext, Task.class, "tasks", "task", "task_id", TaskUserFilter::new, with(TaskIdentifier::new, TaskRequester::new, TaskStatus::new), with()); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ValueSetDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ValueSetDaoJdbc.java index 35a150520..b51fd2800 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ValueSetDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ValueSetDaoJdbc.java @@ -5,7 +5,6 @@ import java.util.Optional; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.ValueSetDao; import org.highmed.dsf.fhir.search.parameters.ValueSetIdentifier; import org.highmed.dsf.fhir.search.parameters.ValueSetStatus; @@ -20,9 +19,9 @@ public class ValueSetDaoJdbc extends AbstractResourceDaoJdbc<ValueSet> implement { private final ReadByUrlDaoJdbc<ValueSet> readByUrl; - public ValueSetDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) + public ValueSetDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { - super(dataSource, fhirContext, ValueSet.class, "value_sets", "value_set", "value_set_id", organizationType, + super(dataSource, fhirContext, ValueSet.class, "value_sets", "value_set", "value_set_id", ValueSetUserFilter::new, with(ValueSetIdentifier::new, ValueSetStatus::new, ValueSetUrl::new, ValueSetVersion::new), with()); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/AbstractMetaTagAuthorizationRoleUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/AbstractMetaTagAuthorizationRoleUserFilter.java index cd1aab2bb..6ac54aae5 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/AbstractMetaTagAuthorizationRoleUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/AbstractMetaTagAuthorizationRoleUserFilter.java @@ -3,7 +3,6 @@ import java.sql.PreparedStatement; import java.sql.SQLException; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.authentication.UserRole; @@ -11,10 +10,9 @@ abstract class AbstractMetaTagAuthorizationRoleUserFilter extends AbstractUserFi { private final String resourceColumn; - public AbstractMetaTagAuthorizationRoleUserFilter(OrganizationType organizationType, User user, - String resourceColumn) + public AbstractMetaTagAuthorizationRoleUserFilter(User user, String resourceColumn) { - super(organizationType, user); + super(user); this.resourceColumn = resourceColumn; } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/AbstractUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/AbstractUserFilter.java index 584569d9d..ab4215213 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/AbstractUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/AbstractUserFilter.java @@ -1,17 +1,14 @@ package org.highmed.dsf.fhir.search.parameters.user; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.search.SearchQueryUserFilter; abstract class AbstractUserFilter implements SearchQueryUserFilter { - protected final OrganizationType organizationType; protected final User user; - public AbstractUserFilter(OrganizationType organizationType, User user) + public AbstractUserFilter(User user) { - this.organizationType = organizationType; this.user = user; } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ActivityDefinitionUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ActivityDefinitionUserFilter.java index 49331c364..56aeb7c7e 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ActivityDefinitionUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ActivityDefinitionUserFilter.java @@ -3,7 +3,6 @@ import java.sql.PreparedStatement; import java.sql.SQLException; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,9 +11,9 @@ public class ActivityDefinitionUserFilter extends AbstractUserFilter { private static final Logger logger = LoggerFactory.getLogger(ActivityDefinitionUserFilter.class); - public ActivityDefinitionUserFilter(OrganizationType organizationType, User user) + public ActivityDefinitionUserFilter(User user) { - super(organizationType, user); + super(user); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java index cfdd9cae2..291e80dbf 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BinaryUserFilter.java @@ -3,15 +3,14 @@ import java.sql.PreparedStatement; import java.sql.SQLException; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.authentication.UserRole; public class BinaryUserFilter extends AbstractUserFilter { - public BinaryUserFilter(OrganizationType organizationType, User user) + public BinaryUserFilter(User user) { - super(organizationType, user); + super(user); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BundleUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BundleUserFilter.java index 39072911d..c01578f97 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BundleUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/BundleUserFilter.java @@ -1,12 +1,11 @@ package org.highmed.dsf.fhir.search.parameters.user; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; public class BundleUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter { - public BundleUserFilter(OrganizationType organizationType, User user) + public BundleUserFilter(User user) { - super(organizationType, user, "bundle"); + super(user, "bundle"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/CodeSystemUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/CodeSystemUserFilter.java index d180af084..82693757d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/CodeSystemUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/CodeSystemUserFilter.java @@ -1,12 +1,11 @@ package org.highmed.dsf.fhir.search.parameters.user; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; public class CodeSystemUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter { - public CodeSystemUserFilter(OrganizationType organizationType, User user) + public CodeSystemUserFilter(User user) { - super(organizationType, user, "code_system"); + super(user, "code_system"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/EndpointUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/EndpointUserFilter.java index 684511f34..074f8e40b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/EndpointUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/EndpointUserFilter.java @@ -1,12 +1,11 @@ package org.highmed.dsf.fhir.search.parameters.user; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; public class EndpointUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter { - public EndpointUserFilter(OrganizationType organizationType, User user) + public EndpointUserFilter(User user) { - super(organizationType, user, "endpoint"); + super(user, "endpoint"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/GroupUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/GroupUserFilter.java index 89db54cb3..7ad2da8af 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/GroupUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/GroupUserFilter.java @@ -3,7 +3,6 @@ import java.sql.PreparedStatement; import java.sql.SQLException; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,9 +11,9 @@ public class GroupUserFilter extends AbstractUserFilter { private static final Logger logger = LoggerFactory.getLogger(GroupUserFilter.class); - public GroupUserFilter(OrganizationType organizationType, User user) + public GroupUserFilter(User user) { - super(organizationType, user); + super(user); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/HealthcareServiceUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/HealthcareServiceUserFilter.java index 134691973..0e012319c 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/HealthcareServiceUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/HealthcareServiceUserFilter.java @@ -1,12 +1,11 @@ package org.highmed.dsf.fhir.search.parameters.user; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; public class HealthcareServiceUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter { - public HealthcareServiceUserFilter(OrganizationType organizationType, User user) + public HealthcareServiceUserFilter(User user) { - super(organizationType, user, "healthcare_service"); + super(user, "healthcare_service"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/LocationUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/LocationUserFilter.java index 15663912a..b174f9230 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/LocationUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/LocationUserFilter.java @@ -1,12 +1,11 @@ package org.highmed.dsf.fhir.search.parameters.user; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; public class LocationUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter { - public LocationUserFilter(OrganizationType organizationType, User user) + public LocationUserFilter(User user) { - super(organizationType, user, "location"); + super(user, "location"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/NamingSystemUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/NamingSystemUserFilter.java index 6834d8f68..b3d186bf9 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/NamingSystemUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/NamingSystemUserFilter.java @@ -1,12 +1,11 @@ package org.highmed.dsf.fhir.search.parameters.user; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; public class NamingSystemUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter { - public NamingSystemUserFilter(OrganizationType organizationType, User user) + public NamingSystemUserFilter(User user) { - super(organizationType, user, "naming_system"); + super(user, "naming_system"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/OrganizationUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/OrganizationUserFilter.java index 52e4da8a7..e09d1b9ab 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/OrganizationUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/OrganizationUserFilter.java @@ -1,12 +1,11 @@ package org.highmed.dsf.fhir.search.parameters.user; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; public class OrganizationUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter { - public OrganizationUserFilter(OrganizationType organizationType, User user) + public OrganizationUserFilter(User user) { - super(organizationType, user, "organization"); + super(user, "organization"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PatientUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PatientUserFilter.java index 8bdb19bc8..06ddfe308 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PatientUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PatientUserFilter.java @@ -3,7 +3,6 @@ import java.sql.PreparedStatement; import java.sql.SQLException; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,9 +11,9 @@ public class PatientUserFilter extends AbstractUserFilter { private static final Logger logger = LoggerFactory.getLogger(PatientUserFilter.class); - public PatientUserFilter(OrganizationType organizationType, User user) + public PatientUserFilter(User user) { - super(organizationType, user); + super(user); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerRoleUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerRoleUserFilter.java index 0e9759312..b8a22499a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerRoleUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerRoleUserFilter.java @@ -3,7 +3,6 @@ import java.sql.PreparedStatement; import java.sql.SQLException; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,9 +11,9 @@ public class PractitionerRoleUserFilter extends AbstractUserFilter { private static final Logger logger = LoggerFactory.getLogger(PractitionerRoleUserFilter.class); - public PractitionerRoleUserFilter(OrganizationType organizationType, User user) + public PractitionerRoleUserFilter(User user) { - super(organizationType, user); + super(user); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerUserFilter.java index 1cad112ac..7547e51a1 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerUserFilter.java @@ -3,7 +3,6 @@ import java.sql.PreparedStatement; import java.sql.SQLException; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,9 +11,9 @@ public class PractitionerUserFilter extends AbstractUserFilter { private static final Logger logger = LoggerFactory.getLogger(PractitionerUserFilter.class); - public PractitionerUserFilter(OrganizationType organizationType, User user) + public PractitionerUserFilter(User user) { - super(organizationType, user); + super(user); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ProvenanceUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ProvenanceUserFilter.java index eaaf651b2..54516617d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ProvenanceUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ProvenanceUserFilter.java @@ -3,7 +3,6 @@ import java.sql.PreparedStatement; import java.sql.SQLException; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,9 +11,9 @@ public class ProvenanceUserFilter extends AbstractUserFilter { private static final Logger logger = LoggerFactory.getLogger(ProvenanceUserFilter.class); - public ProvenanceUserFilter(OrganizationType organizationType, User user) + public ProvenanceUserFilter(User user) { - super(organizationType, user); + super(user); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ResearchStudyUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ResearchStudyUserFilter.java index 5ebf86fe9..fa212ed28 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ResearchStudyUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ResearchStudyUserFilter.java @@ -3,7 +3,6 @@ import java.sql.PreparedStatement; import java.sql.SQLException; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,9 +11,9 @@ public class ResearchStudyUserFilter extends AbstractUserFilter { private static final Logger logger = LoggerFactory.getLogger(ResearchStudyUserFilter.class); - public ResearchStudyUserFilter(OrganizationType organizationType, User user) + public ResearchStudyUserFilter(User user) { - super(organizationType, user); + super(user); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/StructureDefinitionSnapshotUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/StructureDefinitionSnapshotUserFilter.java index a86e13394..96f0dc08a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/StructureDefinitionSnapshotUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/StructureDefinitionSnapshotUserFilter.java @@ -1,12 +1,11 @@ package org.highmed.dsf.fhir.search.parameters.user; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; public class StructureDefinitionSnapshotUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter { - public StructureDefinitionSnapshotUserFilter(OrganizationType organizationType, User user) + public StructureDefinitionSnapshotUserFilter(User user) { - super(organizationType, user, "structure_definition_snapshot"); + super(user, "structure_definition_snapshot"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/StructureDefinitionUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/StructureDefinitionUserFilter.java index 3dc131a9d..90820fc98 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/StructureDefinitionUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/StructureDefinitionUserFilter.java @@ -1,12 +1,11 @@ package org.highmed.dsf.fhir.search.parameters.user; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; public class StructureDefinitionUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter { - public StructureDefinitionUserFilter(OrganizationType organizationType, User user) + public StructureDefinitionUserFilter(User user) { - super(organizationType, user, "structure_definition"); + super(user, "structure_definition"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/SubscriptionUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/SubscriptionUserFilter.java index 48905012d..1277f0f3f 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/SubscriptionUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/SubscriptionUserFilter.java @@ -1,12 +1,11 @@ package org.highmed.dsf.fhir.search.parameters.user; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; public class SubscriptionUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter { - public SubscriptionUserFilter(OrganizationType organizationType, User user) + public SubscriptionUserFilter(User user) { - super(organizationType, user, "subscription"); + super(user, "subscription"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/TaskUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/TaskUserFilter.java index c87c7386a..5faf6ccaf 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/TaskUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/TaskUserFilter.java @@ -3,14 +3,13 @@ import java.sql.PreparedStatement; import java.sql.SQLException; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; public class TaskUserFilter extends AbstractUserFilter { - public TaskUserFilter(OrganizationType organizationType, User user) + public TaskUserFilter(User user) { - super(organizationType, user); + super(user); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ValueSetUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ValueSetUserFilter.java index f87edfcc6..4b047365c 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ValueSetUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ValueSetUserFilter.java @@ -1,12 +1,11 @@ package org.highmed.dsf.fhir.search.parameters.user; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.User; public class ValueSetUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter { - public ValueSetUserFilter(OrganizationType organizationType, User user) + public ValueSetUserFilter(User user) { - super(organizationType, user, "value_set"); + super(user, "value_set"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java index db8648d45..e49f94695 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java @@ -96,97 +96,97 @@ public OrganizationType organizationType() @Bean public ActivityDefinitionDao activityDefinitionDao() { - return new ActivityDefinitionDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new ActivityDefinitionDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public BinaryDao binaryDao() { - return new BinaryDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new BinaryDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public BundleDao bundleDao() { - return new BundleDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new BundleDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public CodeSystemDao codeSystemDao() { - return new CodeSystemDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new CodeSystemDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public EndpointDao endpointDao() { - return new EndpointDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new EndpointDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public GroupDao groupDao() { - return new GroupDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new GroupDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public HealthcareServiceDao healthcareServiceDao() { - return new HealthcareServiceDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new HealthcareServiceDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public LocationDao locationDao() { - return new LocationDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new LocationDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public NamingSystemDao namingSystemDao() { - return new NamingSystemDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new NamingSystemDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public OrganizationDao organizationDao() { - return new OrganizationDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new OrganizationDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public PatientDao patientDao() { - return new PatientDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new PatientDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public PractitionerDao practitionerDao() { - return new PractitionerDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new PractitionerDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public PractitionerRoleDao practitionerRoleDao() { - return new PractitionerRoleDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new PractitionerRoleDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public ProvenanceDao provenanceDao() { - return new ProvenanceDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new ProvenanceDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public ResearchStudyDao researchStudyDao() { - return new ResearchStudyDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new ResearchStudyDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public StructureDefinitionDao structureDefinitionDao() { - return new StructureDefinitionDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new StructureDefinitionDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean @@ -198,26 +198,25 @@ public SnapshotInfoConverter snapshotInfoConverter() @Bean public StructureDefinitionSnapshotDao structureDefinitionSnapshotDao() { - return new StructureDefinitionSnapshotDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType(), - snapshotInfoConverter()); + return new StructureDefinitionSnapshotDaoJdbc(dataSource(), fhirConfig.fhirContext(), snapshotInfoConverter()); } @Bean public SubscriptionDao subscriptionDao() { - return new SubscriptionDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new SubscriptionDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public TaskDao taskDao() { - return new TaskDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new TaskDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean public ValueSetDao valueSetDao() { - return new ValueSetDaoJdbc(dataSource(), fhirConfig.fhirContext(), organizationType()); + return new ValueSetDaoJdbc(dataSource(), fhirConfig.fhirContext()); } @Bean diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java index 690541859..194a86f0c 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java @@ -140,7 +140,7 @@ public Response create(R resource, UriInfo uri, HttpHeaders headers) R createdResource = exceptionHandler.handleSqlException(() -> { - try (Connection connection = dao.getNewTransaction()) + try (Connection connection = dao.newReadWriteTransaction()) { try { @@ -381,7 +381,7 @@ public Response update(String id, R resource, UriInfo uri, HttpHeaders headers) R updatedResource = exceptionHandler .handleSqlExAndResourceNotFoundExAndResouceVersionNonMatchEx(resourceTypeName, () -> { - try (Connection connection = dao.getNewTransaction()) + try (Connection connection = dao.newReadWriteTransaction()) { try { diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/AbstractResourceDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/AbstractResourceDaoTest.java index 8a54d1f80..571d5986d 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/AbstractResourceDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/AbstractResourceDaoTest.java @@ -11,7 +11,6 @@ import java.util.UUID; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.exception.ResourceDeletedException; import org.highmed.dsf.fhir.dao.exception.ResourceNotFoundException; import org.highmed.dsf.fhir.dao.exception.ResourceVersionNoMatchException; @@ -38,7 +37,7 @@ public abstract class AbstractResourceDaoTest<D extends Resource, C extends Reso protected final Class<D> resouceClass; protected final FhirContext fhirContext = FhirContext.forR4(); - protected C ttpDao, medicDao; + protected C dao; protected AbstractResourceDaoTest(Class<D> resouceClass) { @@ -48,33 +47,20 @@ protected AbstractResourceDaoTest(Class<D> resouceClass) @Before public void before() throws Exception { - ttpDao = createDao(database.getDataSource(), fhirContext, OrganizationType.TTP); - medicDao = createDao(database.getDataSource(), fhirContext, OrganizationType.MeDIC); + dao = createDao(database.getDataSource(), fhirContext); } - protected abstract C createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType); + protected abstract C createDao(BasicDataSource dataSource, FhirContext fhirContext); @Test - public void testEmptyForTtp() throws Exception + public void testEmpty() throws Exception { - Optional<D> read = ttpDao.read(UUID.randomUUID()); + Optional<D> read = dao.read(UUID.randomUUID()); assertTrue(read.isEmpty()); } - @Test - public void testEmptyForMedic() throws Exception - { - testEmpty(medicDao); - } - @Test public void testEmptyWithVersion() throws Exception - { - testEmpty(ttpDao); - } - - private void testEmpty(C dao) throws SQLException { Optional<D> read = dao.readVersion(UUID.randomUUID(), 1L); assertTrue(read.isEmpty()); @@ -83,18 +69,7 @@ private void testEmpty(C dao) throws SQLException protected abstract D createResource(); @Test - public void testCreateForTtp() throws Exception - { - testCreate(ttpDao); - } - - @Test - public void testCreateForMedic() throws Exception - { - testCreate(medicDao); - } - - private void testCreate(C dao) throws SQLException, ResourceDeletedException + public void testCreate() throws Exception { D newResource = createResource(); assertNull(newResource.getId()); @@ -125,18 +100,7 @@ private void testCreate(C dao) throws SQLException, ResourceDeletedException protected abstract D updateResource(D resource); @Test - public void testUpdateForTtp() throws Exception - { - testUpdate(ttpDao); - } - - @Test - public void testUpdateForMedic() throws Exception - { - testUpdate(medicDao); - } - - private void testUpdate(C dao) throws SQLException, ResourceNotFoundException, ResourceVersionNoMatchException + public void testUpdate() throws Exception { D newResource = createResource(); assertNull(newResource.getId()); @@ -159,19 +123,7 @@ private void testUpdate(C dao) throws SQLException, ResourceNotFoundException, R } @Test(expected = ResourceNotFoundException.class) - public void testUpdateNonExistingForTtp() throws Exception - { - testUpdateNonExisting(ttpDao); - } - - @Test(expected = ResourceNotFoundException.class) - public void testUpdateNonExistingForMedic() throws Exception - { - testUpdateNonExisting(medicDao); - } - - private void testUpdateNonExisting(C dao) - throws SQLException, ResourceNotFoundException, ResourceVersionNoMatchException + public void testUpdateNonExisting() throws Exception { D newResource = createResource(); assertNull(newResource.getId()); @@ -181,19 +133,7 @@ private void testUpdateNonExisting(C dao) } @Test(expected = ResourceVersionNoMatchException.class) - public void testUpdateNotLatestForTtp() throws Exception - { - testUpdateNotLatest(ttpDao); - } - - @Test(expected = ResourceVersionNoMatchException.class) - public void testUpdateNotLatestForMedic() throws Exception - { - testUpdateNotLatest(medicDao); - } - - private void testUpdateNotLatest(C dao) - throws SQLException, ResourceNotFoundException, ResourceVersionNoMatchException + public void testUpdateNotLatest() throws Exception { D newResource = createResource(); assertNull(newResource.getId()); @@ -213,18 +153,7 @@ private void testUpdateNotLatest(C dao) } @Test - public void testUpdateLatestForTtp() throws Exception - { - testUpdateLatest(ttpDao); - } - - @Test - public void testUpdateLatestForMedic() throws Exception - { - testUpdateLatest(medicDao); - } - - private void testUpdateLatest(C dao) throws SQLException, ResourceNotFoundException, ResourceVersionNoMatchException + public void testUpdateLatest() throws Exception { D newResource = createResource(); assertNull(newResource.getId()); @@ -247,18 +176,7 @@ private void testUpdateLatest(C dao) throws SQLException, ResourceNotFoundExcept protected abstract void checkUpdates(D resource); @Test(expected = ResourceDeletedException.class) - public void testDeleteForTtp() throws Exception - { - testDelete(ttpDao); - } - - @Test(expected = ResourceDeletedException.class) - public void testDeleteForMedic() throws Exception - { - testDelete(medicDao); - } - - private void testDelete(C dao) throws SQLException, ResourceDeletedException, ResourceNotFoundException + public void testDelete() throws Exception { D newResource = createResource(); assertNull(newResource.getId()); @@ -283,18 +201,7 @@ private void testDelete(C dao) throws SQLException, ResourceDeletedException, Re } @Test - public void testReadWithVersionForTtp() throws Exception - { - testReadWithVersion(ttpDao); - } - - @Test - public void testReadWithVersionFotMedic() throws Exception - { - testReadWithVersion(medicDao); - } - - private void testReadWithVersion(C dao) throws SQLException + public void testReadWithVersion() throws Exception { D newResource = createResource(); assertNull(newResource.getId()); @@ -318,18 +225,7 @@ private void testReadWithVersion(C dao) throws SQLException } @Test - public void testReadForTtp() throws Exception - { - testRead(ttpDao); - } - - @Test - public void testReadForMedic() throws Exception - { - testRead(medicDao); - } - - private void testRead(C dao) throws SQLException, ResourceDeletedException + public void testRead() throws Exception { D newResource = createResource(); assertNull(newResource.getId()); @@ -354,19 +250,7 @@ private void testRead(C dao) throws SQLException, ResourceDeletedException } @Test - public void testReadLatestForTtp() throws Exception - { - testReadLatest(ttpDao); - } - - @Test - public void testReadLatestForMedic() throws Exception - { - testReadLatest(medicDao); - } - - private void testReadLatest(C dao) - throws SQLException, ResourceNotFoundException, ResourceVersionNoMatchException, ResourceDeletedException + public void testReadLatest() throws Exception { D newResource = createResource(); assertNull(newResource.getId()); @@ -405,18 +289,7 @@ private void testReadLatest(C dao) } @Test - public void testUpdateSameRowForTtp() throws Exception - { - testUpdateSameRow(ttpDao); - } - - @Test - public void testUpdateSameRowForMedic() throws Exception - { - testUpdateSameRow(medicDao); - } - - private void testUpdateSameRow(C dao) throws SQLException, ResourceNotFoundException, ResourceDeletedException + public void testUpdateSameRow() throws Exception { D newResource = createResource(); assertNull(newResource.getId()); @@ -433,7 +306,7 @@ private void testUpdateSameRow(C dao) throws SQLException, ResourceNotFoundExcep assertTrue(newResource.equalsDeep(createdResource)); D updateResource = updateResource(createdResource); - try (Connection connection = dao.getNewTransaction()) + try (Connection connection = getNewTransaction()) { D updatedResource = dao.updateSameRowWithTransaction(connection, updateResource); @@ -457,4 +330,14 @@ private void testUpdateSameRow(C dao) throws SQLException, ResourceNotFoundExcep assertEquals(createdResource.getIdElement().getIdPart(), read.get().getIdElement().getIdPart()); assertEquals(createdResource.getMeta().getVersionId(), read.get().getMeta().getVersionId()); } + + private Connection getNewTransaction() throws SQLException + { + Connection connection = database.getDataSource().getConnection(); + connection.setReadOnly(false); + connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ); + connection.setAutoCommit(false); + + return connection; + } } diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDaoTest.java index 69fee17a8..ef93df470 100644 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDaoTest.java @@ -3,7 +3,6 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.ActivityDefinitionDaoJdbc; import org.hl7.fhir.r4.model.ActivityDefinition; @@ -20,10 +19,9 @@ public ActivityDefinitionDaoTest() } @Override - protected ActivityDefinitionDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected ActivityDefinitionDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new ActivityDefinitionDaoJdbc(dataSource, fhirContext, organizationType); + return new ActivityDefinitionDaoJdbc(dataSource, fhirContext); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/BinaryDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/BinaryDaoTest.java index 8d11229e5..9645368ac 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/BinaryDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/BinaryDaoTest.java @@ -12,7 +12,6 @@ import java.util.Arrays; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.BinaryDaoJdbc; import org.hl7.fhir.r4.model.Binary; import org.junit.Test; @@ -32,10 +31,9 @@ public BinaryDaoTest() } @Override - protected BinaryDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected BinaryDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new BinaryDaoJdbc(dataSource, fhirContext, organizationType); + return new BinaryDaoJdbc(dataSource, fhirContext); } @Override @@ -77,7 +75,7 @@ public void testCreateCheckDataNullInJsonColumn() throws Exception assertNull(newResource.getId()); assertNull(newResource.getMeta().getVersionId()); - Binary createdResource = ttpDao.create(newResource); + Binary createdResource = dao.create(newResource); assertNotNull(createdResource); assertNotNull(createdResource.getId()); assertNotNull(createdResource.getMeta().getVersionId()); diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/BundleDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/BundleDaoTest.java index 36f04d112..48618a1b2 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/BundleDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/BundleDaoTest.java @@ -3,7 +3,6 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.BundleDaoJdbc; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleType; @@ -21,10 +20,9 @@ public BundleDaoTest() } @Override - protected BundleDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected BundleDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new BundleDaoJdbc(dataSource, fhirContext, organizationType); + return new BundleDaoJdbc(dataSource, fhirContext); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/CodeSystemDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/CodeSystemDaoTest.java index fb6fbebd7..69bae42f0 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/CodeSystemDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/CodeSystemDaoTest.java @@ -3,7 +3,6 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.CodeSystemDaoJdbc; import org.hl7.fhir.r4.model.CodeSystem; @@ -20,10 +19,9 @@ public CodeSystemDaoTest() } @Override - protected CodeSystemDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected CodeSystemDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new CodeSystemDaoJdbc(dataSource, fhirContext, organizationType); + return new CodeSystemDaoJdbc(dataSource, fhirContext); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/EndpointDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/EndpointDaoTest.java index a729d527b..e96f9b966 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/EndpointDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/EndpointDaoTest.java @@ -8,7 +8,6 @@ import java.util.UUID; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.EndpointDaoJdbc; import org.hl7.fhir.r4.model.Endpoint; import org.hl7.fhir.r4.model.Endpoint.EndpointStatus; @@ -27,10 +26,9 @@ public EndpointDaoTest() } @Override - protected EndpointDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected EndpointDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new EndpointDaoJdbc(dataSource, fhirContext, organizationType); + return new EndpointDaoJdbc(dataSource, fhirContext); } @Override @@ -69,10 +67,10 @@ public void testExistsActiveNotDeletedByAddress() throws Exception e.setStatus(EndpointStatus.ACTIVE); e.setAddress(address); - Endpoint created = ttpDao.create(e); + Endpoint created = dao.create(e); assertNotNull(created); - assertTrue(ttpDao.existsActiveNotDeletedByAddress(address)); + assertTrue(dao.existsActiveNotDeletedByAddress(address)); } @Test @@ -84,10 +82,10 @@ public void testExistsActiveNotDeletedByAddressNotActive() throws Exception e.setStatus(EndpointStatus.OFF); e.setAddress(address); - Endpoint created = ttpDao.create(e); + Endpoint created = dao.create(e); assertNotNull(created); - assertFalse(ttpDao.existsActiveNotDeletedByAddress(address)); + assertFalse(dao.existsActiveNotDeletedByAddress(address)); } @Test @@ -99,10 +97,10 @@ public void testExistsActiveNotDeletedByAddressDeleted() throws Exception e.setStatus(EndpointStatus.ACTIVE); e.setAddress(address); - Endpoint created = ttpDao.create(e); + Endpoint created = dao.create(e); assertNotNull(created); - ttpDao.delete(UUID.fromString(created.getIdElement().getIdPart())); + dao.delete(UUID.fromString(created.getIdElement().getIdPart())); - assertFalse(ttpDao.existsActiveNotDeletedByAddress(address)); + assertFalse(dao.existsActiveNotDeletedByAddress(address)); } } diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/GroupDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/GroupDaoTest.java index 8ea8fc9cf..efd56e622 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/GroupDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/GroupDaoTest.java @@ -3,7 +3,6 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.GroupDaoJdbc; import org.hl7.fhir.r4.model.Group; @@ -21,9 +20,9 @@ public GroupDaoTest() } @Override - protected GroupDao createDao(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) + protected GroupDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new GroupDaoJdbc(dataSource, fhirContext, organizationType); + return new GroupDaoJdbc(dataSource, fhirContext); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/HealthcareServiceDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/HealthcareServiceDaoTest.java index b29fdddaf..bc7b1c522 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/HealthcareServiceDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/HealthcareServiceDaoTest.java @@ -3,7 +3,6 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.HealthcareServiceDaoJdbc; import org.hl7.fhir.r4.model.HealthcareService; @@ -20,10 +19,9 @@ public HealthcareServiceDaoTest() } @Override - protected HealthcareServiceDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected HealthcareServiceDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new HealthcareServiceDaoJdbc(dataSource, fhirContext, organizationType); + return new HealthcareServiceDaoJdbc(dataSource, fhirContext); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/LocationDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/LocationDaoTest.java index 52e029919..9b3f5894b 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/LocationDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/LocationDaoTest.java @@ -3,7 +3,6 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.LocationDaoJdbc; import org.hl7.fhir.r4.model.Location; @@ -20,10 +19,9 @@ public LocationDaoTest() } @Override - protected LocationDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected LocationDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new LocationDaoJdbc(dataSource, fhirContext, organizationType); + return new LocationDaoJdbc(dataSource, fhirContext); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/NamingSystemDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/NamingSystemDaoTest.java index bd2a7fc8a..3407cab63 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/NamingSystemDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/NamingSystemDaoTest.java @@ -3,7 +3,6 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.NamingSystemDaoJdbc; import org.hl7.fhir.r4.model.NamingSystem; @@ -20,10 +19,9 @@ public NamingSystemDaoTest() } @Override - protected NamingSystemDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected NamingSystemDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new NamingSystemDaoJdbc(dataSource, fhirContext, organizationType); + return new NamingSystemDaoJdbc(dataSource, fhirContext); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/OrganizationDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/OrganizationDaoTest.java index 340783405..0cc0f14aa 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/OrganizationDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/OrganizationDaoTest.java @@ -10,7 +10,6 @@ import org.apache.commons.codec.binary.Hex; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.OrganizationDaoJdbc; import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.StringType; @@ -29,10 +28,9 @@ public OrganizationDaoTest() } @Override - protected OrganizationDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected OrganizationDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new OrganizationDaoJdbc(dataSource, fhirContext, organizationType); + return new OrganizationDaoJdbc(dataSource, fhirContext); } @Override @@ -73,10 +71,10 @@ public void testReadActiveNotDeletedByThumbprint() throws Exception org.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/certificate-thumbprint") .setValue(new StringType(certHex)); - Organization created = ttpDao.create(org); + Organization created = dao.create(org); assertNotNull(created); - Optional<Organization> read = ttpDao.readActiveNotDeletedByThumbprint(certHex); + Optional<Organization> read = dao.readActiveNotDeletedByThumbprint(certHex); assertNotNull(read); assertTrue(read.isPresent()); assertNotNull( @@ -101,14 +99,14 @@ public void testReadActiveNotDeletedByThumbprintNotActive() throws Exception org.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/certificate-thumbprint") .setValue(new StringType(certHex)); - Organization created = ttpDao.create(org); + Organization created = dao.create(org); assertNotNull(created); - Optional<Organization> read = ttpDao.readActiveNotDeletedByThumbprint(certHex); + Optional<Organization> read = dao.readActiveNotDeletedByThumbprint(certHex); assertNotNull(read); assertTrue(read.isEmpty()); - Optional<Organization> read2 = ttpDao.read(UUID.fromString(created.getIdElement().getIdPart())); + Optional<Organization> read2 = dao.read(UUID.fromString(created.getIdElement().getIdPart())); assertNotNull(read2); assertTrue(read2.isPresent()); } @@ -124,11 +122,11 @@ public void testReadActiveNotDeletedByThumbprintDeleted() throws Exception org.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/certificate-thumbprint") .setValue(new StringType(certHex)); - Organization created = ttpDao.create(org); + Organization created = dao.create(org); assertNotNull(created); - ttpDao.delete(UUID.fromString(created.getIdElement().getIdPart())); + dao.delete(UUID.fromString(created.getIdElement().getIdPart())); - Optional<Organization> read = ttpDao.readActiveNotDeletedByThumbprint(certHex); + Optional<Organization> read = dao.readActiveNotDeletedByThumbprint(certHex); assertNotNull(read); assertTrue(read.isEmpty()); } @@ -138,7 +136,7 @@ public void testReadActiveNotDeletedByThumbprintNotExisting() throws Exception { final String certHex = Hex.encodeHexString("FooBarBaz".getBytes(StandardCharsets.UTF_8)); - Optional<Organization> read = ttpDao.readActiveNotDeletedByThumbprint(certHex); + Optional<Organization> read = dao.readActiveNotDeletedByThumbprint(certHex); assertNotNull(read); assertTrue(read.isEmpty()); } @@ -146,7 +144,7 @@ public void testReadActiveNotDeletedByThumbprintNotExisting() throws Exception @Test public void testReadActiveNotDeletedByThumbprintNull() throws Exception { - Optional<Organization> read = ttpDao.readActiveNotDeletedByThumbprint(null); + Optional<Organization> read = dao.readActiveNotDeletedByThumbprint(null); assertNotNull(read); assertTrue(read.isEmpty()); } @@ -154,7 +152,7 @@ public void testReadActiveNotDeletedByThumbprintNull() throws Exception @Test public void testReadActiveNotDeletedByThumbprintBlank() throws Exception { - Optional<Organization> read = ttpDao.readActiveNotDeletedByThumbprint(" "); + Optional<Organization> read = dao.readActiveNotDeletedByThumbprint(" "); assertNotNull(read); assertTrue(read.isEmpty()); } diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PatientDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PatientDaoTest.java index b72a10d9a..e7271444b 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PatientDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PatientDaoTest.java @@ -6,7 +6,6 @@ import java.util.GregorianCalendar; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.PatientDaoJdbc; import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender; import org.hl7.fhir.r4.model.Patient; @@ -24,10 +23,9 @@ public PatientDaoTest() } @Override - protected PatientDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected PatientDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new PatientDaoJdbc(dataSource, fhirContext, organizationType); + return new PatientDaoJdbc(dataSource, fhirContext); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PractitionerDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PractitionerDaoTest.java index 12b8b5c80..3edbda4c0 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PractitionerDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PractitionerDaoTest.java @@ -6,7 +6,6 @@ import java.util.GregorianCalendar; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.PractitionerDaoJdbc; import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender; import org.hl7.fhir.r4.model.Practitioner; @@ -24,10 +23,9 @@ public PractitionerDaoTest() } @Override - protected PractitionerDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected PractitionerDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new PractitionerDaoJdbc(dataSource, fhirContext, organizationType); + return new PractitionerDaoJdbc(dataSource, fhirContext); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PractitionerRoleDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PractitionerRoleDaoTest.java index 51a4d1d05..855b07d01 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PractitionerRoleDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/PractitionerRoleDaoTest.java @@ -6,7 +6,6 @@ import java.util.GregorianCalendar; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.PractitionerRoleDaoJdbc; import org.hl7.fhir.r4.model.Period; import org.hl7.fhir.r4.model.PractitionerRole; @@ -25,10 +24,9 @@ public PractitionerRoleDaoTest() } @Override - protected PractitionerRoleDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected PractitionerRoleDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new PractitionerRoleDaoJdbc(dataSource, fhirContext, organizationType); + return new PractitionerRoleDaoJdbc(dataSource, fhirContext); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ProvenanceDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ProvenanceDaoTest.java index 0c0a807a0..464910b07 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ProvenanceDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ProvenanceDaoTest.java @@ -9,7 +9,6 @@ import java.util.GregorianCalendar; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.ProvenanceDaoJdbc; import org.hl7.fhir.r4.model.Provenance; import org.hl7.fhir.r4.model.Signature; @@ -27,10 +26,9 @@ public ProvenanceDaoTest() } @Override - protected ProvenanceDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected ProvenanceDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new ProvenanceDaoJdbc(dataSource, fhirContext, organizationType); + return new ProvenanceDaoJdbc(dataSource, fhirContext); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ResearchStudyDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ResearchStudyDaoTest.java index a4c2b1646..6a8ca974a 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ResearchStudyDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ResearchStudyDaoTest.java @@ -6,7 +6,6 @@ import java.util.GregorianCalendar; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.ResearchStudyDaoJdbc; import org.hl7.fhir.r4.model.Period; import org.hl7.fhir.r4.model.ResearchStudy; @@ -25,10 +24,9 @@ public ResearchStudyDaoTest() } @Override - protected ResearchStudyDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected ResearchStudyDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new ResearchStudyDaoJdbc(dataSource, fhirContext, organizationType); + return new ResearchStudyDaoJdbc(dataSource, fhirContext); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/StructureDefinitionDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/StructureDefinitionDaoTest.java index 249e7b3f0..7336dffb7 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/StructureDefinitionDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/StructureDefinitionDaoTest.java @@ -3,7 +3,6 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.StructureDefinitionDaoJdbc; import org.hl7.fhir.r4.model.StructureDefinition; @@ -20,10 +19,9 @@ public StructureDefinitionDaoTest() } @Override - protected StructureDefinitionDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected StructureDefinitionDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new StructureDefinitionDaoJdbc(dataSource, fhirContext, organizationType); + return new StructureDefinitionDaoJdbc(dataSource, fhirContext); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/StructureDefinitionSnapshotDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/StructureDefinitionSnapshotDaoTest.java index 00eace7a9..5e9793228 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/StructureDefinitionSnapshotDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/StructureDefinitionSnapshotDaoTest.java @@ -3,7 +3,6 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.converter.SnapshotInfoConverter; import org.highmed.dsf.fhir.dao.jdbc.StructureDefinitionSnapshotDaoJdbc; import org.highmed.dsf.fhir.spring.config.JsonConfig; @@ -27,11 +26,9 @@ public StructureDefinitionSnapshotDaoTest() } @Override - protected StructureDefinitionSnapshotDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected StructureDefinitionSnapshotDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new StructureDefinitionSnapshotDaoJdbc(dataSource, fhirContext, organizationType, - new SnapshotInfoConverter(objectMapper)); + return new StructureDefinitionSnapshotDaoJdbc(dataSource, fhirContext, new SnapshotInfoConverter(objectMapper)); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/SubscriptionDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/SubscriptionDaoTest.java index 2f2d38c76..f54001c38 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/SubscriptionDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/SubscriptionDaoTest.java @@ -3,7 +3,6 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.SubscriptionDaoJdbc; import org.hl7.fhir.r4.model.Subscription; import org.hl7.fhir.r4.model.Subscription.SubscriptionStatus; @@ -21,10 +20,9 @@ public SubscriptionDaoTest() } @Override - protected SubscriptionDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected SubscriptionDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new SubscriptionDaoJdbc(dataSource, fhirContext, organizationType); + return new SubscriptionDaoJdbc(dataSource, fhirContext); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/TaskDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/TaskDaoTest.java index ae3f8499d..d9ac33820 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/TaskDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/TaskDaoTest.java @@ -3,7 +3,6 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.TaskDaoJdbc; import org.hl7.fhir.r4.model.Task; import org.hl7.fhir.r4.model.Task.TaskStatus; @@ -21,9 +20,9 @@ public TaskDaoTest() } @Override - protected TaskDao createDao(BasicDataSource dataSource, FhirContext fhirContext, OrganizationType organizationType) + protected TaskDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new TaskDaoJdbc(dataSource, fhirContext, organizationType); + return new TaskDaoJdbc(dataSource, fhirContext); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ValueSetDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ValueSetDaoTest.java index d53f379fe..ceafc4e5c 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ValueSetDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ValueSetDaoTest.java @@ -3,7 +3,6 @@ import static org.junit.Assert.assertEquals; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.ValueSetDaoJdbc; import org.hl7.fhir.r4.model.ValueSet; @@ -20,10 +19,9 @@ public ValueSetDaoTest() } @Override - protected ValueSetDao createDao(BasicDataSource dataSource, FhirContext fhirContext, - OrganizationType organizationType) + protected ValueSetDao createDao(BasicDataSource dataSource, FhirContext fhirContext) { - return new ValueSetDaoJdbc(dataSource, fhirContext, organizationType); + return new ValueSetDaoJdbc(dataSource, fhirContext); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/service/SnapshotDependencyAnalyzerTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/service/SnapshotDependencyAnalyzerTest.java index febe84dbf..f9bf970de 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/service/SnapshotDependencyAnalyzerTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/service/SnapshotDependencyAnalyzerTest.java @@ -5,6 +5,9 @@ import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import org.hl7.fhir.r4.model.StructureDefinition; import org.junit.Test; @@ -23,10 +26,14 @@ public void testAnalyze() throws Exception FhirContext context = FhirContext.forR4(); StructureDefinition patientDeBasis; - try (InputStream in = Files.newInputStream(Paths.get("src/test/resources/profiles/patient-de-basis-0.2.xml"))) + try (InputStream in = Files + .newInputStream(Paths.get("src/test/resources/profiles/DeBasis/patient-de-basis-0.2.1.xml"))) { patientDeBasis = context.newXmlParser().parseResource(StructureDefinition.class, in); } + SnapshotGenerator generator = new SnapshotGeneratorImpl(context, + new DefaultProfileValidationSupportWithCustomResources()); + patientDeBasis = generator.generateSnapshot(patientDeBasis).getSnapshot(); SnapshotDependencyAnalyzer analyzer = new SnapshotDependencyAnalyzer(); SnapshotDependencies dependencies = analyzer.analyzeSnapshotDependencies(patientDeBasis); @@ -34,5 +41,23 @@ public void testAnalyze() throws Exception assertNotNull(dependencies); logger.debug("Profiles: {}", dependencies.getProfiles()); logger.debug("TargetProfiles: {}", dependencies.getTargetProfiles()); + + assertEquals(2, dependencies.getProfiles().size()); + assertEquals(sorted(Arrays.asList("http://fhir.de/StructureDefinition/address-de-basis", + "http://fhir.de/StructureDefinition/humanname-de-basis")), sorted(dependencies.getProfiles())); + assertEquals( + sorted(Arrays.asList("http://fhir.de/StructureDefinition/organization-de-basis", + "http://fhir.de/StructureDefinition/practitioner-de-basis", + "http://hl7.org/fhir/StructureDefinition/Organization", + "http://hl7.org/fhir/StructureDefinition/Patient", + "http://hl7.org/fhir/StructureDefinition/RelatedPerson")), + sorted(dependencies.getTargetProfiles())); + } + + private List<String> sorted(List<String> list) + { + list = new ArrayList<>(list); + list.sort(String::compareTo); + return list; } } diff --git a/dsf-fhir/dsf-fhir-server/src/test/resources/integration/config.properties b/dsf-fhir/dsf-fhir-server/src/test/resources/integration/config.properties index 80a236e55..820edc703 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/resources/integration/config.properties +++ b/dsf-fhir/dsf-fhir-server/src/test/resources/integration/config.properties @@ -8,6 +8,7 @@ org.highmed.dsf.fhir.serverBase=https://localhost:8001/fhir org.highmed.dsf.fhir.defaultPageCount=20 org.highmed.dsf.fhir.local-user.thumbprints= +org.highmed.dsf.fhir.local-organization.identifier=Test_Organization org.highmed.dsf.fhir.init.bundle.file= diff --git a/pom.xml b/pom.xml index cac644a45..bba6b784c 100755 --- a/pom.xml +++ b/pom.xml @@ -27,7 +27,7 @@ <tyrus.version>1.15</tyrus.version> <spring.version>5.2.3.RELEASE</spring.version> - <hapi.version>4.1.0</hapi.version> + <hapi.version>4.2.0</hapi.version> </properties> <name>highmed-dsf</name> @@ -130,7 +130,7 @@ <dependency> <groupId>de.hs-heilbronn.mi</groupId> <artifactId>db-test-utils</artifactId> - <version>0.5.0</version> + <version>0.6.0</version> </dependency> <dependency> From 6ae3dbf4d9416556a0e863c0252ea77302d6e79f Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Wed, 26 Feb 2020 15:21:26 +0100 Subject: [PATCH 12/55] work on authorization rules, include/revinclude filter during search --- .../AuthorizationRuleProvider.java | 6 +-- .../AuthorizationRuleProviderImpl.java | 13 +++-- .../EndpointAuthorizationRule.java | 20 +++++++- .../OrganizationAuthorizationRule.java | 23 +++++++-- .../org/highmed/dsf/fhir/dao/ResourceDao.java | 2 +- .../dao/jdbc/AbstractResourceDaoJdbc.java | 2 + .../spring/config/AuthorizationConfig.java | 14 +++++ .../fhir/spring/config/WebserviceConfig.java | 51 +++++++++++-------- .../impl/AbstractResourceServiceImpl.java | 44 +++++++++++++++- .../impl/ActivityDefinitionServiceImpl.java | 5 +- .../webservice/impl/BinaryServiceImpl.java | 7 ++- .../webservice/impl/BundleServiceImpl.java | 7 ++- .../impl/CodeSystemServiceImpl.java | 7 ++- .../webservice/impl/EndpointServiceImpl.java | 7 ++- .../webservice/impl/GroupServiceImpl.java | 7 ++- .../impl/HealthcareServiceServiceImpl.java | 6 ++- .../webservice/impl/LocationServiceImpl.java | 7 ++- .../impl/NamingSystemServiceImpl.java | 7 ++- .../impl/OrganizationServiceImpl.java | 7 ++- .../webservice/impl/PatientServiceImpl.java | 7 ++- .../impl/PractitionerRoleServiceImpl.java | 6 ++- .../impl/PractitionerServiceImpl.java | 6 ++- .../impl/ProvenanceServiceImpl.java | 7 ++- .../impl/ResearchStudyServiceImpl.java | 7 ++- .../impl/StructureDefinitionServiceImpl.java | 10 ++-- .../impl/SubscriptionServiceImpl.java | 7 ++- .../fhir/webservice/impl/TaskServiceImpl.java | 7 ++- .../webservice/impl/ValueSetServiceImpl.java | 7 ++- .../secure/AbstractResourceServiceSecure.java | 2 +- 29 files changed, 227 insertions(+), 81 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProvider.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProvider.java index be1c95114..d966d7525 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProvider.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProvider.java @@ -2,8 +2,6 @@ import java.util.Optional; -import org.hl7.fhir.r4.model.Resource; - public interface AuthorizationRuleProvider { ActivityDefinitionAuthorizationRule getActivityDefinitionAuthorizationRule(); @@ -32,7 +30,7 @@ public interface AuthorizationRuleProvider PractitionerRoleAuthorizationRule getPractitionerRoleAuthorizationRule(); - ProvenanceAuthorizationRule getpProvenanceAuthorizationRule(); + ProvenanceAuthorizationRule getProvenanceAuthorizationRule(); ResearchStudyAuthorizationRule getResearchStudyAuthorizationRule(); @@ -44,7 +42,7 @@ public interface AuthorizationRuleProvider ValueSetAuthorizationRule getValueSetAuthorizationRule(); - <R extends Resource> Optional<? extends AuthorizationRule<R>> getAuthorizationRule(Class<R> resourceClass); + Optional<AuthorizationRule<?>> getAuthorizationRule(Class<?> resourceClass); Optional<AuthorizationRule<?>> getAuthorizationRule(String resourceTypeName); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProviderImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProviderImpl.java index e86da5097..4af4770e5 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProviderImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRuleProviderImpl.java @@ -88,7 +88,7 @@ public AuthorizationRuleProviderImpl(ActivityDefinitionAuthorizationRule activit this.subscriptionAuthorizationRule = subscriptionAuthorizationRule; this.taskAuthorizationRule = taskAuthorizationRule; this.valueSetAuthorizationRule = valueSetAuthorizationRule; - + authorizationRulesByResourecClass.put(ActivityDefinition.class, activityDefinitionAuthorizationRule); authorizationRulesByResourecClass.put(Binary.class, binaryAuthorizationRule); authorizationRulesByResourecClass.put(Bundle.class, bundleAuthorizationRule); @@ -109,7 +109,8 @@ public AuthorizationRuleProviderImpl(ActivityDefinitionAuthorizationRule activit authorizationRulesByResourecClass.put(Task.class, taskAuthorizationRule); authorizationRulesByResourecClass.put(ValueSet.class, valueSetAuthorizationRule); - authorizationRulesByResourecClass.forEach((k, v) -> authorizationRulesByResourceTypeName.put(k.getAnnotation(ResourceDef.class).name(), v)); + authorizationRulesByResourecClass.forEach( + (k, v) -> authorizationRulesByResourceTypeName.put(k.getAnnotation(ResourceDef.class).name(), v)); } @Override @@ -191,7 +192,7 @@ public PractitionerRoleAuthorizationRule getPractitionerRoleAuthorizationRule() } @Override - public ProvenanceAuthorizationRule getpProvenanceAuthorizationRule() + public ProvenanceAuthorizationRule getProvenanceAuthorizationRule() { return provenanceAuthorizationRule; } @@ -227,11 +228,9 @@ public ValueSetAuthorizationRule getValueSetAuthorizationRule() } @Override - public <R extends Resource> Optional<? extends AuthorizationRule<R>> getAuthorizationRule(Class<R> resourceClass) + public Optional<AuthorizationRule<?>> getAuthorizationRule(Class<?> resourceClass) { - @SuppressWarnings("unchecked") - AuthorizationRule<R> authorizationRule = (AuthorizationRule<R>) authorizationRulesByResourecClass - .get(resourceClass); + AuthorizationRule<?> authorizationRule = authorizationRulesByResourecClass.get(resourceClass); return Optional.ofNullable(authorizationRule); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java index aa8a1dd35..a0f1e0524 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java @@ -30,8 +30,24 @@ public Optional<String> reasonCreateAllowed(User user, Endpoint newResource) @Override public Optional<String> reasonReadAllowed(User user, Endpoint existingResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user) && hasLocalOrRemoteAuthorizationRole(existingResource)) + { + logger.info( + "Read of Endpoint authorized for local user '{}', Endpoint has local or remote authorization role", + user.getName()); + return Optional.of("local user, local or remote authorized Endpoint"); + } + else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) + { + logger.info("Read of Endpoint authorized for remote user '{}', Endpoint has remote authorization role", + user.getName()); + return Optional.of("remote user, remote authorized Endpoint"); + } + else + { + logger.warn("Read of Endpoint unauthorized, no matching user role resource authorization role found"); + return Optional.empty(); + } } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java index 1f1d3bbf5..afff0c253 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java @@ -34,10 +34,25 @@ public Optional<String> reasonCreateAllowed(User user, Organization newResource) @Override public Optional<String> reasonReadAllowed(User user, Organization existingResource) { - // see create, no two organizations can have the same certificate thumb-print - - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user) && hasLocalOrRemoteAuthorizationRole(existingResource)) + { + logger.info( + "Read of Organization authorized for local user '{}', Organization has local or remote authorization role", + user.getName()); + return Optional.of("local user, local or remote authorized Organization"); + } + else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) + { + logger.info( + "Read of Organization authorized for remote user '{}', Organization has remote authorization role", + user.getName()); + return Optional.of("remote user, remote authorized Organization"); + } + else + { + logger.warn("Read of Organization unauthorized, no matching user role resource authorization role found"); + return Optional.empty(); + } } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResourceDao.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResourceDao.java index 453f8b6c0..4c2c80bb7 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResourceDao.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResourceDao.java @@ -25,7 +25,7 @@ public interface ResourceDao<R extends Resource> Class<R> getResourceType(); Connection newReadWriteTransaction() throws SQLException; - + /** * @param resource * not <code>null</code> diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java index 6fdfb4c0f..f383e2d08 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java @@ -169,6 +169,7 @@ public void afterPropertiesSet() throws Exception Objects.requireNonNull(resourceColumn, "resourceColumn"); Objects.requireNonNull(resourceIdColumn, "resourceIdColumn"); Objects.requireNonNull(preparedStatementFactory, "preparedStatementFactory"); + Objects.requireNonNull(userFilter, "userFilter"); } protected DataSource getDataSource() @@ -831,6 +832,7 @@ public PartialResult<R> searchWithTransaction(Connection connection, DbSearchQue } } + // needs to be filtered by read rules, before returning to user, see rest access layer includes = includes.stream().map(r -> new ResourceDistinctById(r.getIdElement(), r)).distinct() .map(ResourceDistinctById::getResource).collect(Collectors.toList()); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthorizationConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthorizationConfig.java index 9324270cd..1a5f7ed03 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthorizationConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthorizationConfig.java @@ -1,6 +1,8 @@ package org.highmed.dsf.fhir.spring.config; import org.highmed.dsf.fhir.authorization.ActivityDefinitionAuthorizationRule; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProviderImpl; import org.highmed.dsf.fhir.authorization.BinaryAuthorizationRule; import org.highmed.dsf.fhir.authorization.BundleAuthorizationRule; import org.highmed.dsf.fhir.authorization.CodeSystemAuthorizationRule; @@ -160,4 +162,16 @@ public ValueSetAuthorizationRule valueSetAuthorizationRule() { return new ValueSetAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); } + + @Bean + public AuthorizationRuleProvider authorizationRuleProvider() + { + return new AuthorizationRuleProviderImpl(activityDefinitionAuthorizationRule(), binaryAuthorizationRule(), + bundleAuthorizationRule(), codeSystemAuthorizationRule(), endpointAuthorizationRule(), + groupAuthorizationRule(), healthcareServiceAuthorizationRule(), locationAuthorizationRule(), + namingSystemAuthorizationRule(), organizationAuthorizationRule(), patientAuthorizationRule(), + practitionerAuthorizationRule(), practitionerRoleAuthorizationRule(), provenanceAuthorizationRule(), + researchStudyAuthorizationRule(), structureDefinitionAuthorizationRule(), + subscriptionAuthorizationRule(), taskAuthorizationRule(), valueSetAuthorizationRule()); + } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java index 71aaa1ce5..0704ee5e7 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java @@ -156,7 +156,7 @@ private ActivityDefinitionServiceImpl activityDefinitionServiceImpl() daoConfig.activityDefinitionDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), authorizationConfig.authorizationRuleProvider()); } @Bean @@ -178,7 +178,7 @@ private CodeSystemServiceImpl codeSystemServiceImpl() daoConfig.codeSystemDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), authorizationConfig.authorizationRuleProvider()); } @Bean @@ -199,7 +199,8 @@ private BinaryService binaryServiceImpl() return new BinaryServiceImpl(BinaryServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.binaryDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), - referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver(), + authorizationConfig.authorizationRuleProvider()); } @Bean @@ -220,7 +221,8 @@ private BundleService bundleServiceImpl() return new BundleServiceImpl(BundleServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.bundleDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), - referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver(), + authorizationConfig.authorizationRuleProvider()); } @Bean @@ -241,7 +243,8 @@ private EndpointServiceImpl endpointServiceImpl() return new EndpointServiceImpl(EndpointServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.endpointDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), - referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver(), + authorizationConfig.authorizationRuleProvider()); } @Bean @@ -262,7 +265,8 @@ private GroupServiceImpl groupServiceImpl() return new GroupServiceImpl(GroupServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.groupDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), - referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver(), + authorizationConfig.authorizationRuleProvider()); } @Bean @@ -285,7 +289,7 @@ private HealthcareServiceServiceImpl healthcareServiceServiceImpl() daoConfig.healthcareServiceDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), authorizationConfig.authorizationRuleProvider()); } @Bean @@ -306,7 +310,8 @@ private LocationServiceImpl locationServiceImpl() return new LocationServiceImpl(LocationServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.locationDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), - referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver(), + authorizationConfig.authorizationRuleProvider()); } @Bean @@ -328,7 +333,7 @@ private NamingSystemService namingSystemServiceImpl() daoConfig.namingSystemDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), authorizationConfig.authorizationRuleProvider()); } @Bean @@ -350,7 +355,7 @@ private OrganizationServiceImpl organizationServiceImpl() daoConfig.organizationDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), authorizationConfig.authorizationRuleProvider()); } @Bean @@ -371,7 +376,8 @@ private PatientServiceImpl patientServiceImpl() return new PatientServiceImpl(PatientServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.patientDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), - referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver(), + authorizationConfig.authorizationRuleProvider()); } @Bean @@ -394,7 +400,7 @@ private PractitionerRoleServiceImpl practitionerRoleServiceImpl() daoConfig.practitionerRoleDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), authorizationConfig.authorizationRuleProvider()); } @Bean @@ -416,7 +422,7 @@ private PractitionerServiceImpl practitionerServiceImpl() daoConfig.practitionerDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), authorizationConfig.authorizationRuleProvider()); } @Bean @@ -438,7 +444,7 @@ private ProvenanceServiceImpl provenanceServiceImpl() daoConfig.provenanceDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), authorizationConfig.authorizationRuleProvider()); } @Bean @@ -460,7 +466,7 @@ private ResearchStudyServiceImpl researchStudyServiceImpl() daoConfig.researchStudyDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), authorizationConfig.authorizationRuleProvider()); } @Bean @@ -482,9 +488,10 @@ private StructureDefinitionServiceImpl structureDefinitionServiceImpl() return new StructureDefinitionServiceImpl(StructureDefinitionServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.structureDefinitionDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), - helperConfig.parameterConverter(), daoConfig.structureDefinitionSnapshotDao(), - snapshotConfig.snapshotGenerator(), snapshotConfig.snapshotDependencyAnalyzer(), - referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); + helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), + referenceConfig.referenceResolver(), authorizationConfig.authorizationRuleProvider(), + daoConfig.structureDefinitionSnapshotDao(), snapshotConfig.snapshotGenerator(), + snapshotConfig.snapshotDependencyAnalyzer()); } @Bean @@ -506,7 +513,7 @@ private SubscriptionServiceImpl subscriptionServiceImpl() daoConfig.subscriptionDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), referenceConfig.referenceExtractor(), - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), authorizationConfig.authorizationRuleProvider()); } @Bean @@ -527,7 +534,8 @@ private TaskServiceImpl taskServiceImpl() return new TaskServiceImpl(TaskServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.taskDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), - referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver(), + authorizationConfig.authorizationRuleProvider()); } @Bean @@ -548,7 +556,8 @@ private ValueSetServiceImpl valueSetServiceImpl() return new ValueSetServiceImpl(ValueSetServiceJaxrs.PATH, serverBase, defaultPageCount, daoConfig.valueSetDao(), validationConfig.resourceValidator(), eventConfig.eventManager(), helperConfig.exceptionHandler(), eventConfig.eventGenerator(), helperConfig.responseGenerator(), helperConfig.parameterConverter(), - referenceConfig.referenceExtractor(), referenceConfig.referenceResolver()); + referenceConfig.referenceExtractor(), referenceConfig.referenceResolver(), + authorizationConfig.authorizationRuleProvider()); } @Bean diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java index 194a86f0c..dbf1868e3 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java @@ -28,6 +28,8 @@ import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; +import org.highmed.dsf.fhir.authorization.AuthorizationRule; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.ResourceDao; import org.highmed.dsf.fhir.dao.exception.ResourceNotFoundException; import org.highmed.dsf.fhir.event.EventGenerator; @@ -89,11 +91,13 @@ public abstract class AbstractResourceServiceImpl<D extends ResourceDao<R>, R ex protected final ParameterConverter parameterConverter; protected final ReferenceExtractor referenceExtractor; protected final ReferenceResolver referenceResolver; + protected final AuthorizationRuleProvider authorizationRuleProvider; public AbstractResourceServiceImpl(String path, Class<R> resourceType, String serverBase, int defaultPageCount, D dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path); @@ -110,6 +114,7 @@ public AbstractResourceServiceImpl(String path, Class<R> resourceType, String se this.parameterConverter = parameterConverter; this.referenceExtractor = referenceExtractor; this.referenceResolver = referenceResolver; + this.authorizationRuleProvider = authorizationRuleProvider; } public void afterPropertiesSet() throws Exception @@ -129,6 +134,7 @@ public void afterPropertiesSet() throws Exception Objects.requireNonNull(parameterConverter, "parameterConverter"); Objects.requireNonNull(referenceExtractor, "referenceExtractor"); Objects.requireNonNull(referenceResolver, "referenceResolver"); + Objects.requireNonNull(authorizationRuleProvider, "authorizationRuleProvider"); } @Override @@ -612,6 +618,8 @@ public Response search(UriInfo uri, HttpHeaders headers) PartialResult<R> result = exceptionHandler.handleSqlException(() -> dao.search(query)); + result = filterIncludeResources(result); + UriBuilder bundleUri = query.configureBundleUri(UriBuilder.fromPath(serverBase).path(getPath())); String format = queryParameters.getFirst(SearchQuery.PARAMETER_FORMAT); @@ -621,6 +629,40 @@ public Response search(UriInfo uri, HttpHeaders headers) return responseGenerator.response(Status.OK, searchSet, parameterConverter.getMediaType(uri, headers)).build(); } + private PartialResult<R> filterIncludeResources(PartialResult<R> result) + { + List<Resource> includes = filterIncludeResources(result.getIncludes()); + return new PartialResult<R>(result.getOverallCount(), result.getPageAndCount(), result.getPartialResult(), + includes, result.isCountOnly()); + } + + private List<Resource> filterIncludeResources(List<Resource> includes) + { + return includes.stream().filter(this::filterIncludeResource).collect(Collectors.toList()); + } + + @SuppressWarnings("unchecked") + private boolean filterIncludeResource(Resource include) + { + Optional<AuthorizationRule<? extends Resource>> optRule = authorizationRuleProvider + .getAuthorizationRule(include.getClass()); + + return optRule.map(rule -> (AuthorizationRule<Resource>) rule) + .flatMap(rule -> rule.reasonReadAllowed(getCurrentUser(), include)).map(reason -> + { + logger.debug("Include resource of type {} with id {}, allowed - {}", + include.getClass().getAnnotation(ResourceDef.class).name(), + include.getIdElement().getValue(), reason); + return true; + }).orElseGet(() -> + { + logger.debug("Include resource of type {} with id {}, filtered (read not allowed)", + include.getClass().getAnnotation(ResourceDef.class).name(), + include.getIdElement().getValue()); + return false; + }); + } + private Optional<Resource> getResource(Parameters parameters, String parameterName) { return parameters.getParameter().stream().filter(p -> parameterName.equals(p.getName())).findFirst() diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ActivityDefinitionServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ActivityDefinitionServiceImpl.java index 231800049..8daaae460 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ActivityDefinitionServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ActivityDefinitionServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -19,10 +20,10 @@ public ActivityDefinitionServiceImpl(String path, String serverBase, int default ActivityDefinitionDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, ReferenceExtractor referenceExtractor, - ReferenceResolver referenceResolver) + ReferenceResolver referenceResolver, AuthorizationRuleProvider authorizationRuleProvider) { super(path, ActivityDefinition.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, eventGenerator, responseGenerator, parameterConverter, referenceExtractor, - referenceResolver); + referenceResolver, authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/BinaryServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/BinaryServiceImpl.java index 179eed3af..0bbcaafc1 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/BinaryServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/BinaryServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.BinaryDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -17,9 +18,11 @@ public class BinaryServiceImpl extends AbstractResourceServiceImpl<BinaryDao, Bi public BinaryServiceImpl(String path, String serverBase, int defaultPageCount, BinaryDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path, Binary.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, - eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver); + eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver, + authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/BundleServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/BundleServiceImpl.java index 7517feae0..d5615d8be 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/BundleServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/BundleServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.BundleDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -17,9 +18,11 @@ public class BundleServiceImpl extends AbstractResourceServiceImpl<BundleDao, Bu public BundleServiceImpl(String path, String serverBase, int defaultPageCount, BundleDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path, Bundle.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, - eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver); + eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver, + authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/CodeSystemServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/CodeSystemServiceImpl.java index 264919645..ac068a160 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/CodeSystemServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/CodeSystemServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.CodeSystemDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -18,9 +19,11 @@ public class CodeSystemServiceImpl extends AbstractResourceServiceImpl<CodeSyste public CodeSystemServiceImpl(String path, String serverBase, int defaultPageCount, CodeSystemDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path, CodeSystem.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, - eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver); + eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver, + authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/EndpointServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/EndpointServiceImpl.java index 6ddd8479f..5993c6211 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/EndpointServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/EndpointServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.EndpointDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -17,9 +18,11 @@ public class EndpointServiceImpl extends AbstractResourceServiceImpl<EndpointDao public EndpointServiceImpl(String path, String serverBase, int defaultPageCount, EndpointDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path, Endpoint.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, - eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver); + eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver, + authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/GroupServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/GroupServiceImpl.java index 4b0c4ff99..cd40e00f2 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/GroupServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/GroupServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.GroupDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -17,9 +18,11 @@ public class GroupServiceImpl extends AbstractResourceServiceImpl<GroupDao, Grou public GroupServiceImpl(String path, String serverBase, int defaultPageCount, GroupDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path, Group.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, - eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver); + eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver, + authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/HealthcareServiceServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/HealthcareServiceServiceImpl.java index bd479ee5d..b57990e93 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/HealthcareServiceServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/HealthcareServiceServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.HealthcareServiceDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -18,10 +19,11 @@ public class HealthcareServiceServiceImpl extends AbstractResourceServiceImpl<He public HealthcareServiceServiceImpl(String path, String serverBase, int defaultPageCount, HealthcareServiceDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path, HealthcareService.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, eventGenerator, responseGenerator, parameterConverter, referenceExtractor, - referenceResolver); + referenceResolver, authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/LocationServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/LocationServiceImpl.java index 91725fec1..5a25c8b45 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/LocationServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/LocationServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.LocationDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -17,9 +18,11 @@ public class LocationServiceImpl extends AbstractResourceServiceImpl<LocationDao public LocationServiceImpl(String path, String serverBase, int defaultPageCount, LocationDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path, Location.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, - eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver); + eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver, + authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/NamingSystemServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/NamingSystemServiceImpl.java index 1428a3037..8ac640087 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/NamingSystemServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/NamingSystemServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.NamingSystemDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -18,9 +19,11 @@ public class NamingSystemServiceImpl extends AbstractResourceServiceImpl<NamingS public NamingSystemServiceImpl(String path, String serverBase, int defaultPageCount, NamingSystemDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path, NamingSystem.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, - eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver); + eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver, + authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/OrganizationServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/OrganizationServiceImpl.java index a62b955a3..58dc4fae9 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/OrganizationServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/OrganizationServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.OrganizationDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -18,9 +19,11 @@ public class OrganizationServiceImpl extends AbstractResourceServiceImpl<Organiz public OrganizationServiceImpl(String path, String serverBase, int defaultPageCount, OrganizationDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path, Organization.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, - eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver); + eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver, + authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/PatientServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/PatientServiceImpl.java index 15700b661..058821feb 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/PatientServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/PatientServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.PatientDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -17,9 +18,11 @@ public class PatientServiceImpl extends AbstractResourceServiceImpl<PatientDao, public PatientServiceImpl(String path, String serverBase, int defaultPageCount, PatientDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path, Patient.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, - eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver); + eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver, + authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/PractitionerRoleServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/PractitionerRoleServiceImpl.java index aafdf31a0..7292c311f 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/PractitionerRoleServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/PractitionerRoleServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.PractitionerRoleDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -18,10 +19,11 @@ public class PractitionerRoleServiceImpl extends AbstractResourceServiceImpl<Pra public PractitionerRoleServiceImpl(String path, String serverBase, int defaultPageCount, PractitionerRoleDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path, PractitionerRole.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, eventGenerator, responseGenerator, parameterConverter, referenceExtractor, - referenceResolver); + referenceResolver, authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/PractitionerServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/PractitionerServiceImpl.java index 9153f5680..222420b1e 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/PractitionerServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/PractitionerServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.PractitionerDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -18,9 +19,10 @@ public class PractitionerServiceImpl extends AbstractResourceServiceImpl<Practit public PractitionerServiceImpl(String path, String serverBase, int defaultPageCount, PractitionerDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, AuthorizationRuleProvider authorizationRuleProvider) { super(path, Practitioner.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, - eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver); + eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver, + authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ProvenanceServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ProvenanceServiceImpl.java index c4956a6dd..bab91529d 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ProvenanceServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ProvenanceServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.ProvenanceDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -18,9 +19,11 @@ public class ProvenanceServiceImpl extends AbstractResourceServiceImpl<Provenanc public ProvenanceServiceImpl(String path, String serverBase, int defaultPageCount, ProvenanceDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path, Provenance.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, - eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver); + eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver, + authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ResearchStudyServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ResearchStudyServiceImpl.java index fa4d55634..9096b39d8 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ResearchStudyServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ResearchStudyServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.ResearchStudyDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -18,9 +19,11 @@ public class ResearchStudyServiceImpl extends AbstractResourceServiceImpl<Resear public ResearchStudyServiceImpl(String path, String serverBase, int defaultPageCount, ResearchStudyDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path, ResearchStudy.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, - eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver); + eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver, + authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/StructureDefinitionServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/StructureDefinitionServiceImpl.java index ecd8faff6..5bf294dc7 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/StructureDefinitionServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/StructureDefinitionServiceImpl.java @@ -15,6 +15,7 @@ import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriInfo; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.StructureDefinitionDao; import org.highmed.dsf.fhir.dao.StructureDefinitionSnapshotDao; import org.highmed.dsf.fhir.event.EventGenerator; @@ -62,13 +63,14 @@ public class StructureDefinitionServiceImpl extends public StructureDefinitionServiceImpl(String path, String serverBase, int defaultPageCount, StructureDefinitionDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, - ParameterConverter parameterConverter, StructureDefinitionSnapshotDao structureDefinitionSnapshotDao, - SnapshotGenerator sanapshotGenerator, SnapshotDependencyAnalyzer snapshotDependencyAnalyzer, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ParameterConverter parameterConverter, ReferenceExtractor referenceExtractor, + ReferenceResolver referenceResolver, AuthorizationRuleProvider authorizationRuleProvider, + StructureDefinitionSnapshotDao structureDefinitionSnapshotDao, SnapshotGenerator sanapshotGenerator, + SnapshotDependencyAnalyzer snapshotDependencyAnalyzer) { super(path, StructureDefinition.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, eventGenerator, responseGenerator, parameterConverter, referenceExtractor, - referenceResolver); + referenceResolver, authorizationRuleProvider); this.snapshotDao = structureDefinitionSnapshotDao; this.snapshotGenerator = sanapshotGenerator; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/SubscriptionServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/SubscriptionServiceImpl.java index fdad5b07a..321e53c21 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/SubscriptionServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/SubscriptionServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.SubscriptionDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -18,9 +19,11 @@ public class SubscriptionServiceImpl extends AbstractResourceServiceImpl<Subscri public SubscriptionServiceImpl(String path, String serverBase, int defaultPageCount, SubscriptionDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path, Subscription.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, - eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver); + eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver, + authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/TaskServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/TaskServiceImpl.java index 292bbfe9b..5a8ffcf25 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/TaskServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/TaskServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.TaskDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -17,9 +18,11 @@ public class TaskServiceImpl extends AbstractResourceServiceImpl<TaskDao, Task> public TaskServiceImpl(String path, String serverBase, int defaultPageCount, TaskDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path, Task.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, - eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver); + eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver, + authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ValueSetServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ValueSetServiceImpl.java index d1b839a12..9692bc008 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ValueSetServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ValueSetServiceImpl.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.webservice.impl; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.ValueSetDao; import org.highmed.dsf.fhir.event.EventGenerator; import org.highmed.dsf.fhir.event.EventManager; @@ -17,9 +18,11 @@ public class ValueSetServiceImpl extends AbstractResourceServiceImpl<ValueSetDao public ValueSetServiceImpl(String path, String serverBase, int defaultPageCount, ValueSetDao dao, ResourceValidator validator, EventManager eventManager, ExceptionHandler exceptionHandler, EventGenerator eventGenerator, ResponseGenerator responseGenerator, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, + AuthorizationRuleProvider authorizationRuleProvider) { super(path, ValueSet.class, serverBase, defaultPageCount, dao, validator, eventManager, exceptionHandler, - eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver); + eventGenerator, responseGenerator, parameterConverter, referenceExtractor, referenceResolver, + authorizationRuleProvider); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java index 97ef6fe0a..ceaa91d1b 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java @@ -3,8 +3,8 @@ import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Map.Entry; +import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; From 266d08ccc70e4b9344cce7a9c3d36935781971f6 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Sun, 1 Mar 2020 20:41:35 +0100 Subject: [PATCH 13/55] work on authorization in handling of batch and transaction bundles --- .../AbstractAuthorizationRule.java | 88 +- .../ActivityDefinitionAuthorizationRule.java | 11 +- .../fhir/authorization/AuthorizationRule.java | 64 ++ .../BinaryAuthorizationRule.java | 23 +- .../BundleAuthorizationRule.java | 12 +- .../CodeSystemAuthorizationRule.java | 30 +- .../EndpointAuthorizationRule.java | 142 +++- .../authorization/GroupAuthorizationRule.java | 11 +- .../HealthcareServiceAuthorizationRule.java | 12 +- .../LocationAuthorizationRule.java | 12 +- .../NamingSystemAuthorizationRule.java | 128 ++- .../OrganizationAuthorizationRule.java | 151 +++- .../PatientAuthorizationRule.java | 12 +- .../PractitionerAuthorizationRule.java | 12 +- .../PractitionerRoleAuthorizationRule.java | 12 +- .../ProvenanceAuthorizationRule.java | 12 +- .../ResearchStudyAuthorizationRule.java | 12 +- .../StructureDefinitionAuthorizationRule.java | 63 +- .../SubscriptionAuthorizationRule.java | 150 +++- .../authorization/TaskAuthorizationRule.java | 11 +- .../ValueSetAuthorizationRule.java | 30 +- .../highmed/dsf/fhir/dao/NamingSystemDao.java | 7 + .../highmed/dsf/fhir/dao/OrganizationDao.java | 4 + .../dsf/fhir/dao/command/AbstractCommand.java | 10 +- .../command/AbstractCommandWithResource.java | 6 +- .../dao/command/AuthorizationCommand.java | 23 + .../command/AuthorizationCommandFactory.java | 22 + .../AuthorizationCommandFactoryImpl.java | 164 ++++ .../fhir/dao/command/BatchCommandList.java | 98 ++- .../highmed/dsf/fhir/dao/command/Command.java | 3 +- .../fhir/dao/command/CommandFactoryImpl.java | 67 +- .../dsf/fhir/dao/command/CreateCommand.java | 38 +- .../CreateStructureDefinitionCommand.java | 11 +- .../dsf/fhir/dao/command/DeleteCommand.java | 36 +- .../dsf/fhir/dao/command/ReadCommand.java | 84 +- .../dao/command/ResolveReferencesCommand.java | 11 +- .../dao/command/TransactionCommandList.java | 7 +- .../dsf/fhir/dao/command/UpdateCommand.java | 68 +- .../UpdateStructureDefinitionCommand.java | 11 +- .../fhir/dao/jdbc/NamingSystemDaoJdbc.java | 43 + .../fhir/dao/jdbc/OrganizationDaoJdbc.java | 34 + .../dsf/fhir/dao/provider/DaoProvider.java | 6 + .../fhir/dao/provider/DaoProviderImpl.java | 32 +- .../dsf/fhir/help/ResponseGenerator.java | 9 + .../search/parameters/EndpointAddress.java | 89 ++ .../basic/AbstractUrlAndVersionParameter.java | 1 - .../dsf/fhir/service/ReferenceResolver.java | 16 + .../fhir/service/ReferenceResolverImpl.java | 73 +- .../dsf/fhir/spring/config/CommandConfig.java | 15 +- .../dsf/fhir/spring/config/DaoConfig.java | 9 +- .../impl/AbstractResourceServiceImpl.java | 120 --- .../impl/ConformanceServiceImpl.java | 4 +- .../secure/AbstractResourceServiceSecure.java | 28 +- .../webservice/secure/RootServiceSecure.java | 24 +- .../highmed-endpoint-0.1.0.xml | 6 + ...extension-certificate-thumbprint-0.1.0.xml | 6 + .../highmed-extension-group-id-0.1.0.xml | 6 + ...ed-extension-participating-medic-0.1.0.xml | 6 + ...-extension-process-authorization-0.1.0.xml | 6 + .../highmed-extension-query-0.1.0.xml | 6 + .../highmed-group-0.1.0.xml | 6 + .../highmed-organization-0.1.0.xml | 6 + .../highmed-practitioner-0.1.0.xml | 6 + .../highmed-practitioner-role-0.1.0.xml | 6 + .../highmed-research-study-0.1.0.xml | 6 + .../highmed-task-base-0.1.0.xml | 6 + ...-task-compute-simple-feasibility-0.1.0.xml | 6 + ...-task-execute-simple-feasibility-0.1.0.xml | 6 + ...ed-task-execute-update-resources-0.1.0.xml | 6 + ...-medic-result-simple-feasibility-0.1.0.xml | 6 + .../highmed-task-parent-plugin-0.1.0.xml | 6 + .../highmed-task-ping-0.1.0.xml | 6 + .../highmed-task-pong-0.1.0.xml | 6 + ...-task-request-simple-feasibility-0.1.0.xml | 6 + ...ed-task-request-update-resources-0.1.0.xml | 6 + ...-medic-result-simple-feasibility-0.1.0.xml | 6 + .../highmed-task-start-process-0.1.0.xml | 6 + .../highmed-task-update-whitelist-0.1.0.xml | 6 + .../dsf/fhir/db/TransactionLearningTest.java | 177 ++++ .../integration/AbstractIntegrationTest.java | 4 +- .../integration/BinaryIntegrationTest.java | 801 +++++++++++++++++- .../resources/integration/test-bundle.xml | 6 +- .../src/test/resources/log4j2.xml | 9 +- 83 files changed, 2815 insertions(+), 497 deletions(-) create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommand.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommandFactory.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommandFactoryImpl.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointAddress.java create mode 100644 dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/db/TransactionLearningTest.java diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java index af75af301..39ae94f0e 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java @@ -1,5 +1,7 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; +import java.sql.SQLException; import java.util.Collection; import java.util.EnumSet; import java.util.Objects; @@ -52,6 +54,76 @@ public void afterPropertiesSet() throws Exception Objects.requireNonNull(daoProvider, "daoProvider"); } + @Override + public final Optional<String> reasonCreateAllowed(User user, R newResource) + { + try (Connection connection = daoProvider.newReadOnlyAutoCommitTransaction()) + { + return reasonCreateAllowed(connection, user, newResource); + } + catch (SQLException e) + { + logger.warn("Error while accessing database", e); + throw new RuntimeException(e); + } + } + + @Override + public final Optional<String> reasonReadAllowed(User user, R existingResource) + { + try (Connection connection = daoProvider.newReadOnlyAutoCommitTransaction()) + { + return reasonReadAllowed(connection, user, existingResource); + } + catch (SQLException e) + { + logger.warn("Error while accessing database", e); + throw new RuntimeException(e); + } + } + + @Override + public final Optional<String> reasonUpdateAllowed(User user, R oldResource, R newResource) + { + try (Connection connection = daoProvider.newReadOnlyAutoCommitTransaction()) + { + return reasonUpdateAllowed(connection, user, oldResource, newResource); + } + catch (SQLException e) + { + logger.warn("Error while accessing database", e); + throw new RuntimeException(e); + } + } + + @Override + public final Optional<String> reasonDeleteAllowed(User user, R oldResource) + { + try (Connection connection = daoProvider.newReadOnlyAutoCommitTransaction()) + { + return reasonDeleteAllowed(connection, user, oldResource); + } + catch (SQLException e) + { + logger.warn("Error while accessing database", e); + throw new RuntimeException(e); + } + } + + @Override + public final Optional<String> reasonSearchAllowed(User user) + { + try (Connection connection = daoProvider.newReadOnlyAutoCommitTransaction()) + { + return reasonSearchAllowed(connection, user); + } + catch (SQLException e) + { + logger.warn("Error while accessing database", e); + throw new RuntimeException(e); + } + } + protected final boolean isLocalUser(User user) { return user != null && UserRole.LOCAL.equals(user.getRole()); @@ -86,14 +158,15 @@ private boolean hasAuthorizationRole(Resource resource, String role) c -> SearchQueryUserFilter.AUTHORIZATION_ROLE_SYSTEM.equals(c.getSystem()) && role.equals(c.getCode())); } - protected final boolean isCurrentUserPartOfReferencedOrganizations(User user, String referenceLocation, - Collection<? extends Reference> references) + protected final boolean isCurrentUserPartOfReferencedOrganizations(Connection connection, User user, + String referenceLocation, Collection<? extends Reference> references) { - return references.stream().anyMatch(r -> isCurrentUserPartOfReferencedOrganization(user, referenceLocation, r)); + return references.stream() + .anyMatch(r -> isCurrentUserPartOfReferencedOrganization(connection, user, referenceLocation, r)); } - protected final boolean isCurrentUserPartOfReferencedOrganization(User user, String referenceLocation, - Reference reference) + protected final boolean isCurrentUserPartOfReferencedOrganization(Connection connection, User user, + String referenceLocation, Reference reference) { if (reference == null) { @@ -112,13 +185,13 @@ protected final boolean isCurrentUserPartOfReferencedOrganization(User user, Str return false; } - Optional<Resource> resource = referenceResolver.resolveReference(user, resReference); + Optional<Resource> resource = referenceResolver.resolveReference(user, resReference, connection); if (resource.isPresent() && resource.get() instanceof Organization) { boolean sameOrganization = user.getOrganization().getIdElement().equals(resource.get().getIdElement()); if (!sameOrganization) logger.warn( - "Current user not part organization {} while checking if user part of referenced organization", + "Current user not part of organization {} while checking if user part of referenced organization", resource.get().getIdElement().getValue()); return sameOrganization; @@ -131,5 +204,4 @@ protected final boolean isCurrentUserPartOfReferencedOrganization(User user, Str } } } - } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java index e49b42f89..e2358f183 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; @@ -18,21 +19,21 @@ public ActivityDefinitionAuthorizationRule(DaoProvider daoProvider, String serve } @Override - public Optional<String> reasonCreateAllowed(User user, ActivityDefinition newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, ActivityDefinition newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonReadAllowed(User user, ActivityDefinition existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, ActivityDefinition existingResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonUpdateAllowed(User user, ActivityDefinition oldResource, + public Optional<String> reasonUpdateAllowed(Connection connection, User user, ActivityDefinition oldResource, ActivityDefinition newResource) { // TODO Auto-generated method stub @@ -40,14 +41,14 @@ public Optional<String> reasonUpdateAllowed(User user, ActivityDefinition oldRes } @Override - public Optional<String> reasonDeleteAllowed(User user, ActivityDefinition oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, ActivityDefinition oldResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { // TODO Auto-generated method stub return Optional.empty(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRule.java index 7eb0ed7ec..24064cb1c 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRule.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; @@ -18,6 +19,19 @@ public interface AuthorizationRule<R extends Resource> */ Optional<String> reasonCreateAllowed(User user, R newResource); + /** + * Override this method for non default behavior. Default: Not allowed. + * + * @param connection + * not <code>null</code> + * @param user + * not <code>null</code> + * @param newResource + * not <code>null</code> + * @return Reason as String in {@link Optional#of(Object))} if create allowed + */ + Optional<String> reasonCreateAllowed(Connection connection, User user, R newResource); + /** * Override this method for non default behavior. Default: Not allowed. * @@ -29,6 +43,19 @@ public interface AuthorizationRule<R extends Resource> */ Optional<String> reasonReadAllowed(User user, R existingResource); + /** + * Override this method for non default behavior. Default: Not allowed. + * + * @param connection + * not <code>null</code> + * @param user + * not <code>null</code> + * @param existingResource + * not <code>null</code> + * @return Reason as String in {@link Optional#of(Object)} if read allowed + */ + Optional<String> reasonReadAllowed(Connection connection, User user, R existingResource); + /** * Override this method for non default behavior. Default: Not allowed. * @@ -42,6 +69,21 @@ public interface AuthorizationRule<R extends Resource> */ Optional<String> reasonUpdateAllowed(User user, R oldResource, R newResource); + /** + * Override this method for non default behavior. Default: Not allowed. + * + * @param connection + * not <code>null</code> + * @param user + * not <code>null</code> + * @param oldResource + * not <code>null</code> + * @param newResource + * not <code>null</code> + * @return Reason as String in {@link Optional#of(Object))} if update allowed + */ + Optional<String> reasonUpdateAllowed(Connection connection, User user, R oldResource, R newResource); + /** * Override this method for non default behavior. Default: Not allowed. * @@ -53,6 +95,19 @@ public interface AuthorizationRule<R extends Resource> */ Optional<String> reasonDeleteAllowed(User user, R oldResource); + /** + * Override this method for non default behavior. Default: Not allowed. + * + * @param connection + * not <code>null</code> + * @param user + * not <code>null</code> + * @param oldResource + * not <code>null</code> + * @return Reason as String in {@link Optional#of(Object)} if delete allowed + */ + Optional<String> reasonDeleteAllowed(Connection connection, User user, R oldResource); + /** * Override this method for non default behavior. Default: Not allowed. * @@ -61,4 +116,13 @@ public interface AuthorizationRule<R extends Resource> * @return Reason as String in {@link Optional#of(Object)} if delete allowed */ Optional<String> reasonSearchAllowed(User user); + + /** + * Override this method for non default behavior. Default: Not allowed. + * + * @param user + * not <code>null</code> + * @return Reason as String in {@link Optional#of(Object)} if delete allowed + */ + Optional<String> reasonSearchAllowed(Connection connection, User user); } \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java index 29ab99399..340afd9dd 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; import java.util.EnumSet; import java.util.Optional; @@ -25,7 +26,7 @@ public BinaryAuthorizationRule(DaoProvider daoProvider, String serverBase, Refer } @Override - public Optional<String> reasonCreateAllowed(User user, Binary newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, Binary newResource) { if (isLocalUser(user)) { @@ -36,7 +37,8 @@ public Optional<String> reasonCreateAllowed(User user, Binary newResource) if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL) .contains(reference.getType(serverBase))) { - Optional<Resource> securityContext = referenceResolver.resolveReference(user, reference); + Optional<Resource> securityContext = referenceResolver.resolveReference(user, reference, + connection); if (securityContext.isPresent()) { if (securityContext.get() instanceof Organization) @@ -80,14 +82,14 @@ public Optional<String> reasonCreateAllowed(User user, Binary newResource) } @Override - public Optional<String> reasonReadAllowed(User user, Binary existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, Binary existingResource) { if (isLocalUser(user)) { logger.info("Read of Binary authorized for local user '{}'", user.getName()); return Optional.of("local user"); } - else if (isCurrentUserPartOfReferencedOrganization(user, "Binary.SecurityContext", + else if (isCurrentUserPartOfReferencedOrganization(connection, user, "Binary.SecurityContext", existingResource.getSecurityContext())) { logger.info( @@ -105,7 +107,8 @@ else if (isCurrentUserPartOfReferencedOrganization(user, "Binary.SecurityContext } @Override - public Optional<String> reasonUpdateAllowed(User user, Binary oldResource, Binary newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, Binary oldResource, + Binary newResource) { if (isLocalUser(user)) { @@ -120,8 +123,10 @@ public Optional<String> reasonUpdateAllowed(User user, Binary oldResource, Binar && EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL) .contains(newReference.getType(serverBase))) { - Optional<Resource> oldSecurityContext = referenceResolver.resolveReference(user, oldReference); - Optional<Resource> newSecurityContext = referenceResolver.resolveReference(user, newReference); + Optional<Resource> oldSecurityContext = referenceResolver.resolveReference(user, oldReference, + connection); + Optional<Resource> newSecurityContext = referenceResolver.resolveReference(user, newReference, + connection); if (oldSecurityContext.isPresent() && newSecurityContext.isPresent()) { if (oldSecurityContext.get() instanceof Organization @@ -167,7 +172,7 @@ public Optional<String> reasonUpdateAllowed(User user, Binary oldResource, Binar } @Override - public Optional<String> reasonDeleteAllowed(User user, Binary oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, Binary oldResource) { if (isLocalUser(user)) { @@ -182,7 +187,7 @@ public Optional<String> reasonDeleteAllowed(User user, Binary oldResource) } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { logger.info("Search of Binary authorized for {} user '{}', will be fitered by users organization {}", user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString()); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java index 8c06f650b..8526602e6 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; @@ -16,35 +17,36 @@ public BundleAuthorizationRule(DaoProvider daoProvider, String serverBase, Refer } @Override - public Optional<String> reasonCreateAllowed(User user, Bundle newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, Bundle newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonReadAllowed(User user, Bundle existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, Bundle existingResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonUpdateAllowed(User user, Bundle oldResource, Bundle newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, Bundle oldResource, + Bundle newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonDeleteAllowed(User user, Bundle oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, Bundle oldResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { // TODO Auto-generated method stub return Optional.empty(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java index db8d5d0df..73a3c566d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; import java.sql.SQLException; import java.util.Optional; @@ -21,17 +22,17 @@ public CodeSystemAuthorizationRule(DaoProvider daoProvider, String serverBase, R } @Override - public Optional<String> reasonCreateAllowed(User user, CodeSystem newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, CodeSystem newResource) { if (isLocalUser(user)) { - // TODO move check for url, version, authorization tag, to validation layer + // TODO move check for url, version and authorization tag to validation layer if (newResource.hasUrl() && newResource.hasVersion() && hasLocalOrRemoteAuthorizationRole(newResource)) { try { - Optional<CodeSystem> existing = getDao().readByUrlAndVersion(newResource.getUrl(), - newResource.getVersion()); + Optional<CodeSystem> existing = getDao().readByUrlAndVersionWithTransaction(connection, + newResource.getUrl(), newResource.getVersion()); if (existing.isEmpty()) { logger.info( @@ -42,7 +43,7 @@ public Optional<String> reasonCreateAllowed(User user, CodeSystem newResource) else { logger.warn( - "Create of CodeSystem unauthorized, CodeSystem wirh url and version already exists"); + "Create of CodeSystem unauthorized, CodeSystem with url and version already exists"); return Optional.empty(); } } @@ -68,7 +69,7 @@ public Optional<String> reasonCreateAllowed(User user, CodeSystem newResource) } @Override - public Optional<String> reasonReadAllowed(User user, CodeSystem existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, CodeSystem existingResource) { if (isLocalUser(user) && hasLocalOrRemoteAuthorizationRole(existingResource)) { @@ -91,20 +92,21 @@ else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) } @Override - public Optional<String> reasonUpdateAllowed(User user, CodeSystem oldResource, CodeSystem newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, CodeSystem oldResource, + CodeSystem newResource) { if (isLocalUser(user)) { - // TODO move check for url, version, authorization tag, to validation layer + // TODO move check for url, version and authorization tag to validation layer if (newResource.hasUrl() && newResource.hasVersion() && hasLocalOrRemoteAuthorizationRole(newResource)) { if (oldResource.getUrl().equals(newResource.getUrl()) && oldResource.getVersion().equals(newResource.getVersion())) { logger.info( - "Update of CodeSystem authorized for local user '{}', version and url same as existing one", + "Update of CodeSystem authorized for local user '{}', CodeSystem with version and url exists", user.getName()); - return Optional.of("local user, CodeSystem with version and url does not exist yet"); + return Optional.of("local user, CodeSystem with version and url exists"); } else { @@ -126,22 +128,22 @@ public Optional<String> reasonUpdateAllowed(User user, CodeSystem oldResource, C } @Override - public Optional<String> reasonDeleteAllowed(User user, CodeSystem oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, CodeSystem oldResource) { if (isLocalUser(user)) { - logger.info("Delete of new CodeSystem authorized for local user '{}'", user.getName()); + logger.info("Delete of CodeSystem authorized for local user '{}'", user.getName()); return Optional.of("local user"); } else { - logger.warn("Update of CodeSystem unauthorized, not a local user"); + logger.warn("Delete of CodeSystem unauthorized, not a local user"); return Optional.empty(); } } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { logger.info("Search of CodeSystem authorized for {} user '{}', will be fitered by user role", user.getRole(), user.getName()); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java index a0f1e0524..ba52b7039 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java @@ -1,10 +1,20 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.EndpointDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.search.PartialResult; +import org.highmed.dsf.fhir.search.SearchQuery; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Endpoint; import org.slf4j.Logger; @@ -14,21 +24,136 @@ public class EndpointAuthorizationRule extends AbstractAuthorizationRule<Endpoin { private static final Logger logger = LoggerFactory.getLogger(EndpointAuthorizationRule.class); + private static final String IDENTIFIER_SYSTEM = "http://highmed.org/fhir/NamingSystem/endpoint-identifier"; + private static final String ENDPOINT_ADDRESS_PATTERN_STRING = "https:\\/\\/([0-9a-zA-Z\\.]+)+(:\\d{1,4})?([-\\w\\/]*)"; + private static final Pattern ENDPOINT_ADDRESS_PATTERN = Pattern.compile(ENDPOINT_ADDRESS_PATTERN_STRING); + public EndpointAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { super(Endpoint.class, daoProvider, serverBase, referenceResolver); } @Override - public Optional<String> reasonCreateAllowed(User user, Endpoint newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, Endpoint newResource) { - // TODO validate unique on Endpoint.address - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + Optional<String> errors = newResourceOk(newResource); + if (errors.isEmpty()) + { + if (!endpointExists(connection, newResource)) + { + logger.info( + "Create of Endpoint authorized for local user '{}', Endpoint with address and identifier does not exist", + user.getName()); + return Optional.of("local user, Endpoint with address and identifier does not exist yet"); + } + else + { + logger.warn("Create of Endpoint unauthorized, Endpoint with address and identifier already exists"); + return Optional.empty(); + } + } + else + { + logger.warn("Create of Endpoint unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else + { + logger.warn("Create of Endpoint unauthorized, not a local user"); + return Optional.empty(); + } + } + + private Optional<String> newResourceOk(Endpoint newResource) + { + List<String> errors = new ArrayList<String>(); + + if (newResource.hasIdentifier()) + { + if (newResource.getIdentifier().stream() + .map(i -> i.hasSystem() && i.hasValue() && IDENTIFIER_SYSTEM.equals(i.getSystem())).count() != 1) + { + errors.add( + "endpoint.identifier one with system '" + IDENTIFIER_SYSTEM + "' and non empty value expected"); + } + } + else + { + errors.add("endpoint.identifier missing"); + } + + if (newResource.hasAddress()) + { + if (!ENDPOINT_ADDRESS_PATTERN.matcher(newResource.getAddress()).matches()) + { + errors.add("endpoint.address not matching " + ENDPOINT_ADDRESS_PATTERN_STRING + " pattern"); + } + } + else + { + errors.add("endpoint.address missing"); + } + + if (!hasLocalOrRemoteAuthorizationRole(newResource)) + { + errors.add("endpoint missing authorization tag"); + } + + if (errors.isEmpty()) + return Optional.empty(); + else + return Optional.of(errors.stream().collect(Collectors.joining(", "))); + } + + private boolean endpointExists(Connection connection, Endpoint newResource) + { + String identifierValue = newResource.getIdentifier().stream() + .filter(i -> IDENTIFIER_SYSTEM.equals(i.getSystem())).map(i -> i.getValue()).findFirst().orElseThrow(); + + return endpointWithAddressExists(connection, newResource.getAddress()) + || endpointWithIdentifierExists(connection, identifierValue); + } + + private boolean endpointWithIdentifierExists(Connection connection, String identifierValue) + { + Map<String, List<String>> queryParameters = Map.of("identifier", + Collections.singletonList(IDENTIFIER_SYSTEM + "|" + identifierValue)); + EndpointDao dao = getDao(); + SearchQuery<Endpoint> query = dao.createSearchQueryWithoutUserFilter(1, 1).configureParameters(queryParameters); + try + { + PartialResult<Endpoint> result = dao.searchWithTransaction(connection, query); + return result.getOverallCount() >= 1; + } + catch (SQLException e) + { + logger.warn("Error while searching for Endpoint with identifier", e); + return false; + } + } + + private boolean endpointWithAddressExists(Connection connection, String address) + { + Map<String, List<String>> queryParameters = Map.of("address", Collections.singletonList(address)); + EndpointDao dao = getDao(); + SearchQuery<Endpoint> query = dao.createSearchQueryWithoutUserFilter(1, 1).configureParameters(queryParameters); + try + { + PartialResult<Endpoint> result = dao.searchWithTransaction(connection, query); + return result.getOverallCount() >= 1; + } + catch (SQLException e) + { + logger.warn("Error while searching for Endpoint with address", e); + return false; + } } @Override - public Optional<String> reasonReadAllowed(User user, Endpoint existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, Endpoint existingResource) { if (isLocalUser(user) && hasLocalOrRemoteAuthorizationRole(existingResource)) { @@ -51,7 +176,8 @@ else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) } @Override - public Optional<String> reasonUpdateAllowed(User user, Endpoint oldResource, Endpoint newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, Endpoint oldResource, + Endpoint newResource) { // TODO validate unique on Endpoint.address // TODO Auto-generated method stub @@ -59,14 +185,14 @@ public Optional<String> reasonUpdateAllowed(User user, Endpoint oldResource, End } @Override - public Optional<String> reasonDeleteAllowed(User user, Endpoint oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, Endpoint oldResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { logger.info("Search of Endpoint authorized for {} user '{}', will be fitered by user role", user.getRole(), user.getName()); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java index a8d2dd64e..9dc542ae7 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; @@ -16,35 +17,35 @@ public GroupAuthorizationRule(DaoProvider daoProvider, String serverBase, Refere } @Override - public Optional<String> reasonCreateAllowed(User user, Group newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, Group newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonReadAllowed(User user, Group existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, Group existingResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonUpdateAllowed(User user, Group oldResource, Group newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, Group oldResource, Group newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonDeleteAllowed(User user, Group oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, Group oldResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { // TODO Auto-generated method stub return Optional.empty(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java index b47ec3e4a..18201796f 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; @@ -18,35 +19,36 @@ public HealthcareServiceAuthorizationRule(DaoProvider daoProvider, String server } @Override - public Optional<String> reasonCreateAllowed(User user, HealthcareService newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, HealthcareService newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonReadAllowed(User user, HealthcareService existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, HealthcareService existingResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonUpdateAllowed(User user, HealthcareService oldResource, HealthcareService newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, HealthcareService oldResource, + HealthcareService newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonDeleteAllowed(User user, HealthcareService oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, HealthcareService oldResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { // TODO Auto-generated method stub return Optional.empty(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java index 9925c0383..28954f18b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; @@ -16,35 +17,36 @@ public LocationAuthorizationRule(DaoProvider daoProvider, String serverBase, Ref } @Override - public Optional<String> reasonCreateAllowed(User user, Location newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, Location newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonReadAllowed(User user, Location existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, Location existingResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonUpdateAllowed(User user, Location oldResource, Location newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, Location oldResource, + Location newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonDeleteAllowed(User user, Location oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, Location oldResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { // TODO Auto-generated method stub return Optional.empty(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java index 7258c203b..ca436358a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java @@ -1,5 +1,7 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; +import java.sql.SQLException; import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; @@ -7,9 +9,13 @@ import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.NamingSystem; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class NamingSystemAuthorizationRule extends AbstractAuthorizationRule<NamingSystem, NamingSystemDao> { + private static final Logger logger = LoggerFactory.getLogger(NamingSystemAuthorizationRule.class); + public NamingSystemAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { @@ -17,37 +23,129 @@ public NamingSystemAuthorizationRule(DaoProvider daoProvider, String serverBase, } @Override - public Optional<String> reasonCreateAllowed(User user, NamingSystem newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, NamingSystem newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + // TODO move check for name and authorization tag to validation layer + if (newResource.hasName() && hasLocalOrRemoteAuthorizationRole(newResource)) + { + try + { + Optional<NamingSystem> existing = getDao().readByNameWithTransaction(connection, + newResource.getName()); + if (existing.isEmpty()) + { + logger.info( + "Create of NamingSystem authorized for local user '{}', NamingSystem with name does not exist", + user.getName()); + return Optional.of("local user, NamingSystem with name does not exist yet"); + } + else + { + logger.warn("Create of NamingSystem unauthorized, NamingSystem with name already exists"); + return Optional.empty(); + } + } + catch (SQLException e) + { + logger.warn( + "Create of NamingSystem unauthorized, error while checking for existing NamingSystem with name", + e); + return Optional.empty(); + } + } + else + { + logger.warn("Create of NamingSystem unauthorized, missing name or authorization tag"); + return Optional.empty(); + } + } + else + { + logger.warn("Create of NamingSystem unauthorized, not a local user"); + return Optional.empty(); + } } @Override - public Optional<String> reasonReadAllowed(User user, NamingSystem existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, NamingSystem existingResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user) && hasLocalOrRemoteAuthorizationRole(existingResource)) + { + logger.info( + "Read of NamingSystem authorized for local user '{}', NamingSystem has local or remote authorization role", + user.getName()); + return Optional.of("local user, local or remote authorized NamingSystem"); + } + else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) + { + logger.info( + "Read of NamingSystem authorized for remote user '{}', NamingSystem has remote authorization role", + user.getName()); + return Optional.of("remote user, remote authorized NamingSystem"); + } + else + { + logger.warn("Read of NamingSystem unauthorized, no matching user role resource authorization role found"); + return Optional.empty(); + } } @Override - public Optional<String> reasonUpdateAllowed(User user, NamingSystem oldResource, NamingSystem newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, NamingSystem oldResource, + NamingSystem newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + // TODO move check for name and authorization tag to validation layer + if (newResource.hasName() && hasLocalOrRemoteAuthorizationRole(newResource)) + { + if (oldResource.getName().equals(newResource.getName())) + { + logger.info("Update of NamingSystem authorized for local user '{}', NamingSystem with name exist", + user.getName()); + return Optional.of("local user, NamingSystem with name exist"); + } + else + { + logger.warn("Update of NamingSystem unauthorized, new name not equal to existing resource"); + return Optional.empty(); + } + } + else + { + logger.warn("Update of NamingSystem unauthorized, missing name or authorization tag"); + return Optional.empty(); + } + } + else + { + logger.warn("Update of NamingSystem unauthorized, not a local user"); + return Optional.empty(); + } } @Override - public Optional<String> reasonDeleteAllowed(User user, NamingSystem oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, NamingSystem oldResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Delete of NamingSystem authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Delete of NamingSystem unauthorized, not a local user"); + return Optional.empty(); + } } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { - // TODO Auto-generated method stub - return Optional.empty(); + logger.info("Search of NamingSystem authorized for {} user '{}', will be fitered by user role", user.getRole(), + user.getName()); + return Optional.of("Allowed for all, filtered by user role"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java index afff0c253..fd100693d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java @@ -1,12 +1,23 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.regex.Pattern; +import java.util.stream.Collectors; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.OrganizationDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.search.PartialResult; +import org.highmed.dsf.fhir.search.SearchQuery; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.StringType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,6 +25,12 @@ public class OrganizationAuthorizationRule extends AbstractAuthorizationRule<Org { private static final Logger logger = LoggerFactory.getLogger(OrganizationAuthorizationRule.class); + private static final String IDENTIFIER_SYSTEM = "http://highmed.org/fhir/NamingSystem/organization-identifier"; + private static final String EXTENSION_THUMBPRINT_URL = "http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"; + private static final String EXTENSION_THUMBPRINT_VALUE_PATTERN_STRING = "[a-z0-9]{128}"; + private static final Pattern EXTENSION_THUMBPRINT_VALUE_PATTERN = Pattern + .compile(EXTENSION_THUMBPRINT_VALUE_PATTERN_STRING); + public OrganizationAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { @@ -21,18 +38,137 @@ public OrganizationAuthorizationRule(DaoProvider daoProvider, String serverBase, } @Override - public Optional<String> reasonCreateAllowed(User user, Organization newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, Organization newResource) { + if (isLocalUser(user)) + { + Optional<String> errors = newResourceOk(newResource); + if (errors.isEmpty()) + { + if (!organizationExists(connection, newResource)) + { + logger.info( + "Create of Organization authorized for local user '{}', Organization with certificate-thumbprint and identifier does not exist", + user.getName()); + return Optional.of( + "local user, Organization with certificate-thumbprint and identifier does not exist yet"); + } + else + { + logger.warn( + "Create of Organization unauthorized, Organization with certificate-thumbprint and identifier already exists"); + return Optional.empty(); + } + } + else + { + logger.warn("Create of Organization unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else + { + logger.warn("Create of Organization unauthorized, not a local user"); + return Optional.empty(); + } + // check organization not existing if contains identifier with identifier.system (or extension) // http://highmed.org/fhir/NamingSystem/certificate-thumbprint-hex with same identifier.value // no two organizations can have the same certificate thumb-print - // TODO Auto-generated method stub - return Optional.empty(); + } + + private Optional<String> newResourceOk(Organization newResource) + { + List<String> errors = new ArrayList<String>(); + + if (newResource.hasIdentifier()) + { + if (newResource.getIdentifier().stream() + .map(i -> i.hasSystem() && i.hasValue() && IDENTIFIER_SYSTEM.equals(i.getSystem())).count() != 1) + { + errors.add("organization.identifier one with system '" + IDENTIFIER_SYSTEM + + "' and non empty value expected"); + } + } + else + { + errors.add("organization.identifier missing"); + } + + if (newResource.hasExtension()) + { + if (!newResource.getExtension().stream().anyMatch(e -> e.hasUrl() && e.hasValue() + && (e.getValue() instanceof StringType) && EXTENSION_THUMBPRINT_URL.equals(e.getUrl()) + && EXTENSION_THUMBPRINT_VALUE_PATTERN.matcher(((StringType) e.getValue()).getValue()).matches())) + { + errors.add("organization.extension missing extension with url '" + EXTENSION_THUMBPRINT_URL + + "' and value matching " + EXTENSION_THUMBPRINT_VALUE_PATTERN_STRING + " pattern"); + } + } + else + { + errors.add("organization.extension missing"); + } + + if (!hasLocalOrRemoteAuthorizationRole(newResource)) + { + errors.add("organization missing authorization tag"); + } + + if (errors.isEmpty()) + return Optional.empty(); + else + return Optional.of(errors.stream().collect(Collectors.joining(", "))); + } + + private boolean organizationExists(Connection connection, Organization newResource) + { + String identifierValue = newResource.getIdentifier().stream() + .filter(i -> IDENTIFIER_SYSTEM.equals(i.getSystem())).map(i -> i.getValue()).findFirst().orElseThrow(); + String thumbPrintValue = newResource.getExtension().stream() + .filter(e -> EXTENSION_THUMBPRINT_URL.equals(e.getUrl())) + .map(e -> ((StringType) e.getValue()).getValue()).findFirst().orElseThrow(); + + return organizationWithThumbPrintExists(connection, thumbPrintValue) + || organizationWithIdentifierExists(connection, identifierValue); + } + + private boolean organizationWithThumbPrintExists(Connection connection, String thumbprintHex) + { + try + { + OrganizationDao dao = getDao(); + return dao.existsNotDeletedByThumbprintWithTransaction(connection, thumbprintHex); + } + catch (SQLException e) + { + logger.warn("Error while searching for Endpoint with thumbprint", e); + return false; + } + } + + private boolean organizationWithIdentifierExists(Connection connection, String identifierValue) + { + Map<String, List<String>> queryParameters = Map.of("identifier", + Collections.singletonList(IDENTIFIER_SYSTEM + "|" + identifierValue)); + OrganizationDao dao = getDao(); + SearchQuery<Organization> query = dao.createSearchQueryWithoutUserFilter(1, 1) + .configureParameters(queryParameters); + try + { + PartialResult<Organization> result = dao.searchWithTransaction(connection, query); + return result.getOverallCount() >= 1; + } + catch (SQLException e) + { + logger.warn("Error while searching for Endpoint with identifier", e); + return false; + } } @Override - public Optional<String> reasonReadAllowed(User user, Organization existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, Organization existingResource) { if (isLocalUser(user) && hasLocalOrRemoteAuthorizationRole(existingResource)) { @@ -56,21 +192,22 @@ else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) } @Override - public Optional<String> reasonUpdateAllowed(User user, Organization oldResource, Organization newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, Organization oldResource, + Organization newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonDeleteAllowed(User user, Organization oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, Organization oldResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { logger.info("Search of Organization authorized for {} user '{}', will be fitered by user role", user.getRole(), user.getName()); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java index e0860438b..17437ee90 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; @@ -16,35 +17,36 @@ public PatientAuthorizationRule(DaoProvider daoProvider, String serverBase, Refe } @Override - public Optional<String> reasonCreateAllowed(User user, Patient newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, Patient newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonReadAllowed(User user, Patient existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, Patient existingResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonUpdateAllowed(User user, Patient oldResource, Patient newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, Patient oldResource, + Patient newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonDeleteAllowed(User user, Patient oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, Patient oldResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { // TODO Auto-generated method stub return Optional.empty(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java index a49d7a97a..7f3977c94 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; @@ -17,35 +18,36 @@ public PractitionerAuthorizationRule(DaoProvider daoProvider, String serverBase, } @Override - public Optional<String> reasonCreateAllowed(User user, Practitioner newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, Practitioner newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonReadAllowed(User user, Practitioner existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, Practitioner existingResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonUpdateAllowed(User user, Practitioner oldResource, Practitioner newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, Practitioner oldResource, + Practitioner newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonDeleteAllowed(User user, Practitioner oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, Practitioner oldResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { // TODO Auto-generated method stub return Optional.empty(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java index bf9d1de08..bc11ec231 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; @@ -17,35 +18,36 @@ public PractitionerRoleAuthorizationRule(DaoProvider daoProvider, String serverB } @Override - public Optional<String> reasonCreateAllowed(User user, PractitionerRole newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, PractitionerRole newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonReadAllowed(User user, PractitionerRole existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, PractitionerRole existingResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonUpdateAllowed(User user, PractitionerRole oldResource, PractitionerRole newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, PractitionerRole oldResource, + PractitionerRole newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonDeleteAllowed(User user, PractitionerRole oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, PractitionerRole oldResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { // TODO Auto-generated method stub return Optional.empty(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java index f04deaad6..b594f4718 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; @@ -16,35 +17,36 @@ public ProvenanceAuthorizationRule(DaoProvider daoProvider, String serverBase, R } @Override - public Optional<String> reasonCreateAllowed(User user, Provenance newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, Provenance newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonReadAllowed(User user, Provenance existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, Provenance existingResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonUpdateAllowed(User user, Provenance oldResource, Provenance newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, Provenance oldResource, + Provenance newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonDeleteAllowed(User user, Provenance oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, Provenance oldResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { // TODO Auto-generated method stub return Optional.empty(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java index 55a73ae5f..d92d3da3e 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; @@ -17,35 +18,36 @@ public ResearchStudyAuthorizationRule(DaoProvider daoProvider, String serverBase } @Override - public Optional<String> reasonCreateAllowed(User user, ResearchStudy newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, ResearchStudy newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonReadAllowed(User user, ResearchStudy existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, ResearchStudy existingResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonUpdateAllowed(User user, ResearchStudy oldResource, ResearchStudy newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, ResearchStudy oldResource, + ResearchStudy newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonDeleteAllowed(User user, ResearchStudy oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, ResearchStudy oldResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { // TODO Auto-generated method stub return Optional.empty(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java index f58aa4ffc..a28b9024f 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java @@ -1,5 +1,7 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; +import java.sql.SQLException; import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; @@ -7,10 +9,14 @@ import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.StructureDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class StructureDefinitionAuthorizationRule extends AbstractAuthorizationRule<StructureDefinition, StructureDefinitionDao> { + private static final Logger logger = LoggerFactory.getLogger(StructureDefinitionAuthorizationRule.class); + public StructureDefinitionAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { @@ -18,24 +24,61 @@ public StructureDefinitionAuthorizationRule(DaoProvider daoProvider, String serv } @Override - public Optional<String> reasonCreateAllowed(User user, StructureDefinition newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, StructureDefinition newResource) { - // check logged in, check "local" user (local user only could be default) - // check against existing profiles, no create if profile with same URL, version and status exists - - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + // TODO move check for url, version and authorization tag to validation layer + if (newResource.hasUrl() && newResource.hasVersion() && hasLocalOrRemoteAuthorizationRole(newResource)) + { + try + { + Optional<StructureDefinition> existing = getDao().readByUrlAndVersionWithTransaction(connection, + newResource.getUrl(), newResource.getVersion()); + if (existing.isEmpty()) + { + logger.info( + "Create of StructureDefinition authorized for local user '{}', StructureDefinition with version and url does not exist", + user.getName()); + return Optional.of("local user, StructureDefinition with version and url does not exist yet"); + } + else + { + logger.warn( + "Create of StructureDefinition unauthorized, StructureDefinition with url and version already exists"); + return Optional.empty(); + } + } + catch (SQLException e) + { + logger.warn( + "Create of StructureDefinition unauthorized, error while checking for existing StructureDefinition with version and url", + e); + return Optional.empty(); + } + } + else + { + logger.warn("Create of StructureDefinition unauthorized, missing url or version or authorization tag"); + return Optional.empty(); + } + } + else + { + logger.warn("Create of StructureDefinition unauthorized, not a local user"); + return Optional.empty(); + } } @Override - public Optional<String> reasonReadAllowed(User user, StructureDefinition existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, StructureDefinition existingResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonUpdateAllowed(User user, StructureDefinition oldResource, + public Optional<String> reasonUpdateAllowed(Connection connection, User user, StructureDefinition oldResource, StructureDefinition newResource) { // check logged in, check "local" user (local user only could be default) @@ -49,14 +92,14 @@ public Optional<String> reasonUpdateAllowed(User user, StructureDefinition oldRe } @Override - public Optional<String> reasonDeleteAllowed(User user, StructureDefinition oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, StructureDefinition oldResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { // TODO Auto-generated method stub return Optional.empty(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java index c8c5941ba..13aa4b1c7 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java @@ -1,15 +1,35 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.ResourceDao; import org.highmed.dsf.fhir.dao.SubscriptionDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.search.PartialResult; +import org.highmed.dsf.fhir.search.SearchQuery; +import org.highmed.dsf.fhir.search.SearchQueryParameterError; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Subscription; +import org.hl7.fhir.r4.model.Subscription.SubscriptionChannelType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; + +import ca.uhn.fhir.rest.api.Constants; public class SubscriptionAuthorizationRule extends AbstractAuthorizationRule<Subscription, SubscriptionDao> { + private static final Logger logger = LoggerFactory.getLogger(SubscriptionAuthorizationRule.class); + public SubscriptionAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) { @@ -17,40 +37,148 @@ public SubscriptionAuthorizationRule(DaoProvider daoProvider, String serverBase, } @Override - public Optional<String> reasonCreateAllowed(User user, Subscription newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, Subscription newResource) { - // check subscription.channel.payload null or one of the supported mimetypes - // check subscription.channel.type = websocket - // check subscription.criteria is implemented as search query - // check if subscription.channel.type = websocket, Task unique on subscription.criteria + if (isLocalUser(user)) + { + Optional<String> errors = newResourceOk(newResource); + if (errors.isEmpty()) + { + if (!subscriptionExists(connection, newResource)) + { + logger.info( + "Create of Subscription authorized for local user '{}', Subscription with criteria, type and payload does not exist", + user.getName()); + return Optional.of("local user, Subscription with criteria, type and payload does not exist yet"); + } + else + { + logger.warn( + "Create of Subscription unauthorized, Subscription with criteria, type and payload already exists"); + return Optional.empty(); + } + } + else + { + logger.warn("Create of Subscription unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else + { + logger.warn("Create of Subscription unauthorized, not a local user"); + return Optional.empty(); + } + } - // TODO Auto-generated method stub - return Optional.empty(); + private Optional<String> newResourceOk(Subscription newResource) + { + List<String> errors = new ArrayList<String>(); + + if (newResource.hasChannel()) + { + if (newResource.getChannel().hasPayload() + && !(Constants.CT_FHIR_JSON_NEW.equals(newResource.getChannel().getPayload()) + || Constants.CT_FHIR_XML_NEW.equals(newResource.getChannel().getPayload()))) + { + errors.add("subscription.channel.payload not " + Constants.CT_FHIR_JSON_NEW + " or " + Constants.CT_FHIR_XML_NEW); + } + + if (!SubscriptionChannelType.WEBSOCKET.equals(newResource.getChannel().getType())) + { + errors.add("subscription.channel.type not " + SubscriptionChannelType.WEBSOCKET); + } + } + else + { + errors.add("subscription.channel not defined"); + } + + if (newResource.hasCriteria()) + { + UriComponents cComponentes = UriComponentsBuilder.fromUriString(newResource.getCriteria()).build(); + if (cComponentes.getPathSegments().size() == 1) + { + Optional<ResourceDao<?>> optDao = daoProvider.getDao(cComponentes.getPathSegments().get(0)); + if (optDao.isPresent()) + { + SearchQuery<?> searchQuery = optDao.get().createSearchQueryWithoutUserFilter(1, 1); + List<SearchQueryParameterError> unsupportedQueryParameters = searchQuery + .getUnsupportedQueryParameters(cComponentes.getQueryParams()); + + if (!unsupportedQueryParameters.isEmpty()) + { + errors.add("subscription.criteria invalid (parameters '" + unsupportedQueryParameters.stream() + .map(SearchQueryParameterError::toString).collect(Collectors.joining(", ")) + + "' not supported)"); + } + } + else + { + errors.add("subscription.criteria invalid (resource '" + cComponentes.getPath() + "' not supported)"); + } + } + else + { + errors.add("subscription.criteria invalid ('" + cComponentes.getPath() + "')"); + } + } + else + { + errors.add("subscription.criteria not defined"); + } + + if (errors.isEmpty()) + return Optional.empty(); + else + return Optional.of(errors.stream().collect(Collectors.joining(", "))); + } + + private boolean subscriptionExists(Connection connection, Subscription newResource) + { + Map<String, List<String>> queryParameters = Map.of("criteria", + Collections.singletonList(newResource.getCriteria()), "type", + Collections.singletonList(newResource.getChannel().getType().toCode()), "payload", + Collections.singletonList(newResource.getChannel().getPayload())); + SubscriptionDao dao = getDao(); + SearchQuery<Subscription> query = dao.createSearchQueryWithoutUserFilter(1, 1) + .configureParameters(queryParameters); + try + { + PartialResult<Subscription> result = dao.searchWithTransaction(connection, query); + return result.getOverallCount() >= 1; + } + catch (SQLException e) + { + logger.warn("Error while searching for Subscriptions", e); + return false; + } } @Override - public Optional<String> reasonReadAllowed(User user, Subscription existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, Subscription existingResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonUpdateAllowed(User user, Subscription oldResource, Subscription newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, Subscription oldResource, + Subscription newResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonDeleteAllowed(User user, Subscription oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, Subscription oldResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { // TODO Auto-generated method stub return Optional.empty(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java index b6e5ed7ba..b2214e346 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; @@ -20,7 +21,7 @@ public TaskAuthorizationRule(DaoProvider daoProvider, String serverBase, Referen } @Override - public Optional<String> reasonCreateAllowed(User user, Task newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, Task newResource) { // allowed status draft | requested for all users // task.requester must be organization of current user @@ -30,14 +31,14 @@ public Optional<String> reasonCreateAllowed(User user, Task newResource) } @Override - public Optional<String> reasonReadAllowed(User user, Task existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, Task existingResource) { // TODO Auto-generated method stub return Optional.empty(); } @Override - public Optional<String> reasonUpdateAllowed(User user, Task oldResource, Task newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, Task oldResource, Task newResource) { // allowed status change from draft to requested for remote users // update only allowed at status draft for remote users @@ -49,7 +50,7 @@ public Optional<String> reasonUpdateAllowed(User user, Task oldResource, Task ne } @Override - public Optional<String> reasonDeleteAllowed(User user, Task oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, Task oldResource) { // allowed if oldResouce created by current user and status draft @@ -58,7 +59,7 @@ public Optional<String> reasonDeleteAllowed(User user, Task oldResource) } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { logger.info("Search of Task authorized for {} user '{}', will be fitered by users organization {}", user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString()); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ValueSetAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ValueSetAuthorizationRule.java index 44d00fafd..1396ffb7b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ValueSetAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ValueSetAuthorizationRule.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.authorization; +import java.sql.Connection; import java.sql.SQLException; import java.util.Optional; @@ -21,17 +22,17 @@ public ValueSetAuthorizationRule(DaoProvider daoProvider, String serverBase, Ref } @Override - public Optional<String> reasonCreateAllowed(User user, ValueSet newResource) + public Optional<String> reasonCreateAllowed(Connection connection, User user, ValueSet newResource) { if (isLocalUser(user)) { - // TODO move check for url, version, authorization tag, to validation layer + // TODO move check for url, version and authorization tag to validation layer if (newResource.hasUrl() && newResource.hasVersion() && hasLocalOrRemoteAuthorizationRole(newResource)) { try { - Optional<ValueSet> existing = getDao().readByUrlAndVersion(newResource.getUrl(), - newResource.getVersion()); + Optional<ValueSet> existing = getDao().readByUrlAndVersionWithTransaction(connection, + newResource.getUrl(), newResource.getVersion()); if (existing.isEmpty()) { logger.info( @@ -41,7 +42,7 @@ public Optional<String> reasonCreateAllowed(User user, ValueSet newResource) } else { - logger.warn("Create of ValueSet unauthorized, ValueSet wirh url and version already exists"); + logger.warn("Create of ValueSet unauthorized, ValueSet with url and version already exists"); return Optional.empty(); } } @@ -67,7 +68,7 @@ public Optional<String> reasonCreateAllowed(User user, ValueSet newResource) } @Override - public Optional<String> reasonReadAllowed(User user, ValueSet existingResource) + public Optional<String> reasonReadAllowed(Connection connection, User user, ValueSet existingResource) { if (isLocalUser(user) && hasLocalOrRemoteAuthorizationRole(existingResource)) { @@ -90,20 +91,21 @@ else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) } @Override - public Optional<String> reasonUpdateAllowed(User user, ValueSet oldResource, ValueSet newResource) + public Optional<String> reasonUpdateAllowed(Connection connection, User user, ValueSet oldResource, + ValueSet newResource) { if (isLocalUser(user)) { - // TODO move check for url, version, authorization tag, to validation layer + // TODO move check for url, version and authorization tag to validation layer if (newResource.hasUrl() && newResource.hasVersion() && hasLocalOrRemoteAuthorizationRole(newResource)) { if (oldResource.getUrl().equals(newResource.getUrl()) && oldResource.getVersion().equals(newResource.getVersion())) { logger.info( - "Update of ValueSet authorized for local user '{}', version and url same as existing one", + "Update of ValueSet authorized for local user '{}', ValueSet with version and url exists", user.getName()); - return Optional.of("local user, ValueSet with version and url does not exist yet"); + return Optional.of("local user, ValueSet with version and url exists"); } else { @@ -125,22 +127,22 @@ public Optional<String> reasonUpdateAllowed(User user, ValueSet oldResource, Val } @Override - public Optional<String> reasonDeleteAllowed(User user, ValueSet oldResource) + public Optional<String> reasonDeleteAllowed(Connection connection, User user, ValueSet oldResource) { if (isLocalUser(user)) { - logger.info("Delete of new ValueSet authorized for local user '{}'", user.getName()); + logger.info("Delete of ValueSet authorized for local user '{}'", user.getName()); return Optional.of("local user"); } else { - logger.warn("Update of ValueSet unauthorized, not a local user"); + logger.warn("Delete of ValueSet unauthorized, not a local user"); return Optional.empty(); } } @Override - public Optional<String> reasonSearchAllowed(User user) + public Optional<String> reasonSearchAllowed(Connection connection, User user) { logger.info("Search of ValueSet authorized for {} user '{}', will be fitered by user role", user.getRole(), user.getName()); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/NamingSystemDao.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/NamingSystemDao.java index 4a5857d27..85f903306 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/NamingSystemDao.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/NamingSystemDao.java @@ -1,7 +1,14 @@ package org.highmed.dsf.fhir.dao; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Optional; + import org.hl7.fhir.r4.model.NamingSystem; public interface NamingSystemDao extends ResourceDao<NamingSystem> { + Optional<NamingSystem> readByName(String name) throws SQLException; + + Optional<NamingSystem> readByNameWithTransaction(Connection connection, String name) throws SQLException; } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/OrganizationDao.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/OrganizationDao.java index 7b8f52aaa..fcf286a59 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/OrganizationDao.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/OrganizationDao.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.dao; +import java.sql.Connection; import java.sql.SQLException; import java.util.Optional; @@ -10,4 +11,7 @@ public interface OrganizationDao extends ResourceDao<Organization> Optional<Organization> readActiveNotDeletedByThumbprint(String thumbprintHex) throws SQLException; Optional<Organization> readActiveNotDeletedByIdentifier(String identifierValue) throws SQLException; + + boolean existsNotDeletedByThumbprintWithTransaction(Connection connection, String thumbprintHex) + throws SQLException; } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommand.java index c39382106..3355323b3 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommand.java @@ -3,9 +3,13 @@ import org.highmed.dsf.fhir.authentication.User; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public abstract class AbstractCommand implements Command { + protected static final Logger audit = LoggerFactory.getLogger("dsf-audit-logger"); + private final int transactionPriority; protected final int index; @@ -16,8 +20,10 @@ public abstract class AbstractCommand implements Command protected final String serverBase; + protected final AuthorizationCommandFactory authorizationCommandFactory; + public AbstractCommand(int transactionPriority, int index, User user, Bundle bundle, BundleEntryComponent entry, - String serverBase) + String serverBase, AuthorizationCommandFactory authorizationCommandFactory) { this.transactionPriority = transactionPriority; @@ -27,6 +33,8 @@ public AbstractCommand(int transactionPriority, int index, User user, Bundle bun this.bundle = bundle; this.entry = entry; this.serverBase = serverBase; + + this.authorizationCommandFactory = authorizationCommandFactory; } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommandWithResource.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommandWithResource.java index 94304cdc5..1b634ae59 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommandWithResource.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommandWithResource.java @@ -17,10 +17,10 @@ public abstract class AbstractCommandWithResource<R extends Resource, D extends protected final ParameterConverter parameterConverter; public AbstractCommandWithResource(int transactionPriority, int index, User user, Bundle bundle, - BundleEntryComponent entry, String serverBase, R resource, D dao, ExceptionHandler exceptionHandler, - ParameterConverter parameterConverter) + BundleEntryComponent entry, String serverBase, AuthorizationCommandFactory authorizationCommandFactory, + R resource, D dao, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter) { - super(transactionPriority, index, user, bundle, entry, serverBase); + super(transactionPriority, index, user, bundle, entry, serverBase, authorizationCommandFactory); this.resource = resource; this.dao = dao; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommand.java new file mode 100644 index 000000000..212c4ed07 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommand.java @@ -0,0 +1,23 @@ +package org.highmed.dsf.fhir.dao.command; + +@FunctionalInterface +public interface AuthorizationCommand +{ + static AuthorizationCommand empty() + { + return () -> + { + }; + } + + static AuthorizationCommand concat(AuthorizationCommand c1, AuthorizationCommand c2) + { + return () -> + { + c1.execute(); + c2.execute(); + }; + } + + void execute(); +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommandFactory.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommandFactory.java new file mode 100644 index 000000000..b6d0e4516 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommandFactory.java @@ -0,0 +1,22 @@ +package org.highmed.dsf.fhir.dao.command; + +import java.sql.Connection; + +import org.highmed.dsf.fhir.authentication.User; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Resource; + +public interface AuthorizationCommandFactory +{ + void checkCreateAllowed(Connection connection, User user, Resource newResource); + + void checkReadAllowed(Connection connection, User user, Resource existingResource); + + void checkUpdateAllowed(Connection connection, User user, Resource oldResource, Resource newResource); + + void checkDeleteAllowed(Connection connection, User user, Resource oldResource); + + void checkSearchAllowed(Connection connection, User user, String resourceTypeName); + + void filterIncludeResults(Connection connection, User user, Bundle multipleResult); +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommandFactoryImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommandFactoryImpl.java new file mode 100644 index 000000000..b58e57a66 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommandFactoryImpl.java @@ -0,0 +1,164 @@ +package org.highmed.dsf.fhir.dao.command; + +import java.sql.Connection; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import javax.ws.rs.WebApplicationException; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.authorization.AuthorizationRule; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; +import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Resource; +import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; +import org.hl7.fhir.r4.model.Bundle.SearchEntryMode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ca.uhn.fhir.model.api.annotation.ResourceDef; + +public class AuthorizationCommandFactoryImpl implements AuthorizationCommandFactory +{ + private static final Logger logger = LoggerFactory.getLogger(AuthorizationCommandFactoryImpl.class); + private static final Logger audit = LoggerFactory.getLogger("dsf-audit-logger"); + + private final AuthorizationRuleProvider authorizationRuleProvider; + private final ResponseGenerator responseGenerator; + + public AuthorizationCommandFactoryImpl(AuthorizationRuleProvider authorizationRuleProvider, + ResponseGenerator responseGenerator) + { + this.authorizationRuleProvider = authorizationRuleProvider; + this.responseGenerator = responseGenerator; + } + + @SuppressWarnings("unchecked") + private Optional<AuthorizationRule<Resource>> getAuthorizationRule(Class<?> resourceClass) + { + return authorizationRuleProvider.getAuthorizationRule(resourceClass) + .map(rule -> (AuthorizationRule<Resource>) rule); + } + + @SuppressWarnings("unchecked") + private Optional<AuthorizationRule<Resource>> getAuthorizationRule(String resourceTypeName) + { + return authorizationRuleProvider.getAuthorizationRule(resourceTypeName) + .map(rule -> (AuthorizationRule<Resource>) rule); + } + + private WebApplicationException forbidden(String operation, User user) throws WebApplicationException + { + return new WebApplicationException(responseGenerator.forbiddenNotAllowed(operation, user)); + } + + @Override + public void checkCreateAllowed(Connection connection, User user, Resource newResource) + { + Optional<AuthorizationRule<Resource>> optRule = getAuthorizationRule(newResource.getClass()); + optRule.flatMap(rule -> rule.reasonCreateAllowed(connection, user, newResource)).ifPresentOrElse(reason -> + { + audit.info("Create of resource {} allowed for user '{}' via bundle, reason: {}", + newResource.getResourceType().name(), user.getName(), reason); + }, () -> + { + audit.info("Create of resource {} denied for user '{}' via bundle", newResource.getResourceType().name(), + user.getName()); + throw forbidden("create", user); + }); + } + + @Override + public void checkReadAllowed(Connection connection, User user, Resource existingResource) + { + Optional<AuthorizationRule<Resource>> optRule = getAuthorizationRule(existingResource.getClass()); + optRule.flatMap(rule -> rule.reasonReadAllowed(connection, user, existingResource)).ifPresentOrElse(reason -> + { + audit.info("Read of resource {} allowed for user '{}' via bundle, reason: {}", + existingResource.getIdElement().getValue(), user.getName(), reason); + }, () -> + { + audit.info("Read of resource {} denied for user '{}' via bundle", + existingResource.getIdElement().getValue(), user.getName()); + throw forbidden("read", user); + }); + } + + @Override + public void checkUpdateAllowed(Connection connection, User user, Resource oldResource, Resource newResource) + { + Optional<AuthorizationRule<Resource>> optRule = getAuthorizationRule(oldResource.getClass()); + optRule.flatMap(rule -> rule.reasonUpdateAllowed(connection, user, oldResource, newResource)) + .ifPresentOrElse(reason -> + { + audit.info("Update of resource {} allowed for user '{}', reason: {}", + oldResource.getIdElement().getValue(), user.getName(), reason); + }, () -> + { + audit.info("Update of resource {} denied for user '{}'", oldResource.getIdElement().getValue(), + user.getName()); + throw forbidden("update", user); + }); + } + + @Override + public void checkDeleteAllowed(Connection connection, User user, Resource oldResource) + { + Optional<AuthorizationRule<Resource>> optRule = getAuthorizationRule(oldResource.getClass()); + optRule.flatMap(rule -> rule.reasonDeleteAllowed(user, oldResource)).ifPresentOrElse(reason -> + { + audit.info("Delete of resource {} allowed for user '{}', reason: {}", oldResource.getIdElement().getValue(), + user.getName(), reason); + }, () -> + { + audit.info("Delete of resource {} denied for user '{}'", oldResource.getIdElement().getValue(), + user.getName()); + throw forbidden("delete", user); + }); + } + + @Override + public void checkSearchAllowed(Connection connection, User user, String resourceTypeName) + { + Optional<AuthorizationRule<Resource>> optRule = getAuthorizationRule(resourceTypeName); + optRule.flatMap(rule -> rule.reasonSearchAllowed(connection, user)).ifPresentOrElse(reason -> + { + audit.info("Search of resource {} allowed for user '{}', reason: {}", resourceTypeName, user.getName(), + reason); + }, () -> + { + audit.info("Search of resource {} denied for user '{}'", resourceTypeName, user.getName()); + throw forbidden("search", user); + }); + } + + @Override + public void filterIncludeResults(Connection connection, User user, Bundle multipleResult) + { + List<BundleEntryComponent> filteredEntries = multipleResult.getEntry().stream() + .filter(c -> SearchEntryMode.MATCH.equals(c.getSearch().getMode()) + || (SearchEntryMode.INCLUDE.equals(c.getSearch().getMode()) + && filterIncludeResource(user, c.getResource()))) + .collect(Collectors.toList()); + multipleResult.setEntry(filteredEntries); + } + + private boolean filterIncludeResource(User user, Resource include) + { + Optional<AuthorizationRule<Resource>> optRule = getAuthorizationRule(include.getClass()); + return optRule.flatMap(rule -> rule.reasonReadAllowed(user, include)).map(reason -> + { + logger.debug("Include resource of type {} with id {}, allowed - {}", + include.getClass().getAnnotation(ResourceDef.class).name(), include.getIdElement().getValue(), + reason); + return true; + }).orElseGet(() -> + { + logger.debug("Include resource of type {} with id {}, filtered (read not allowed)", + include.getClass().getAnnotation(ResourceDef.class).name(), include.getIdElement().getValue()); + return false; + }); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/BatchCommandList.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/BatchCommandList.java index 4105f90e9..d0d99eccd 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/BatchCommandList.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/BatchCommandList.java @@ -1,15 +1,15 @@ package org.highmed.dsf.fhir.dao.command; import java.sql.Connection; +import java.sql.SQLException; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import java.util.function.Consumer; -import java.util.stream.IntStream; import javax.sql.DataSource; import javax.ws.rs.WebApplicationException; @@ -42,14 +42,24 @@ public BatchCommandList(DataSource dataSource, ExceptionHandler exceptionHandler this.commands.addAll(commands); } + private boolean hasModifyingCommands() + { + return commands.stream() + .anyMatch(c -> c instanceof CreateCommand || c instanceof UpdateCommand || c instanceof DeleteCommand); + } + @Override public Bundle execute() throws WebApplicationException { try (Connection connection = dataSource.getConnection()) { - if (commands.stream().anyMatch( - c -> c instanceof CreateCommand || c instanceof UpdateCommand || c instanceof DeleteCommand)) - connection.setReadOnly(false); + boolean initialReadOnly = connection.isReadOnly(); + boolean initialAutoCommit = connection.getAutoCommit(); + int initialTransactionIsolationLevel = connection.getTransactionIsolation(); + logger.debug( + "Running batch with DB connection setting: read-only {}, auto-commit {}, transaction-isolation-level {}", + initialReadOnly, initialAutoCommit, + getTransactionIsolationLevelString(initialTransactionIsolationLevel)); Map<Integer, Exception> caughtExceptions = new HashMap<Integer, Exception>( (int) (commands.size() / 0.75) + 1); @@ -57,14 +67,34 @@ public Bundle execute() throws WebApplicationException commands.forEach(preExecute(idTranslationTable, caughtExceptions)); - IntStream.range(0, commands.size()).filter(index -> !caughtExceptions.containsKey(index)) - .mapToObj(index -> commands.get(index)) - .forEach(execute(idTranslationTable, connection, caughtExceptions)); + if (hasModifyingCommands()) + { + logger.debug( + "Elevating DB connection setting to: read-only {}, auto-commit {}, transaction-isolation-level {}", + false, false, getTransactionIsolationLevelString(Connection.TRANSACTION_REPEATABLE_READ)); + + connection.setReadOnly(false); + connection.setAutoCommit(false); + connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ); + } + + commands.forEach(execute(idTranslationTable, connection, caughtExceptions)); + + if (hasModifyingCommands()) + { + logger.debug( + "Reseting DB connection setting to: read-only {}, auto-commit {}, transaction-isolation-level {}", + initialReadOnly, initialAutoCommit, + getTransactionIsolationLevelString(initialTransactionIsolationLevel)); + + connection.setReadOnly(initialReadOnly); + connection.setAutoCommit(initialAutoCommit); + connection.setTransactionIsolation(initialTransactionIsolationLevel); + } Map<Integer, BundleEntryComponent> results = new HashMap<>((int) ((commands.size() / 0.75) + 1)); - IntStream.range(0, commands.size()).filter(index -> !caughtExceptions.containsKey(index)) - .mapToObj(index -> commands.get(index)).forEach(postExecute(connection, caughtExceptions, results)); + commands.forEach(postExecute(connection, caughtExceptions, results)); Bundle result = new Bundle(); result.setType(BundleType.BATCHRESPONSE); @@ -81,6 +111,26 @@ public Bundle execute() throws WebApplicationException } } + private String getTransactionIsolationLevelString(int level) + { + switch (level) + { + case Connection.TRANSACTION_NONE: + return "NONE"; + case Connection.TRANSACTION_READ_UNCOMMITTED: + return "READ_UNCOMMITTED"; + case Connection.TRANSACTION_READ_COMMITTED: + return "READ_COMMITTED"; + case Connection.TRANSACTION_REPEATABLE_READ: + return "REPEATABLE_READ"; + case Connection.TRANSACTION_SERIALIZABLE: + return "SERIALIZABLE"; + + default: + return "?"; + } + } + private BundleEntryComponent toEntry(Exception exception) { var entry = new BundleEntryComponent(); @@ -141,7 +191,7 @@ private Consumer<Command> execute(Map<String, IdType> idTranslationTable, Connec { logger.debug("Running execute of command {} for entry at index {}", command.getClass().getName(), command.getIndex()); - command.execute(Collections.unmodifiableMap(idTranslationTable), connection); + command.execute(idTranslationTable, connection); } else { @@ -150,15 +200,31 @@ private Consumer<Command> execute(Map<String, IdType> idTranslationTable, Connec caughtExceptions.get(command.getIndex()).getClass().getName() + ": " + caughtExceptions.get(command.getIndex()).getMessage()); } + + if (!connection.getAutoCommit()) + connection.commit(); } catch (Exception e) { - logger.warn("Error while executing command " + command.getClass().getName() + " for entry at index " - + command.getIndex(), e); + logger.warn("Error while executing command " + command.getClass().getName() + + ", rolling back transaction for entry at index " + command.getIndex(), e); caughtExceptions.put(command.getIndex(), e); + + try + { + if (!connection.getAutoCommit()) + connection.rollback(); + } + catch (SQLException e1) + { + logger.warn( + "Error while executing command " + command.getClass().getName() + + ", error while rolling back transaction for entry at index " + command.getIndex(), + e1); + caughtExceptions.put(command.getIndex(), e1); + } } }; - } private Consumer<Command> postExecute(Connection connection, Map<Integer, Exception> caughtExceptions, @@ -172,7 +238,9 @@ private Consumer<Command> postExecute(Connection connection, Map<Integer, Except { logger.debug("Running post-execute of command {} for entry at index {}", command.getClass().getName(), command.getIndex()); - results.put(command.getIndex(), command.postExecute(connection)); + + Optional<BundleEntryComponent> optResult = command.postExecute(connection); + optResult.ifPresent(result -> results.put(command.getIndex(), result)); } else { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/Command.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/Command.java index 74b5b5d74..14b35c685 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/Command.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/Command.java @@ -3,6 +3,7 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.Map; +import java.util.Optional; import javax.ws.rs.WebApplicationException; @@ -22,5 +23,5 @@ public interface Command void execute(Map<String, IdType> idTranslationTable, Connection connection) throws SQLException, WebApplicationException; - BundleEntryComponent postExecute(Connection connection); + Optional<BundleEntryComponent> postExecute(Connection connection); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CommandFactoryImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CommandFactoryImpl.java index 46382d33d..b7de06639 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CommandFactoryImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CommandFactoryImpl.java @@ -27,7 +27,6 @@ import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r4.model.Bundle.BundleType; -import org.hl7.fhir.r4.model.DomainResource; import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.StructureDefinition; import org.springframework.beans.factory.InitializingBean; @@ -47,12 +46,14 @@ public class CommandFactoryImpl implements InitializingBean, CommandFactory private final SnapshotGenerator snapshotGenerator; private final SnapshotDependencyAnalyzer snapshotDependencyAnalyzer; private final ParameterConverter parameterConverter; + private final AuthorizationCommandFactory authorizationCommandFactory; public CommandFactoryImpl(String serverBase, int defaultPageCount, DataSource dataSource, DaoProvider daoProvider, ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, ResponseGenerator responseGenerator, ExceptionHandler exceptionHandler, EventManager eventManager, EventGenerator eventGenerator, SnapshotGenerator snapshotGenerator, - SnapshotDependencyAnalyzer snapshotDependencyAnalyzer, ParameterConverter parameterConverter) + SnapshotDependencyAnalyzer snapshotDependencyAnalyzer, ParameterConverter parameterConverter, + AuthorizationCommandFactory authorizationCommandFactory) { this.serverBase = serverBase; this.defaultPageCount = defaultPageCount; @@ -67,6 +68,7 @@ public CommandFactoryImpl(String serverBase, int defaultPageCount, DataSource da this.snapshotGenerator = snapshotGenerator; this.snapshotDependencyAnalyzer = snapshotDependencyAnalyzer; this.parameterConverter = parameterConverter; + this.authorizationCommandFactory = authorizationCommandFactory; } @Override @@ -83,13 +85,14 @@ public void afterPropertiesSet() throws Exception Objects.requireNonNull(snapshotGenerator, "snapshotGenerator"); Objects.requireNonNull(snapshotDependencyAnalyzer, "snapshotDependencyAnalyzer"); Objects.requireNonNull(parameterConverter, "parameterConverter"); + Objects.requireNonNull(authorizationCommandFactory, "authorizationRuleProvider"); } // read, vread private Command get(int index, User user, Bundle bundle, BundleEntryComponent entry) { - return new ReadCommand(index, user, bundle, entry, serverBase, defaultPageCount, daoProvider, - parameterConverter, responseGenerator, exceptionHandler); + return new ReadCommand(index, user, bundle, entry, serverBase, authorizationCommandFactory, defaultPageCount, + daoProvider, parameterConverter, responseGenerator, exceptionHandler); } // create, conditional create @@ -104,14 +107,14 @@ private <R extends Resource> Command post(int index, User user, Bundle bundle, B if (resource instanceof StructureDefinition) return new CreateStructureDefinitionCommand(index, user, bundle, entry, serverBase, - (StructureDefinition) resource, (StructureDefinitionDao) dao.get(), exceptionHandler, - parameterConverter, responseGenerator, eventManager, eventGenerator, + authorizationCommandFactory, (StructureDefinition) resource, (StructureDefinitionDao) dao.get(), + exceptionHandler, parameterConverter, responseGenerator, eventManager, eventGenerator, daoProvider.getStructureDefinitionSnapshotDao(), snapshotGenerator, snapshotDependencyAnalyzer); else return dao - .map(d -> new CreateCommand<R, ResourceDao<R>>(index, user, bundle, entry, serverBase, resource, - d, exceptionHandler, parameterConverter, responseGenerator, eventManager, - eventGenerator)) + .map(d -> new CreateCommand<R, ResourceDao<R>>(index, user, bundle, entry, serverBase, + authorizationCommandFactory, resource, d, exceptionHandler, parameterConverter, + responseGenerator, eventManager, eventGenerator)) .orElseThrow(() -> new IllegalStateException( "Resource of type " + resource.getClass().getName() + " not supported")); } @@ -121,7 +124,7 @@ private <R extends Resource> Command post(int index, User user, Bundle bundle, B } // update, conditional update - private <R extends DomainResource> Command put(int index, User user, Bundle bundle, BundleEntryComponent entry, + private <R extends Resource> Command put(int index, User user, Bundle bundle, BundleEntryComponent entry, EventManager eventManager, R resource) { if (entry.getRequest().getUrl() != null && !entry.getRequest().getUrl().isBlank() @@ -133,14 +136,14 @@ private <R extends DomainResource> Command put(int index, User user, Bundle bund if (resource instanceof StructureDefinition) return new UpdateStructureDefinitionCommand(index, user, bundle, entry, serverBase, - (StructureDefinition) resource, (StructureDefinitionDao) dao.get(), exceptionHandler, - parameterConverter, responseGenerator, eventManager, eventGenerator, + authorizationCommandFactory, (StructureDefinition) resource, (StructureDefinitionDao) dao.get(), + exceptionHandler, parameterConverter, responseGenerator, eventManager, eventGenerator, daoProvider.getStructureDefinitionSnapshotDao(), snapshotGenerator, snapshotDependencyAnalyzer); else return dao - .map(d -> new UpdateCommand<R, ResourceDao<R>>(index, user, bundle, entry, serverBase, resource, - d, exceptionHandler, parameterConverter, responseGenerator, eventManager, - eventGenerator)) + .map(d -> new UpdateCommand<R, ResourceDao<R>>(index, user, bundle, entry, serverBase, + authorizationCommandFactory, resource, d, exceptionHandler, parameterConverter, + responseGenerator, eventManager, eventGenerator)) .orElseThrow(() -> new IllegalStateException( "Resource of type " + resource.getClass().getName() + " not supported")); } @@ -154,8 +157,8 @@ private Command delete(int index, User user, Bundle bundle, BundleEntryComponent { if (entry.getRequest().getUrl() != null && !entry.getRequest().getUrl().isBlank()) { - return new DeleteCommand(index, user, bundle, entry, serverBase, responseGenerator, daoProvider, - exceptionHandler, parameterConverter, eventManager, eventGenerator); + return new DeleteCommand(index, user, bundle, entry, serverBase, authorizationCommandFactory, + responseGenerator, daoProvider, exceptionHandler, parameterConverter, eventManager, eventGenerator); } else throw new BadBundleException( @@ -204,43 +207,37 @@ protected Stream<Command> createCommand(int index, Bundle bundle, User user, Bun { switch (entry.getRequest().getMethod()) { - case GET: + case GET: // read return Stream.of(get(index, user, bundle, entry)); - case DELETE: + case DELETE: // delete return Stream.of(delete(index, user, bundle, entry, eventManager)); default: throw new BadBundleException("Request method " + entry.getRequest().getMethod() + " at index " - + index + " not supported without resource of type " + DomainResource.class.getName()); + + index + " not supported without resource"); } } - else if (entry.getResource() instanceof DomainResource) + else { switch (entry.getRequest().getMethod()) { case POST: // create - Command post = post(index, user, bundle, entry, eventManager, - (DomainResource) entry.getResource()); - return resolveReferences(post, index, user, bundle, entry, - (DomainResource) entry.getResource()); + Command post = post(index, user, bundle, entry, eventManager, (Resource) entry.getResource()); + return resolveReferences(post, index, user, bundle, entry, (Resource) entry.getResource()); case PUT: // update - Command put = put(index, user, bundle, entry, eventManager, - (DomainResource) entry.getResource()); - return resolveReferences(put, index, user, bundle, entry, (DomainResource) entry.getResource()); + Command put = put(index, user, bundle, entry, eventManager, (Resource) entry.getResource()); + return resolveReferences(put, index, user, bundle, entry, (Resource) entry.getResource()); default: throw new BadBundleException("Request method " + entry.getRequest().getMethod() + " at index " + index + " not supported with resource"); } } - else - throw new BadBundleException("BundleEntry at index " + index + " has no resource of type " - + DomainResource.class.getName()); } else throw new BadBundleException("BundleEntry at index " + index + " has no request or request has no method"); } - private <R extends DomainResource> Stream<Command> resolveReferences(Command cmd, int index, User user, - Bundle bundle, BundleEntryComponent entry, R resource) + private <R extends Resource> Stream<Command> resolveReferences(Command cmd, int index, User user, Bundle bundle, + BundleEntryComponent entry, R resource) { @SuppressWarnings("unchecked") Optional<? extends ResourceDao<R>> dao = (Optional<? extends ResourceDao<R>>) daoProvider @@ -251,8 +248,8 @@ private <R extends DomainResource> Stream<Command> resolveReferences(Command cmd return dao .map(d -> Stream.of(cmd, new ResolveReferencesCommand<R, ResourceDao<R>>(index, user, bundle, entry, serverBase, - resource, d, exceptionHandler, parameterConverter, referenceExtractor, - responseGenerator, referenceResolver))) + authorizationCommandFactory, resource, d, exceptionHandler, parameterConverter, + referenceExtractor, responseGenerator, referenceResolver))) .orElseThrow(() -> new IllegalStateException( "Resource of type " + resource.getClass().getName() + " not supported")); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateCommand.java index 2c81f549a..36d00e9b3 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateCommand.java @@ -51,11 +51,13 @@ public class CreateCommand<R extends Resource, D extends ResourceDao<R>> extends protected R createdResource; protected Response responseResult; - public CreateCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, R resource, - D dao, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, + public CreateCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, + AuthorizationCommandFactory authorizationCommandFactory, R resource, D dao, + ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, ResponseGenerator responseGenerator, EventManager eventManager, EventGenerator eventGenerator) { - super(2, index, user, bundle, entry, serverBase, resource, dao, exceptionHandler, parameterConverter); + super(2, index, user, bundle, entry, serverBase, authorizationCommandFactory, resource, dao, exceptionHandler, + parameterConverter); this.responseGenerator = responseGenerator; this.eventManager = eventManager; @@ -65,14 +67,34 @@ public CreateCommand(int index, User user, Bundle bundle, BundleEntryComponent e @Override public void preExecute(Map<String, IdType> idTranslationTable) { - // TODO validate entry.getFullUrl() vs resource.getIdElement() - // TODO validate entry.getFullUrl() is urn:uuid:... + UriComponents eruComponentes = UriComponentsBuilder.fromUriString(entry.getRequest().getUrl()).build(); + + // check standard update request url: Patient + if (eruComponentes.getPathSegments().size() == 1 && eruComponentes.getQueryParams().isEmpty()) + { + if (!entry.getFullUrl().startsWith(URL_UUID_PREFIX)) + throw new WebApplicationException( + responseGenerator.badCreateRequestUrl(index, entry.getRequest().getUrl())); + else if (resource.hasIdElement() && !resource.getIdElement().getValue().startsWith(URL_UUID_PREFIX)) + throw new WebApplicationException(responseGenerator.bundleEntryBadResourceId(index, + resource.getResourceType().name(), URL_UUID_PREFIX)); + else if (resource.hasIdElement() && !entry.getFullUrl().equals(resource.getIdElement().getValue())) + throw new WebApplicationException(responseGenerator.badBundleEntryFullUrlVsResourceId(index, + entry.getFullUrl(), resource.getIdElement().getValue())); + } + + // all other request urls + else + throw new WebApplicationException( + responseGenerator.badCreateRequestUrl(index, entry.getRequest().getUrl())); } @Override public void execute(Map<String, IdType> idTranslationTable, Connection connection) throws SQLException, WebApplicationException { + authorizationCommandFactory.checkCreateAllowed(connection, user, resource); + Optional<Resource> exists = checkAlreadyExists(connection, entry.getRequest().getIfNoneExist(), resource.getResourceType()); @@ -142,7 +164,7 @@ else if (result.getOverallCount() > 1) } @Override - public BundleEntryComponent postExecute(Connection connection) + public Optional<BundleEntryComponent> postExecute(Connection connection) { if (responseResult == null) { @@ -168,7 +190,7 @@ public BundleEntryComponent postExecute(Connection connection) response.setEtag(new EntityTag(createdResource.getMeta().getVersionId(), true).toString()); response.setLastModified(createdResource.getMeta().getLastUpdated()); - return resultEntry; + return Optional.of(resultEntry); } else { @@ -184,7 +206,7 @@ public BundleEntryComponent postExecute(Connection connection) if (responseResult.getLastModified() != null) response.setLastModified(responseResult.getLastModified()); - return resultEntry; + return Optional.of(resultEntry); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateStructureDefinitionCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateStructureDefinitionCommand.java index 5b7003fd1..14bd34739 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateStructureDefinitionCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateStructureDefinitionCommand.java @@ -2,6 +2,7 @@ import java.sql.Connection; import java.util.Map; +import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.StructureDefinitionDao; @@ -35,14 +36,14 @@ public class CreateStructureDefinitionCommand extends CreateCommand<StructureDef private StructureDefinition resourceWithSnapshot; public CreateStructureDefinitionCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, - String serverBase, StructureDefinition resource, StructureDefinitionDao dao, - ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, + String serverBase, AuthorizationCommandFactory authorizationCommandFactory, StructureDefinition resource, + StructureDefinitionDao dao, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, ResponseGenerator responseGenerator, EventManager eventManager, EventGenerator eventGenerator, StructureDefinitionSnapshotDao snapshotDao, SnapshotGenerator snapshotGenerator, SnapshotDependencyAnalyzer snapshotDependencyAnalyzer) { - super(index, user, bundle, entry, serverBase, resource, dao, exceptionHandler, parameterConverter, - responseGenerator, eventManager, eventGenerator); + super(index, user, bundle, entry, serverBase, authorizationCommandFactory, resource, dao, exceptionHandler, + parameterConverter, responseGenerator, eventManager, eventGenerator); this.snapshotDao = snapshotDao; this.snapshotGenerator = snapshotGenerator; @@ -59,7 +60,7 @@ public void preExecute(Map<String, IdType> idTranslationTable) } @Override - public BundleEntryComponent postExecute(Connection connection) + public Optional<BundleEntryComponent> postExecute(Connection connection) { if (responseResult != null) return super.postExecute(connection); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/DeleteCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/DeleteCommand.java index 74a6417a4..f361ae9d4 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/DeleteCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/DeleteCommand.java @@ -7,6 +7,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Optional; +import java.util.UUID; import java.util.stream.Collectors; import javax.ws.rs.WebApplicationException; @@ -51,10 +52,11 @@ public class DeleteCommand extends AbstractCommand implements Command private String id; public DeleteCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, - ResponseGenerator responseGenerator, DaoProvider daoProvider, ExceptionHandler exceptionHandler, - ParameterConverter parameterConverter, EventManager eventManager, EventGenerator eventGenerator) + AuthorizationCommandFactory authorizationCommandFactory, ResponseGenerator responseGenerator, + DaoProvider daoProvider, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, + EventManager eventManager, EventGenerator eventGenerator) { - super(1, index, user, bundle, entry, serverBase); + super(1, index, user, bundle, entry, serverBase, authorizationCommandFactory); this.responseGenerator = responseGenerator; this.daoProvider = daoProvider; @@ -74,6 +76,7 @@ public void execute(Map<String, IdType> idTranslationTable, Connection connectio throws SQLException, WebApplicationException { UriComponents componentes = UriComponentsBuilder.fromUriString(entry.getRequest().getUrl()).build(); + resourceTypeName = componentes.getPathSegments().get(0); if (componentes.getPathSegments().size() == 2 && componentes.getQueryParams().isEmpty()) deleteById(connection, componentes.getPathSegments().get(0), componentes.getPathSegments().get(1)); @@ -83,24 +86,33 @@ else if (componentes.getPathSegments().size() == 1 && !componentes.getQueryParam else throw new WebApplicationException( responseGenerator.badDeleteRequestUrl(index, entry.getRequest().getUrl())); - - resourceTypeName = componentes.getPathSegments().get(0); } private void deleteById(Connection connection, String resourceTypeName, String id) { - Optional<ResourceDao<?>> dao = daoProvider.getDao(resourceTypeName); + Optional<ResourceDao<?>> optDao = daoProvider.getDao(resourceTypeName); - if (dao.isEmpty()) + if (optDao.isEmpty()) throw new WebApplicationException( responseGenerator.resourceTypeNotSupportedByImplementation(index, resourceTypeName)); else { + @SuppressWarnings("unchecked") + ResourceDao<Resource> dao = (ResourceDao<Resource>) optDao.get(); + UUID uuid = parameterConverter.toUuid(resourceTypeName, id); + + Optional<Resource> dbResource = exceptionHandler + .handleSqlException(() -> dao.readIncludingDeletedWithTransaction(connection, uuid)); + + dbResource.ifPresent( + oldResource -> authorizationCommandFactory.checkDeleteAllowed(connection, user, oldResource)); + deleted = exceptionHandler.handleSqlAndResourceNotFoundException(resourceTypeName, - () -> dao.get().deleteWithTransaction(connection, parameterConverter.toUuid(resourceTypeName, id))); + () -> dao.deleteWithTransaction(connection, uuid)); - this.resourceType = dao.get().getResourceType(); + this.resourceType = dao.getResourceType(); this.id = id; + } } @@ -117,6 +129,8 @@ private void deleteByCondition(Connection connection, String resourceTypeName, Optional<Resource> resourceToDelete = search(connection, dao.get(), queryParameters); if (resourceToDelete.isPresent()) { + authorizationCommandFactory.checkDeleteAllowed(connection, user, resourceToDelete.get()); + deleted = exceptionHandler.handleSqlAndResourceNotFoundException(resourceTypeName, () -> dao.get().deleteWithTransaction(connection, parameterConverter.toUuid(resourceTypeName, resourceToDelete.get().getIdElement().getIdPart()))); @@ -174,7 +188,7 @@ else if (result.getOverallCount() == 1) } @Override - public BundleEntryComponent postExecute(Connection connection) + public Optional<BundleEntryComponent> postExecute(Connection connection) { try { @@ -196,6 +210,6 @@ public BundleEntryComponent postExecute(Connection connection) else response.setStatus(Status.NO_CONTENT.getStatusCode() + " " + Status.NO_CONTENT.getReasonPhrase()); - return resultEntry; + return Optional.of(resultEntry); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ReadCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ReadCommand.java index d34e7889d..73d62f8fa 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ReadCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ReadCommand.java @@ -50,13 +50,15 @@ public class ReadCommand extends AbstractCommand implements Command private Bundle multipleResult; private Resource singleResult; + private OperationOutcome singleResultSearchWarning; private Response responseResult; public ReadCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, - int defaultPageCount, DaoProvider daoProvider, ParameterConverter parameterConverter, - ResponseGenerator responseGenerator, ExceptionHandler exceptionHandler) + AuthorizationCommandFactory authorizationCommandFactory, int defaultPageCount, DaoProvider daoProvider, + ParameterConverter parameterConverter, ResponseGenerator responseGenerator, + ExceptionHandler exceptionHandler) { - super(5, index, user, bundle, entry, serverBase); + super(5, index, user, bundle, entry, serverBase, authorizationCommandFactory); this.defaultPageCount = defaultPageCount; @@ -102,19 +104,13 @@ private void readById(Connection connection, String resourceTypeName, String id) { Optional<ResourceDao<? extends Resource>> optDao = daoProvider.getDao(resourceTypeName); if (optDao.isEmpty()) - { responseResult = Response.status(Status.NOT_FOUND).build(); - return; - } ResourceDao<? extends Resource> dao = optDao.get(); Optional<?> read = exceptionHandler.handleSqlAndResourceDeletedException(resourceTypeName, () -> dao.readWithTransaction(connection, parameterConverter.toUuid(resourceTypeName, id))); if (read.isEmpty()) - { responseResult = Response.status(Status.NOT_FOUND).build(); - return; - } Resource r = (Resource) read.get(); @@ -128,6 +124,8 @@ private void readById(Connection connection, String resourceTypeName, String id) responseResult = Response.notModified(resourceTag).lastModified(r.getMeta().getLastUpdated()).build(); else singleResult = r; + + authorizationCommandFactory.checkReadAllowed(connection, user, r); } private void readByIdAndVersion(Connection connection, String resourceTypeName, String id, String version) @@ -135,20 +133,14 @@ private void readByIdAndVersion(Connection connection, String resourceTypeName, Optional<ResourceDao<? extends Resource>> optDao = daoProvider.getDao(resourceTypeName); Optional<Long> longVersion = parameterConverter.toVersion(version); if (optDao.isEmpty() || longVersion.isEmpty()) - { responseResult = Response.status(Status.NOT_FOUND).build(); - return; - } ResourceDao<? extends Resource> dao = optDao.get(); Optional<?> read = exceptionHandler.handleSqlAndResourceDeletedException(resourceTypeName, () -> dao.readVersionWithTransaction(connection, parameterConverter.toUuid(resourceTypeName, id), longVersion.get())); if (read.isEmpty()) - { responseResult = Response.status(Status.NOT_FOUND).build(); - return; - } Resource r = (Resource) read.get(); @@ -162,6 +154,8 @@ private void readByIdAndVersion(Connection connection, String resourceTypeName, responseResult = Response.notModified(resourceTag).lastModified(r.getMeta().getLastUpdated()).build(); else singleResult = r; + + authorizationCommandFactory.checkReadAllowed(connection, user, r); } private void readByCondition(Connection connection, String resourceTypeName, @@ -169,10 +163,7 @@ private void readByCondition(Connection connection, String resourceTypeName, { Optional<ResourceDao<? extends Resource>> optDao = daoProvider.getDao(resourceTypeName); if (optDao.isEmpty()) - { responseResult = Response.status(Status.NOT_FOUND).build(); - return; - } Integer page = parameterConverter.getFirstInt(cleanQueryParameters, SearchQuery.PARAMETER_PAGE); int effectivePage = page == null ? 1 : page; @@ -191,27 +182,45 @@ private void readByCondition(Connection connection, String resourceTypeName, UriBuilder bundleUri = query.configureBundleUri(UriBuilder.fromPath(serverBase + "/" + resourceTypeName)); multipleResult = responseGenerator.createSearchSet(result, errors, bundleUri, null, null); - } - - @Override - public BundleEntryComponent postExecute(Connection connection) - { - OperationOutcome searchWarning = null; + // map single search result from multipleResult field to singleResult field if (multipleResult != null && multipleResult.getEntry().size() == 1) + { singleResult = (Resource) multipleResult.getEntry().get(0).getResource(); - else if (multipleResult != null && multipleResult.getEntry().size() == 2 && multipleResult.getEntry().stream() - .filter(e -> SearchEntryMode.MATCH.equals(e.getSearch().getMode())).count() == 1) + multipleResult = null; + + authorizationCommandFactory.checkReadAllowed(connection, user, singleResult); + } + else if (multipleResult != null && multipleResult.getEntry().size() == 2 + && SearchEntryMode.MATCH.equals(multipleResult.getEntry().get(0).getSearch().getMode()) + && SearchEntryMode.OUTCOME.equals(multipleResult.getEntry().get(1).getSearch().getMode())) { - singleResult = (Resource) multipleResult.getEntry().stream() - .filter(e -> SearchEntryMode.MATCH.equals(e.getSearch().getMode())).findFirst() - .map(BundleEntryComponent::getResource).get(); + singleResult = (Resource) multipleResult.getEntry().get(0).getResource(); + singleResultSearchWarning = (OperationOutcome) multipleResult.getEntry().get(1).getResource(); + multipleResult = null; - searchWarning = (OperationOutcome) multipleResult.getEntry().stream() - .filter(e -> SearchEntryMode.OUTCOME.equals(e.getSearch().getMode())).findFirst() - .map(BundleEntryComponent::getResource).get(); + authorizationCommandFactory.checkReadAllowed(connection, user, singleResult); } + else if (multipleResult != null && multipleResult.getEntry().size() == 2 + && SearchEntryMode.MATCH.equals(multipleResult.getEntry().get(1).getSearch().getMode()) + && SearchEntryMode.OUTCOME.equals(multipleResult.getEntry().get(0).getSearch().getMode())) + { + singleResult = (Resource) multipleResult.getEntry().get(1).getResource(); + singleResultSearchWarning = (OperationOutcome) multipleResult.getEntry().get(0).getResource(); + multipleResult = null; + authorizationCommandFactory.checkReadAllowed(connection, user, singleResult); + } + else + { + authorizationCommandFactory.checkSearchAllowed(connection, user, resourceTypeName); + authorizationCommandFactory.filterIncludeResults(connection, user, multipleResult); + } + } + + @Override + public Optional<BundleEntryComponent> postExecute(Connection connection) + { if (singleResult != null) { BundleEntryComponent resultEntry = new BundleEntryComponent(); @@ -225,10 +234,10 @@ else if (multipleResult != null && multipleResult.getEntry().size() == 2 && mult response.setLastModified(singleResult.getMeta().getLastUpdated()); resultEntry.setResource(singleResult); - if (searchWarning != null) - response.setOutcome(searchWarning); + if (singleResultSearchWarning != null) + response.setOutcome(singleResultSearchWarning); - return resultEntry; + return Optional.of(resultEntry); } else if (multipleResult != null) { @@ -237,7 +246,8 @@ else if (multipleResult != null) BundleEntryResponseComponent response = resultEntry.getResponse(); response.setStatus(Status.OK.getStatusCode() + " " + Status.OK.getReasonPhrase()); resultEntry.setResource(multipleResult); - return resultEntry; + + return Optional.of(resultEntry); } else { @@ -251,7 +261,7 @@ else if (multipleResult != null) if (responseResult.getLastModified() != null) response.setLastModified(responseResult.getLastModified()); - return resultEntry; + return Optional.of(resultEntry); } } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java index b3f69d6a9..f92e7e739 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java @@ -4,6 +4,7 @@ import java.sql.SQLException; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.stream.Collectors; import javax.ws.rs.WebApplicationException; @@ -31,11 +32,13 @@ public class ResolveReferencesCommand<R extends Resource, D extends ResourceDao< private final ReferenceResolver referenceResolver; public ResolveReferencesCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, - R resource, D dao, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, + AuthorizationCommandFactory authorizationCommandFactory, R resource, D dao, + ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, ReferenceExtractor referenceExtractor, ResponseGenerator responseGenerator, ReferenceResolver referenceResolver) { - super(4, index, user, bundle, entry, serverBase, resource, dao, exceptionHandler, parameterConverter); + super(4, index, user, bundle, entry, serverBase, authorizationCommandFactory, resource, dao, exceptionHandler, + parameterConverter); this.referenceExtractor = referenceExtractor; this.responseGenerator = responseGenerator; @@ -128,8 +131,8 @@ private boolean resolveTemporaryReference(ResourceReference resourceReference, } @Override - public BundleEntryComponent postExecute(Connection connection) + public Optional<BundleEntryComponent> postExecute(Connection connection) { - return null; + return Optional.empty(); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/TransactionCommandList.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/TransactionCommandList.java index 447693256..dcd025704 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/TransactionCommandList.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/TransactionCommandList.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import javax.sql.DataSource; import javax.ws.rs.WebApplicationException; @@ -112,7 +113,8 @@ public Bundle execute() throws WebApplicationException { logger.debug("Running post-execute of command {} for entry at index {}", c.getClass().getName(), c.getIndex()); - results.putIfAbsent(c.getIndex(), c.postExecute(connection)); + Optional<BundleEntryComponent> optResult = c.postExecute(connection); + optResult.ifPresent(result -> results.putIfAbsent(c.getIndex(), result)); } catch (Exception e) { @@ -155,6 +157,9 @@ public Bundle execute() throws WebApplicationException } catch (WebApplicationException e) { + if (e.getResponse() != null && Status.FORBIDDEN.getStatusCode() == e.getResponse().getStatus()) + throw e; + throw new WebApplicationException( Response.status(Status.BAD_REQUEST).entity(e.getResponse().getEntity()).build()); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java index e7ab2c87b..44edf5d2f 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java @@ -49,11 +49,13 @@ public class UpdateCommand<R extends Resource, D extends ResourceDao<R>> extends protected UUID id; protected R updatedResource; - public UpdateCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, R resource, - D dao, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, + public UpdateCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, + AuthorizationCommandFactory authorizationCommandFactory, R resource, D dao, + ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, ResponseGenerator responseGenerator, EventManager eventManager, EventGenerator eventGenerator) { - super(3, index, user, bundle, entry, serverBase, resource, dao, exceptionHandler, parameterConverter); + super(3, index, user, bundle, entry, serverBase, authorizationCommandFactory, resource, dao, exceptionHandler, + parameterConverter); this.responseGenerator = responseGenerator; this.eventManager = eventManager; @@ -63,8 +65,10 @@ public UpdateCommand(int index, User user, Bundle bundle, BundleEntryComponent e @Override public void preExecute(Map<String, IdType> idTranslationTable) { - UriComponents componentes = UriComponentsBuilder.fromUriString(entry.getRequest().getUrl()).build(); - if (componentes.getPathSegments().size() == 2 && componentes.getQueryParams().isEmpty()) + UriComponents eruComponentes = UriComponentsBuilder.fromUriString(entry.getRequest().getUrl()).build(); + + // check standard update request url: Patient/123 + if (eruComponentes.getPathSegments().size() == 2 && eruComponentes.getQueryParams().isEmpty()) { if (entry.getFullUrl().startsWith(URL_UUID_PREFIX)) throw new WebApplicationException( @@ -83,12 +87,14 @@ else if (resource.getIdElement().getIdPart().startsWith(URL_UUID_PREFIX)) if (!expectedfullUrl.equals(entry.getFullUrl())) throw new WebApplicationException(responseGenerator.badBundleEntryFullUrl(index, entry.getFullUrl())); - else if (!expectedResourceTypeName.equals(componentes.getPathSegments().get(0)) - || !expectedId.equals(componentes.getPathSegments().get(1))) + else if (!expectedResourceTypeName.equals(eruComponentes.getPathSegments().get(0)) + || !expectedId.equals(eruComponentes.getPathSegments().get(1))) throw new WebApplicationException( responseGenerator.badUpdateRequestUrl(index, entry.getRequest().getUrl())); } - else if (componentes.getPathSegments().size() == 1 && !componentes.getQueryParams().isEmpty()) + + // check conditional update request url: Patient?... + else if (eruComponentes.getPathSegments().size() == 1 && !eruComponentes.getQueryParams().isEmpty()) { if (!entry.getFullUrl().startsWith(URL_UUID_PREFIX)) throw new WebApplicationException( @@ -100,6 +106,8 @@ else if (resource.hasIdElement() && !entry.getFullUrl().equals(resource.getIdEle throw new WebApplicationException(responseGenerator.badBundleEntryFullUrlVsResourceId(index, entry.getFullUrl(), resource.getIdElement().getValue())); } + + // all other request urls else throw new WebApplicationException( responseGenerator.badUpdateRequestUrl(index, entry.getRequest().getUrl())); @@ -138,6 +146,8 @@ private void updateById(Map<String, IdType> idTranslationTable, Connection conne throw new WebApplicationException(responseGenerator.nonMatchingResourceTypeAndRequestUrlInBundle(index, resourceTypeName, entry.getRequest().getUrl())); + checkUpdateAllowed(user, connection, resource); + Optional<Long> ifMatch = Optional.ofNullable(entry.getRequest().getIfMatch()) .flatMap(parameterConverter::toEntityTag).flatMap(parameterConverter::toVersion); @@ -145,6 +155,28 @@ private void updateById(Map<String, IdType> idTranslationTable, Connection conne () -> dao.updateWithTransaction(connection, resource, ifMatch.orElse(null))); } + private void checkUpdateAllowed(User user, Connection connection, Resource newResource) + { + String resourceTypeName = newResource.getResourceType().name(); + String id = newResource.getIdElement().getIdPart(); + + Optional<R> dbResource = exceptionHandler.handleSqlAndResourceDeletedException(resourceTypeName, + () -> dao.readWithTransaction(connection, parameterConverter.toUuid(resourceTypeName, id))); + + if (dbResource.isEmpty()) + { + audit.info("Create as Update of non existing resource {} denied for user '{}'", resourceTypeName + "/" + id, + user.getName()); + throw new WebApplicationException( + responseGenerator.updateAsCreateNotAllowed(resourceTypeName, resourceTypeName + "/" + id)); + } + else + { + R oldResource = dbResource.get(); + authorizationCommandFactory.checkUpdateAllowed(connection, user, oldResource, newResource); + } + } + private void updateByCondition(Map<String, IdType> idTranslationTable, Connection connection, String resourceTypeName, Map<String, List<String>> queryParameters) throws SQLException { @@ -176,6 +208,8 @@ private void updateByCondition(Map<String, IdType> idTranslationTable, Connectio if (result.getOverallCount() <= 0 && (!resource.hasId() || resource.getIdElement().getValue().startsWith(URL_UUID_PREFIX))) { + authorizationCommandFactory.checkCreateAllowed(connection, user, resource); + id = UUID.randomUUID(); idTranslationTable.put(entry.getFullUrl(), new IdType(resource.getResourceType().toString(), id.toString())); @@ -196,24 +230,28 @@ else if (result.getOverallCount() == 1) R dbResource = result.getPartialResult().get(0); IdType dbResourceId = dbResource.getIdElement(); - // BaseUrl - The server base URL (e.g. "http://example.com/fhir") - // ResourceType - The resource type (e.g. "Patient") - // IdPart - The ID (e.g. "123") - // Version - The version ID ("e.g. "456") + // update: resource has no id or resource has temporary id if (!resource.hasId() || resource.getIdElement().getValue().startsWith(URL_UUID_PREFIX)) { resource.setIdElement(dbResourceId); + + // more security checks and audit log in update method + updateById(idTranslationTable, connection, resourceTypeName, resource.getIdElement().getIdPart()); + idTranslationTable.put(entry.getFullUrl(), new IdType(resource.getResourceType().toString(), dbResource.getIdElement().getIdPart())); - updateById(idTranslationTable, connection, resourceTypeName, resource.getIdElement().getIdPart()); } + // update: resource has same id else if (resource.hasId() && (!resource.getIdElement().hasBaseUrl() || serverBase.equals(resource.getIdElement().getBaseUrl())) && (!resource.getIdElement().hasResourceType() || resourceTypeName.equals(resource.getIdElement().getResourceType())) && (dbResourceId.getIdPart().equals(resource.getIdElement().getIdPart()))) + { + // more security checks and audit log in update method updateById(idTranslationTable, connection, resourceTypeName, resource.getIdElement().getIdPart()); + } else // TODO bundle specific error throw new WebApplicationException(responseGenerator.badRequestIdsNotMatching( @@ -230,7 +268,7 @@ else if (resource.hasId() } @Override - public BundleEntryComponent postExecute(Connection connection) + public Optional<BundleEntryComponent> postExecute(Connection connection) { try { @@ -254,7 +292,7 @@ public BundleEntryComponent postExecute(Connection connection) response.setEtag(new EntityTag(updatedResource.getMeta().getVersionId(), true).toString()); response.setLastModified(updatedResource.getMeta().getLastUpdated()); - return resultEntry; + return Optional.of(resultEntry); } private R latestOrErrorIfDeletedOrNotFound(Connection connection, Resource resource) throws Exception diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateStructureDefinitionCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateStructureDefinitionCommand.java index 04bce61d7..1132e6c44 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateStructureDefinitionCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateStructureDefinitionCommand.java @@ -2,6 +2,7 @@ import java.sql.Connection; import java.util.Map; +import java.util.Optional; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.StructureDefinitionDao; @@ -36,14 +37,14 @@ public class UpdateStructureDefinitionCommand extends UpdateCommand<StructureDef private StructureDefinition resourceWithSnapshot; public UpdateStructureDefinitionCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, - String serverBase, StructureDefinition resource, StructureDefinitionDao dao, - ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, + String serverBase, AuthorizationCommandFactory authorizationCommandFactory, StructureDefinition resource, + StructureDefinitionDao dao, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, ResponseGenerator responseGenerator, EventManager eventManager, EventGenerator eventGenerator, StructureDefinitionSnapshotDao snapshotDao, SnapshotGenerator snapshotGenerator, SnapshotDependencyAnalyzer snapshotDependencyAnalyzer) { - super(index, user, bundle, entry, serverBase, resource, dao, exceptionHandler, parameterConverter, - responseGenerator, eventManager, eventGenerator); + super(index, user, bundle, entry, serverBase, authorizationCommandFactory, resource, dao, exceptionHandler, + parameterConverter, responseGenerator, eventManager, eventGenerator); this.snapshotDao = snapshotDao; this.snapshotGenerator = snapshotGenerator; @@ -60,7 +61,7 @@ public void preExecute(Map<String, IdType> idTranslationTable) } @Override - public BundleEntryComponent postExecute(Connection connection) + public Optional<BundleEntryComponent> postExecute(Connection connection) { if (resourceWithSnapshot != null) { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/NamingSystemDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/NamingSystemDaoJdbc.java index 908a03519..6be6c6188 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/NamingSystemDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/NamingSystemDaoJdbc.java @@ -1,15 +1,26 @@ package org.highmed.dsf.fhir.dao.jdbc; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Objects; +import java.util.Optional; + import org.apache.commons.dbcp2.BasicDataSource; import org.highmed.dsf.fhir.dao.NamingSystemDao; import org.highmed.dsf.fhir.search.parameters.NamingSystemName; import org.highmed.dsf.fhir.search.parameters.user.NamingSystemUserFilter; import org.hl7.fhir.r4.model.NamingSystem; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import ca.uhn.fhir.context.FhirContext; public class NamingSystemDaoJdbc extends AbstractResourceDaoJdbc<NamingSystem> implements NamingSystemDao { + private static final Logger logger = LoggerFactory.getLogger(NamingSystemDaoJdbc.class); + public NamingSystemDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, NamingSystem.class, "naming_systems", "naming_system", "naming_system_id", @@ -21,4 +32,36 @@ protected NamingSystem copy(NamingSystem resource) { return resource.copy(); } + + @Override + public Optional<NamingSystem> readByName(String name) throws SQLException + { + try (Connection connection = getDataSource().getConnection()) + { + return readByNameWithTransaction(connection, name); + } + } + + @Override + public Optional<NamingSystem> readByNameWithTransaction(Connection connection, String name) throws SQLException + { + Objects.requireNonNull(connection, "connection"); + if (name == null || name.isBlank()) + return Optional.empty(); + + try (PreparedStatement statement = connection + .prepareStatement("SELECT naming_system FROM current_naming_systems WHERE naming_system->>'name' = ?")) + { + statement.setString(1, name); + + logger.trace("Executing query '{}'", statement); + try (ResultSet result = statement.executeQuery()) + { + if (result.next()) + return Optional.of(getResource(result, 1)); + else + return Optional.empty(); + } + } + } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java index c2846d5c5..ccfea5518 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java @@ -124,4 +124,38 @@ public Optional<Organization> readActiveNotDeletedByIdentifier(String identifier } } } + + @Override + public boolean existsNotDeletedByThumbprintWithTransaction(Connection connection, String thumbprintHex) + throws SQLException + { + if (thumbprintHex == null || thumbprintHex.isBlank()) + return false; + + try (PreparedStatement statement = connection.prepareStatement( + "SELECT organization FROM current_organizations WHERE organization->'extension' @> ?::jsonb")) + { + String search = "[{\"url\": \"http://highmed.org/fhir/StructureDefinition/certificate-thumbprint\", \"valueString\": \"" + + thumbprintHex + "\"}]"; + statement.setString(1, search); + + logger.trace("Executing query '{}'", statement); + try (ResultSet result = statement.executeQuery()) + { + if (result.next()) + { + Organization organization = getResource(result, 1); + logger.debug("Organization with thumprint {}, IdPart {} found", thumbprintHex, + organization.getIdElement().getIdPart()); + return true; + } + else + { + logger.debug("Organization with thumprint {} not found", thumbprintHex); + return false; + } + } + } + } + } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProvider.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProvider.java index 4ac988eef..1fd482577 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProvider.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProvider.java @@ -1,5 +1,7 @@ package org.highmed.dsf.fhir.dao.provider; +import java.sql.Connection; +import java.sql.SQLException; import java.util.Optional; import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; @@ -27,6 +29,10 @@ public interface DaoProvider { + Connection newReadOnlyAutoCommitTransaction() throws SQLException; + + Connection newReadWriteTransaction() throws SQLException; + ActivityDefinitionDao getActivityDefinitionDao(); BinaryDao getBinaryDao(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProviderImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProviderImpl.java index 343a403c6..2d20adce6 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProviderImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/provider/DaoProviderImpl.java @@ -1,10 +1,14 @@ package org.highmed.dsf.fhir.dao.provider; +import java.sql.Connection; +import java.sql.SQLException; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.Optional; +import javax.sql.DataSource; + import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; import org.highmed.dsf.fhir.dao.BinaryDao; import org.highmed.dsf.fhir.dao.BundleDao; @@ -52,6 +56,7 @@ public class DaoProviderImpl implements DaoProvider, InitializingBean { + private final DataSource dataSource; private final ActivityDefinitionDao activityDefinitionDao; private final BinaryDao binaryDao; private final BundleDao bundleDao; @@ -76,8 +81,8 @@ public class DaoProviderImpl implements DaoProvider, InitializingBean private final Map<Class<? extends Resource>, ResourceDao<?>> daosByResourecClass = new HashMap<>(); private final Map<String, ResourceDao<?>> daosByResourceTypeName = new HashMap<>(); - public DaoProviderImpl(ActivityDefinitionDao activityDefinitionDao, BinaryDao binaryDao, BundleDao bundleDao, - CodeSystemDao codeSystemDao, EndpointDao endpointDao, GroupDao groupDao, + public DaoProviderImpl(DataSource dataSource, ActivityDefinitionDao activityDefinitionDao, BinaryDao binaryDao, + BundleDao bundleDao, CodeSystemDao codeSystemDao, EndpointDao endpointDao, GroupDao groupDao, HealthcareServiceDao healthcareServiceDao, LocationDao locationDao, NamingSystemDao namingSystemDao, OrganizationDao organizationDao, PatientDao patientDao, PractitionerDao practitionerDao, PractitionerRoleDao practitionerRoleDao, ProvenanceDao provenanceDao, ResearchStudyDao researchStudyDao, @@ -85,6 +90,7 @@ public DaoProviderImpl(ActivityDefinitionDao activityDefinitionDao, BinaryDao bi StructureDefinitionSnapshotDao structureDefinitionSnapshotDao, SubscriptionDao subscriptionDao, TaskDao taskDao, ValueSetDao valueSetDao) { + this.dataSource = dataSource; this.activityDefinitionDao = activityDefinitionDao; this.binaryDao = binaryDao; this.bundleDao = bundleDao; @@ -154,6 +160,28 @@ public void afterPropertiesSet() throws Exception Objects.requireNonNull(valueSetDao, "valueSetDao"); } + @Override + public Connection newReadOnlyAutoCommitTransaction() throws SQLException + { + Connection connection = dataSource.getConnection(); + + if (!connection.isReadOnly() || !connection.getAutoCommit()) + throw new IllegalStateException("read only, auto commit connection expected from data source"); + + return connection; + } + + @Override + public Connection newReadWriteTransaction() throws SQLException + { + Connection connection = dataSource.getConnection(); + connection.setReadOnly(false); + connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ); + connection.setAutoCommit(false); + + return connection; + } + @Override public ActivityDefinitionDao getActivityDefinitionDao() { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ResponseGenerator.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ResponseGenerator.java index e03998668..f90b7dd54 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ResponseGenerator.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/help/ResponseGenerator.java @@ -554,6 +554,15 @@ public Response badDeleteRequestUrl(int bundleIndex, String url) return Response.status(Status.BAD_REQUEST).entity(outcome).build(); } + public Response badCreateRequestUrl(int bundleIndex, String url) + { + logger.warn("Bad crate request url {} at bundle index {}", url, bundleIndex); + + OperationOutcome outcome = createOutcome(IssueSeverity.ERROR, IssueType.PROCESSING, + "Bad crete request url " + url + " at bundle index " + bundleIndex); + return Response.status(Status.BAD_REQUEST).entity(outcome).build(); + } + public Response badUpdateRequestUrl(int bundleIndex, String url) { logger.warn("Bad update request url {} at bundle index {}", url, bundleIndex); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointAddress.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointAddress.java new file mode 100644 index 000000000..dc070a108 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointAddress.java @@ -0,0 +1,89 @@ +package org.highmed.dsf.fhir.search.parameters; + +import java.sql.Array; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Objects; + +import org.highmed.dsf.fhir.function.BiFunctionWithSqlException; +import org.highmed.dsf.fhir.search.SearchQueryParameter.SearchParameterDefinition; +import org.highmed.dsf.fhir.search.parameters.basic.AbstractCanonicalUrlParameter; +import org.hl7.fhir.r4.model.Endpoint; +import org.hl7.fhir.r4.model.Enumerations.SearchParamType; +import org.hl7.fhir.r4.model.Resource; + +@SearchParameterDefinition(name = EndpointAddress.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Endpoint-address", type = SearchParamType.URI, documentation = "The address (url) of the endpoint") +public class EndpointAddress extends AbstractCanonicalUrlParameter<Endpoint> +{ + public static final String PARAMETER_NAME = "address"; + + public EndpointAddress() + { + super(PARAMETER_NAME); + } + + @Override + public String getFilterQuery() + { + switch (valueAndType.type) + { + case PRECISE: + return "endpoint->>'address' = ?"; + case BELOW: + return "endpoint->>'address' LIKE ?"; + default: + return ""; + } + } + + @Override + public int getSqlParameterCount() + { + return 1; + } + + @Override + public void modifyStatement(int parameterIndex, int subqueryParameterIndex, PreparedStatement statement, + BiFunctionWithSqlException<String, Object[], Array> arrayCreator) throws SQLException + { + switch (valueAndType.type) + { + case PRECISE: + statement.setString(parameterIndex, valueAndType.url); + return; + case BELOW: + statement.setString(parameterIndex, valueAndType.url + "%"); + return; + default: + return; + } + } + + @Override + public boolean matches(Resource resource) + { + if (!isDefined()) + throw notDefined(); + + if (!(resource instanceof Endpoint)) + return false; + + Endpoint endpoint = (Endpoint) resource; + + switch (valueAndType.type) + { + case PRECISE: + return Objects.equals(endpoint.getAddress(), valueAndType.url); + case BELOW: + return endpoint.getAddress() != null && endpoint.getAddress().startsWith(valueAndType.url); + default: + throw notDefined(); + } + } + + @Override + protected String getSortSql(String sortDirectionWithSpacePrefix) + { + return "endpoint->>'address'" + sortDirectionWithSpacePrefix; + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/basic/AbstractUrlAndVersionParameter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/basic/AbstractUrlAndVersionParameter.java index 5a5fda208..f7d97732f 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/basic/AbstractUrlAndVersionParameter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/basic/AbstractUrlAndVersionParameter.java @@ -60,7 +60,6 @@ public void modifyStatement(int parameterIndex, int subqueryParameterIndex, Prep return; default: return; - } else if (subqueryParameterIndex == 2) statement.setString(parameterIndex, valueAndType.version); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolver.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolver.java index 165828577..48372a377 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolver.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolver.java @@ -43,6 +43,22 @@ Optional<Resource> resolveReference(User user, String referenceLocation, Referen */ Optional<Resource> resolveReference(User user, ResourceReference reference); + /** + * @param user + * not <code>null</code> + * @param reference + * not <code>null</code> + * @param connection + * not <code>null</code> + * @return {@link Optional#empty()} if the reference could not be resolved + * @throws IllegalArgumentException + * if the reference is not of type {@link ResourceReference.ReferenceType#LITERAL_INTERNAL}, + * {@link ResourceReference.ReferenceType#LITERAL_EXTERNAL}, + * {@link ResourceReference.ReferenceType#CONDITIONAL} or + * {@link ResourceReference.ReferenceType#LOGICAL} + */ + Optional<Resource> resolveReference(User user, ResourceReference reference, Connection connection); + /** * @param user * not <code>null</code> diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolverImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolverImpl.java index 8a477a74a..282ddd1ab 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolverImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/service/ReferenceResolverImpl.java @@ -88,13 +88,36 @@ public Optional<Resource> resolveReference(User user, ResourceReference referenc switch (reference.getType(serverBase)) { case LITERAL_INTERNAL: - return resolveLiteralInternalReference(reference); + return resolveLiteralInternalReference(reference, null); case LITERAL_EXTERNAL: return resolveLiteralExternalReference(reference); case CONDITIONAL: - return resolveConditionalReference(user, reference); + return resolveConditionalReference(user, reference, null); case LOGICAL: - return resolveLogicalReference(user, reference); + return resolveLogicalReference(user, reference, null); + default: + throw new IllegalArgumentException( + "Reference of type " + reference.getType(serverBase) + " not supported"); + } + } + + @Override + public Optional<Resource> resolveReference(User user, ResourceReference reference, Connection connection) + { + Objects.requireNonNull(user, "user"); + Objects.requireNonNull(reference, "reference"); + Objects.requireNonNull(connection, "connection"); + + switch (reference.getType(serverBase)) + { + case LITERAL_INTERNAL: + return resolveLiteralInternalReference(reference, connection); + case LITERAL_EXTERNAL: + return resolveLiteralExternalReference(reference); + case CONDITIONAL: + return resolveConditionalReference(user, reference, connection); + case LOGICAL: + return resolveLogicalReference(user, reference, connection); default: throw new IllegalArgumentException( "Reference of type " + reference.getType(serverBase) + " not supported"); @@ -133,7 +156,8 @@ public boolean resolveReference(User user, Resource resource, Integer bundleInde } } - private Optional<Resource> resolveLiteralInternalReference(ResourceReference resourceReference) + private Optional<Resource> resolveLiteralInternalReference(ResourceReference resourceReference, + Connection connection) { Objects.requireNonNull(resourceReference, "resourceReference"); if (!ReferenceType.LITERAL_INTERNAL.equals(resourceReference.getType(serverBase))) @@ -162,11 +186,21 @@ private Optional<Resource> resolveLiteralInternalReference(ResourceReference res Optional<UUID> uuid = parameterConverter.toUuid(id.getIdPart()); if (!id.hasVersionIdPart()) - return uuid.flatMap(i -> exceptionHandler.catchAndLogSqlAndResourceDeletedExceptionAndIfReturn( - () -> d.read(i), Optional::empty, Optional::empty)); + return uuid.flatMap(i -> exceptionHandler.catchAndLogSqlAndResourceDeletedExceptionAndIfReturn(() -> + { + if (connection == null) + return d.read(i); + else + return d.readWithTransaction(connection, i); + }, Optional::empty, Optional::empty)); else - return uuid.flatMap(i -> exceptionHandler.catchAndLogSqlAndResourceDeletedExceptionAndIfReturn( - () -> d.readVersion(i, id.getVersionIdPartAsLong()), Optional::empty, Optional::empty)); + return uuid.flatMap(i -> exceptionHandler.catchAndLogSqlAndResourceDeletedExceptionAndIfReturn(() -> + { + if (connection == null) + return d.readVersion(i, id.getVersionIdPartAsLong()); + else + return d.readVersionWithTransaction(connection, i, id.getVersionIdPartAsLong()); + }, Optional::empty, Optional::empty)); } } @@ -286,7 +320,8 @@ public boolean resolveLiteralExternalReference(Resource resource, Integer bundle return true; // throws exception if reference could not be resolved } - private Optional<Resource> resolveConditionalReference(User user, ResourceReference resourceReference) + private Optional<Resource> resolveConditionalReference(User user, ResourceReference resourceReference, + Connection connection) { Objects.requireNonNull(resourceReference, "resourceReference"); if (!ReferenceType.CONDITIONAL.equals(resourceReference.getType(serverBase))) @@ -320,7 +355,7 @@ private Optional<Resource> resolveConditionalReference(User user, ResourceRefere return Optional.empty(); } - return search(user, d, resourceReference, condition.getQueryParams(), true); + return search(user, connection, d, resourceReference, condition.getQueryParams(), true); } } @@ -372,7 +407,8 @@ public boolean resolveConditionalReference(User user, Resource resource, Integer return true; // throws exception if reference could not be resolved } - private Optional<Resource> resolveLogicalReference(User user, ResourceReference resourceReference) + private Optional<Resource> resolveLogicalReference(User user, ResourceReference resourceReference, + Connection connection) { Objects.requireNonNull(resourceReference, "resourceReference"); if (!ReferenceType.LOGICAL.equals(resourceReference.getType(serverBase))) @@ -399,7 +435,7 @@ private Optional<Resource> resolveLogicalReference(User user, ResourceReference } Identifier targetIdentifier = resourceReference.getReference().getIdentifier(); - return search(user, d, resourceReference, Map.of("identifier", + return search(user, connection, d, resourceReference, Map.of("identifier", Collections.singletonList(targetIdentifier.getSystem() + "|" + targetIdentifier.getValue())), true); } } @@ -448,8 +484,9 @@ public boolean resolveLogicalReference(User user, Resource resource, Integer bun return true; // throws exception if reference could not be resolved } - private Optional<Resource> search(User user, ResourceDao<?> referenceTargetDao, ResourceReference resourceReference, - Map<String, List<String>> queryParameters, boolean logicalNotConditional) + private Optional<Resource> search(User user, Connection connection, ResourceDao<?> referenceTargetDao, + ResourceReference resourceReference, Map<String, List<String>> queryParameters, + boolean logicalNotConditional) { if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) { @@ -482,7 +519,13 @@ private Optional<Resource> search(User user, ResourceDao<?> referenceTargetDao, return Optional.empty(); } - PartialResult<?> result = exceptionHandler.handleSqlException(() -> referenceTargetDao.search(query)); + PartialResult<?> result = exceptionHandler.handleSqlException(() -> + { + if (connection == null) + return referenceTargetDao.search(query); + else + return referenceTargetDao.searchWithTransaction(connection, query); + }); if (result.getOverallCount() <= 0) { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/CommandConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/CommandConfig.java index 1a7c9a7f9..ebaa10afc 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/CommandConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/CommandConfig.java @@ -1,5 +1,7 @@ package org.highmed.dsf.fhir.spring.config; +import org.highmed.dsf.fhir.dao.command.AuthorizationCommandFactory; +import org.highmed.dsf.fhir.dao.command.AuthorizationCommandFactoryImpl; import org.highmed.dsf.fhir.dao.command.CommandFactory; import org.highmed.dsf.fhir.dao.command.CommandFactoryImpl; import org.springframework.beans.factory.annotation.Autowired; @@ -31,6 +33,9 @@ public class CommandConfig @Autowired private ReferenceConfig referenceConfig; + @Autowired + private AuthorizationConfig authorizationConfig; + @Bean public CommandFactory commandFactory() { @@ -38,6 +43,14 @@ public CommandFactory commandFactory() referenceConfig.referenceExtractor(), referenceConfig.referenceResolver(), helperConfig.responseGenerator(), helperConfig.exceptionHandler(), eventConfig.eventManager(), eventConfig.eventGenerator(), snapshotConfig.snapshotGenerator(), - snapshotConfig.snapshotDependencyAnalyzer(), helperConfig.parameterConverter()); + snapshotConfig.snapshotDependencyAnalyzer(), helperConfig.parameterConverter(), + authorizationCommandFactory()); + } + + @Bean + public AuthorizationCommandFactory authorizationCommandFactory() + { + return new AuthorizationCommandFactoryImpl(authorizationConfig.authorizationRuleProvider(), + helperConfig.responseGenerator()); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java index e49f94695..6c825e687 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java @@ -222,9 +222,10 @@ public ValueSetDao valueSetDao() @Bean public DaoProvider daoProvider() { - return new DaoProviderImpl(activityDefinitionDao(), binaryDao(), bundleDao(), codeSystemDao(), endpointDao(), - groupDao(), healthcareServiceDao(), locationDao(), namingSystemDao(), organizationDao(), patientDao(), - practitionerDao(), practitionerRoleDao(), provenanceDao(), researchStudyDao(), structureDefinitionDao(), - structureDefinitionSnapshotDao(), subscriptionDao(), taskDao(), valueSetDao()); + return new DaoProviderImpl(dataSource(), activityDefinitionDao(), binaryDao(), bundleDao(), codeSystemDao(), + endpointDao(), groupDao(), healthcareServiceDao(), locationDao(), namingSystemDao(), organizationDao(), + patientDao(), practitionerDao(), practitionerRoleDao(), provenanceDao(), researchStudyDao(), + structureDefinitionDao(), structureDefinitionSnapshotDao(), subscriptionDao(), taskDao(), + valueSetDao()); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java index dbf1868e3..3e3d9e0c0 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/AbstractResourceServiceImpl.java @@ -437,80 +437,6 @@ protected Consumer<R> preUpdate(R resource) public Response update(R resource, UriInfo uri, HttpHeaders headers) { throw new UnsupportedOperationException("Implemented and delegated by security layer"); - - // Map<String, List<String>> queryParameters = uri.getQueryParameters(); - // if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) - // { - // logger.warn( - // "Query contains parameter not applicable in this conditional update context: '{}', parameters {} will be - // ignored", - // UriComponentsBuilder.newInstance() - // .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), - // Arrays.toString(SearchQuery.STANDARD_PARAMETERS)); - // - // queryParameters = queryParameters.entrySet().stream() - // .filter(e -> !Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(p -> p.equals(e.getKey()))) - // .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); - // } - // - // SearchQuery<R> query = dao.createSearchQuery(1, 1); - // query.configureParameters(queryParameters); - // - // List<SearchQueryParameterError> unsupportedQueryParameters = query - // .getUnsupportedQueryParameters(queryParameters); - // if (!unsupportedQueryParameters.isEmpty()) - // return responseGenerator.badRequest( - // UriComponentsBuilder.newInstance() - // .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), - // unsupportedQueryParameters); - // - // PartialResult<R> result = exceptionHandler.handleSqlException(() -> dao.search(query)); - // - // // No matches, no id provided: The server creates the resource. - // if (result.getOverallCount() <= 0 && !resource.hasId()) - // return create(resource, uri, headers); - // - // // No matches, id provided: The server treats the interaction as an Update as Create interaction (or rejects - // it, - // // if it does not support Update as Create) -> reject - // else if (result.getOverallCount() <= 0 && resource.hasId()) - // return responseGenerator.updateAsCreateNotAllowed(resourceTypeName, resource.getId()); - // - // // One Match, no resource id provided OR (resource id provided and it matches the found resource): - // // The server performs the update against the matching resource - // else if (result.getOverallCount() == 1) - // { - // R dbResource = result.getPartialResult().get(0); - // IdType dbResourceId = dbResource.getIdElement(); - // - // // BaseUrl - The server base URL (e.g. "http://example.com/fhir") - // // ResourceType - The resource type (e.g. "Patient") - // // IdPart - The ID (e.g. "123") - // // Version - The version ID ("e.g. "456") - // if (!resource.hasId()) - // { - // resource.setIdElement(dbResourceId); - // return update(resource.getIdElement().getIdPart(), resource, uri, headers); - // } - // else if (resource.hasId() - // && (!resource.getIdElement().hasBaseUrl() - // || serverBase.equals(resource.getIdElement().getBaseUrl())) - // && (!resource.getIdElement().hasResourceType() - // || resourceTypeName.equals(resource.getIdElement().getResourceType())) - // && (dbResourceId.getIdPart().equals(resource.getIdElement().getIdPart()))) - // return update(resource.getIdElement().getIdPart(), resource, uri, headers); - // else - // return responseGenerator.badRequestIdsNotMatching( - // dbResourceId.withServerBase(serverBase, resourceTypeName), - // resource.getIdElement().hasBaseUrl() && resource.getIdElement().hasResourceType() - // ? resource.getIdElement() - // : resource.getIdElement().withServerBase(serverBase, resourceTypeName)); - // } - // // Multiple matches: The server returns a 412 Precondition Failed error indicating the client's criteria were - // // not selective enough preferably with an OperationOutcome - // else // if (result.getOverallCount() > 1) - // throw new WebApplicationException(responseGenerator.multipleExists(resourceTypeName, UriComponentsBuilder - // .newInstance().replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString())); } @Override @@ -552,52 +478,6 @@ protected Consumer<String> preDelete(String id) public Response delete(UriInfo uri, HttpHeaders headers) { throw new UnsupportedOperationException("Implemented and delegated by security layer"); - - // Map<String, List<String>> queryParameters = uri.getQueryParameters(); - // if (Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(queryParameters::containsKey)) - // { - // logger.warn( - // "Query contains parameter not applicable in this conditional delete context: '{}', parameters {} will be - // ignored", - // UriComponentsBuilder.newInstance() - // .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), - // Arrays.toString(SearchQuery.STANDARD_PARAMETERS)); - // - // queryParameters = queryParameters.entrySet().stream() - // .filter(e -> !Arrays.stream(SearchQuery.STANDARD_PARAMETERS).anyMatch(p -> p.equals(e.getKey()))) - // .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); - // } - // - // SearchQuery<R> query = dao.createSearchQuery(1, 1); - // query.configureParameters(queryParameters); - // - // List<SearchQueryParameterError> unsupportedQueryParameters = query - // .getUnsupportedQueryParameters(queryParameters); - // if (!unsupportedQueryParameters.isEmpty()) - // return responseGenerator.badRequest( - // UriComponentsBuilder.newInstance() - // .replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString(), - // unsupportedQueryParameters); - // - // PartialResult<R> result = exceptionHandler.handleSqlException(() -> dao.search(query)); - // - // // No matches - // if (result.getOverallCount() <= 0) - // { - // return Response.noContent().build(); // TODO return OperationOutcome - // } - // // One Match: The server performs an ordinary delete on the matching resource - // else if (result.getOverallCount() == 1) - // { - // R resource = result.getPartialResult().get(0); - // return delete(resource.getIdElement().getIdPart(), uri, headers); - // } - // // Multiple matches: A server may choose to delete all the matching resources, or it may choose to return a - // 412 - // // Precondition Failed error indicating the client's criteria were not selective enough. - // else - // throw new WebApplicationException(responseGenerator.multipleExists(resourceTypeName, UriComponentsBuilder - // .newInstance().replaceQueryParams(CollectionUtils.toMultiValueMap(queryParameters)).toUriString())); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java index 64ac098cf..6f65d4cbe 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java @@ -28,6 +28,7 @@ import org.highmed.dsf.fhir.search.parameters.CodeSystemStatus; import org.highmed.dsf.fhir.search.parameters.CodeSystemUrl; import org.highmed.dsf.fhir.search.parameters.CodeSystemVersion; +import org.highmed.dsf.fhir.search.parameters.EndpointAddress; import org.highmed.dsf.fhir.search.parameters.EndpointIdentifier; import org.highmed.dsf.fhir.search.parameters.EndpointName; import org.highmed.dsf.fhir.search.parameters.EndpointOrganization; @@ -221,12 +222,13 @@ private CapabilityStatement createCapabilityStatement(String serverBase, int def searchParameters.put(CodeSystem.class, Arrays.asList(codeSystemIdentifier, codeSystemUrl, codeSystemVersion, codeSystemStatus)); + var endpointAddress = createSearchParameter(EndpointAddress.class); var endpointIdentifier = createSearchParameter(EndpointIdentifier.class); var endpointName = createSearchParameter(EndpointName.class); var endpointOrganization = createSearchParameter(EndpointOrganization.class); var endpointStatus = createSearchParameter(EndpointStatus.class); searchParameters.put(Endpoint.class, - Arrays.asList(endpointIdentifier, endpointName, endpointOrganization, endpointStatus)); + Arrays.asList(endpointAddress, endpointIdentifier, endpointName, endpointOrganization, endpointStatus)); revIncludeParameters.put(Endpoint.class, Collections.singletonList(OrganizationEndpointRevInclude.class)); // Group diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java index ceaa91d1b..8c2d3b5f9 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java @@ -92,7 +92,8 @@ public Response create(R resource, UriInfo uri, HttpHeaders headers) } else { - audit.info("Create of resource {} allowed for user '{}'", resourceTypeName, getCurrentUser().getName()); + audit.info("Create of resource {} allowed for user '{}': {}", resourceTypeName, getCurrentUser().getName(), + reasonCreateAllowed.get()); return delegate.create(resource, uri, headers); } } @@ -118,8 +119,8 @@ public Response read(String id, UriInfo uri, HttpHeaders headers) } else { - audit.info("Read of resource {} allowed for user '{}'", entity.getIdElement().getValue(), - getCurrentUser().getName()); + audit.info("Read of resource {} allowed for user '{}': {}", entity.getIdElement().getValue(), + getCurrentUser().getName(), reasonReadAllowed.get()); return read; } } @@ -170,8 +171,8 @@ public Response vread(String id, long version, UriInfo uri, HttpHeaders headers) } else { - audit.info("Read of resource {} allowed for user '{}'", entity.getIdElement().getValue(), - getCurrentUser().getName()); + audit.info("Read of resource {} allowed for user '{}': {}", entity.getIdElement().getValue(), + getCurrentUser().getName(), reasonReadAllowed.get()); return read; } } @@ -233,8 +234,8 @@ private Response update(String id, R newResource, UriInfo uri, HttpHeaders heade } else { - audit.info("Update of resource {} allowed for user '{}'", oldResource.getIdElement().getValue(), - getCurrentUser().getName()); + audit.info("Update of resource {} allowed for user '{}': {}", oldResource.getIdElement().getValue(), + getCurrentUser().getName(), reasonUpdateAllowed.get()); Response update = delegate.update(id, newResource, uri, headers); @@ -279,7 +280,7 @@ else if (result.getOverallCount() == 1) R dbResource = result.getPartialResult().get(0); IdType dbResourceId = dbResource.getIdElement(); - // update resource has no id + // update: resource has no id if (!resource.hasId()) { resource.setIdElement(dbResourceId); @@ -287,15 +288,17 @@ else if (result.getOverallCount() == 1) return update(resource.getIdElement().getIdPart(), resource, uri, headers, resource); } - // update resource has same id + // update: resource has same id else if (resource.hasId() && (!resource.getIdElement().hasBaseUrl() || serverBase.equals(resource.getIdElement().getBaseUrl())) && (!resource.getIdElement().hasResourceType() || resourceTypeName.equals(resource.getIdElement().getResourceType())) && (dbResourceId.getIdPart().equals(resource.getIdElement().getIdPart()))) + { // more security checks and audit log in update method return update(resource.getIdElement().getIdPart(), resource, uri, headers, resource); + } // update resource has different id -> 400 Bad Request else @@ -373,8 +376,8 @@ public Response delete(String id, UriInfo uri, HttpHeaders headers) } else { - audit.info("Delete of resource {} allowed for user '{}'", oldResource.getIdElement().getValue(), - getCurrentUser().getName()); + audit.info("Delete of resource {} allowed for user '{}': {}", oldResource.getIdElement().getValue(), + getCurrentUser().getName(), reasonDeleteAllowed.get()); return delegate.delete(id, uri, headers); } } @@ -462,7 +465,8 @@ public Response search(UriInfo uri, HttpHeaders headers) } else { - audit.info("Search of resource {} allowed for user '{}'", resourceTypeName, getCurrentUser().getName()); + audit.info("Search of resource {} allowed for user '{}': {}", resourceTypeName, getCurrentUser().getName(), + reasonSearchAllowed.get()); return delegate.search(uri, headers); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/RootServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/RootServiceSecure.java index 95fdbe513..ca747e811 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/RootServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/RootServiceSecure.java @@ -10,6 +10,7 @@ import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.webservice.specification.RootService; import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Bundle.BundleType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,21 +50,24 @@ public Response handleBundle(Bundle bundle, UriInfo uri, HttpHeaders headers) } else { - audit.info("Handling of transaction or batch bundle allowed for user '{}'", getCurrentUser().getName()); + audit.info("Handling of transaction or batch bundle allowed for user '{}': {}", getCurrentUser().getName(), + reasonHandleBundleAllowed.get()); return delegate.handleBundle(bundle, uri, headers); } } private Optional<String> reasonHandleBundleAllowed(Bundle bundle) { - /* - * TODO check if operation for each entry in transaction / batch bundle is allowed, batch can have not allowed - * operations and will return 403 for those, transaction can't and will return 403 for all - */ - - // if (!UserRole.LOCAL.equals(userProvider.getCurrentUser().getRole())) - // return Optional.of("Missing role 'LOCAL'"); - // else - return Optional.empty(); + if (BundleType.BATCH.equals(bundle.getType()) || BundleType.TRANSACTION.equals(bundle.getType())) + { + logger.info( + "Handling of batch or transaction bundles generaly allowed for all, entries will be individualy evaluated"); + return Optional.of("Allowed for all, entries individualy evaluated"); + } + else + { + logger.warn("Handling bundle denied, not a batch or transaction bundle"); + return Optional.empty(); + } } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-endpoint-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-endpoint-0.1.0.xml index e5e1f468a..cd3b2543e 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-endpoint-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-endpoint-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-endpoint" /> <version value="0.1.0" /> <name value="Endpoint" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-certificate-thumbprint-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-certificate-thumbprint-0.1.0.xml index a46d46580..2d907ecfe 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-certificate-thumbprint-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-certificate-thumbprint-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"/> <version value="0.1.0"/> <name value="CertificateThumbprint"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-group-id-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-group-id-0.1.0.xml index 088e0572e..7745eceeb 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-group-id-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-group-id-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/group-id" /> <version value="0.1.0" /> <name value="group-id" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-medic-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-medic-0.1.0.xml index bf1c25812..99e12927b 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-medic-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-medic-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/participating-medic"/> <version value="0.1.0"/> <name value="ParticipatingMedic"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml index 34d6ee228..9b8399723 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/process-authorization" /> <version value="0.1.0" /> <name value="ProcessAuthorization" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-query-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-query-0.1.0.xml index ebbdaab2c..f327fb0da 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-query-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-query-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/query"/> <version value="0.1.0"/> <name value="Query"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-group-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-group-0.1.0.xml index 696762c94..172bbf943 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-group-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-group-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-group"/> <version value="0.1.0"/> <name value="Group"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-organization-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-organization-0.1.0.xml index eebcd083b..beb541bae 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-organization-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-organization-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-organization" /> <version value="0.1.0" /> <name value="Organization" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-practitioner-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-practitioner-0.1.0.xml index f9be2be90..a0fb80555 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-practitioner-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-practitioner-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-practitioner"/> <version value="0.1.0"/> <name value="Practitioner"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-practitioner-role-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-practitioner-role-0.1.0.xml index bc829e1b9..f88b8955c 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-practitioner-role-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-practitioner-role-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-practitioner-role"/> <version value="0.1.0"/> <name value="PractitionerRole"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-research-study-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-research-study-0.1.0.xml index cd93e05f0..8eab7dc16 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-research-study-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-research-study-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-research-study"/> <version value="0.1.0"/> <name value="ResearchStudy"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-base-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-base-0.1.0.xml index 821ba8fb4..53c01ec14 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-base-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-base-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-base" /> <version value="0.1.0" /> <name value="TaskBase" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-compute-simple-feasibility-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-compute-simple-feasibility-0.1.0.xml index 08309f28c..5b38ee2c7 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-compute-simple-feasibility-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-compute-simple-feasibility-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-compute-simple-feasibility" /> <version value="0.1.0" /> <name value="TaskComputeSimpleFeasibility" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-execute-simple-feasibility-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-execute-simple-feasibility-0.1.0.xml index 3408d68e7..8287bf014 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-execute-simple-feasibility-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-execute-simple-feasibility-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-execute-simple-feasibility" /> <version value="0.1.0" /> <name value="TaskExecuteSimpleFeasibility" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-execute-update-resources-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-execute-update-resources-0.1.0.xml index 01a6715cf..b2d01560a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-execute-update-resources-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-execute-update-resources-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-execute-update-resources" /> <version value="0.1.0" /> <name value="TaskExecuteUpdateResources" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-simple-feasibility-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-simple-feasibility-0.1.0.xml index 6fb8a8826..5631c56e7 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-simple-feasibility-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-simple-feasibility-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-multi-medic-result-simple-feasibility" /> <version value="0.1.0" /> <name value="TaskMultiMedicResultSimpleFeasibility" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-parent-plugin-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-parent-plugin-0.1.0.xml index ccd1e0c25..fd196b201 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-parent-plugin-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-parent-plugin-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-parent-plugin" /> <version value="0.1.0" /> <name value="ParentPlugin" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-ping-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-ping-0.1.0.xml index 7bfb535bf..91b4f906b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-ping-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-ping-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-ping" /> <version value="0.1.0" /> <name value="TaskPing" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-pong-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-pong-0.1.0.xml index 930e5de96..0f05366e9 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-pong-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-pong-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-pong" /> <version value="0.1.0" /> <name value="TaskPong" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-simple-feasibility-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-simple-feasibility-0.1.0.xml index b81283acb..52237d5a3 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-simple-feasibility-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-simple-feasibility-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-request-simple-feasibility" /> <version value="0.1.0" /> <name value="TaskRequestSimpleFeasibility" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-update-resources-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-update-resources-0.1.0.xml index eccfc6963..9a71198d4 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-update-resources-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-update-resources-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-request-update-resources" /> <version value="0.1.0" /> <name value="TaskRequestUpdateResources" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-simple-feasibility-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-simple-feasibility-0.1.0.xml index 8b3903220..3c2aa0db5 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-simple-feasibility-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-simple-feasibility-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-single-medic-result-simple-feasibility" /> <version value="0.1.0" /> <name value="TaskSingleMedicResultSimpleFeasibility" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-start-process-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-start-process-0.1.0.xml index 189b12578..34995ae79 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-start-process-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-start-process-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highemd-task-start-process" /> <version value="0.1.0" /> <name value="TaskStartProcess" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-update-whitelist-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-update-whitelist-0.1.0.xml index 6fe35f5a9..0774c92d0 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-update-whitelist-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-update-whitelist-0.1.0.xml @@ -1,5 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-update-whitelist" /> <version value="0.1.0" /> <name value="TaskUpdateWhiteList" /> diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/db/TransactionLearningTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/db/TransactionLearningTest.java new file mode 100644 index 000000000..5c6002ac0 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/db/TransactionLearningTest.java @@ -0,0 +1,177 @@ +package org.highmed.dsf.fhir.db; + +import static org.junit.Assert.*; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.UUID; + +import org.highmed.dsf.fhir.test.FhirEmbeddedPostgresWithLiquibase; +import org.highmed.dsf.fhir.test.TestSuiteIntegrationTests; +import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.Resource; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.postgresql.util.PGobject; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.parser.DataFormatException; +import de.rwh.utils.test.Database; + +public class TransactionLearningTest +{ + @ClassRule + public static final FhirEmbeddedPostgresWithLiquibase template = new FhirEmbeddedPostgresWithLiquibase( + TestSuiteIntegrationTests.template); + + @Rule + public final Database database = new Database(template); + + private final FhirContext context = FhirContext.forR4(); + + @Test + public void testTransactionsCommitTwice() throws Exception + { + try (Connection connection = database.getDataSource().getConnection()) + { + connection.setAutoCommit(false); + connection.setReadOnly(false); + connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ); + + for (int i = 1; i <= 2; i++) + try (PreparedStatement statement = connection + .prepareStatement("INSERT INTO patients (patient_id, patient) VALUES (?, ?)")) + { + UUID id = UUID.randomUUID(); + Patient patient = new Patient(); + patient.setIdElement(new IdType("Patient", id.toString())); + + statement.setObject(1, uuidToPgObject(id)); + statement.setObject(2, resourceToPgObject(patient)); + + statement.execute(); + } + + connection.commit(); + + try (PreparedStatement statement = connection + .prepareStatement("INSERT INTO patients (patient_id, patient) VALUES (?, ?)")) + { + UUID id = UUID.randomUUID(); + Patient patient = new Patient(); + patient.setIdElement(new IdType("Patient", id.toString())); + + statement.setObject(1, uuidToPgObject(id)); + statement.setObject(2, resourceToPgObject(patient)); + + statement.execute(); + } + + connection.commit(); + } + + try (Connection connection = database.getDataSource().getConnection()) + { + try (PreparedStatement statement = connection.prepareStatement("SELECT COUNT(*) FROM patients"); + ResultSet result = statement.executeQuery()) + { + assertTrue(result.next()); + assertEquals(3, result.getInt(1)); + } + } + } + + @Test + public void testTransactionsCommitRollback() throws Exception + { + try (Connection connection = database.getDataSource().getConnection()) + { + connection.setAutoCommit(false); + connection.setReadOnly(false); + connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ); + + for (int i = 1; i <= 2; i++) + try (PreparedStatement statement = connection + .prepareStatement("INSERT INTO patients (patient_id, patient) VALUES (?, ?)")) + { + UUID id = UUID.randomUUID(); + Patient patient = new Patient(); + patient.setIdElement(new IdType("Patient", id.toString())); + + statement.setObject(1, uuidToPgObject(id)); + statement.setObject(2, resourceToPgObject(patient)); + + statement.execute(); + } + + connection.commit(); + + try (PreparedStatement statement = connection + .prepareStatement("INSERT INTO patients (patient_id, patient) VALUES (?, ?)")) + { + UUID id = UUID.randomUUID(); + Patient patient = new Patient(); + patient.setIdElement(new IdType("Patient", id.toString())); + + statement.setObject(1, uuidToPgObject(id)); + statement.setObject(2, resourceToPgObject(patient)); + + statement.execute(); + } + + // checking if consecutive roll backs work without commit in between + connection.rollback(); + connection.rollback(); + } + + try (Connection connection = database.getDataSource().getConnection()) + { + try (PreparedStatement statement = connection.prepareStatement("SELECT COUNT(*) FROM patients"); + ResultSet result = statement.executeQuery()) + { + assertTrue(result.next()); + assertEquals(2, result.getInt(1)); + } + } + } + + private final PGobject resourceToPgObject(Resource resource) + { + if (resource == null) + return null; + + try + { + PGobject o = new PGobject(); + o.setType("JSONB"); + o.setValue(context.newJsonParser().encodeResourceToString(resource)); + return o; + } + catch (DataFormatException | SQLException e) + { + throw new RuntimeException(e); + } + } + + private final PGobject uuidToPgObject(UUID uuid) + { + if (uuid == null) + return null; + + try + { + PGobject o = new PGobject(); + o.setType("UUID"); + o.setValue(uuid.toString()); + return o; + } + catch (DataFormatException | SQLException e) + { + throw new RuntimeException(e); + } + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java index 2439e7f42..0b8367c39 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java @@ -92,8 +92,8 @@ public abstract class AbstractIntegrationTest private static final Logger logger = LoggerFactory.getLogger(AbstractIntegrationTest.class); - private static final String BASE_URL = "https://localhost:8001/fhir/"; - private static final String WEBSOCKET_URL = "wss://localhost:8001/fhir/ws"; + protected static final String BASE_URL = "https://localhost:8001/fhir/"; + protected static final String WEBSOCKET_URL = "wss://localhost:8001/fhir/ws"; private static final Path FHIR_BUNDLE_FILE = Paths.get("target", UUID.randomUUID().toString() + ".xml"); private static final List<Path> FILES_TO_DELETE = Arrays.asList(FHIR_BUNDLE_FILE); diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/BinaryIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/BinaryIntegrationTest.java index 455c516a7..1adf9f43f 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/BinaryIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/BinaryIntegrationTest.java @@ -2,6 +2,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.nio.charset.StandardCharsets; @@ -21,6 +22,8 @@ import org.highmed.dsf.fhir.search.PartialResult; import org.hl7.fhir.r4.model.Binary; import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Bundle.BundleType; +import org.hl7.fhir.r4.model.Bundle.HTTPVerb; import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Reference; import org.junit.Test; @@ -119,6 +122,246 @@ public void testReadNotAllowedExternalUser() throws Exception } } + @Test + public void testReadAllowedLocalUserViaTransactionBundle() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + PartialResult<Organization> result = orgDao.search(orgDao.createSearchQueryWithoutUserFilter(1, 1) + .configureParameters(Map.of("name", Arrays.asList("Test Organization")))); + assertNotNull(result); + assertEquals(1, result.getOverallCount()); + assertNotNull(result.getPartialResult()); + assertEquals(1, result.getPartialResult().size()); + assertNotNull(result.getPartialResult().get(0)); + + Organization org = result.getPartialResult().get(0); + + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference(org.getIdElement().toVersionless())); + + BinaryDao binDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binDao.create(binary); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.TRANSACTION); + bundle.addEntry().getRequest().setMethod(HTTPVerb.GET).setUrl("Binary/" + created.getIdElement().getIdPart()); + + Bundle responseBundle = getWebserviceClient().postBundle(bundle); + assertNotNull(responseBundle); + assertEquals(BundleType.TRANSACTIONRESPONSE, responseBundle.getType()); + assertEquals(1, responseBundle.getEntry().size()); + assertNotNull(responseBundle.getEntry().get(0)); + assertNotNull(responseBundle.getEntry().get(0).getResource()); + assertTrue(responseBundle.getEntry().get(0).getResource() instanceof Binary); + assertEquals(created.getIdElement().getIdPart(), + responseBundle.getEntry().get(0).getResource().getIdElement().getIdPart()); + } + + @Test + public void testReadAllowedExternalUserViaTransactionBundle() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + PartialResult<Organization> result = orgDao.search(orgDao.createSearchQueryWithoutUserFilter(1, 1) + .configureParameters(Map.of("name", Arrays.asList("External Test Organization")))); + assertNotNull(result); + assertEquals(1, result.getOverallCount()); + assertNotNull(result.getPartialResult()); + assertEquals(1, result.getPartialResult().size()); + assertNotNull(result.getPartialResult().get(0)); + + Organization org = result.getPartialResult().get(0); + + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference(org.getIdElement().toVersionless())); + + BinaryDao binDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binDao.create(binary); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.TRANSACTION); + bundle.addEntry().getRequest().setMethod(HTTPVerb.GET).setUrl("Binary/" + created.getIdElement().getIdPart()); + + Bundle responseBundle = getExternalWebserviceClient().postBundle(bundle); + assertNotNull(responseBundle); + assertEquals(BundleType.TRANSACTIONRESPONSE, responseBundle.getType()); + assertEquals(1, responseBundle.getEntry().size()); + assertNotNull(responseBundle.getEntry().get(0)); + assertNotNull(responseBundle.getEntry().get(0).getResource()); + assertTrue(responseBundle.getEntry().get(0).getResource() instanceof Binary); + assertEquals(created.getIdElement().getIdPart(), + responseBundle.getEntry().get(0).getResource().getIdElement().getIdPart()); + } + + @Test(expected = WebApplicationException.class) + public void testReadNotAllowedExternalUserViaTransactionBundle() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + PartialResult<Organization> result = orgDao.search(orgDao.createSearchQueryWithoutUserFilter(1, 1) + .configureParameters(Map.of("name", Arrays.asList("Test Organization")))); + assertNotNull(result); + assertEquals(1, result.getOverallCount()); + assertNotNull(result.getPartialResult()); + assertEquals(1, result.getPartialResult().size()); + assertNotNull(result.getPartialResult().get(0)); + + Organization org = result.getPartialResult().get(0); + + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference(org.getIdElement().toVersionless())); + + BinaryDao binDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binDao.create(binary); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.TRANSACTION); + bundle.addEntry().getRequest().setMethod(HTTPVerb.GET).setUrl("Binary/" + created.getIdElement().getIdPart()); + + try + { + getExternalWebserviceClient().postBundle(bundle); + } + catch (WebApplicationException e) + { + assertEquals(Status.FORBIDDEN.getStatusCode(), e.getResponse().getStatus()); + throw e; + } + } + + @Test + public void testReadAllowedLocalUserViaBatchBundle() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + PartialResult<Organization> result = orgDao.search(orgDao.createSearchQueryWithoutUserFilter(1, 1) + .configureParameters(Map.of("name", Arrays.asList("Test Organization")))); + assertNotNull(result); + assertEquals(1, result.getOverallCount()); + assertNotNull(result.getPartialResult()); + assertEquals(1, result.getPartialResult().size()); + assertNotNull(result.getPartialResult().get(0)); + + Organization org = result.getPartialResult().get(0); + + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference(org.getIdElement().toVersionless())); + + BinaryDao binDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binDao.create(binary); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.BATCH); + bundle.addEntry().getRequest().setMethod(HTTPVerb.GET).setUrl("Binary/" + created.getIdElement().getIdPart()); + + Bundle responseBundle = getWebserviceClient().postBundle(bundle); + assertNotNull(responseBundle); + assertEquals(BundleType.BATCHRESPONSE, responseBundle.getType()); + assertEquals(1, responseBundle.getEntry().size()); + assertNotNull(responseBundle.getEntry().get(0)); + assertNotNull(responseBundle.getEntry().get(0).getResource()); + assertTrue(responseBundle.getEntry().get(0).getResource() instanceof Binary); + assertEquals(created.getIdElement().getIdPart(), + responseBundle.getEntry().get(0).getResource().getIdElement().getIdPart()); + } + + @Test + public void testReadAllowedExternalUserViaBatchBundle() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + PartialResult<Organization> result = orgDao.search(orgDao.createSearchQueryWithoutUserFilter(1, 1) + .configureParameters(Map.of("name", Arrays.asList("External Test Organization")))); + assertNotNull(result); + assertEquals(1, result.getOverallCount()); + assertNotNull(result.getPartialResult()); + assertEquals(1, result.getPartialResult().size()); + assertNotNull(result.getPartialResult().get(0)); + + Organization org = result.getPartialResult().get(0); + + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference(org.getIdElement().toVersionless())); + + BinaryDao binDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binDao.create(binary); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.BATCH); + bundle.addEntry().getRequest().setMethod(HTTPVerb.GET).setUrl("Binary/" + created.getIdElement().getIdPart()); + + Bundle responseBundle = getExternalWebserviceClient().postBundle(bundle); + assertNotNull(responseBundle); + assertEquals(BundleType.BATCHRESPONSE, responseBundle.getType()); + assertEquals(1, responseBundle.getEntry().size()); + assertNotNull(responseBundle.getEntry().get(0)); + assertNotNull(responseBundle.getEntry().get(0).getResource()); + assertTrue(responseBundle.getEntry().get(0).getResource() instanceof Binary); + assertEquals(created.getIdElement().getIdPart(), + responseBundle.getEntry().get(0).getResource().getIdElement().getIdPart()); + } + + @Test + public void testReadNotAllowedExternalUserViaBatchBundle() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + PartialResult<Organization> result = orgDao.search(orgDao.createSearchQueryWithoutUserFilter(1, 1) + .configureParameters(Map.of("name", Arrays.asList("Test Organization")))); + assertNotNull(result); + assertEquals(1, result.getOverallCount()); + assertNotNull(result.getPartialResult()); + assertEquals(1, result.getPartialResult().size()); + assertNotNull(result.getPartialResult().get(0)); + + Organization org = result.getPartialResult().get(0); + + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference(org.getIdElement().toVersionless())); + + BinaryDao binDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binDao.create(binary); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.BATCH); + bundle.addEntry().getRequest().setMethod(HTTPVerb.GET).setUrl("Binary/" + created.getIdElement().getIdPart()); + + Bundle responseBundle = getExternalWebserviceClient().postBundle(bundle); + assertNotNull(responseBundle); + assertEquals(BundleType.BATCHRESPONSE, responseBundle.getType()); + assertEquals(1, responseBundle.getEntry().size()); + assertNotNull(responseBundle.getEntry().get(0)); + + assertNull(responseBundle.getEntry().get(0).getResource()); + assertNotNull(responseBundle.getEntry().get(0).getResponse().getStatus()); + assertEquals("403 Forbidden", responseBundle.getEntry().get(0).getResponse().getStatus()); + } + @Test public void testCreate() throws Exception { @@ -126,14 +369,272 @@ public void testCreate() throws Exception Organization createdOrg = orgDao.create(new Organization()); final String contentType = "text/plain"; - final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); + + Binary created = getWebserviceClient().create(binary); + + assertNotNull(created); + assertNotNull(created.getIdElement().toString()); + assertEquals("1", created.getMeta().getVersionId()); + assertNotNull(created.getMeta().getLastUpdated()); + + assertNotNull(created.getContentType()); + assertEquals(contentType, created.getContentType()); + assertTrue(Arrays.equals(data, created.getData())); + + assertNotNull(created.getSecurityContext()); + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + } + + @Test(expected = WebApplicationException.class) + public void testCreateNotAllowedExternalUser() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); + + try + { + getExternalWebserviceClient().create(binary); + } + catch (WebApplicationException e) + { + assertEquals(Status.FORBIDDEN.getStatusCode(), e.getResponse().getStatus()); + throw e; + } + } + + @Test(expected = WebApplicationException.class) + public void testCreateSecurityContextOrgNotExisting() throws Exception + { + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference("Organization/" + UUID.randomUUID().toString())); + + try + { + getWebserviceClient().create(binary); + } + catch (WebApplicationException e) + { + assertEquals(Status.FORBIDDEN.getStatusCode(), e.getResponse().getStatus()); + throw e; + } + } + + @Test + public void testCreateViaTransactionBundle() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.TRANSACTION); + bundle.addEntry().setFullUrl("urn:uuid:" + UUID.randomUUID().toString()).setResource(binary).getRequest() + .setMethod(HTTPVerb.POST).setUrl("Binary"); + + Bundle responseBundle = getWebserviceClient().postBundle(bundle); + + assertNotNull(responseBundle); + assertEquals(BundleType.TRANSACTIONRESPONSE, responseBundle.getType()); + assertEquals(1, responseBundle.getEntry().size()); + assertNotNull(responseBundle.getEntry().get(0)); + + assertNotNull(responseBundle.getEntry().get(0).getResponse().getStatus()); + assertEquals("201 Created", responseBundle.getEntry().get(0).getResponse().getStatus()); + assertNotNull(responseBundle.getEntry().get(0).getResponse().getLocation()); + assertNotNull(responseBundle.getEntry().get(0).getResponse().getEtag()); + assertEquals("W/\"1\"", responseBundle.getEntry().get(0).getResponse().getEtag()); + } + + @Test(expected = WebApplicationException.class) + public void testCreateNotAllowedExternalUserViaTransactionBundle() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.TRANSACTION); + bundle.addEntry().setFullUrl("urn:uuid:" + UUID.randomUUID().toString()).setResource(binary).getRequest() + .setMethod(HTTPVerb.POST).setUrl("Binary"); + + try + { + getExternalWebserviceClient().postBundle(bundle); + } + catch (WebApplicationException e) + { + assertEquals(Status.FORBIDDEN.getStatusCode(), e.getResponse().getStatus()); + throw e; + } + } + + @Test(expected = WebApplicationException.class) + public void testCreateSecurityContextOrgNotExistingViaTransactionBundle() throws Exception + { + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference("Organization/" + UUID.randomUUID().toString())); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.TRANSACTION); + bundle.addEntry().setFullUrl("urn:uuid:" + UUID.randomUUID().toString()).setResource(binary).getRequest() + .setMethod(HTTPVerb.POST).setUrl("Binary"); + + try + { + getWebserviceClient().create(binary); + } + catch (WebApplicationException e) + { + assertEquals(Status.FORBIDDEN.getStatusCode(), e.getResponse().getStatus()); + throw e; + } + } + + @Test + public void testCreateViaBatchBundle() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.BATCH); + bundle.addEntry().setFullUrl("urn:uuid:" + UUID.randomUUID().toString()).setResource(binary).getRequest() + .setMethod(HTTPVerb.POST).setUrl("Binary"); + + Bundle responseBundle = getWebserviceClient().postBundle(bundle); + + assertNotNull(responseBundle); + assertEquals(BundleType.BATCHRESPONSE, responseBundle.getType()); + assertEquals(1, responseBundle.getEntry().size()); + assertNotNull(responseBundle.getEntry().get(0)); + + assertNotNull(responseBundle.getEntry().get(0).getResponse().getStatus()); + assertEquals("201 Created", responseBundle.getEntry().get(0).getResponse().getStatus()); + assertNotNull(responseBundle.getEntry().get(0).getResponse().getLocation()); + assertNotNull(responseBundle.getEntry().get(0).getResponse().getEtag()); + assertEquals("W/\"1\"", responseBundle.getEntry().get(0).getResponse().getEtag()); + } + + @Test + public void testCreateNotAllowedExternalUserViaBatchBundle() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.BATCH); + bundle.addEntry().setFullUrl("urn:uuid:" + UUID.randomUUID().toString()).setResource(binary).getRequest() + .setMethod(HTTPVerb.POST).setUrl("Binary"); + + Bundle responseBundle = getExternalWebserviceClient().postBundle(bundle); + assertNotNull(responseBundle); + assertEquals(BundleType.BATCHRESPONSE, responseBundle.getType()); + assertEquals(1, responseBundle.getEntry().size()); + assertNotNull(responseBundle.getEntry().get(0)); + + assertNull(responseBundle.getEntry().get(0).getResource()); + assertNotNull(responseBundle.getEntry().get(0).getResponse().getStatus()); + assertEquals("403 Forbidden", responseBundle.getEntry().get(0).getResponse().getStatus()); + } + + @Test + public void testCreateSecurityContextOrgNotExistingViaBatchBundle() throws Exception + { + final String contentType = "text/plain"; + final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data); + binary.setSecurityContext(new Reference("Organization/" + UUID.randomUUID().toString())); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.BATCH); + bundle.addEntry().setFullUrl("urn:uuid:" + UUID.randomUUID().toString()).setResource(binary).getRequest() + .setMethod(HTTPVerb.POST).setUrl("Binary"); + + Bundle responseBundle = getWebserviceClient().postBundle(bundle); + assertNotNull(responseBundle); + assertEquals(BundleType.BATCHRESPONSE, responseBundle.getType()); + assertEquals(1, responseBundle.getEntry().size()); + assertNotNull(responseBundle.getEntry().get(0)); + + assertNull(responseBundle.getEntry().get(0).getResource()); + assertNotNull(responseBundle.getEntry().get(0).getResponse().getStatus()); + assertEquals("403 Forbidden", responseBundle.getEntry().get(0).getResponse().getStatus()); + } + + @Test + public void testUpdate() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + + final String contentType = "text/plain"; + final byte[] data1 = "Hello World".getBytes(StandardCharsets.UTF_8); + final byte[] data2 = "Hello World and goodbye".getBytes(StandardCharsets.UTF_8); Binary binary = new Binary(); binary.setContentType(contentType); - binary.setData(data); + binary.setData(data1); binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); - Binary created = getWebserviceClient().create(binary); + BinaryDao binaryDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binaryDao.create(binary); assertNotNull(created); assertNotNull(created.getIdElement().toString()); @@ -142,29 +643,66 @@ public void testCreate() throws Exception assertNotNull(created.getContentType()); assertEquals(contentType, created.getContentType()); - assertTrue(Arrays.equals(data, created.getData())); + assertTrue(Arrays.equals(data1, created.getData())); + + assertNotNull(created.getSecurityContext()); + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + + created.setData(data2); assertNotNull(created.getSecurityContext()); assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + + Binary updated = getWebserviceClient().update(created); + + assertNotNull(updated); + assertNotNull(updated.getIdElement().toString()); + assertEquals("2", updated.getMeta().getVersionId()); + assertNotNull(updated.getMeta().getLastUpdated()); + + assertNotNull(updated.getContentType()); + assertEquals(contentType, updated.getContentType()); + assertTrue(Arrays.equals(data2, updated.getData())); } @Test(expected = WebApplicationException.class) - public void testCreateNotAllowedExternalUser() throws Exception + public void testUpdateNotAllowedExternalUser() throws Exception { OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); Organization createdOrg = orgDao.create(new Organization()); final String contentType = "text/plain"; - final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + final byte[] data1 = "Hello World".getBytes(StandardCharsets.UTF_8); + final byte[] data2 = "Hello World and goodbye".getBytes(StandardCharsets.UTF_8); Binary binary = new Binary(); binary.setContentType(contentType); - binary.setData(data); + binary.setData(data1); binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); + BinaryDao binaryDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binaryDao.create(binary); + + assertNotNull(created); + assertNotNull(created.getIdElement().toString()); + assertEquals("1", created.getMeta().getVersionId()); + assertNotNull(created.getMeta().getLastUpdated()); + + assertNotNull(created.getContentType()); + assertEquals(contentType, created.getContentType()); + assertTrue(Arrays.equals(data1, created.getData())); + + assertNotNull(created.getSecurityContext()); + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + + created.setData(data2); + + assertNotNull(created.getSecurityContext()); + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + try { - getExternalWebserviceClient().create(binary); + getExternalWebserviceClient().update(created); } catch (WebApplicationException e) { @@ -173,20 +711,154 @@ public void testCreateNotAllowedExternalUser() throws Exception } } + @Test + public void testUpdateViaTransactionBundle() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + + final String contentType = "text/plain"; + final byte[] data1 = "Hello World".getBytes(StandardCharsets.UTF_8); + final byte[] data2 = "Hello World and goodbye".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data1); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); + + BinaryDao binaryDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binaryDao.create(binary); + + assertNotNull(created); + assertNotNull(created.getIdElement().toString()); + assertEquals("1", created.getMeta().getVersionId()); + assertNotNull(created.getMeta().getLastUpdated()); + + assertNotNull(created.getContentType()); + assertEquals(contentType, created.getContentType()); + assertTrue(Arrays.equals(data1, created.getData())); + + assertNotNull(created.getSecurityContext()); + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + + created.setData(data2); + + assertNotNull(created.getSecurityContext()); + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.TRANSACTION); + bundle.addEntry().setFullUrl(BASE_URL + "Binary/" + created.getIdElement().getIdPart()).setResource(created) + .getRequest().setMethod(HTTPVerb.PUT).setUrl("Binary/" + created.getIdElement().getIdPart()); + + Bundle responseBundle = getWebserviceClient().postBundle(bundle); + + assertNotNull(responseBundle); + assertEquals(BundleType.TRANSACTIONRESPONSE, responseBundle.getType()); + assertEquals(1, responseBundle.getEntry().size()); + assertNotNull(responseBundle.getEntry().get(0)); + + assertNotNull(responseBundle.getEntry().get(0).getResponse().getStatus()); + assertEquals("200 OK", responseBundle.getEntry().get(0).getResponse().getStatus()); + assertNotNull(responseBundle.getEntry().get(0).getResponse().getLocation()); + assertNotNull(responseBundle.getEntry().get(0).getResponse().getEtag()); + assertEquals("W/\"2\"", responseBundle.getEntry().get(0).getResponse().getEtag()); + } + @Test(expected = WebApplicationException.class) - public void testCreateSecurityContextOrgNotExisting() throws Exception + public void testUpdateNotAllowedExternalUserViaTransactionBundle() throws Exception { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + final String contentType = "text/plain"; - final byte[] data = "Hello World".getBytes(StandardCharsets.UTF_8); + final byte[] data1 = "Hello World".getBytes(StandardCharsets.UTF_8); + final byte[] data2 = "Hello World and goodbye".getBytes(StandardCharsets.UTF_8); Binary binary = new Binary(); binary.setContentType(contentType); - binary.setData(data); - binary.setSecurityContext(new Reference("Organization/" + UUID.randomUUID().toString())); + binary.setData(data1); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); + + BinaryDao binaryDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binaryDao.create(binary); + + assertNotNull(created); + assertNotNull(created.getIdElement().toString()); + assertEquals("1", created.getMeta().getVersionId()); + assertNotNull(created.getMeta().getLastUpdated()); + + assertNotNull(created.getContentType()); + assertEquals(contentType, created.getContentType()); + assertTrue(Arrays.equals(data1, created.getData())); + + assertNotNull(created.getSecurityContext()); + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + + created.setData(data2); + + assertNotNull(created.getSecurityContext()); + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.TRANSACTION); + bundle.addEntry().setFullUrl(BASE_URL + "Binary/" + created.getIdElement().getIdPart()).setResource(created) + .getRequest().setMethod(HTTPVerb.PUT).setUrl("Binary/" + created.getIdElement().getIdPart()); try { - getWebserviceClient().create(binary); + getExternalWebserviceClient().postBundle(bundle); + } + catch (WebApplicationException e) + { + assertEquals(Status.FORBIDDEN.getStatusCode(), e.getResponse().getStatus()); + throw e; + } + } + + @Test(expected = WebApplicationException.class) + public void testUpdateSecurityContextOrgNotExistingViaTransactionBundle() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + + final String contentType = "text/plain"; + final byte[] data1 = "Hello World".getBytes(StandardCharsets.UTF_8); + final byte[] data2 = "Hello World and goodbye".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data1); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); + + BinaryDao binaryDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binaryDao.create(binary); + + assertNotNull(created); + assertNotNull(created.getIdElement().toString()); + assertEquals("1", created.getMeta().getVersionId()); + assertNotNull(created.getMeta().getLastUpdated()); + + assertNotNull(created.getContentType()); + assertEquals(contentType, created.getContentType()); + assertTrue(Arrays.equals(data1, created.getData())); + + assertNotNull(created.getSecurityContext()); + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + + created.setData(data2); + created.setSecurityContext(new Reference("Organization/" + UUID.randomUUID().toString())); + + assertNotNull(created.getSecurityContext()); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.TRANSACTION); + bundle.addEntry().setFullUrl(BASE_URL + "Binary/" + created.getIdElement().getIdPart()).setResource(created) + .getRequest().setMethod(HTTPVerb.PUT).setUrl("Binary/" + created.getIdElement().getIdPart()); + + try + { + getWebserviceClient().postBundle(bundle); } catch (WebApplicationException e) { @@ -196,7 +868,7 @@ public void testCreateSecurityContextOrgNotExisting() throws Exception } @Test - public void testUpdate() throws Exception + public void testUpdateViaBatchBundle() throws Exception { OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); Organization createdOrg = orgDao.create(new Organization()); @@ -230,20 +902,27 @@ public void testUpdate() throws Exception assertNotNull(created.getSecurityContext()); assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); - Binary updated = getWebserviceClient().update(created); + Bundle bundle = new Bundle(); + bundle.setType(BundleType.BATCH); + bundle.addEntry().setFullUrl(BASE_URL + "Binary/" + created.getIdElement().getIdPart()).setResource(created) + .getRequest().setMethod(HTTPVerb.PUT).setUrl("Binary/" + created.getIdElement().getIdPart()); - assertNotNull(updated); - assertNotNull(updated.getIdElement().toString()); - assertEquals("2", updated.getMeta().getVersionId()); - assertNotNull(updated.getMeta().getLastUpdated()); + Bundle responseBundle = getWebserviceClient().postBundle(bundle); - assertNotNull(updated.getContentType()); - assertEquals(contentType, updated.getContentType()); - assertTrue(Arrays.equals(data2, updated.getData())); + assertNotNull(responseBundle); + assertEquals(BundleType.BATCHRESPONSE, responseBundle.getType()); + assertEquals(1, responseBundle.getEntry().size()); + assertNotNull(responseBundle.getEntry().get(0)); + + assertNotNull(responseBundle.getEntry().get(0).getResponse().getStatus()); + assertEquals("200 OK", responseBundle.getEntry().get(0).getResponse().getStatus()); + assertNotNull(responseBundle.getEntry().get(0).getResponse().getLocation()); + assertNotNull(responseBundle.getEntry().get(0).getResponse().getEtag()); + assertEquals("W/\"2\"", responseBundle.getEntry().get(0).getResponse().getEtag()); } - @Test(expected = WebApplicationException.class) - public void testUpdateNotAllowedExternalUser() throws Exception + @Test + public void testUpdateNotAllowedExternalUserViaBatchBundle() throws Exception { OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); Organization createdOrg = orgDao.create(new Organization()); @@ -277,15 +956,71 @@ public void testUpdateNotAllowedExternalUser() throws Exception assertNotNull(created.getSecurityContext()); assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); - try - { - getExternalWebserviceClient().update(created); - } - catch (WebApplicationException e) - { - assertEquals(Status.FORBIDDEN.getStatusCode(), e.getResponse().getStatus()); - throw e; - } + Bundle bundle = new Bundle(); + bundle.setType(BundleType.BATCH); + bundle.addEntry().setFullUrl(BASE_URL + "Binary/" + created.getIdElement().getIdPart()).setResource(created) + .getRequest().setMethod(HTTPVerb.PUT).setUrl("Binary/" + created.getIdElement().getIdPart()); + + Bundle responseBundle = getExternalWebserviceClient().postBundle(bundle); + assertNotNull(responseBundle); + assertEquals(BundleType.BATCHRESPONSE, responseBundle.getType()); + assertEquals(1, responseBundle.getEntry().size()); + assertNotNull(responseBundle.getEntry().get(0)); + + assertNull(responseBundle.getEntry().get(0).getResource()); + assertNotNull(responseBundle.getEntry().get(0).getResponse().getStatus()); + assertEquals("403 Forbidden", responseBundle.getEntry().get(0).getResponse().getStatus()); + } + + @Test + public void testUpdateSecurityContextOrgNotExistingViaBatchBundle() throws Exception + { + OrganizationDao orgDao = getSpringWebApplicationContext().getBean(OrganizationDao.class); + Organization createdOrg = orgDao.create(new Organization()); + + final String contentType = "text/plain"; + final byte[] data1 = "Hello World".getBytes(StandardCharsets.UTF_8); + final byte[] data2 = "Hello World and goodbye".getBytes(StandardCharsets.UTF_8); + + Binary binary = new Binary(); + binary.setContentType(contentType); + binary.setData(data1); + binary.setSecurityContext(new Reference(createdOrg.getIdElement().toVersionless())); + + BinaryDao binaryDao = getSpringWebApplicationContext().getBean(BinaryDao.class); + Binary created = binaryDao.create(binary); + + assertNotNull(created); + assertNotNull(created.getIdElement().toString()); + assertEquals("1", created.getMeta().getVersionId()); + assertNotNull(created.getMeta().getLastUpdated()); + + assertNotNull(created.getContentType()); + assertEquals(contentType, created.getContentType()); + assertTrue(Arrays.equals(data1, created.getData())); + + assertNotNull(created.getSecurityContext()); + assertEquals(createdOrg.getIdElement().toVersionless(), created.getSecurityContext().getReferenceElement()); + + created.setData(data2); + created.setSecurityContext(new Reference("Organization/" + UUID.randomUUID().toString())); + + assertNotNull(created.getSecurityContext()); + + Bundle bundle = new Bundle(); + bundle.setType(BundleType.BATCH); + bundle.addEntry().setFullUrl(BASE_URL + "Binary/" + created.getIdElement().getIdPart()).setResource(created) + .getRequest().setMethod(HTTPVerb.PUT).setUrl("Binary/" + created.getIdElement().getIdPart()); + + Bundle responseBundle = getWebserviceClient().postBundle(bundle); + assertNotNull(responseBundle); + assertEquals(BundleType.BATCHRESPONSE, responseBundle.getType()); + assertEquals(1, responseBundle.getEntry().size()); + assertNotNull(responseBundle.getEntry().get(0)); + + assertNull(responseBundle.getEntry().get(0).getResource()); + assertNotNull(responseBundle.getEntry().get(0).getResponse().getStatus()); + assertEquals("403 Forbidden", responseBundle.getEntry().get(0).getResponse().getStatus()); } @Test diff --git a/dsf-fhir/dsf-fhir-server/src/test/resources/integration/test-bundle.xml b/dsf-fhir/dsf-fhir-server/src/test/resources/integration/test-bundle.xml index e4eeb8a7b..a040656c0 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/resources/integration/test-bundle.xml +++ b/dsf-fhir/dsf-fhir-server/src/test/resources/integration/test-bundle.xml @@ -6,7 +6,7 @@ <Organization xmlns="http://hl7.org/fhir"> <meta> <tag> - <system value="http://highmed.org/fhir/CodeSystem/authorization"/> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> <code value="REMOTE"/> </tag> </meta> @@ -42,7 +42,7 @@ <Endpoint xmlns="http://hl7.org/fhir"> <meta> <tag> - <system value="http://highmed.org/fhir/CodeSystem/authorization"/> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> <code value="REMOTE"/> </tag> </meta> @@ -82,7 +82,7 @@ <Organization xmlns="http://hl7.org/fhir"> <meta> <tag> - <system value="http://highmed.org/fhir/CodeSystem/authorization"/> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> <code value="REMOTE"/> </tag> </meta> diff --git a/dsf-fhir/dsf-fhir-server/src/test/resources/log4j2.xml b/dsf-fhir/dsf-fhir-server/src/test/resources/log4j2.xml index 78079a716..9999bb653 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/resources/log4j2.xml +++ b/dsf-fhir/dsf-fhir-server/src/test/resources/log4j2.xml @@ -5,9 +5,16 @@ <Console name="CONSOLE" target="SYSTEM_OUT"> <PatternLayout pattern="%p\t%t - %C{1}.%M(%L) | %m%n"/> </Console> + <Console name="AUDIT" target="SYSTEM_ERR"> + <PatternLayout pattern="%p\t%t - %C{1}.%M(%L) | %m%n"/> + </Console> </Appenders> <Loggers> + <Logger name="dsf-audit-logger" level="INFO" additivity="false"> + <AppenderRef ref="AUDIT"/> + </Logger> + <Logger name="de.rwh" level="TRACE"/> <Logger name="org.highmed" level="TRACE"/> <Logger name="org.apache" level="WARN"/> @@ -17,7 +24,7 @@ <Logger name="com.sun.jersey" level="WARN"/> <Logger name="liquibase" level="WARN"/> <Logger name="ca.uhn.hl7v2" level="WARN"/> - + <Root level="WARN"> <AppenderRef ref="CONSOLE"/> </Root> From ca45baf5039ab855c16c766320e692d290fe5583 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Mon, 2 Mar 2020 00:11:25 +0100 Subject: [PATCH 14/55] work on authorization rules --- .../EndpointAuthorizationRule.java | 70 ++++++- .../OrganizationAuthorizationRule.java | 86 ++++++-- .../StructureDefinitionAuthorizationRule.java | 185 ++++++++++++++---- .../SubscriptionAuthorizationRule.java | 103 ++++++++-- .../dsf/fhir/dao/command/AbstractCommand.java | 6 +- .../command/AbstractCommandWithResource.java | 4 +- .../dao/command/AuthorizationCommand.java | 23 --- ...dFactory.java => AuthorizationHelper.java} | 2 +- ...Impl.java => AuthorizationHelperImpl.java} | 6 +- .../fhir/dao/command/CommandFactoryImpl.java | 32 +-- .../dsf/fhir/dao/command/CreateCommand.java | 6 +- .../CreateStructureDefinitionCommand.java | 4 +- .../dsf/fhir/dao/command/DeleteCommand.java | 8 +- .../dsf/fhir/dao/command/ReadCommand.java | 18 +- .../dao/command/ResolveReferencesCommand.java | 4 +- .../dsf/fhir/dao/command/UpdateCommand.java | 8 +- .../UpdateStructureDefinitionCommand.java | 4 +- .../AbstractStructureDefinitionDaoJdbc.java | 2 + .../parameters/StructureDefinitionStatus.java | 120 ++++++++++++ .../dsf/fhir/spring/config/CommandConfig.java | 10 +- .../impl/ConformanceServiceImpl.java | 6 +- .../highmed-endpoint-0.1.0.xml | 2 +- ...extension-certificate-thumbprint-0.1.0.xml | 2 +- .../highmed-extension-group-id-0.1.0.xml | 2 +- ...ed-extension-participating-medic-0.1.0.xml | 2 +- ...-extension-process-authorization-0.1.0.xml | 2 +- .../highmed-extension-query-0.1.0.xml | 2 +- .../highmed-group-0.1.0.xml | 2 +- .../highmed-organization-0.1.0.xml | 2 +- .../highmed-task-base-0.1.0.xml | 2 +- ...-task-compute-simple-feasibility-0.1.0.xml | 2 +- ...-task-execute-simple-feasibility-0.1.0.xml | 2 +- ...ed-task-execute-update-resources-0.1.0.xml | 2 +- ...-medic-result-simple-feasibility-0.1.0.xml | 2 +- .../highmed-task-parent-plugin-0.1.0.xml | 2 +- .../highmed-task-ping-0.1.0.xml | 2 +- .../highmed-task-pong-0.1.0.xml | 2 +- ...-task-request-simple-feasibility-0.1.0.xml | 2 +- ...ed-task-request-update-resources-0.1.0.xml | 2 +- ...-medic-result-simple-feasibility-0.1.0.xml | 2 +- .../highmed-task-start-process-0.1.0.xml | 2 +- .../highmed-task-update-whitelist-0.1.0.xml | 2 +- .../Subscription/bpmn-task-subscription.xml | 6 + 43 files changed, 583 insertions(+), 172 deletions(-) delete mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommand.java rename dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/{AuthorizationCommandFactory.java => AuthorizationHelper.java} (94%) rename dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/{AuthorizationCommandFactoryImpl.java => AuthorizationHelperImpl.java} (96%) create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/StructureDefinitionStatus.java diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java index ba52b7039..174d54671 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java @@ -41,7 +41,7 @@ public Optional<String> reasonCreateAllowed(Connection connection, User user, En Optional<String> errors = newResourceOk(newResource); if (errors.isEmpty()) { - if (!endpointExists(connection, newResource)) + if (!resourceExists(connection, newResource)) { logger.info( "Create of Endpoint authorized for local user '{}', Endpoint with address and identifier does not exist", @@ -99,7 +99,7 @@ private Optional<String> newResourceOk(Endpoint newResource) if (!hasLocalOrRemoteAuthorizationRole(newResource)) { - errors.add("endpoint missing authorization tag"); + errors.add("missing authorization tag"); } if (errors.isEmpty()) @@ -108,7 +108,7 @@ private Optional<String> newResourceOk(Endpoint newResource) return Optional.of(errors.stream().collect(Collectors.joining(", "))); } - private boolean endpointExists(Connection connection, Endpoint newResource) + private boolean resourceExists(Connection connection, Endpoint newResource) { String identifierValue = newResource.getIdentifier().stream() .filter(i -> IDENTIFIER_SYSTEM.equals(i.getSystem())).map(i -> i.getValue()).findFirst().orElseThrow(); @@ -179,16 +179,70 @@ else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) public Optional<String> reasonUpdateAllowed(Connection connection, User user, Endpoint oldResource, Endpoint newResource) { - // TODO validate unique on Endpoint.address - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + Optional<String> errors = newResourceOk(newResource); + if (errors.isEmpty()) + { + if (isSame(oldResource, newResource)) + { + logger.info( + "Update of Endpoint authorized for local user '{}', address and identifier same as existing Endpoint", + user.getName()); + return Optional.of("local user; address and identifier same as existing Endpoint"); + + } + else if (!resourceExists(connection, newResource)) + { + logger.info( + "Update of Endpoint authorized for local user '{}', other Endpoint with address and identifier does not exist", + user.getName()); + return Optional.of("local user; other Endpoint with address and identifier does not exist yet"); + } + else + { + logger.warn( + "Create of Endpoint unauthorized, other Endpoint with address and identifier already exists"); + return Optional.empty(); + } + } + else + { + logger.warn("Update of Endpoint unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else + { + logger.warn("Update of Endpoint unauthorized, not a local user"); + return Optional.empty(); + } + } + + private boolean isSame(Endpoint oldResource, Endpoint newResource) + { + String oldIdentifierValue = oldResource.getIdentifier().stream() + .filter(i -> IDENTIFIER_SYSTEM.equals(i.getSystem())).map(i -> i.getValue()).findFirst().orElseThrow(); + String newIdentifierValue = newResource.getIdentifier().stream() + .filter(i -> IDENTIFIER_SYSTEM.equals(i.getSystem())).map(i -> i.getValue()).findFirst().orElseThrow(); + + return oldResource.getAddress().equals(newResource.getAddress()) + && oldIdentifierValue.equals(newIdentifierValue); } @Override public Optional<String> reasonDeleteAllowed(Connection connection, User user, Endpoint oldResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Delete of Endpoint authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Delete of Endpoint unauthorized, not a local user"); + return Optional.empty(); + } } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java index fd100693d..9943ab21b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java @@ -45,7 +45,7 @@ public Optional<String> reasonCreateAllowed(Connection connection, User user, Or Optional<String> errors = newResourceOk(newResource); if (errors.isEmpty()) { - if (!organizationExists(connection, newResource)) + if (!resourceExists(connection, newResource)) { logger.info( "Create of Organization authorized for local user '{}', Organization with certificate-thumbprint and identifier does not exist", @@ -71,11 +71,6 @@ public Optional<String> reasonCreateAllowed(Connection connection, User user, Or logger.warn("Create of Organization unauthorized, not a local user"); return Optional.empty(); } - - // check organization not existing if contains identifier with identifier.system (or extension) - // http://highmed.org/fhir/NamingSystem/certificate-thumbprint-hex with same identifier.value - // no two organizations can have the same certificate thumb-print - } private Optional<String> newResourceOk(Organization newResource) @@ -113,7 +108,7 @@ private Optional<String> newResourceOk(Organization newResource) if (!hasLocalOrRemoteAuthorizationRole(newResource)) { - errors.add("organization missing authorization tag"); + errors.add("missing authorization tag"); } if (errors.isEmpty()) @@ -122,15 +117,15 @@ private Optional<String> newResourceOk(Organization newResource) return Optional.of(errors.stream().collect(Collectors.joining(", "))); } - private boolean organizationExists(Connection connection, Organization newResource) + private boolean resourceExists(Connection connection, Organization newResource) { String identifierValue = newResource.getIdentifier().stream() .filter(i -> IDENTIFIER_SYSTEM.equals(i.getSystem())).map(i -> i.getValue()).findFirst().orElseThrow(); - String thumbPrintValue = newResource.getExtension().stream() + String thumbprintValue = newResource.getExtension().stream() .filter(e -> EXTENSION_THUMBPRINT_URL.equals(e.getUrl())) .map(e -> ((StringType) e.getValue()).getValue()).findFirst().orElseThrow(); - return organizationWithThumbPrintExists(connection, thumbPrintValue) + return organizationWithThumbPrintExists(connection, thumbprintValue) || organizationWithIdentifierExists(connection, identifierValue); } @@ -195,15 +190,78 @@ else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) public Optional<String> reasonUpdateAllowed(Connection connection, User user, Organization oldResource, Organization newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + Optional<String> errors = newResourceOk(newResource); + if (errors.isEmpty()) + { + if (isSame(oldResource, newResource)) + { + logger.info( + "Update of Organization authorized for local user '{}', certificate-thumbprint and identifier same as existing Organization", + user.getName()); + return Optional + .of("local user; certificate-thumbprint and identifier same as existing Organization"); + + } + else if (!resourceExists(connection, newResource)) + { + logger.info( + "Update of Organization authorized for local user '{}', other Organization with certificate-thumbprint and identifier does not exist", + user.getName()); + return Optional.of( + "local user; other Organization with certificate-thumbprint and identifier does not exist yet"); + } + else + { + logger.warn( + "Create of Organization unauthorized, other Organization with certificate-thumbprint and identifier already exists"); + return Optional.empty(); + } + } + else + { + logger.warn("Update of Organization unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else + { + logger.warn("Update of Organization unauthorized, not a local user"); + return Optional.empty(); + } + } + + private boolean isSame(Organization oldResource, Organization newResource) + { + String oldIdentifierValue = oldResource.getIdentifier().stream() + .filter(i -> IDENTIFIER_SYSTEM.equals(i.getSystem())).map(i -> i.getValue()).findFirst().orElseThrow(); + String oldThumbprintValue = oldResource.getExtension().stream() + .filter(e -> EXTENSION_THUMBPRINT_URL.equals(e.getUrl())) + .map(e -> ((StringType) e.getValue()).getValue()).findFirst().orElseThrow(); + + String newIdentifierValue = newResource.getIdentifier().stream() + .filter(i -> IDENTIFIER_SYSTEM.equals(i.getSystem())).map(i -> i.getValue()).findFirst().orElseThrow(); + String newThumbprintValue = newResource.getExtension().stream() + .filter(e -> EXTENSION_THUMBPRINT_URL.equals(e.getUrl())) + .map(e -> ((StringType) e.getValue()).getValue()).findFirst().orElseThrow(); + + return oldIdentifierValue.equals(newIdentifierValue) && oldThumbprintValue.equals(newThumbprintValue); } @Override public Optional<String> reasonDeleteAllowed(Connection connection, User user, Organization oldResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Delete of Organization authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Delete of Organization unauthorized, not a local user"); + return Optional.empty(); + } } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java index a28b9024f..f40ad456d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java @@ -2,12 +2,17 @@ import java.sql.Connection; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.StructureDefinitionDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.service.ReferenceResolver; +import org.hl7.fhir.r4.model.Enumerations.PublicationStatus; import org.hl7.fhir.r4.model.StructureDefinition; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -28,38 +33,26 @@ public Optional<String> reasonCreateAllowed(Connection connection, User user, St { if (isLocalUser(user)) { - // TODO move check for url, version and authorization tag to validation layer - if (newResource.hasUrl() && newResource.hasVersion() && hasLocalOrRemoteAuthorizationRole(newResource)) + Optional<String> errors = newResourceOk(newResource); + if (errors.isEmpty()) { - try + if (!resourceExists(connection, newResource)) { - Optional<StructureDefinition> existing = getDao().readByUrlAndVersionWithTransaction(connection, - newResource.getUrl(), newResource.getVersion()); - if (existing.isEmpty()) - { - logger.info( - "Create of StructureDefinition authorized for local user '{}', StructureDefinition with version and url does not exist", - user.getName()); - return Optional.of("local user, StructureDefinition with version and url does not exist yet"); - } - else - { - logger.warn( - "Create of StructureDefinition unauthorized, StructureDefinition with url and version already exists"); - return Optional.empty(); - } + logger.info( + "Create of StructureDefinition authorized for local user '{}', StructureDefinition with version and url does not exist", + user.getName()); + return Optional.of("local user, StructureDefinition with version and url does not exist yet"); } - catch (SQLException e) + else { logger.warn( - "Create of StructureDefinition unauthorized, error while checking for existing StructureDefinition with version and url", - e); + "Create of StructureDefinition unauthorized, StructureDefinition with url and version already exists"); return Optional.empty(); } } else { - logger.warn("Create of StructureDefinition unauthorized, missing url or version or authorization tag"); + logger.warn("Create of StructureDefinition unauthorized, " + errors.get()); return Optional.empty(); } } @@ -70,38 +63,158 @@ public Optional<String> reasonCreateAllowed(Connection connection, User user, St } } + private Optional<String> newResourceOk(StructureDefinition newResource) + { + List<String> errors = new ArrayList<String>(); + + if (newResource.hasStatus()) + { + if (!EnumSet.of(PublicationStatus.DRAFT, PublicationStatus.ACTIVE, PublicationStatus.RETIRED) + .contains(newResource.getStatus())) + { + errors.add("StructureDefinition.status not one of DRAFT, ACTIVE or RETIRED"); + } + } + else + { + errors.add("StructureDefinition.status not defined"); + } + + if (!newResource.hasUrl()) + { + errors.add("StructureDefinition.url not defined"); + } + if (!newResource.hasVersion()) + { + errors.add("StructureDefinition.version not defined"); + } + + if (!hasLocalOrRemoteAuthorizationRole(newResource)) + { + errors.add("missing authorization tag"); + } + + if (errors.isEmpty()) + return Optional.empty(); + else + return Optional.of(errors.stream().collect(Collectors.joining(", "))); + } + + private boolean resourceExists(Connection connection, StructureDefinition newResource) + { + try + { + return getDao() + .readByUrlAndVersionWithTransaction(connection, newResource.getUrl(), newResource.getVersion()) + .map(s -> true).orElse(false); + } + catch (SQLException e) + { + logger.warn("Error while searching for StructureDefinition", e); + return false; + } + } + @Override public Optional<String> reasonReadAllowed(Connection connection, User user, StructureDefinition existingResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user) && hasLocalOrRemoteAuthorizationRole(existingResource)) + { + logger.info( + "Read of StructureDefinition authorized for local user '{}', StructureDefinition has local or remote authorization role", + user.getName()); + return Optional.of("local user, local or remote authorized StructureDefinition"); + } + else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) + { + logger.info( + "Read of StructureDefinition authorized for remote user '{}', StructureDefinition has remote authorization role", + user.getName()); + return Optional.of("remote user, remote authorized StructureDefinition"); + } + else + { + logger.warn( + "Read of StructureDefinition unauthorized, no matching user role resource authorization role found"); + return Optional.empty(); + } } @Override public Optional<String> reasonUpdateAllowed(Connection connection, User user, StructureDefinition oldResource, StructureDefinition newResource) { - // check logged in, check "local" user (local user only could be default) - // check resource exists for given path id - // check against existing profile (by path id), no update if profile has different URL, version or status, - // status change via create - // check against existing profile (by path id), no update if status ACTIVE or RETIRED - - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + Optional<String> errors = newResourceOk(newResource); + if (errors.isEmpty()) + { + if (isSame(oldResource, newResource) && statusOk(oldResource, newResource)) + { + logger.info( + "Update of StructureDefinition authorized for local user '{}', criteria, type and payload same as existing StructureDefinition", + user.getName()); + return Optional.of("local user; criteria, type and payload same as existing StructureDefinition"); + } + else + { + logger.warn( + "Create of StructureDefinition unauthorized, other StructureDefinition with criteria, type and payload already exists"); + return Optional.empty(); + } + } + else + { + logger.warn("Update of StructureDefinition unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else + { + logger.warn("Update of StructureDefinition unauthorized, not a local user"); + return Optional.empty(); + } + } + + private boolean isSame(StructureDefinition oldResource, StructureDefinition newResource) + { + return oldResource.getUrl().equals(newResource.getUrl()) + && oldResource.getVersion().equals(newResource.getVersion()); + } + + private boolean statusOk(StructureDefinition oldResource, StructureDefinition newResource) + { + // draft -> draft/active/retired OK + if (PublicationStatus.DRAFT.equals(oldResource.getStatus())) + return true; + // active -> retired OK + else if (PublicationStatus.ACTIVE.equals(oldResource.getStatus()) + && PublicationStatus.RETIRED.equals(newResource.getStatus())) + return true; + else + return false; } @Override public Optional<String> reasonDeleteAllowed(Connection connection, User user, StructureDefinition oldResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Delete of StructureDefinition authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Delete of StructureDefinition unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonSearchAllowed(Connection connection, User user) { - // TODO Auto-generated method stub - return Optional.empty(); + logger.info("Search of StructureDefinition authorized for {} user '{}', will be fitered by user role", + user.getRole(), user.getName()); + return Optional.of("Allowed for all, filtered by user role"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java index 13aa4b1c7..e219d6c5f 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java @@ -44,7 +44,7 @@ public Optional<String> reasonCreateAllowed(Connection connection, User user, Su Optional<String> errors = newResourceOk(newResource); if (errors.isEmpty()) { - if (!subscriptionExists(connection, newResource)) + if (!resourceExists(connection, newResource)) { logger.info( "Create of Subscription authorized for local user '{}', Subscription with criteria, type and payload does not exist", @@ -81,7 +81,8 @@ private Optional<String> newResourceOk(Subscription newResource) && !(Constants.CT_FHIR_JSON_NEW.equals(newResource.getChannel().getPayload()) || Constants.CT_FHIR_XML_NEW.equals(newResource.getChannel().getPayload()))) { - errors.add("subscription.channel.payload not " + Constants.CT_FHIR_JSON_NEW + " or " + Constants.CT_FHIR_XML_NEW); + errors.add("subscription.channel.payload not " + Constants.CT_FHIR_JSON_NEW + " or " + + Constants.CT_FHIR_XML_NEW); } if (!SubscriptionChannelType.WEBSOCKET.equals(newResource.getChannel().getType())) @@ -115,7 +116,8 @@ private Optional<String> newResourceOk(Subscription newResource) } else { - errors.add("subscription.criteria invalid (resource '" + cComponentes.getPath() + "' not supported)"); + errors.add( + "subscription.criteria invalid (resource '" + cComponentes.getPath() + "' not supported)"); } } else @@ -128,13 +130,18 @@ private Optional<String> newResourceOk(Subscription newResource) errors.add("subscription.criteria not defined"); } + if (!hasLocalOrRemoteAuthorizationRole(newResource)) + { + errors.add("missing authorization tag"); + } + if (errors.isEmpty()) return Optional.empty(); else return Optional.of(errors.stream().collect(Collectors.joining(", "))); } - private boolean subscriptionExists(Connection connection, Subscription newResource) + private boolean resourceExists(Connection connection, Subscription newResource) { Map<String, List<String>> queryParameters = Map.of("criteria", Collections.singletonList(newResource.getCriteria()), "type", @@ -158,29 +165,101 @@ private boolean subscriptionExists(Connection connection, Subscription newResour @Override public Optional<String> reasonReadAllowed(Connection connection, User user, Subscription existingResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user) && hasLocalOrRemoteAuthorizationRole(existingResource)) + { + logger.info( + "Read of Subscription authorized for local user '{}', Subscription has local or remote authorization role", + user.getName()); + return Optional.of("local user, local or remote authorized Subscription"); + } + else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) + { + logger.info( + "Read of Subscription authorized for remote user '{}', Subscription has remote authorization role", + user.getName()); + return Optional.of("remote user, remote authorized Subscription"); + } + else + { + logger.warn("Read of Subscription unauthorized, no matching user role resource authorization role found"); + return Optional.empty(); + } } @Override public Optional<String> reasonUpdateAllowed(Connection connection, User user, Subscription oldResource, Subscription newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + Optional<String> errors = newResourceOk(newResource); + if (errors.isEmpty()) + { + if (isSame(oldResource, newResource)) + { + logger.info( + "Update of Subscription authorized for local user '{}', criteria, type and payload same as existing Subscription", + user.getName()); + return Optional.of("local user; criteria, type and payload same as existing Subscription"); + + } + else if (!resourceExists(connection, newResource)) + { + logger.info( + "Update of Subscription authorized for local user '{}', other Subscription with criteria, type and payload does not exist", + user.getName()); + return Optional + .of("local user; other Subscription with criteria, type and payload does not exist yet"); + } + else + { + logger.warn( + "Create of Subscription unauthorized, other Subscription with criteria, type and payload already exists"); + return Optional.empty(); + } + } + else + { + logger.warn("Update of Subscription unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else + { + logger.warn("Update of Subscription unauthorized, not a local user"); + return Optional.empty(); + } + } + + private boolean isSame(Subscription oldResource, Subscription newResource) + { + return oldResource.getCriteria().equals(newResource.getCriteria()) + && oldResource.getChannel().getType().equals(newResource.getChannel().getType()) + && (oldResource.getChannel().getPayload().equals(newResource.getChannel().getPayload()) + || (oldResource.getChannel().getPayload() == null + && newResource.getChannel().getPayload() == null)); } @Override public Optional<String> reasonDeleteAllowed(Connection connection, User user, Subscription oldResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Delete of Subscription authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Delete of Subscription unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonSearchAllowed(Connection connection, User user) { - // TODO Auto-generated method stub - return Optional.empty(); + logger.info("Search of Subscription authorized for {} user '{}', will be fitered by user role", user.getRole(), + user.getName()); + return Optional.of("Allowed for all, filtered by user role"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommand.java index 3355323b3..3d02ba199 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommand.java @@ -20,10 +20,10 @@ public abstract class AbstractCommand implements Command protected final String serverBase; - protected final AuthorizationCommandFactory authorizationCommandFactory; + protected final AuthorizationHelper authorizationHelper; public AbstractCommand(int transactionPriority, int index, User user, Bundle bundle, BundleEntryComponent entry, - String serverBase, AuthorizationCommandFactory authorizationCommandFactory) + String serverBase, AuthorizationHelper authorizationHelper) { this.transactionPriority = transactionPriority; @@ -34,7 +34,7 @@ public AbstractCommand(int transactionPriority, int index, User user, Bundle bun this.entry = entry; this.serverBase = serverBase; - this.authorizationCommandFactory = authorizationCommandFactory; + this.authorizationHelper = authorizationHelper; } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommandWithResource.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommandWithResource.java index 1b634ae59..db2551838 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommandWithResource.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AbstractCommandWithResource.java @@ -17,10 +17,10 @@ public abstract class AbstractCommandWithResource<R extends Resource, D extends protected final ParameterConverter parameterConverter; public AbstractCommandWithResource(int transactionPriority, int index, User user, Bundle bundle, - BundleEntryComponent entry, String serverBase, AuthorizationCommandFactory authorizationCommandFactory, + BundleEntryComponent entry, String serverBase, AuthorizationHelper authorizationHelper, R resource, D dao, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter) { - super(transactionPriority, index, user, bundle, entry, serverBase, authorizationCommandFactory); + super(transactionPriority, index, user, bundle, entry, serverBase, authorizationHelper); this.resource = resource; this.dao = dao; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommand.java deleted file mode 100644 index 212c4ed07..000000000 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommand.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.highmed.dsf.fhir.dao.command; - -@FunctionalInterface -public interface AuthorizationCommand -{ - static AuthorizationCommand empty() - { - return () -> - { - }; - } - - static AuthorizationCommand concat(AuthorizationCommand c1, AuthorizationCommand c2) - { - return () -> - { - c1.execute(); - c2.execute(); - }; - } - - void execute(); -} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommandFactory.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationHelper.java similarity index 94% rename from dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommandFactory.java rename to dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationHelper.java index b6d0e4516..3199a2c9e 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommandFactory.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationHelper.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Resource; -public interface AuthorizationCommandFactory +public interface AuthorizationHelper { void checkCreateAllowed(Connection connection, User user, Resource newResource); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommandFactoryImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationHelperImpl.java similarity index 96% rename from dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommandFactoryImpl.java rename to dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationHelperImpl.java index b58e57a66..2792823f8 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationCommandFactoryImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/AuthorizationHelperImpl.java @@ -20,15 +20,15 @@ import ca.uhn.fhir.model.api.annotation.ResourceDef; -public class AuthorizationCommandFactoryImpl implements AuthorizationCommandFactory +public class AuthorizationHelperImpl implements AuthorizationHelper { - private static final Logger logger = LoggerFactory.getLogger(AuthorizationCommandFactoryImpl.class); + private static final Logger logger = LoggerFactory.getLogger(AuthorizationHelperImpl.class); private static final Logger audit = LoggerFactory.getLogger("dsf-audit-logger"); private final AuthorizationRuleProvider authorizationRuleProvider; private final ResponseGenerator responseGenerator; - public AuthorizationCommandFactoryImpl(AuthorizationRuleProvider authorizationRuleProvider, + public AuthorizationHelperImpl(AuthorizationRuleProvider authorizationRuleProvider, ResponseGenerator responseGenerator) { this.authorizationRuleProvider = authorizationRuleProvider; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CommandFactoryImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CommandFactoryImpl.java index b7de06639..c51367ceb 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CommandFactoryImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CommandFactoryImpl.java @@ -46,14 +46,14 @@ public class CommandFactoryImpl implements InitializingBean, CommandFactory private final SnapshotGenerator snapshotGenerator; private final SnapshotDependencyAnalyzer snapshotDependencyAnalyzer; private final ParameterConverter parameterConverter; - private final AuthorizationCommandFactory authorizationCommandFactory; + private final AuthorizationHelper authorizationHelper; public CommandFactoryImpl(String serverBase, int defaultPageCount, DataSource dataSource, DaoProvider daoProvider, ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, ResponseGenerator responseGenerator, ExceptionHandler exceptionHandler, EventManager eventManager, EventGenerator eventGenerator, SnapshotGenerator snapshotGenerator, SnapshotDependencyAnalyzer snapshotDependencyAnalyzer, ParameterConverter parameterConverter, - AuthorizationCommandFactory authorizationCommandFactory) + AuthorizationHelper authorizationHelper) { this.serverBase = serverBase; this.defaultPageCount = defaultPageCount; @@ -68,7 +68,7 @@ public CommandFactoryImpl(String serverBase, int defaultPageCount, DataSource da this.snapshotGenerator = snapshotGenerator; this.snapshotDependencyAnalyzer = snapshotDependencyAnalyzer; this.parameterConverter = parameterConverter; - this.authorizationCommandFactory = authorizationCommandFactory; + this.authorizationHelper = authorizationHelper; } @Override @@ -85,13 +85,13 @@ public void afterPropertiesSet() throws Exception Objects.requireNonNull(snapshotGenerator, "snapshotGenerator"); Objects.requireNonNull(snapshotDependencyAnalyzer, "snapshotDependencyAnalyzer"); Objects.requireNonNull(parameterConverter, "parameterConverter"); - Objects.requireNonNull(authorizationCommandFactory, "authorizationRuleProvider"); + Objects.requireNonNull(authorizationHelper, "authorizationHelper"); } // read, vread private Command get(int index, User user, Bundle bundle, BundleEntryComponent entry) { - return new ReadCommand(index, user, bundle, entry, serverBase, authorizationCommandFactory, defaultPageCount, + return new ReadCommand(index, user, bundle, entry, serverBase, authorizationHelper, defaultPageCount, daoProvider, parameterConverter, responseGenerator, exceptionHandler); } @@ -106,14 +106,14 @@ private <R extends Resource> Command post(int index, User user, Bundle bundle, B .getDao(resource.getClass()); if (resource instanceof StructureDefinition) - return new CreateStructureDefinitionCommand(index, user, bundle, entry, serverBase, - authorizationCommandFactory, (StructureDefinition) resource, (StructureDefinitionDao) dao.get(), - exceptionHandler, parameterConverter, responseGenerator, eventManager, eventGenerator, + return new CreateStructureDefinitionCommand(index, user, bundle, entry, serverBase, authorizationHelper, + (StructureDefinition) resource, (StructureDefinitionDao) dao.get(), exceptionHandler, + parameterConverter, responseGenerator, eventManager, eventGenerator, daoProvider.getStructureDefinitionSnapshotDao(), snapshotGenerator, snapshotDependencyAnalyzer); else return dao .map(d -> new CreateCommand<R, ResourceDao<R>>(index, user, bundle, entry, serverBase, - authorizationCommandFactory, resource, d, exceptionHandler, parameterConverter, + authorizationHelper, resource, d, exceptionHandler, parameterConverter, responseGenerator, eventManager, eventGenerator)) .orElseThrow(() -> new IllegalStateException( "Resource of type " + resource.getClass().getName() + " not supported")); @@ -135,14 +135,14 @@ private <R extends Resource> Command put(int index, User user, Bundle bundle, Bu .getDao(resource.getClass()); if (resource instanceof StructureDefinition) - return new UpdateStructureDefinitionCommand(index, user, bundle, entry, serverBase, - authorizationCommandFactory, (StructureDefinition) resource, (StructureDefinitionDao) dao.get(), - exceptionHandler, parameterConverter, responseGenerator, eventManager, eventGenerator, + return new UpdateStructureDefinitionCommand(index, user, bundle, entry, serverBase, authorizationHelper, + (StructureDefinition) resource, (StructureDefinitionDao) dao.get(), exceptionHandler, + parameterConverter, responseGenerator, eventManager, eventGenerator, daoProvider.getStructureDefinitionSnapshotDao(), snapshotGenerator, snapshotDependencyAnalyzer); else return dao .map(d -> new UpdateCommand<R, ResourceDao<R>>(index, user, bundle, entry, serverBase, - authorizationCommandFactory, resource, d, exceptionHandler, parameterConverter, + authorizationHelper, resource, d, exceptionHandler, parameterConverter, responseGenerator, eventManager, eventGenerator)) .orElseThrow(() -> new IllegalStateException( "Resource of type " + resource.getClass().getName() + " not supported")); @@ -157,8 +157,8 @@ private Command delete(int index, User user, Bundle bundle, BundleEntryComponent { if (entry.getRequest().getUrl() != null && !entry.getRequest().getUrl().isBlank()) { - return new DeleteCommand(index, user, bundle, entry, serverBase, authorizationCommandFactory, - responseGenerator, daoProvider, exceptionHandler, parameterConverter, eventManager, eventGenerator); + return new DeleteCommand(index, user, bundle, entry, serverBase, authorizationHelper, responseGenerator, + daoProvider, exceptionHandler, parameterConverter, eventManager, eventGenerator); } else throw new BadBundleException( @@ -248,7 +248,7 @@ private <R extends Resource> Stream<Command> resolveReferences(Command cmd, int return dao .map(d -> Stream.of(cmd, new ResolveReferencesCommand<R, ResourceDao<R>>(index, user, bundle, entry, serverBase, - authorizationCommandFactory, resource, d, exceptionHandler, parameterConverter, + authorizationHelper, resource, d, exceptionHandler, parameterConverter, referenceExtractor, responseGenerator, referenceResolver))) .orElseThrow(() -> new IllegalStateException( "Resource of type " + resource.getClass().getName() + " not supported")); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateCommand.java index 36d00e9b3..86fde63a2 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateCommand.java @@ -52,11 +52,11 @@ public class CreateCommand<R extends Resource, D extends ResourceDao<R>> extends protected Response responseResult; public CreateCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, - AuthorizationCommandFactory authorizationCommandFactory, R resource, D dao, + AuthorizationHelper authorizationHelper, R resource, D dao, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, ResponseGenerator responseGenerator, EventManager eventManager, EventGenerator eventGenerator) { - super(2, index, user, bundle, entry, serverBase, authorizationCommandFactory, resource, dao, exceptionHandler, + super(2, index, user, bundle, entry, serverBase, authorizationHelper, resource, dao, exceptionHandler, parameterConverter); this.responseGenerator = responseGenerator; @@ -93,7 +93,7 @@ else if (resource.hasIdElement() && !entry.getFullUrl().equals(resource.getIdEle public void execute(Map<String, IdType> idTranslationTable, Connection connection) throws SQLException, WebApplicationException { - authorizationCommandFactory.checkCreateAllowed(connection, user, resource); + authorizationHelper.checkCreateAllowed(connection, user, resource); Optional<Resource> exists = checkAlreadyExists(connection, entry.getRequest().getIfNoneExist(), resource.getResourceType()); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateStructureDefinitionCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateStructureDefinitionCommand.java index 14bd34739..0fa9dff5c 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateStructureDefinitionCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateStructureDefinitionCommand.java @@ -36,13 +36,13 @@ public class CreateStructureDefinitionCommand extends CreateCommand<StructureDef private StructureDefinition resourceWithSnapshot; public CreateStructureDefinitionCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, - String serverBase, AuthorizationCommandFactory authorizationCommandFactory, StructureDefinition resource, + String serverBase, AuthorizationHelper authorizationHelper, StructureDefinition resource, StructureDefinitionDao dao, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, ResponseGenerator responseGenerator, EventManager eventManager, EventGenerator eventGenerator, StructureDefinitionSnapshotDao snapshotDao, SnapshotGenerator snapshotGenerator, SnapshotDependencyAnalyzer snapshotDependencyAnalyzer) { - super(index, user, bundle, entry, serverBase, authorizationCommandFactory, resource, dao, exceptionHandler, + super(index, user, bundle, entry, serverBase, authorizationHelper, resource, dao, exceptionHandler, parameterConverter, responseGenerator, eventManager, eventGenerator); this.snapshotDao = snapshotDao; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/DeleteCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/DeleteCommand.java index f361ae9d4..8179e2a56 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/DeleteCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/DeleteCommand.java @@ -52,11 +52,11 @@ public class DeleteCommand extends AbstractCommand implements Command private String id; public DeleteCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, - AuthorizationCommandFactory authorizationCommandFactory, ResponseGenerator responseGenerator, + AuthorizationHelper authorizationHelper, ResponseGenerator responseGenerator, DaoProvider daoProvider, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, EventManager eventManager, EventGenerator eventGenerator) { - super(1, index, user, bundle, entry, serverBase, authorizationCommandFactory); + super(1, index, user, bundle, entry, serverBase, authorizationHelper); this.responseGenerator = responseGenerator; this.daoProvider = daoProvider; @@ -105,7 +105,7 @@ private void deleteById(Connection connection, String resourceTypeName, String i .handleSqlException(() -> dao.readIncludingDeletedWithTransaction(connection, uuid)); dbResource.ifPresent( - oldResource -> authorizationCommandFactory.checkDeleteAllowed(connection, user, oldResource)); + oldResource -> authorizationHelper.checkDeleteAllowed(connection, user, oldResource)); deleted = exceptionHandler.handleSqlAndResourceNotFoundException(resourceTypeName, () -> dao.deleteWithTransaction(connection, uuid)); @@ -129,7 +129,7 @@ private void deleteByCondition(Connection connection, String resourceTypeName, Optional<Resource> resourceToDelete = search(connection, dao.get(), queryParameters); if (resourceToDelete.isPresent()) { - authorizationCommandFactory.checkDeleteAllowed(connection, user, resourceToDelete.get()); + authorizationHelper.checkDeleteAllowed(connection, user, resourceToDelete.get()); deleted = exceptionHandler.handleSqlAndResourceNotFoundException(resourceTypeName, () -> dao.get().deleteWithTransaction(connection, parameterConverter.toUuid(resourceTypeName, diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ReadCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ReadCommand.java index 73d62f8fa..ff4a4d104 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ReadCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ReadCommand.java @@ -54,11 +54,11 @@ public class ReadCommand extends AbstractCommand implements Command private Response responseResult; public ReadCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, - AuthorizationCommandFactory authorizationCommandFactory, int defaultPageCount, DaoProvider daoProvider, + AuthorizationHelper authorizationHelper, int defaultPageCount, DaoProvider daoProvider, ParameterConverter parameterConverter, ResponseGenerator responseGenerator, ExceptionHandler exceptionHandler) { - super(5, index, user, bundle, entry, serverBase, authorizationCommandFactory); + super(5, index, user, bundle, entry, serverBase, authorizationHelper); this.defaultPageCount = defaultPageCount; @@ -125,7 +125,7 @@ private void readById(Connection connection, String resourceTypeName, String id) else singleResult = r; - authorizationCommandFactory.checkReadAllowed(connection, user, r); + authorizationHelper.checkReadAllowed(connection, user, r); } private void readByIdAndVersion(Connection connection, String resourceTypeName, String id, String version) @@ -155,7 +155,7 @@ private void readByIdAndVersion(Connection connection, String resourceTypeName, else singleResult = r; - authorizationCommandFactory.checkReadAllowed(connection, user, r); + authorizationHelper.checkReadAllowed(connection, user, r); } private void readByCondition(Connection connection, String resourceTypeName, @@ -189,7 +189,7 @@ private void readByCondition(Connection connection, String resourceTypeName, singleResult = (Resource) multipleResult.getEntry().get(0).getResource(); multipleResult = null; - authorizationCommandFactory.checkReadAllowed(connection, user, singleResult); + authorizationHelper.checkReadAllowed(connection, user, singleResult); } else if (multipleResult != null && multipleResult.getEntry().size() == 2 && SearchEntryMode.MATCH.equals(multipleResult.getEntry().get(0).getSearch().getMode()) @@ -199,7 +199,7 @@ else if (multipleResult != null && multipleResult.getEntry().size() == 2 singleResultSearchWarning = (OperationOutcome) multipleResult.getEntry().get(1).getResource(); multipleResult = null; - authorizationCommandFactory.checkReadAllowed(connection, user, singleResult); + authorizationHelper.checkReadAllowed(connection, user, singleResult); } else if (multipleResult != null && multipleResult.getEntry().size() == 2 && SearchEntryMode.MATCH.equals(multipleResult.getEntry().get(1).getSearch().getMode()) @@ -209,12 +209,12 @@ else if (multipleResult != null && multipleResult.getEntry().size() == 2 singleResultSearchWarning = (OperationOutcome) multipleResult.getEntry().get(0).getResource(); multipleResult = null; - authorizationCommandFactory.checkReadAllowed(connection, user, singleResult); + authorizationHelper.checkReadAllowed(connection, user, singleResult); } else { - authorizationCommandFactory.checkSearchAllowed(connection, user, resourceTypeName); - authorizationCommandFactory.filterIncludeResults(connection, user, multipleResult); + authorizationHelper.checkSearchAllowed(connection, user, resourceTypeName); + authorizationHelper.filterIncludeResults(connection, user, multipleResult); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java index f92e7e739..5c37ddeb0 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java @@ -32,12 +32,12 @@ public class ResolveReferencesCommand<R extends Resource, D extends ResourceDao< private final ReferenceResolver referenceResolver; public ResolveReferencesCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, - AuthorizationCommandFactory authorizationCommandFactory, R resource, D dao, + AuthorizationHelper authorizationHelper, R resource, D dao, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, ReferenceExtractor referenceExtractor, ResponseGenerator responseGenerator, ReferenceResolver referenceResolver) { - super(4, index, user, bundle, entry, serverBase, authorizationCommandFactory, resource, dao, exceptionHandler, + super(4, index, user, bundle, entry, serverBase, authorizationHelper, resource, dao, exceptionHandler, parameterConverter); this.referenceExtractor = referenceExtractor; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java index 44edf5d2f..756b1dabc 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java @@ -50,11 +50,11 @@ public class UpdateCommand<R extends Resource, D extends ResourceDao<R>> extends protected R updatedResource; public UpdateCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, - AuthorizationCommandFactory authorizationCommandFactory, R resource, D dao, + AuthorizationHelper authorizationHelper, R resource, D dao, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, ResponseGenerator responseGenerator, EventManager eventManager, EventGenerator eventGenerator) { - super(3, index, user, bundle, entry, serverBase, authorizationCommandFactory, resource, dao, exceptionHandler, + super(3, index, user, bundle, entry, serverBase, authorizationHelper, resource, dao, exceptionHandler, parameterConverter); this.responseGenerator = responseGenerator; @@ -173,7 +173,7 @@ private void checkUpdateAllowed(User user, Connection connection, Resource newRe else { R oldResource = dbResource.get(); - authorizationCommandFactory.checkUpdateAllowed(connection, user, oldResource, newResource); + authorizationHelper.checkUpdateAllowed(connection, user, oldResource, newResource); } } @@ -208,7 +208,7 @@ private void updateByCondition(Map<String, IdType> idTranslationTable, Connectio if (result.getOverallCount() <= 0 && (!resource.hasId() || resource.getIdElement().getValue().startsWith(URL_UUID_PREFIX))) { - authorizationCommandFactory.checkCreateAllowed(connection, user, resource); + authorizationHelper.checkCreateAllowed(connection, user, resource); id = UUID.randomUUID(); idTranslationTable.put(entry.getFullUrl(), diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateStructureDefinitionCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateStructureDefinitionCommand.java index 1132e6c44..7c6d6f8ce 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateStructureDefinitionCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateStructureDefinitionCommand.java @@ -37,13 +37,13 @@ public class UpdateStructureDefinitionCommand extends UpdateCommand<StructureDef private StructureDefinition resourceWithSnapshot; public UpdateStructureDefinitionCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, - String serverBase, AuthorizationCommandFactory authorizationCommandFactory, StructureDefinition resource, + String serverBase, AuthorizationHelper authorizationHelper, StructureDefinition resource, StructureDefinitionDao dao, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, ResponseGenerator responseGenerator, EventManager eventManager, EventGenerator eventGenerator, StructureDefinitionSnapshotDao snapshotDao, SnapshotGenerator snapshotGenerator, SnapshotDependencyAnalyzer snapshotDependencyAnalyzer) { - super(index, user, bundle, entry, serverBase, authorizationCommandFactory, resource, dao, exceptionHandler, + super(index, user, bundle, entry, serverBase, authorizationHelper, resource, dao, exceptionHandler, parameterConverter, responseGenerator, eventManager, eventGenerator); this.snapshotDao = snapshotDao; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractStructureDefinitionDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractStructureDefinitionDaoJdbc.java index 4bc5a2dac..eed0fe1b2 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractStructureDefinitionDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractStructureDefinitionDaoJdbc.java @@ -14,6 +14,7 @@ import org.highmed.dsf.fhir.dao.StructureDefinitionDaoBase; import org.highmed.dsf.fhir.search.SearchQueryUserFilter; import org.highmed.dsf.fhir.search.parameters.StructureDefinitionIdentifier; +import org.highmed.dsf.fhir.search.parameters.StructureDefinitionStatus; import org.highmed.dsf.fhir.search.parameters.StructureDefinitionUrl; import org.highmed.dsf.fhir.search.parameters.StructureDefinitionVersion; import org.hl7.fhir.r4.model.StructureDefinition; @@ -35,6 +36,7 @@ public AbstractStructureDefinitionDaoJdbc(BasicDataSource dataSource, FhirContex super(dataSource, fhirContext, StructureDefinition.class, resourceTable, resourceColumn, resourceIdColumn, userFilter, with(() -> new StructureDefinitionIdentifier(resourceColumn), + () -> new StructureDefinitionStatus(resourceColumn), () -> new StructureDefinitionUrl(resourceColumn), () -> new StructureDefinitionVersion(resourceColumn)), with()); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/StructureDefinitionStatus.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/StructureDefinitionStatus.java new file mode 100644 index 000000000..26492ed7f --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/StructureDefinitionStatus.java @@ -0,0 +1,120 @@ +package org.highmed.dsf.fhir.search.parameters; + +import java.sql.Array; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import javax.ws.rs.core.UriBuilder; + +import org.highmed.dsf.fhir.function.BiFunctionWithSqlException; +import org.highmed.dsf.fhir.search.SearchQueryParameter.SearchParameterDefinition; +import org.highmed.dsf.fhir.search.SearchQueryParameterError; +import org.highmed.dsf.fhir.search.SearchQueryParameterError.SearchQueryParameterErrorType; +import org.highmed.dsf.fhir.search.parameters.basic.AbstractTokenParameter; +import org.highmed.dsf.fhir.search.parameters.basic.TokenSearchType; +import org.hl7.fhir.exceptions.FHIRException; +import org.hl7.fhir.r4.model.Enumerations.PublicationStatus; +import org.hl7.fhir.r4.model.Enumerations.SearchParamType; +import org.hl7.fhir.r4.model.Resource; +import org.hl7.fhir.r4.model.StructureDefinition; + +@SearchParameterDefinition(name = StructureDefinitionStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/StructureDefinition-status", type = SearchParamType.TOKEN, documentation = "The current status of the structure definition") +public class StructureDefinitionStatus extends AbstractTokenParameter<StructureDefinition> +{ + public static final String RESOURCE_COLUMN = "structure_definition"; + public static final String PARAMETER_NAME = "status"; + + private final String resourceColumn; + + private PublicationStatus status; + + public StructureDefinitionStatus() + { + this(RESOURCE_COLUMN); + } + + public StructureDefinitionStatus(String resourceColumn) + { + super(PARAMETER_NAME); + + this.resourceColumn = resourceColumn; + } + + @Override + protected void configureSearchParameter(Map<String, List<String>> queryParameters) + { + super.configureSearchParameter(queryParameters); + + if (valueAndType != null && valueAndType.type == TokenSearchType.CODE) + status = toStatus(valueAndType.codeValue, queryParameters.get(parameterName)); + } + + private PublicationStatus toStatus(String status, List<String> parameterValues) + { + if (status == null || status.isBlank()) + return null; + + try + { + return PublicationStatus.fromCode(status); + } + catch (FHIRException e) + { + addError(new SearchQueryParameterError(SearchQueryParameterErrorType.UNPARSABLE_VALUE, parameterName, + parameterValues, e)); + return null; + } + } + + @Override + public boolean isDefined() + { + return super.isDefined() && status != null; + } + + @Override + public String getFilterQuery() + { + return resourceColumn + "->>'status' = ?"; + } + + @Override + public int getSqlParameterCount() + { + return 1; + } + + @Override + public void modifyStatement(int parameterIndex, int subqueryParameterIndex, PreparedStatement statement, + BiFunctionWithSqlException<String, Object[], Array> arrayCreator) throws SQLException + { + statement.setString(parameterIndex, status.toCode()); + } + + @Override + public void modifyBundleUri(UriBuilder bundleUri) + { + bundleUri.replaceQueryParam(PARAMETER_NAME, status.toCode()); + } + + @Override + public boolean matches(Resource resource) + { + if (!isDefined()) + throw notDefined(); + + if (!(resource instanceof StructureDefinition)) + return false; + + return Objects.equals(((StructureDefinition) resource).getStatus(), status); + } + + @Override + protected String getSortSql(String sortDirectionWithSpacePrefix) + { + return resourceColumn + "->>'status'" + sortDirectionWithSpacePrefix; + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/CommandConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/CommandConfig.java index ebaa10afc..872dc476b 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/CommandConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/CommandConfig.java @@ -1,7 +1,7 @@ package org.highmed.dsf.fhir.spring.config; -import org.highmed.dsf.fhir.dao.command.AuthorizationCommandFactory; -import org.highmed.dsf.fhir.dao.command.AuthorizationCommandFactoryImpl; +import org.highmed.dsf.fhir.dao.command.AuthorizationHelper; +import org.highmed.dsf.fhir.dao.command.AuthorizationHelperImpl; import org.highmed.dsf.fhir.dao.command.CommandFactory; import org.highmed.dsf.fhir.dao.command.CommandFactoryImpl; import org.springframework.beans.factory.annotation.Autowired; @@ -44,13 +44,13 @@ public CommandFactory commandFactory() helperConfig.responseGenerator(), helperConfig.exceptionHandler(), eventConfig.eventManager(), eventConfig.eventGenerator(), snapshotConfig.snapshotGenerator(), snapshotConfig.snapshotDependencyAnalyzer(), helperConfig.parameterConverter(), - authorizationCommandFactory()); + authorizationHelper()); } @Bean - public AuthorizationCommandFactory authorizationCommandFactory() + public AuthorizationHelper authorizationHelper() { - return new AuthorizationCommandFactoryImpl(authorizationConfig.authorizationRuleProvider(), + return new AuthorizationHelperImpl(authorizationConfig.authorizationRuleProvider(), helperConfig.responseGenerator()); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java index 6f65d4cbe..1e2f13cb2 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java @@ -53,6 +53,7 @@ import org.highmed.dsf.fhir.search.parameters.ResourceId; import org.highmed.dsf.fhir.search.parameters.ResourceLastUpdated; import org.highmed.dsf.fhir.search.parameters.StructureDefinitionIdentifier; +import org.highmed.dsf.fhir.search.parameters.StructureDefinitionStatus; import org.highmed.dsf.fhir.search.parameters.StructureDefinitionUrl; import org.highmed.dsf.fhir.search.parameters.StructureDefinitionVersion; import org.highmed.dsf.fhir.search.parameters.SubscriptionChannelPayload; @@ -271,10 +272,11 @@ private CapabilityStatement createCapabilityStatement(String serverBase, int def searchParameters.put(ResearchStudy.class, Arrays.asList(researchStudyIdentifier, researchStudyEnrollment)); var structureDefinitionIdentifier = createSearchParameter(StructureDefinitionIdentifier.class); + var structureDefinitionStatus = createSearchParameter(StructureDefinitionStatus.class); var structureDefinitionUrl = createSearchParameter(StructureDefinitionUrl.class); var structureDefinitionVersion = createSearchParameter(StructureDefinitionVersion.class); - searchParameters.put(StructureDefinition.class, - Arrays.asList(structureDefinitionIdentifier, structureDefinitionUrl, structureDefinitionVersion)); + searchParameters.put(StructureDefinition.class, Arrays.asList(structureDefinitionIdentifier, + structureDefinitionStatus, structureDefinitionUrl, structureDefinitionVersion)); var subscriptionCriteria = createSearchParameter(SubscriptionCriteria.class); var subscriptionStatus = createSearchParameter(SubscriptionStatus.class); diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-endpoint-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-endpoint-0.1.0.xml index cd3b2543e..f2816fae3 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-endpoint-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-endpoint-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/highmed-endpoint" /> <version value="0.1.0" /> <name value="Endpoint" /> - <status value="active" /> + <status value="draft" /> <date value="2019-05-21" /> <fhirVersion value="4.0.0" /> <kind value="resource" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-certificate-thumbprint-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-certificate-thumbprint-0.1.0.xml index 2d907ecfe..292712a9a 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-certificate-thumbprint-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-certificate-thumbprint-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"/> <version value="0.1.0"/> <name value="CertificateThumbprint"/> - <status value="active"/> + <status value="draft"/> <date value="2019-05-21"/> <fhirVersion value="4.0.0"/> <kind value="complex-type"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-group-id-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-group-id-0.1.0.xml index 7745eceeb..97478164b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-group-id-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-group-id-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/group-id" /> <version value="0.1.0" /> <name value="group-id" /> - <status value="active" /> + <status value="draft" /> <date value="2019-12-16" /> <fhirVersion value="4.0.0" /> <mapping> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-medic-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-medic-0.1.0.xml index 99e12927b..f37f0d554 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-medic-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-medic-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/participating-medic"/> <version value="0.1.0"/> <name value="ParticipatingMedic"/> - <status value="active"/> + <status value="draft"/> <date value="2019-08-05"/> <fhirVersion value="4.0.0"/> <kind value="complex-type"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml index 9b8399723..0b9991d4d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/process-authorization" /> <version value="0.1.0" /> <name value="ProcessAuthorization" /> - <status value="active" /> + <status value="draft" /> <experimental value="false" /> <date value="2020-02-24" /> <fhirVersion value="4.0.0" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-query-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-query-0.1.0.xml index f327fb0da..4d345f4b6 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-query-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-query-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/query"/> <version value="0.1.0"/> <name value="Query"/> - <status value="active"/> + <status value="draft"/> <fhirVersion value="4.0.0"/> <kind value="complex-type"/> <abstract value="false"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-group-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-group-0.1.0.xml index 172bbf943..a89e85cc8 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-group-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-group-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/highmed-group"/> <version value="0.1.0"/> <name value="Group"/> - <status value="active"/> + <status value="draft"/> <fhirVersion value="4.0.0"/> <kind value="resource"/> <abstract value="false"/> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-organization-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-organization-0.1.0.xml index beb541bae..13daaf47c 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-organization-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-organization-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/highmed-organization" /> <version value="0.1.0" /> <name value="Organization" /> - <status value="active" /> + <status value="draft" /> <date value="2019-05-21" /> <fhirVersion value="4.0.0" /> <kind value="resource" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-base-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-base-0.1.0.xml index 53c01ec14..8d11963f3 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-base-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-base-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-base" /> <version value="0.1.0" /> <name value="TaskBase" /> - <status value="active" /> + <status value="draft" /> <date value="2019-05-21" /> <fhirVersion value="4.0.0" /> <kind value="resource" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-compute-simple-feasibility-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-compute-simple-feasibility-0.1.0.xml index 5b38ee2c7..fd9d61532 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-compute-simple-feasibility-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-compute-simple-feasibility-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-compute-simple-feasibility" /> <version value="0.1.0" /> <name value="TaskComputeSimpleFeasibility" /> - <status value="active" /> + <status value="draft" /> <date value="2019-05-21" /> <fhirVersion value="4.0.0" /> <kind value="resource" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-execute-simple-feasibility-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-execute-simple-feasibility-0.1.0.xml index 8287bf014..9e8e29458 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-execute-simple-feasibility-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-execute-simple-feasibility-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-execute-simple-feasibility" /> <version value="0.1.0" /> <name value="TaskExecuteSimpleFeasibility" /> - <status value="active" /> + <status value="draft" /> <date value="2019-05-21" /> <fhirVersion value="4.0.0" /> <kind value="resource" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-execute-update-resources-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-execute-update-resources-0.1.0.xml index b2d01560a..fd0b40e85 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-execute-update-resources-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-execute-update-resources-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-execute-update-resources" /> <version value="0.1.0" /> <name value="TaskExecuteUpdateResources" /> - <status value="active" /> + <status value="draft" /> <date value="2019-05-21" /> <fhirVersion value="4.0.0" /> <kind value="resource" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-simple-feasibility-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-simple-feasibility-0.1.0.xml index 5631c56e7..bde33ad08 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-simple-feasibility-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-multi-medic-result-simple-feasibility-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-multi-medic-result-simple-feasibility" /> <version value="0.1.0" /> <name value="TaskMultiMedicResultSimpleFeasibility" /> - <status value="active" /> + <status value="draft" /> <date value="2019-05-21" /> <fhirVersion value="4.0.0" /> <kind value="resource" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-parent-plugin-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-parent-plugin-0.1.0.xml index fd196b201..8da0a75f9 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-parent-plugin-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-parent-plugin-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-parent-plugin" /> <version value="0.1.0" /> <name value="ParentPlugin" /> - <status value="active" /> + <status value="draft" /> <date value="2019-10-24" /> <fhirVersion value="4.0.0" /> <kind value="resource" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-ping-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-ping-0.1.0.xml index 91b4f906b..4f41d6f8d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-ping-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-ping-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-ping" /> <version value="0.1.0" /> <name value="TaskPing" /> - <status value="active" /> + <status value="draft" /> <date value="2019-05-21" /> <fhirVersion value="4.0.0" /> <kind value="resource" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-pong-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-pong-0.1.0.xml index 0f05366e9..918e64ec7 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-pong-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-pong-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-pong" /> <version value="0.1.0" /> <name value="TaskPong" /> - <status value="active" /> + <status value="draft" /> <date value="2019-05-21" /> <fhirVersion value="4.0.0" /> <kind value="resource" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-simple-feasibility-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-simple-feasibility-0.1.0.xml index 52237d5a3..e4252546b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-simple-feasibility-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-simple-feasibility-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-request-simple-feasibility" /> <version value="0.1.0" /> <name value="TaskRequestSimpleFeasibility" /> - <status value="active" /> + <status value="draft" /> <date value="2019-05-21" /> <fhirVersion value="4.0.0" /> <kind value="resource" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-update-resources-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-update-resources-0.1.0.xml index 9a71198d4..12617d40b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-update-resources-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-update-resources-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-request-update-resources" /> <version value="0.1.0" /> <name value="TaskRequestUpdateResources" /> - <status value="active" /> + <status value="draft" /> <date value="2019-05-21" /> <fhirVersion value="4.0.0" /> <kind value="resource" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-simple-feasibility-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-simple-feasibility-0.1.0.xml index 3c2aa0db5..fc6e84037 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-simple-feasibility-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-single-medic-result-simple-feasibility-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-single-medic-result-simple-feasibility" /> <version value="0.1.0" /> <name value="TaskSingleMedicResultSimpleFeasibility" /> - <status value="active" /> + <status value="draft" /> <date value="2019-05-21" /> <fhirVersion value="4.0.0" /> <kind value="resource" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-start-process-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-start-process-0.1.0.xml index 34995ae79..631e2fb42 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-start-process-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-start-process-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/highemd-task-start-process" /> <version value="0.1.0" /> <name value="TaskStartProcess" /> - <status value="active" /> + <status value="draft" /> <date value="2019-05-21" /> <fhirVersion value="4.0.0" /> <kind value="resource" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-update-whitelist-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-update-whitelist-0.1.0.xml index 0774c92d0..003c926a9 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-update-whitelist-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-update-whitelist-0.1.0.xml @@ -9,7 +9,7 @@ <url value="http://highmed.org/fhir/StructureDefinition/highmed-task-update-whitelist" /> <version value="0.1.0" /> <name value="TaskUpdateWhiteList" /> - <status value="active" /> + <status value="draft" /> <date value="2019-05-21" /> <fhirVersion value="4.0.0" /> <kind value="resource" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/Subscription/bpmn-task-subscription.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/Subscription/bpmn-task-subscription.xml index 7c0117890..73c8dcba7 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/Subscription/bpmn-task-subscription.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/Subscription/bpmn-task-subscription.xml @@ -1,5 +1,11 @@ <Subscription xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://hl7.org/fhir" xsi:schemaLocation="http://hl7.org/fhir http://www.hl7.org/fhir/fhir-base.xsd"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="LOCAL"/> + </tag> + </meta> <status value="active"/> <reason value="Businness Process Engine"/> <criteria value="Task?status=requested"/> From 9b40f6e9aa154978d9bca9a313a1639767b72ba8 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Mon, 2 Mar 2020 00:30:56 +0100 Subject: [PATCH 15/55] integration test fix --- .../OrganizationIntegrationTest.java | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/OrganizationIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/OrganizationIntegrationTest.java index 19d9ca678..14238973d 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/OrganizationIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/OrganizationIntegrationTest.java @@ -21,7 +21,7 @@ public void testSearchAll() throws Exception { Bundle searchBundle = getWebserviceClient().search(Organization.class, Collections.emptyMap()); assertNotNull(searchBundle); - assertEquals(1, searchBundle.getTotal()); + assertEquals(2, searchBundle.getTotal()); assertTrue(searchBundle.getEntryFirstRep().getResource() instanceof Organization); } @@ -31,16 +31,22 @@ public void testSearchOrganizationIncludeEndpoint() throws Exception Bundle searchBundle = getWebserviceClient().search(Organization.class, Map.of("_include", Collections.singletonList("Organization:endpoint"))); assertNotNull(searchBundle); - assertEquals(1, searchBundle.getTotal()); - assertEquals(2, searchBundle.getEntry().size()); + assertEquals(2, searchBundle.getTotal()); + assertEquals(3, searchBundle.getEntry().size()); - BundleEntryComponent orgEntry = searchBundle.getEntry().get(0); - assertNotNull(orgEntry); - assertEquals(SearchEntryMode.MATCH, orgEntry.getSearch().getMode()); - assertNotNull(orgEntry.getResource()); - assertTrue(orgEntry.getResource() instanceof Organization); + BundleEntryComponent orgEntry1 = searchBundle.getEntry().get(0); + assertNotNull(orgEntry1); + assertEquals(SearchEntryMode.MATCH, orgEntry1.getSearch().getMode()); + assertNotNull(orgEntry1.getResource()); + assertTrue(orgEntry1.getResource() instanceof Organization); - BundleEntryComponent eptEntry = searchBundle.getEntry().get(1); + BundleEntryComponent orgEntry2 = searchBundle.getEntry().get(1); + assertNotNull(orgEntry2); + assertEquals(SearchEntryMode.MATCH, orgEntry2.getSearch().getMode()); + assertNotNull(orgEntry2.getResource()); + assertTrue(orgEntry2.getResource() instanceof Organization); + + BundleEntryComponent eptEntry = searchBundle.getEntry().get(2); assertNotNull(eptEntry); assertEquals(SearchEntryMode.INCLUDE, eptEntry.getSearch().getMode()); assertNotNull(eptEntry.getResource()); @@ -53,16 +59,22 @@ public void testSearchOrganizationRevIncludeEndpoint() throws Exception Bundle searchBundle = getWebserviceClient().search(Organization.class, Map.of("_revinclude", Collections.singletonList("Endpoint:organization"))); assertNotNull(searchBundle); - assertEquals(1, searchBundle.getTotal()); - assertEquals(2, searchBundle.getEntry().size()); + assertEquals(2, searchBundle.getTotal()); + assertEquals(3, searchBundle.getEntry().size()); + + BundleEntryComponent orgEntry1 = searchBundle.getEntry().get(0); + assertNotNull(orgEntry1); + assertEquals(SearchEntryMode.MATCH, orgEntry1.getSearch().getMode()); + assertNotNull(orgEntry1.getResource()); + assertTrue(orgEntry1.getResource() instanceof Organization); - BundleEntryComponent orgEntry = searchBundle.getEntry().get(0); - assertNotNull(orgEntry); - assertEquals(SearchEntryMode.MATCH, orgEntry.getSearch().getMode()); - assertNotNull(orgEntry.getResource()); - assertTrue(orgEntry.getResource() instanceof Organization); + BundleEntryComponent orgEntry2 = searchBundle.getEntry().get(1); + assertNotNull(orgEntry2); + assertEquals(SearchEntryMode.MATCH, orgEntry2.getSearch().getMode()); + assertNotNull(orgEntry2.getResource()); + assertTrue(orgEntry2.getResource() instanceof Organization); - BundleEntryComponent eptEntry = searchBundle.getEntry().get(1); + BundleEntryComponent eptEntry = searchBundle.getEntry().get(2); assertNotNull(eptEntry); assertEquals(SearchEntryMode.INCLUDE, eptEntry.getSearch().getMode()); assertNotNull(eptEntry.getResource()); From 83bb9b117b4cd92ef1380c967022ea4ad531a06e Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 3 Mar 2020 17:40:49 +0100 Subject: [PATCH 16/55] work on authorization rules, i.a. ActivityDefinition and Task --- .../ActivityDefinitionHtmlFhirAdapter.java | 16 + .../highmed/dsf/fhir/OrganizationType.java | 20 ++ .../authentication/OrganizationProvider.java | 2 + .../OrganizationProviderWithDbBackend.java | 22 +- .../AbstractAuthorizationRule.java | 19 +- .../ActivityDefinitionAuthorizationRule.java | 201 ++++++++++++- ...finitionProcessAuthorizationExtension.java | 87 ++++++ ...initionProcessAuthorizationExtensions.java | 36 +++ .../ActivityDefinitionProvider.java | 13 + .../ActivityDefinitionProviderImpl.java | 63 ++++ .../fhir/authorization/AuthorizationRole.java | 34 +++ .../BinaryAuthorizationRule.java | 6 +- .../BundleAuthorizationRule.java | 106 ++++++- .../CodeSystemAuthorizationRule.java | 6 +- .../EndpointAuthorizationRule.java | 10 +- .../authorization/GroupAuthorizationRule.java | 6 +- .../HealthcareServiceAuthorizationRule.java | 5 +- .../LocationAuthorizationRule.java | 6 +- .../NamingSystemAuthorizationRule.java | 5 +- .../OrganizationAuthorizationRule.java | 7 +- .../PatientAuthorizationRule.java | 6 +- .../PractitionerAuthorizationRule.java | 5 +- .../PractitionerRoleAuthorizationRule.java | 5 +- .../ProvenanceAuthorizationRule.java | 6 +- .../ResearchStudyAuthorizationRule.java | 5 +- .../StructureDefinitionAuthorizationRule.java | 7 +- .../SubscriptionAuthorizationRule.java | 5 +- .../authorization/TaskAuthorizationRule.java | 273 +++++++++++++++++- .../ValueSetAuthorizationRule.java | 6 +- .../dsf/fhir/dao/ActivityDefinitionDao.java | 11 +- .../dao/jdbc/ActivityDefinitionDaoJdbc.java | 84 ++++++ .../user/ActivityDefinitionUserFilter.java | 35 +-- .../spring/config/AuthenticationConfig.java | 22 -- .../spring/config/AuthorizationConfig.java | 88 ++++-- .../dsf/fhir/spring/config/DaoConfig.java | 10 - .../ActivityDefinition-PingProcess-1.0.0.xml | 82 ++++++ ...tivityDefinition-PingProcess-1.0.0.xml.put | 1 + ...-extension-process-authorization-0.1.0.xml | 76 ++++- .../hapi/ActivityDefinitionWithExtension.java | 74 +++++ 39 files changed, 1283 insertions(+), 188 deletions(-) create mode 100644 dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/ActivityDefinitionHtmlFhirAdapter.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProcessAuthorizationExtension.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProcessAuthorizationExtensions.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProvider.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProviderImpl.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRole.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ActivityDefinition-PingProcess-1.0.0.xml create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ActivityDefinition-PingProcess-1.0.0.xml.put create mode 100644 dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/ActivityDefinitionWithExtension.java diff --git a/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/ActivityDefinitionHtmlFhirAdapter.java b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/ActivityDefinitionHtmlFhirAdapter.java new file mode 100644 index 000000000..edacd7b42 --- /dev/null +++ b/dsf-fhir/dsf-fhir-rest-adapter/src/main/java/org/highmed/dsf/fhir/adapter/ActivityDefinitionHtmlFhirAdapter.java @@ -0,0 +1,16 @@ +package org.highmed.dsf.fhir.adapter; + +import javax.ws.rs.ext.Provider; + +import org.hl7.fhir.r4.model.ActivityDefinition; + +import ca.uhn.fhir.context.FhirContext; + +@Provider +public class ActivityDefinitionHtmlFhirAdapter extends HtmlFhirAdapter<ActivityDefinition> +{ + public ActivityDefinitionHtmlFhirAdapter(FhirContext fhirContext, ServerBaseProvider serverBaseProvider) + { + super(fhirContext, serverBaseProvider, ActivityDefinition.class); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/OrganizationType.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/OrganizationType.java index ab8a7c2f4..b8ecc473e 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/OrganizationType.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/OrganizationType.java @@ -1,5 +1,7 @@ package org.highmed.dsf.fhir; +import java.util.Optional; + public enum OrganizationType { MeDIC("MeDIC"), TTP("TTP"); @@ -20,4 +22,22 @@ public String getSystem() { return "http://highmed.org/fhir/CodeSystem/organization-type"; } + + public static Optional<OrganizationType> fromString(String type) + { + switch (type) + { + case "MEDIC": + case "MeDIC": + case "medic": + return Optional.of(MeDIC); + + case "TTP": + case "ttp": + return Optional.of(TTP); + + default: + return Optional.empty(); + } + } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/OrganizationProvider.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/OrganizationProvider.java index 8ac8c31ec..1970d2834 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/OrganizationProvider.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/OrganizationProvider.java @@ -14,4 +14,6 @@ public interface OrganizationProvider * <code>null</code> */ Optional<User> getOrganization(X509Certificate certificate); + + Optional<Organization> getLocalOrganization(); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/OrganizationProviderWithDbBackend.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/OrganizationProviderWithDbBackend.java index 4a15443c8..43705dcae 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/OrganizationProviderWithDbBackend.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/OrganizationProviderWithDbBackend.java @@ -71,18 +71,15 @@ public Optional<User> getOrganization(X509Certificate certificate) UserRole userRole = localUserThumbprints.contains(loginThumbprintHex.toLowerCase()) ? UserRole.LOCAL : UserRole.REMOTE; - if (UserRole.LOCAL.equals(userRole)) + switch (userRole) { - return getLocalOrganization().map(org -> new User(org, userRole)); - } - else if (UserRole.REMOTE.equals(userRole)) - { - return getOrganization(loginThumbprintHex).map(org -> new User(org, userRole)); - } - else - { - logger.warn("UserRole {} not supported", userRole); - return Optional.empty(); + case LOCAL: + return getLocalOrganization().map(org -> new User(org, userRole)); + case REMOTE: + return getOrganization(loginThumbprintHex).map(org -> new User(org, userRole)); + default: + logger.warn("UserRole {} not supported", userRole); + return Optional.empty(); } } @@ -92,7 +89,8 @@ private Optional<Organization> getOrganization(String loginThumbprintHex) () -> dao.readActiveNotDeletedByThumbprint(loginThumbprintHex), Optional::empty); } - private Optional<Organization> getLocalOrganization() + @Override + public Optional<Organization> getLocalOrganization() { return exceptionHandler.catchAndLogSqlExceptionAndIfReturn( () -> dao.readActiveNotDeletedByIdentifier(localIdentifierValue), Optional::empty); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java index 39ae94f0e..071f5ab09 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java @@ -7,6 +7,7 @@ import java.util.Objects; import java.util.Optional; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.authentication.UserRole; import org.highmed.dsf.fhir.dao.ResourceDao; @@ -31,14 +32,16 @@ public abstract class AbstractAuthorizationRule<R extends Resource, D extends Re protected final DaoProvider daoProvider; protected final String serverBase; protected final ReferenceResolver referenceResolver; + protected final OrganizationProvider organizationProvider; public AbstractAuthorizationRule(Class<R> resourceType, DaoProvider daoProvider, String serverBase, - ReferenceResolver referenceResolver) + ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { this.resourceType = resourceType; this.daoProvider = daoProvider; this.serverBase = serverBase; this.referenceResolver = referenceResolver; + this.organizationProvider = organizationProvider; } @SuppressWarnings("unchecked") @@ -52,6 +55,9 @@ public void afterPropertiesSet() throws Exception { Objects.requireNonNull(resourceType, "resourceType"); Objects.requireNonNull(daoProvider, "daoProvider"); + Objects.requireNonNull(serverBase, "serverBase"); + Objects.requireNonNull(referenceResolver, "referenceResolver"); + Objects.requireNonNull(daoProvider, "daoProvider"); } @Override @@ -204,4 +210,15 @@ protected final boolean isCurrentUserPartOfReferencedOrganization(Connection con } } } + + protected final boolean isLocalOrganization(Organization organization) + { + if (organization == null) + return false; + if (!organization.hasIdElement()) + return false; + + return organizationProvider.getLocalOrganization() + .map(localOrg -> localOrg.getIdElement().equals(organization.getIdElement())).orElse(false); + } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java index e2358f183..892d4581f 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java @@ -1,56 +1,233 @@ package org.highmed.dsf.fhir.authorization; import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.ActivityDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ActivityDefinitionAuthorizationRule extends AbstractAuthorizationRule<ActivityDefinition, ActivityDefinitionDao> { + private static final Logger logger = LoggerFactory.getLogger(ActivityDefinitionAuthorizationRule.class); + + private static final String VERSION_PATTERN_STRING = "\\d+\\.\\d+\\.\\d+"; + private static final Pattern VERSION_PATTERN = Pattern.compile(VERSION_PATTERN_STRING); + private static final String URL_PATTERN_STRING = "http://highmed.org/bpe/Process/[-\\w]+"; + private static final Pattern URL_PATTERN = Pattern.compile(URL_PATTERN_STRING); + public ActivityDefinitionAuthorizationRule(DaoProvider daoProvider, String serverBase, - ReferenceResolver referenceResolver) + ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { - super(ActivityDefinition.class, daoProvider, serverBase, referenceResolver); + super(ActivityDefinition.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override public Optional<String> reasonCreateAllowed(Connection connection, User user, ActivityDefinition newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + Optional<String> errors = newResourceOk(newResource); + if (errors.isEmpty()) + { + if (!resourceExists(connection, newResource)) + { + logger.info( + "Create of ActivityDefinition authorized for local user '{}', ActivityDefinition with version and url does not exist", + user.getName()); + return Optional.of("local user, ActivityDefinition with version and url does not exist yet"); + } + else + { + logger.warn( + "Create of ActivityDefinition unauthorized, ActivityDefinition with version and url already exists"); + return Optional.empty(); + } + } + else + { + logger.warn("Create of ActivityDefinition unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else + { + logger.warn("Create of ActivityDefinition unauthorized, not a local user"); + return Optional.empty(); + } + } + + private Optional<String> newResourceOk(ActivityDefinition newResource) + { + List<String> errors = new ArrayList<String>(); + + if (newResource.hasUrl()) + { + if (!URL_PATTERN.matcher(newResource.getUrl()).matches()) + { + errors.add("activitydefinition.url not matching " + URL_PATTERN_STRING + " pattern"); + } + } + else + { + errors.add("activitydefinition.url missing"); + } + + if (newResource.hasVersion()) + { + if (!VERSION_PATTERN.matcher(newResource.getVersion()).matches()) + { + errors.add("activitydefinition.version not matching " + VERSION_PATTERN_STRING + " pattern"); + } + } + else + { + errors.add("activitydefinition.version missing"); + } + + ActivityDefinitionProcessAuthorizationExtensions extensions = new ActivityDefinitionProcessAuthorizationExtensions( + newResource); + if (!extensions.isValid()) + { + errors.add("activitydefinition.extension with url " + + ActivityDefinitionProcessAuthorizationExtensions.PROCESS_AUTHORIZATION_EXTENSION_URL + + " not valid or missing, at least one expected"); + } + + if (!hasLocalOrRemoteAuthorizationRole(newResource)) + { + errors.add("missing authorization tag"); + } + + if (errors.isEmpty()) + return Optional.empty(); + else + return Optional.of(errors.stream().collect(Collectors.joining(", "))); + } + + private boolean resourceExists(Connection connection, ActivityDefinition newResource) + { + try + { + return getDao() + .readByUrlAndVersionWithTransaction(connection, newResource.getUrl(), newResource.getVersion()) + .isPresent(); + } + catch (SQLException e) + { + logger.warn( + "Create of ActivityDefinition unauthorized, error while checking for existing ActivityDefinition with version and url", + e); + return false; + } } @Override public Optional<String> reasonReadAllowed(Connection connection, User user, ActivityDefinition existingResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user) && hasLocalOrRemoteAuthorizationRole(existingResource)) + { + logger.info( + "Read of ActivityDefinition authorized for local user '{}', ActivityDefinition has local or remote authorization role", + user.getName()); + return Optional.of("local user, local or remote authorized CodeSystem"); + } + else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) + { + logger.info( + "Read of ActivityDefinition authorized for remote user '{}', ActivityDefinition has remote authorization role", + user.getName()); + return Optional.of("remote user, remote authorized ActivityDefinition"); + } + else + { + logger.warn( + "Read of ActivityDefinition unauthorized, no matching user role resource authorization role found"); + return Optional.empty(); + } } @Override public Optional<String> reasonUpdateAllowed(Connection connection, User user, ActivityDefinition oldResource, ActivityDefinition newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + Optional<String> errors = newResourceOk(newResource); + if (errors.isEmpty()) + { + if (isSame(oldResource, newResource)) + { + logger.info( + "Update of ActivityDefinition authorized for local user '{}', url and version same as existing ActivityDefinition", + user.getName()); + return Optional.of("local user; url and version same as existing ActivityDefinition"); + + } + else if (!resourceExists(connection, newResource)) + { + logger.info( + "Update of ActivityDefinition authorized for local user '{}', other ActivityDefinition with url and version does not exist", + user.getName()); + return Optional.of("local user; other ActivityDefinition with url and version does not exist yet"); + } + else + { + logger.warn( + "Update of ActivityDefinition unauthorized, other Endpoint with address and identifier already exists"); + return Optional.empty(); + } + } + else + { + logger.warn("Update of ActivityDefinition unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else + { + logger.warn("Update of ActivityDefinition unauthorized, not a local user"); + return Optional.empty(); + } + } + + private boolean isSame(ActivityDefinition oldResource, ActivityDefinition newResource) + { + return oldResource.getUrl().equals(newResource.getUrl()) + && oldResource.getVersion().equals(newResource.getVersion()); } @Override public Optional<String> reasonDeleteAllowed(Connection connection, User user, ActivityDefinition oldResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Delete of ActivityDefinition authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Delete of ActivityDefinition unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonSearchAllowed(Connection connection, User user) { - // TODO Auto-generated method stub - return Optional.empty(); + logger.info("Search of ActivityDefinition authorized for {} user '{}', will be fitered by user role", + user.getRole(), user.getName()); + return Optional.of("Allowed for all, filtered by user role"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProcessAuthorizationExtension.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProcessAuthorizationExtension.java new file mode 100644 index 000000000..f85b72137 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProcessAuthorizationExtension.java @@ -0,0 +1,87 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.highmed.dsf.fhir.OrganizationType; +import org.hl7.fhir.r4.model.CanonicalType; +import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.StringType; + +public class ActivityDefinitionProcessAuthorizationExtension +{ + public static final String MESSAGE_NAME_EXTENSION_URL = "message-name"; + public static final String AUTHORIZATION_ROLE_EXTENSION_URL = "authorization-role"; + public static final String ORGANIZATION_TYPES_EXTENSION_URL = "organization-types"; + public static final String ORGANIZATION_TYPE_EXTENSION_URL = "organization-type"; + public static final String TASK_PROFILE_EXTENSION_URL = "task-profile"; + + private final Extension processAuthorizationExtension; + + public ActivityDefinitionProcessAuthorizationExtension(Extension processAuthorizationExtension) + { + this.processAuthorizationExtension = processAuthorizationExtension; + } + + public boolean isValid() + { + return doGetMessageName().isPresent() && doGetAuthorizationRole().isPresent() + && (getOrganizationTypes().size() == 1 || (getOrganizationTypes().size() == 2 + && !getOrganizationTypes().get(0).equals(getOrganizationTypes().get(1)))) + && doGetTaskProfile().isPresent(); + } + + public String getMessageName() + { + return doGetMessageName().orElseThrow(); + } + + private Optional<String> doGetMessageName() + { + return Optional.ofNullable(processAuthorizationExtension.getExtensionByUrl(MESSAGE_NAME_EXTENSION_URL)) + .map(e -> e.getValue()).filter(t -> t instanceof StringType).map(t -> ((StringType) t).getValue()); + } + + public AuthorizationRole getAuthorizationRole() + { + return doGetAuthorizationRole().orElseThrow(); + } + + private Optional<AuthorizationRole> doGetAuthorizationRole() + { + return Optional.ofNullable(processAuthorizationExtension.getExtensionByUrl(AUTHORIZATION_ROLE_EXTENSION_URL)) + .map(e -> e.getValue()).filter(t -> t instanceof Coding).map(t -> ((Coding) t).getCode()) + .flatMap(AuthorizationRole::fromString); + } + + public List<OrganizationType> getOrganizationTypes() + { + return Optional.ofNullable(processAuthorizationExtension.getExtensionByUrl(ORGANIZATION_TYPES_EXTENSION_URL)) + .map(e -> e.getExtensionsByUrl(ORGANIZATION_TYPE_EXTENSION_URL).stream() + .flatMap(this::getOrganizationType).collect(Collectors.toList())) + .orElseGet(Collections::emptyList); + } + + private Stream<OrganizationType> getOrganizationType(Extension organizationType) + { + return Optional.ofNullable(organizationType).map(ex -> ex.getValue()).filter(t -> t instanceof Coding) + .map(t -> ((Coding) t).getCode()).flatMap(OrganizationType::fromString).stream(); + } + + public String getTaskProfile() + { + return doGetTaskProfile().orElseThrow(); + } + + private Optional<String> doGetTaskProfile() + { + Optional<String> taskProfile = Optional.ofNullable(processAuthorizationExtension.getExtensionByUrl(TASK_PROFILE_EXTENSION_URL)) + .map(e -> e.getValue()).filter(t -> t instanceof CanonicalType) + .map(t -> ((CanonicalType) t).getValue()); + return taskProfile; + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProcessAuthorizationExtensions.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProcessAuthorizationExtensions.java new file mode 100644 index 000000000..fcc565e15 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProcessAuthorizationExtensions.java @@ -0,0 +1,36 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.hl7.fhir.r4.model.ActivityDefinition; + +public class ActivityDefinitionProcessAuthorizationExtensions +{ + public static final String PROCESS_AUTHORIZATION_EXTENSION_URL = "http://highmed.org/fhir/StructureDefinition/process-authorization"; + + private final ActivityDefinition activityDefinition; + + public ActivityDefinitionProcessAuthorizationExtensions(ActivityDefinition activityDefinition) + { + this.activityDefinition = activityDefinition; + } + + public boolean isValid() + { + return doGetExtensions().map(ActivityDefinitionProcessAuthorizationExtension::isValid).count() >= 1; + } + + public List<ActivityDefinitionProcessAuthorizationExtension> getExtensions() + { + return doGetExtensions().filter(ActivityDefinitionProcessAuthorizationExtension::isValid) + .collect(Collectors.toList()); + } + + private Stream<ActivityDefinitionProcessAuthorizationExtension> doGetExtensions() + { + return activityDefinition.getExtensionsByUrl(PROCESS_AUTHORIZATION_EXTENSION_URL).stream() + .map(ActivityDefinitionProcessAuthorizationExtension::new); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProvider.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProvider.java new file mode 100644 index 000000000..6c884888e --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProvider.java @@ -0,0 +1,13 @@ +package org.highmed.dsf.fhir.authorization; + +import java.sql.Connection; +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.UserRole; +import org.hl7.fhir.r4.model.ActivityDefinition; + +public interface ActivityDefinitionProvider +{ + Optional<ActivityDefinition> getActivityDefinition(Connection connection, UserRole userRole, String processUrl, + String processVersion, String messageName); +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProviderImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProviderImpl.java new file mode 100644 index 000000000..200696b1b --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProviderImpl.java @@ -0,0 +1,63 @@ +package org.highmed.dsf.fhir.authorization; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Objects; +import java.util.Optional; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.UserRole; +import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; +import org.hl7.fhir.r4.model.ActivityDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; + +public class ActivityDefinitionProviderImpl implements ActivityDefinitionProvider, InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(ActivityDefinitionProviderImpl.class); + + private final ActivityDefinitionDao dao; + private final OrganizationType organizationType; + + public ActivityDefinitionProviderImpl(ActivityDefinitionDao dao, OrganizationType organizationType) + { + this.dao = dao; + this.organizationType = organizationType; + } + + @Override + public void afterPropertiesSet() throws Exception + { + Objects.requireNonNull(dao, "dao"); + Objects.requireNonNull(organizationType, "organizationType"); + } + + @Override + public Optional<ActivityDefinition> getActivityDefinition(Connection connection, UserRole userRole, + String processUrl, String processVersion, String messageName) + { + try + { + Optional<ActivityDefinition> optAD = dao + .readByOrganizationTypeUserRoleProcessUrlVersionMessageNameAndNotRetiredWithTransaction(connection, + organizationType, userRole, processUrl, processVersion, messageName); + + if (optAD.isPresent()) + logger.debug( + "ActivityDefinition with organization-type {}, user-role {}, process-url {}, process-version {} and message-name {} found", + organizationType, userRole, processUrl, processVersion, messageName); + else + logger.warn( + "ActivityDefinition with organization-type {}, user-role {}, process-url {}, process-version {} and message-name {} not found", + organizationType, userRole, processUrl, processVersion, messageName); + + return optAD; + } + catch (SQLException e) + { + logger.warn("Error while reading ActivityDefinition", e); + return Optional.empty(); + } + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRole.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRole.java new file mode 100644 index 000000000..26c9fb64f --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AuthorizationRole.java @@ -0,0 +1,34 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; + +import org.highmed.dsf.fhir.authentication.UserRole; + +public enum AuthorizationRole +{ + /** + * For users with {@link UserRole#LOCAL} only + */ + LOCAL, + /** + * For users with {@link UserRole#LOCAL} or {@link UserRole#REMOTE} + */ + REMOTE; + + public static Optional<AuthorizationRole> fromString(String role) + { + switch (role) + { + case "LOCAL": + case "local": + return Optional.of(LOCAL); + + case "REMOTE": + case "remote": + return Optional.of(REMOTE); + + default: + return Optional.empty(); + } + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java index 340afd9dd..c8f30cab2 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java @@ -4,6 +4,7 @@ import java.util.EnumSet; import java.util.Optional; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.BinaryDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; @@ -20,9 +21,10 @@ public class BinaryAuthorizationRule extends AbstractAuthorizationRule<Binary, B { private static final Logger logger = LoggerFactory.getLogger(BinaryAuthorizationRule.class); - public BinaryAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) + public BinaryAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, + OrganizationProvider organizationProvider) { - super(Binary.class, daoProvider, serverBase, referenceResolver); + super(Binary.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java index 8526602e6..b6e9e599e 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BundleAuthorizationRule.java @@ -1,54 +1,136 @@ package org.highmed.dsf.fhir.authorization; import java.sql.Connection; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.BundleDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Bundle; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class BundleAuthorizationRule extends AbstractAuthorizationRule<Bundle, BundleDao> { - public BundleAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) + private static final Logger logger = LoggerFactory.getLogger(BundleAuthorizationRule.class); + + public BundleAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, + OrganizationProvider organizationProvider) { - super(Bundle.class, daoProvider, serverBase, referenceResolver); + super(Bundle.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override public Optional<String> reasonCreateAllowed(Connection connection, User user, Bundle newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + Optional<String> errors = newResourceOk(newResource); + if (errors.isEmpty()) + { + logger.info("Create of Bundle authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Create of Bundle unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else + { + logger.warn("Create of Bundle unauthorized, not a local user"); + return Optional.empty(); + } + } + + private Optional<String> newResourceOk(Bundle newResource) + { + List<String> errors = new ArrayList<String>(); + + if (!hasLocalOrRemoteAuthorizationRole(newResource)) + { + errors.add("missing authorization tag"); + } + + if (errors.isEmpty()) + return Optional.empty(); + else + return Optional.of(errors.stream().collect(Collectors.joining(", "))); } @Override public Optional<String> reasonReadAllowed(Connection connection, User user, Bundle existingResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user) && hasLocalAuthorizationRole(existingResource)) + { + logger.info("Read of Bundle authorized for local user '{}', Bundle has local or remote authorization role", + user.getName()); + return Optional.of("local user, local or remote authorized Bundle"); + } + else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) + { + logger.info("Read of Bundle authorized for remote user '{}', Bundle has remote authorization role", + user.getName()); + return Optional.of("remote user, remote authorized Bundle"); + } + else + { + logger.warn("Read of Bundle unauthorized, no matching user role resource authorization role found"); + return Optional.empty(); + } } @Override public Optional<String> reasonUpdateAllowed(Connection connection, User user, Bundle oldResource, Bundle newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + Optional<String> errors = newResourceOk(newResource); + if (errors.isEmpty()) + { + logger.info("Update of Bundle authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Update of Bundle unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else + { + logger.warn("Update of Bundle unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonDeleteAllowed(Connection connection, User user, Bundle oldResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Delete of Bundle authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Delete of Bundle unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonSearchAllowed(Connection connection, User user) { - // TODO Auto-generated method stub - return Optional.empty(); + logger.info("Search of Bundle authorized for {} user '{}', will be fitered by user role", user.getRole(), + user.getName()); + return Optional.of("Allowed for all, filtered by user role"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java index 73a3c566d..a6c6f9cf5 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/CodeSystemAuthorizationRule.java @@ -4,6 +4,7 @@ import java.sql.SQLException; import java.util.Optional; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.CodeSystemDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; @@ -16,9 +17,10 @@ public class CodeSystemAuthorizationRule extends AbstractAuthorizationRule<CodeS { private static final Logger logger = LoggerFactory.getLogger(CodeSystemAuthorizationRule.class); - public CodeSystemAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) + public CodeSystemAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, + OrganizationProvider organizationProvider) { - super(CodeSystem.class, daoProvider, serverBase, referenceResolver); + super(CodeSystem.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java index 174d54671..c7c1fd504 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java @@ -10,6 +10,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.EndpointDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; @@ -25,12 +26,13 @@ public class EndpointAuthorizationRule extends AbstractAuthorizationRule<Endpoin private static final Logger logger = LoggerFactory.getLogger(EndpointAuthorizationRule.class); private static final String IDENTIFIER_SYSTEM = "http://highmed.org/fhir/NamingSystem/endpoint-identifier"; - private static final String ENDPOINT_ADDRESS_PATTERN_STRING = "https:\\/\\/([0-9a-zA-Z\\.]+)+(:\\d{1,4})?([-\\w\\/]*)"; + private static final String ENDPOINT_ADDRESS_PATTERN_STRING = "https://([0-9a-zA-Z\\.]+)+(:\\d{1,4})?([-\\w/]*)"; private static final Pattern ENDPOINT_ADDRESS_PATTERN = Pattern.compile(ENDPOINT_ADDRESS_PATTERN_STRING); - public EndpointAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) + public EndpointAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, + OrganizationProvider organizationProvider) { - super(Endpoint.class, daoProvider, serverBase, referenceResolver); + super(Endpoint.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override @@ -202,7 +204,7 @@ else if (!resourceExists(connection, newResource)) else { logger.warn( - "Create of Endpoint unauthorized, other Endpoint with address and identifier already exists"); + "Update of Endpoint unauthorized, other Endpoint with address and identifier already exists"); return Optional.empty(); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java index 9dc542ae7..b7b546d3b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java @@ -3,6 +3,7 @@ import java.sql.Connection; import java.util.Optional; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.GroupDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; @@ -11,9 +12,10 @@ public class GroupAuthorizationRule extends AbstractAuthorizationRule<Group, GroupDao> { - public GroupAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) + public GroupAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, + OrganizationProvider organizationProvider) { - super(Group.class, daoProvider, serverBase, referenceResolver); + super(Group.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java index 18201796f..04c550c59 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java @@ -3,6 +3,7 @@ import java.sql.Connection; import java.util.Optional; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.HealthcareServiceDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; @@ -13,9 +14,9 @@ public class HealthcareServiceAuthorizationRule extends AbstractAuthorizationRule<HealthcareService, HealthcareServiceDao> { public HealthcareServiceAuthorizationRule(DaoProvider daoProvider, String serverBase, - ReferenceResolver referenceResolver) + ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { - super(HealthcareService.class, daoProvider, serverBase, referenceResolver); + super(HealthcareService.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java index 28954f18b..4c1c96b69 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java @@ -3,6 +3,7 @@ import java.sql.Connection; import java.util.Optional; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.LocationDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; @@ -11,9 +12,10 @@ public class LocationAuthorizationRule extends AbstractAuthorizationRule<Location, LocationDao> { - public LocationAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) + public LocationAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, + OrganizationProvider organizationProvider) { - super(Location.class, daoProvider, serverBase, referenceResolver); + super(Location.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java index ca436358a..1c59a5ffb 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/NamingSystemAuthorizationRule.java @@ -4,6 +4,7 @@ import java.sql.SQLException; import java.util.Optional; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.NamingSystemDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; @@ -17,9 +18,9 @@ public class NamingSystemAuthorizationRule extends AbstractAuthorizationRule<Nam private static final Logger logger = LoggerFactory.getLogger(NamingSystemAuthorizationRule.class); public NamingSystemAuthorizationRule(DaoProvider daoProvider, String serverBase, - ReferenceResolver referenceResolver) + ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { - super(NamingSystem.class, daoProvider, serverBase, referenceResolver); + super(NamingSystem.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java index 9943ab21b..1b4f497dc 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java @@ -10,6 +10,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.OrganizationDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; @@ -32,9 +33,9 @@ public class OrganizationAuthorizationRule extends AbstractAuthorizationRule<Org .compile(EXTENSION_THUMBPRINT_VALUE_PATTERN_STRING); public OrganizationAuthorizationRule(DaoProvider daoProvider, String serverBase, - ReferenceResolver referenceResolver) + ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { - super(Organization.class, daoProvider, serverBase, referenceResolver); + super(Organization.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override @@ -215,7 +216,7 @@ else if (!resourceExists(connection, newResource)) else { logger.warn( - "Create of Organization unauthorized, other Organization with certificate-thumbprint and identifier already exists"); + "Update of Organization unauthorized, other Organization with certificate-thumbprint and identifier already exists"); return Optional.empty(); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java index 17437ee90..777e22864 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java @@ -3,6 +3,7 @@ import java.sql.Connection; import java.util.Optional; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.PatientDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; @@ -11,9 +12,10 @@ public class PatientAuthorizationRule extends AbstractAuthorizationRule<Patient, PatientDao> { - public PatientAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) + public PatientAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, + OrganizationProvider organizationProvider) { - super(Patient.class, daoProvider, serverBase, referenceResolver); + super(Patient.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java index 7f3977c94..1c1b30fa4 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java @@ -3,6 +3,7 @@ import java.sql.Connection; import java.util.Optional; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.PractitionerDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; @@ -12,9 +13,9 @@ public class PractitionerAuthorizationRule extends AbstractAuthorizationRule<Practitioner, PractitionerDao> { public PractitionerAuthorizationRule(DaoProvider daoProvider, String serverBase, - ReferenceResolver referenceResolver) + ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { - super(Practitioner.class, daoProvider, serverBase, referenceResolver); + super(Practitioner.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java index bc11ec231..36aea6baf 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java @@ -3,6 +3,7 @@ import java.sql.Connection; import java.util.Optional; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.PractitionerRoleDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; @@ -12,9 +13,9 @@ public class PractitionerRoleAuthorizationRule extends AbstractAuthorizationRule<PractitionerRole, PractitionerRoleDao> { public PractitionerRoleAuthorizationRule(DaoProvider daoProvider, String serverBase, - ReferenceResolver referenceResolver) + ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { - super(PractitionerRole.class, daoProvider, serverBase, referenceResolver); + super(PractitionerRole.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java index b594f4718..89f76fbe9 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java @@ -3,6 +3,7 @@ import java.sql.Connection; import java.util.Optional; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ProvenanceDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; @@ -11,9 +12,10 @@ public class ProvenanceAuthorizationRule extends AbstractAuthorizationRule<Provenance, ProvenanceDao> { - public ProvenanceAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) + public ProvenanceAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, + OrganizationProvider organizationProvider) { - super(Provenance.class, daoProvider, serverBase, referenceResolver); + super(Provenance.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java index d92d3da3e..a4d0f1f1d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java @@ -3,6 +3,7 @@ import java.sql.Connection; import java.util.Optional; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ResearchStudyDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; @@ -12,9 +13,9 @@ public class ResearchStudyAuthorizationRule extends AbstractAuthorizationRule<ResearchStudy, ResearchStudyDao> { public ResearchStudyAuthorizationRule(DaoProvider daoProvider, String serverBase, - ReferenceResolver referenceResolver) + ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { - super(ResearchStudy.class, daoProvider, serverBase, referenceResolver); + super(ResearchStudy.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java index f40ad456d..717d5da37 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/StructureDefinitionAuthorizationRule.java @@ -8,6 +8,7 @@ import java.util.Optional; import java.util.stream.Collectors; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.StructureDefinitionDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; @@ -23,9 +24,9 @@ public class StructureDefinitionAuthorizationRule private static final Logger logger = LoggerFactory.getLogger(StructureDefinitionAuthorizationRule.class); public StructureDefinitionAuthorizationRule(DaoProvider daoProvider, String serverBase, - ReferenceResolver referenceResolver) + ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { - super(StructureDefinition.class, daoProvider, serverBase, referenceResolver); + super(StructureDefinition.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override @@ -159,7 +160,7 @@ public Optional<String> reasonUpdateAllowed(Connection connection, User user, St else { logger.warn( - "Create of StructureDefinition unauthorized, other StructureDefinition with criteria, type and payload already exists"); + "Update of StructureDefinition unauthorized, other StructureDefinition with criteria, type and payload already exists"); return Optional.empty(); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java index e219d6c5f..474d1213f 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java @@ -9,6 +9,7 @@ import java.util.Optional; import java.util.stream.Collectors; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ResourceDao; import org.highmed.dsf.fhir.dao.SubscriptionDao; @@ -31,9 +32,9 @@ public class SubscriptionAuthorizationRule extends AbstractAuthorizationRule<Sub private static final Logger logger = LoggerFactory.getLogger(SubscriptionAuthorizationRule.class); public SubscriptionAuthorizationRule(DaoProvider daoProvider, String serverBase, - ReferenceResolver referenceResolver) + ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { - super(Subscription.class, daoProvider, serverBase, referenceResolver); + super(Subscription.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java index b2214e346..c67c48ec8 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java @@ -1,13 +1,26 @@ package org.highmed.dsf.fhir.authorization; import java.sql.Connection; +import java.util.ArrayList; +import java.util.EnumSet; +import java.util.List; import java.util.Optional; +import java.util.regex.MatchResult; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.TaskDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.service.ReferenceResolver; +import org.highmed.dsf.fhir.service.ResourceReference; +import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.Resource; +import org.hl7.fhir.r4.model.StringType; import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.Task.TaskStatus; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -15,26 +28,202 @@ public class TaskAuthorizationRule extends AbstractAuthorizationRule<Task, TaskD { private static final Logger logger = LoggerFactory.getLogger(TaskAuthorizationRule.class); - public TaskAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) + private static final String CODE_SYSTEM_BPMN_MESSAGE = "http://highmed.org/fhir/CodeSystem/bpmn-message"; + private static final String CODE_SYSTEM_BPMN_MESSAGE_MESSAGE_NAME = "message-name"; + + private static final String INSTANTIATES_URI_PATTERN_STRING = "(http://highmed.org/bpe/Process/[-\\w]+)/(\\d+\\.\\d+\\.\\d+)"; + private static final Pattern INSTANTIATES_URI_PATTERN = Pattern.compile(INSTANTIATES_URI_PATTERN_STRING); + + private final ActivityDefinitionProvider activityDefinitionProvider; + + public TaskAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, + OrganizationProvider organizationProvider, ActivityDefinitionProvider activityDefinitionProvider) { - super(Task.class, daoProvider, serverBase, referenceResolver); + super(Task.class, daoProvider, serverBase, referenceResolver, organizationProvider); + + this.activityDefinitionProvider = activityDefinitionProvider; } @Override public Optional<String> reasonCreateAllowed(Connection connection, User user, Task newResource) { - // allowed status draft | requested for all users - // task.requester must be organization of current user + if (isLocalUser(user) || isRemoteUser(user)) + { + Optional<String> errors = newResourceOk(connection, user, newResource); + if (errors.isEmpty()) + { + if (taskAllowedForUser(connection, user, newResource.getInstantiatesUri(), + getBpmnMessageName(newResource).findFirst().orElseThrow())) + { + logger.info("Create of Task authorized for local or remote user '{}'", user.getName()); + return Optional.of( + "local or remote user, task.status draft or requested, task.requester current users organization, task.restriction.recipient local organization, process with instantiatesUri and message-name allowed for current user"); + } + else + { + logger.warn( + "Create of Task unauthorized, process with instantiatesUri and message-name not allowed for current user", + user.getName()); + return Optional.empty(); + } + } + else + { + logger.warn("Create of Task unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else + { + logger.warn("Create of Task unauthorized, not a local or remote user"); + return Optional.empty(); + } + } + + private Optional<String> newResourceOk(Connection connection, User user, Task newResource) + { + List<String> errors = new ArrayList<String>(); + + if (newResource.hasStatus()) + { + if (!EnumSet.of(TaskStatus.DRAFT, TaskStatus.REQUESTED).contains(newResource.getStatus())) + errors.add("task.status not draft or requested"); + } + else + { + errors.add("task.status missing"); + } + + if (newResource.hasRequester()) + { + if (!isCurrentUserPartOfReferencedOrganization(connection, user, "task.requester", + newResource.getRequester())) + { + errors.add("task.requester user not part of referenced organization"); + } + } + else + { + errors.add("task.requester missing"); + } + + if (newResource.hasRestriction()) + { + if (newResource.getRestriction().hasRecipient() && newResource.getRestriction().getRecipient().size() == 1) + { + ResourceReference reference = new ResourceReference("task.restriction.recipient", + newResource.getRestriction().getRecipientFirstRep(), Organization.class); + Optional<Resource> recipient = referenceResolver.resolveReference(user, reference, connection); + if (recipient.isPresent()) + { + if (recipient.get() instanceof Organization) + { + if (!isLocalOrganization((Organization) recipient.get())) + errors.add("task.restriction.recipient not local organization"); + } + else + { + errors.add("task.restriction.recipient not a organization"); + } + } + else + { + errors.add("task.restriction.recipient could not be resolved"); + } + } + else + { + errors.add("task.restriction.recipient missing or more than one"); + } + } + else + { + errors.add("task.restriction missing"); + } + + if (newResource.hasInstantiatesUri()) + { + if (!INSTANTIATES_URI_PATTERN.matcher(newResource.getInstantiatesUri()).matches()) + { + errors.add("task.instantiatesUri not matching " + INSTANTIATES_URI_PATTERN_STRING + " pattern"); + } + } + else + { + errors.add("task.instantiatesUri missing"); + } - // TODO Auto-generated method stub - return Optional.empty(); + if (newResource.hasInput()) + { + if (getBpmnMessageName(newResource).count() != 1) + { + errors.add("task.input with system " + CODE_SYSTEM_BPMN_MESSAGE + " and code " + + CODE_SYSTEM_BPMN_MESSAGE_MESSAGE_NAME + " with string value not empty missing"); + } + } + else + { + errors.add("task.input empty"); + } + + if (newResource.hasOutput()) + { + errors.add("task.output not empty"); + } + + if (errors.isEmpty()) + return Optional.empty(); + else + return Optional.of(errors.stream().collect(Collectors.joining(", "))); + } + + private Stream<String> getBpmnMessageName(Task newResource) + { + return newResource.getInput().stream() + .filter(i -> i.getType().getCoding().stream() + .anyMatch(c -> CODE_SYSTEM_BPMN_MESSAGE.equals(c.getSystem()) + && CODE_SYSTEM_BPMN_MESSAGE_MESSAGE_NAME.equals(c.getCode())) + && i.getValue() instanceof StringType && !((StringType) i.getValue()).getValue().isBlank()) + .map(i -> ((StringType) i.getValue()).getValue()); + } + + private boolean taskAllowedForUser(Connection connection, User user, String instantiatesUri, String messageName) + { + MatchResult matchResult = INSTANTIATES_URI_PATTERN.matcher(instantiatesUri).toMatchResult(); + String processUrl = matchResult.group(1); + String processVersion = matchResult.group(2); + + return activityDefinitionProvider + .getActivityDefinition(connection, user.getRole(), processUrl, processVersion, messageName) + .map(ad -> true).orElse(false); } @Override public Optional<String> reasonReadAllowed(Connection connection, User user, Task existingResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isCurrentUserPartOfReferencedOrganization(connection, user, "task.requester", + existingResource.getRequester())) + { + logger.info( + "Read of Task authorized, task.requester reference could be resolved and user '{}' is part of referenced organization", + user.getName()); + return Optional.of("task.requester resolved and user part of referenced organization"); + } + else if (isLocalUser(user) && isCurrentUserPartOfReferencedOrganization(connection, user, + "task.restriction.recipient", existingResource.getRestriction().getRecipientFirstRep())) + { + logger.info( + "Read of Task authorized, task.restriction.recipient reference could be resolved and user '{}' is part of referenced organization", + user.getName()); + return Optional.of("task.restriction.recipient resolved and local user part of referenced organization"); + } + else + { + logger.warn( + "Read of Task unauthorized, task.requester or task.restriction.recipient references could not be resolved or user '{}' not part of referenced organizations", + user.getName()); + return Optional.empty(); + } } @Override @@ -45,17 +234,73 @@ public Optional<String> reasonUpdateAllowed(Connection connection, User user, Ta // task.requester must be organization of current user or local user // only update of tasks with requester = current user allowed for remote users - // TODO Auto-generated method stub - return Optional.empty(); + if (isRemoteUser(user) || isLocalUser(user)) + { + if (TaskStatus.DRAFT.equals(oldResource.getStatus()) && isCurrentUserPartOfReferencedOrganization( + connection, user, "task.requester", oldResource.getRequester())) + { + Optional<String> errors = newResourceOk(connection, user, newResource); + if (errors.isEmpty()) + { + logger.info("Update of Task authorized for local or remote user '{}'", user.getName()); + return Optional.of( + "local or remote user, task.status draft or requested, task.requester current users organization, task.restriction.recipient local organization"); + } + else + { + logger.warn("Create of Task unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else if (isLocalUser(user) + && EnumSet.of(TaskStatus.REQUESTED, TaskStatus.INPROGRESS).contains(oldResource.getStatus()) + && isCurrentUserPartOfReferencedOrganization(connection, user, "task.restriction.recipient", + oldResource.getRestriction().getRecipientFirstRep())) + { + // TODO + return Optional.empty(); + } + else + { + logger.warn( + "Update of Task unauthorized, expected taks.status draft and current user part of task.requester or task.status requester or inprogress and current local user part of task.restriction.recipient"); + return Optional.empty(); + } + } + else + { + logger.warn("Update of Task unauthorized, not a local or remote user"); + return Optional.empty(); + } } @Override public Optional<String> reasonDeleteAllowed(Connection connection, User user, Task oldResource) { - // allowed if oldResouce created by current user and status draft - - // TODO Auto-generated method stub - return Optional.empty(); + if (TaskStatus.DRAFT.equals(oldResource.getStatus()) && isCurrentUserPartOfReferencedOrganization(connection, + user, "task.requester", oldResource.getRequester())) + { + logger.info( + "Delete of Task authorized for user '{}', task.status draft, task.requester resolved and user part of referenced organization", + user.getName()); + return Optional.of("task.status draft, task.requester resolved and user part of referenced organization"); + } + else if (isLocalUser(user) && TaskStatus.DRAFT.equals(oldResource.getStatus()) + && isCurrentUserPartOfReferencedOrganization(connection, user, "task.restriction.recipient", + oldResource.getRestriction().getRecipientFirstRep())) + { + logger.info( + "Delete of Task authorized for local user '{}', task.status draft, task.restriction.recipient resolved and user part of referenced organization", + user.getName()); + return Optional.of( + "local user, task.status draft, task.restriction.recipient resolved and user part of referenced organization"); + } + else + { + logger.warn( + "Delete of Task unauthorized, task.status not draft, task.requester not current user or task.restriction.recipient not local user"); + return Optional.empty(); + } } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ValueSetAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ValueSetAuthorizationRule.java index 1396ffb7b..98ef2713a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ValueSetAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ValueSetAuthorizationRule.java @@ -4,6 +4,7 @@ import java.sql.SQLException; import java.util.Optional; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ValueSetDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; @@ -16,9 +17,10 @@ public class ValueSetAuthorizationRule extends AbstractAuthorizationRule<ValueSe { private static final Logger logger = LoggerFactory.getLogger(ValueSetAuthorizationRule.class); - public ValueSetAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver) + public ValueSetAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, + OrganizationProvider organizationProvider) { - super(ValueSet.class, daoProvider, serverBase, referenceResolver); + super(ValueSet.class, daoProvider, serverBase, referenceResolver, organizationProvider); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDao.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDao.java index 9fbe1e414..04e44554a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDao.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDao.java @@ -1,7 +1,16 @@ package org.highmed.dsf.fhir.dao; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Optional; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.UserRole; import org.hl7.fhir.r4.model.ActivityDefinition; -public interface ActivityDefinitionDao extends ResourceDao<ActivityDefinition> +public interface ActivityDefinitionDao extends ResourceDao<ActivityDefinition>, ReadByUrlDao<ActivityDefinition> { + Optional<ActivityDefinition> readByOrganizationTypeUserRoleProcessUrlVersionMessageNameAndNotRetiredWithTransaction( + Connection connection, OrganizationType organizationType, UserRole userRole, String processUrl, + String processVersion, String messageName) throws SQLException; } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java index b9c20dc03..4d9752055 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java @@ -1,6 +1,15 @@ package org.highmed.dsf.fhir.dao.jdbc; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Objects; +import java.util.Optional; + import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.UserRole; import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionIdentifier; import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionName; @@ -9,12 +18,18 @@ import org.highmed.dsf.fhir.search.parameters.ActivityDefinitionVersion; import org.highmed.dsf.fhir.search.parameters.user.ActivityDefinitionUserFilter; import org.hl7.fhir.r4.model.ActivityDefinition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import ca.uhn.fhir.context.FhirContext; public class ActivityDefinitionDaoJdbc extends AbstractResourceDaoJdbc<ActivityDefinition> implements ActivityDefinitionDao { + private static final Logger logger = LoggerFactory.getLogger(ActivityDefinitionDaoJdbc.class); + + private final ReadByUrlDaoJdbc<ActivityDefinition> readByUrl; + public ActivityDefinitionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, ActivityDefinition.class, "activity_definitions", "activity_definition", @@ -22,6 +37,9 @@ public ActivityDefinitionDaoJdbc(BasicDataSource dataSource, FhirContext fhirCon with(ActivityDefinitionIdentifier::new, ActivityDefinitionName::new, ActivityDefinitionStatus::new, ActivityDefinitionUrl::new, ActivityDefinitionVersion::new), with()); + + readByUrl = new ReadByUrlDaoJdbc<ActivityDefinition>(this::getDataSource, this::getResource, getResourceTable(), + getResourceColumn(), getResourceIdColumn()); } @Override @@ -29,4 +47,70 @@ protected ActivityDefinition copy(ActivityDefinition resource) { return resource.copy(); } + + @Override + public Optional<ActivityDefinition> readByUrlAndVersion(String urlAndVersion) throws SQLException + { + return readByUrl.readByUrlAndVersion(urlAndVersion); + } + + @Override + public Optional<ActivityDefinition> readByUrlAndVersion(String url, String version) throws SQLException + { + return readByUrl.readByUrlAndVersion(url, version); + } + + @Override + public Optional<ActivityDefinition> readByUrlAndVersionWithTransaction(Connection connection, String url, + String version) throws SQLException + { + return readByUrl.readByUrlAndVersionWithTransaction(connection, url, version); + } + + @Override + public Optional<ActivityDefinition> readByOrganizationTypeUserRoleProcessUrlVersionMessageNameAndNotRetiredWithTransaction( + Connection connection, OrganizationType organizationType, UserRole userRole, String processUrl, + String processVersion, String messageName) throws SQLException + { + Objects.requireNonNull(connection, "connection"); + Objects.requireNonNull(organizationType, "organizationType"); + Objects.requireNonNull(userRole, "userRole"); + Objects.requireNonNull(processUrl, "processUrl"); + if (processUrl.isBlank()) + throw new IllegalArgumentException("processUrl blank"); + Objects.requireNonNull(processVersion, "processVersion"); + if (processVersion.isBlank()) + throw new IllegalArgumentException("processVersion blank"); + Objects.requireNonNull(messageName, "messageName"); + if (messageName.isBlank()) + throw new IllegalArgumentException("messageName blank"); + + try (PreparedStatement statement = connection + .prepareStatement("SELECT activity_definition FROM current_activity_definitions WHERE " + + "activity_definition->>'url' = ? AND " + "activity_definition->>'version' = ? AND " + + "activity_definition->'extension' @> ?::jsonb AND " + + "lower(activity_definition->>'status') <> 'retired'")) + { + String extension = "'[{\"url\":\"http://highmed.org/fhir/StructureDefinition/process-authorization\",\"extension\":[" + + "{\"url\":\"message-name\",\"valueString\":\"" + messageName + "\"}," + + "{\"url\":\"authorization-role\",\"valueCoding\":{\"code\":\"" + userRole.toString() + + "\",\"system\":\"http://highmed.org/fhir/CodeSystem/authorization-role\"}}," + + "{\"url\":\"organization-types\",\"extension\":[{\"url\":\"organization-type\",\"valueCoding\":{\"code\":\"" + + organizationType.toString() + + "\",\"system\":\"http://highmed.org/fhir/CodeSystem/authorization-role\"}}]}]}]'"; + + statement.setString(1, processUrl); + statement.setString(2, processVersion); + statement.setString(3, extension); + + logger.trace("Executing query '{}'", statement); + try (ResultSet result = statement.executeQuery()) + { + if (result.next()) + return Optional.of(getResource(result, 1)); + else + return Optional.empty(); + } + } + } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ActivityDefinitionUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ActivityDefinitionUserFilter.java index 56aeb7c7e..56edb6a47 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ActivityDefinitionUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ActivityDefinitionUserFilter.java @@ -1,42 +1,11 @@ package org.highmed.dsf.fhir.search.parameters.user; -import java.sql.PreparedStatement; -import java.sql.SQLException; - import org.highmed.dsf.fhir.authentication.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -public class ActivityDefinitionUserFilter extends AbstractUserFilter +public class ActivityDefinitionUserFilter extends AbstractMetaTagAuthorizationRoleUserFilter { - private static final Logger logger = LoggerFactory.getLogger(ActivityDefinitionUserFilter.class); - public ActivityDefinitionUserFilter(User user) { - super(user); - } - - @Override - public String getFilterQuery() - { - // TODO implement - - logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); - return "false"; - } - - @Override - public int getSqlParameterCount() - { - logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); - return 0; - } - - @Override - public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException - { - // TODO implement - - logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + super(user, "activity_definition"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthenticationConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthenticationConfig.java index 910da3081..f5cd6fcbf 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthenticationConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthenticationConfig.java @@ -5,10 +5,7 @@ import org.highmed.dsf.fhir.authentication.AuthenticationFilterConfig; import org.highmed.dsf.fhir.authentication.AuthenticationFilterConfigImpl; import org.highmed.dsf.fhir.authentication.NeedsAuthentication; -import org.highmed.dsf.fhir.authentication.OrganizationProvider; -import org.highmed.dsf.fhir.authentication.OrganizationProviderWithDbBackend; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -18,28 +15,9 @@ public class AuthenticationConfig @Autowired private List<NeedsAuthentication> needsAuthentication; - @Autowired - private DaoConfig daoConfig; - - @Autowired - private HelperConfig helperConfig; - - @Value("#{'${org.highmed.dsf.fhir.local-user.thumbprints}'.split(',')}") - private List<String> localUserThumbprints; - - @Value("${org.highmed.dsf.fhir.local-organization.identifier}") - private String localIdentifierValue; - @Bean public AuthenticationFilterConfig authenticationFilterConfig() { return AuthenticationFilterConfigImpl.createConfigForPathsRequiringAuthentication("", needsAuthentication); } - - @Bean - public OrganizationProvider organizationProvider() - { - return new OrganizationProviderWithDbBackend(daoConfig.organizationDao(), helperConfig.exceptionHandler(), - localUserThumbprints, localIdentifierValue); - } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthorizationConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthorizationConfig.java index 1a5f7ed03..ef055b097 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthorizationConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/AuthorizationConfig.java @@ -1,6 +1,13 @@ package org.highmed.dsf.fhir.spring.config; +import java.util.List; + +import org.highmed.dsf.fhir.OrganizationType; +import org.highmed.dsf.fhir.authentication.OrganizationProvider; +import org.highmed.dsf.fhir.authentication.OrganizationProviderWithDbBackend; import org.highmed.dsf.fhir.authorization.ActivityDefinitionAuthorizationRule; +import org.highmed.dsf.fhir.authorization.ActivityDefinitionProvider; +import org.highmed.dsf.fhir.authorization.ActivityDefinitionProviderImpl; import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.authorization.AuthorizationRuleProviderImpl; import org.highmed.dsf.fhir.authorization.BinaryAuthorizationRule; @@ -32,135 +39,174 @@ public class AuthorizationConfig @Value("${org.highmed.dsf.fhir.serverBase}") private String serverBase; + @Value("${org.highmed.dsf.fhir.organizationType}") + private String organizationType; + + @Value("#{'${org.highmed.dsf.fhir.local-user.thumbprints}'.split(',')}") + private List<String> localUserThumbprints; + + @Value("${org.highmed.dsf.fhir.local-organization.identifier}") + private String localIdentifierValue; + @Autowired private DaoConfig daoConfig; @Autowired private ReferenceConfig referenceConfig; + @Autowired + private HelperConfig helperConfig; + + @Bean + public OrganizationProvider organizationProvider() + { + return new OrganizationProviderWithDbBackend(daoConfig.organizationDao(), helperConfig.exceptionHandler(), + localUserThumbprints, localIdentifierValue); + } + + @Bean + public OrganizationType organizationType() + { + return OrganizationType.valueOf(organizationType); + } + + @Bean + public ActivityDefinitionProvider activityDefinitionProvider() + { + return new ActivityDefinitionProviderImpl(daoConfig.activityDefinitionDao(), organizationType()); + } + @Bean public ActivityDefinitionAuthorizationRule activityDefinitionAuthorizationRule() { return new ActivityDefinitionAuthorizationRule(daoConfig.daoProvider(), serverBase, - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), organizationProvider()); } @Bean public BinaryAuthorizationRule binaryAuthorizationRule() { - return new BinaryAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); + return new BinaryAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver(), + organizationProvider()); } @Bean public BundleAuthorizationRule bundleAuthorizationRule() { - return new BundleAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); + return new BundleAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver(), + organizationProvider()); } @Bean public CodeSystemAuthorizationRule codeSystemAuthorizationRule() { - return new CodeSystemAuthorizationRule(daoConfig.daoProvider(), serverBase, - referenceConfig.referenceResolver()); + return new CodeSystemAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver(), + organizationProvider()); } @Bean public EndpointAuthorizationRule endpointAuthorizationRule() { - return new EndpointAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); + return new EndpointAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver(), + organizationProvider()); } @Bean public GroupAuthorizationRule groupAuthorizationRule() { - return new GroupAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); + return new GroupAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver(), + organizationProvider()); } @Bean public HealthcareServiceAuthorizationRule healthcareServiceAuthorizationRule() { return new HealthcareServiceAuthorizationRule(daoConfig.daoProvider(), serverBase, - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), organizationProvider()); } @Bean public LocationAuthorizationRule locationAuthorizationRule() { - return new LocationAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); + return new LocationAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver(), + organizationProvider()); } @Bean public NamingSystemAuthorizationRule namingSystemAuthorizationRule() { return new NamingSystemAuthorizationRule(daoConfig.daoProvider(), serverBase, - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), organizationProvider()); } @Bean public OrganizationAuthorizationRule organizationAuthorizationRule() { return new OrganizationAuthorizationRule(daoConfig.daoProvider(), serverBase, - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), organizationProvider()); } @Bean public PatientAuthorizationRule patientAuthorizationRule() { - return new PatientAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); + return new PatientAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver(), + organizationProvider()); } @Bean public PractitionerAuthorizationRule practitionerAuthorizationRule() { return new PractitionerAuthorizationRule(daoConfig.daoProvider(), serverBase, - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), organizationProvider()); } @Bean public PractitionerRoleAuthorizationRule practitionerRoleAuthorizationRule() { return new PractitionerRoleAuthorizationRule(daoConfig.daoProvider(), serverBase, - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), organizationProvider()); } @Bean public ProvenanceAuthorizationRule provenanceAuthorizationRule() { - return new ProvenanceAuthorizationRule(daoConfig.daoProvider(), serverBase, - referenceConfig.referenceResolver()); + return new ProvenanceAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver(), + organizationProvider()); } @Bean public ResearchStudyAuthorizationRule researchStudyAuthorizationRule() { return new ResearchStudyAuthorizationRule(daoConfig.daoProvider(), serverBase, - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), organizationProvider()); } @Bean public StructureDefinitionAuthorizationRule structureDefinitionAuthorizationRule() { return new StructureDefinitionAuthorizationRule(daoConfig.daoProvider(), serverBase, - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), organizationProvider()); } @Bean public SubscriptionAuthorizationRule subscriptionAuthorizationRule() { return new SubscriptionAuthorizationRule(daoConfig.daoProvider(), serverBase, - referenceConfig.referenceResolver()); + referenceConfig.referenceResolver(), organizationProvider()); } @Bean public TaskAuthorizationRule taskAuthorizationRule() { - return new TaskAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); + return new TaskAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver(), + organizationProvider(), activityDefinitionProvider()); } @Bean public ValueSetAuthorizationRule valueSetAuthorizationRule() { - return new ValueSetAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver()); + return new ValueSetAuthorizationRule(daoConfig.daoProvider(), serverBase, referenceConfig.referenceResolver(), + organizationProvider()); } @Bean diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java index 6c825e687..79eee1478 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/DaoConfig.java @@ -1,7 +1,6 @@ package org.highmed.dsf.fhir.spring.config; import org.apache.commons.dbcp2.BasicDataSource; -import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; import org.highmed.dsf.fhir.dao.BinaryDao; import org.highmed.dsf.fhir.dao.BundleDao; @@ -63,9 +62,6 @@ public class DaoConfig @Value("${org.highmed.dsf.fhir.db.server_user_password}") private String dbPassword; - @Value("${org.highmed.dsf.fhir.organizationType}") - private String organizationType; - @Autowired private FhirConfig fhirConfig; @@ -87,12 +83,6 @@ public BasicDataSource dataSource() return dataSource; } - @Bean - public OrganizationType organizationType() - { - return OrganizationType.valueOf(organizationType); - } - @Bean public ActivityDefinitionDao activityDefinitionDao() { diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ActivityDefinition-PingProcess-1.0.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ActivityDefinition-PingProcess-1.0.0.xml new file mode 100644 index 000000000..f546869d2 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ActivityDefinition-PingProcess-1.0.0.xml @@ -0,0 +1,82 @@ +<ActivityDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> + <extension url="http://highmed.org/fhir/StructureDefinition/process-authorization"> + <extension url="message-name"> + <valueString value="startProcessMessage"/> + </extension> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="LOCAL"/> + </valueCoding> + </extension> + <extension url="organization-types"> + <extension url="organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="TTP"/> + </valueCoding> + </extension> + <extension url="organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="MeDIC"/> + </valueCoding> + </extension> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"/> + </extension> + </extension> + <extension url="http://highmed.org/fhir/StructureDefinition/process-authorization"> + <extension url="message-name"> + <valueString value="pongMessage"/> + </extension> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </valueCoding> + </extension> + <extension url="organization-types"> + <extension url="organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="TTP"/> + </valueCoding> + </extension> + <extension url="organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="MeDIC"/> + </valueCoding> + </extension> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/highmed-task-pong"/> + </extension> + </extension> + <url value="http://highmed.org/bpe/Process/ping"/> + <version value="1.0.0"/> + <name value="PingProcess"/> + <title value="PING process"/> + <subtitle value="Communication Testing Process"/> + <status value="draft"/> + <experimental value="true"/> + <date value="2020-03-03T10:14:14+01:00"/> + <publisher value="HiGHmed"/> + <contact> + <name value="HiGHmed"/> + <telecom> + <system value="email"/> + <value value="pmo@highmed.org"/> + </telecom> + </contact> + <description value="Process to send PING messages to remote Organizations and to receive corresponding PONG message"/> + <kind value="Task"/> +</ActivityDefinition> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ActivityDefinition-PingProcess-1.0.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ActivityDefinition-PingProcess-1.0.0.xml.put new file mode 100644 index 000000000..db076a001 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ActivityDefinition-PingProcess-1.0.0.xml.put @@ -0,0 +1 @@ +ActivityDefinition?url=http://highmed.org/bpe/Process/ping&version=1.0.0 \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml index 0b9991d4d..1d77ca992 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml @@ -2,9 +2,9 @@ <StructureDefinition xmlns="http://hl7.org/fhir"> <meta> <tag> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> - <code value="REMOTE"/> - </tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </tag> </meta> <url value="http://highmed.org/fhir/StructureDefinition/process-authorization" /> <version value="0.1.0" /> @@ -62,7 +62,6 @@ </element> <element id="Extension.extension:authorization-role.value[x]"> <path value="Extension.extension.value[x]" /> - <min value="1" /> <type> <code value="Coding" /> </type> @@ -72,27 +71,76 @@ <min value="1" /> <fixedUri value="http://highmed.org/fhir/CodeSystem/authorization-role" /> </element> - <element id="Extension.extension:organization-type"> + <element id="Extension.extension:authorization-role.value[x].code"> + <path value="Extension.extension.value[x].code" /> + <min value="1" /> + </element> + <element id="Extension.extension:organization-types"> <path value="Extension.extension" /> - <sliceName value="organization-type" /> + <sliceName value="organization-types" /> <min value="1" /> <max value="1" /> </element> - <element id="Extension.extension:organization-type.url"> - <path value="Extension.extension.url" /> - <fixedUri value="organization-type" /> + <element id="Extension.extension:organization-types.extension"> + <path value="Extension.extension.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> </element> - <element id="Extension.extension:organization-type.value[x]"> - <path value="Extension.extension.value[x]" /> + <element id="Extension.extension:organization-types.extension:organization-type"> + <path value="Extension.extension.extension" /> + <sliceName value="organization-type" /> <min value="1" /> + <max value="2" /> + </element> + <element id="Extension.extension:organization-types.extension:organization-type.url"> + <path value="Extension.extension.extension.url" /> + <fixedUri value="organization-type" /> + </element> + <element id="Extension.extension:organization-types.extension:organization-type.value[x]"> + <path value="Extension.extension.extension.value[x]" /> <type> <code value="Coding" /> </type> </element> - <element id="Extension.extension:organization-type.value[x].system"> - <path value="Extension.extension.value[x].system" /> + <element id="Extension.extension:organization-types.extension:organization-type.value[x].system"> + <path value="Extension.extension.extension.value[x].system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + </element> + <element id="Extension.extension:organization-types.extension:organization-type.value[x].code"> + <path value="Extension.extension.extension.value[x].code" /> + <min value="1" /> + </element> + <element id="Extension.extension:organization-types.url"> + <path value="Extension.extension.url" /> + <fixedUri value="organization-types" /> + </element> + <element id="Extension.extension:organization-types.value[x]"> + <path value="Extension.extension.value[x]" /> + <max value="0" /> + </element> + <element id="Extension.extension:task-profile"> + <path value="Extension.extension" /> + <sliceName value="task-profile" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Extension.extension:task-profile.url"> + <path value="Extension.extension.url" /> + <fixedUri value="task-profile" /> + </element> + <element id="Extension.extension:task-profile.value[x]"> + <path value="Extension.extension.value[x]" /> + <min value="1" /> + <type> + <code value="canonical" /> + <targetProfile value="http://hl7.org/fhir/StructureDefinition/StructureDefinition" /> + </type> </element> <element id="Extension.url"> <path value="Extension.url" /> diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/ActivityDefinitionWithExtension.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/ActivityDefinitionWithExtension.java new file mode 100644 index 000000000..2a3dd7f78 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/ActivityDefinitionWithExtension.java @@ -0,0 +1,74 @@ +package org.highmed.dsf.fhir.hapi; + +import java.util.Date; + +import org.hl7.fhir.r4.model.ActivityDefinition; +import org.hl7.fhir.r4.model.ActivityDefinition.ActivityDefinitionKind; +import org.hl7.fhir.r4.model.CanonicalType; +import org.hl7.fhir.r4.model.Coding; +import org.hl7.fhir.r4.model.ContactPoint.ContactPointSystem; +import org.hl7.fhir.r4.model.Enumerations.PublicationStatus; +import org.hl7.fhir.r4.model.Extension; +import org.hl7.fhir.r4.model.StringType; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ca.uhn.fhir.context.FhirContext; + +public class ActivityDefinitionWithExtension +{ + private static final Logger logger = LoggerFactory.getLogger(ActivityDefinitionWithExtension.class); + + @Test + public void test() throws Exception + { + ActivityDefinition a = new ActivityDefinition(); + a.getMeta().addTag("http://highmed.org/fhir/CodeSystem/authorization-role", "REMOTE", null); + a.setUrl("http://highmed.org/bpe/Process/ping"); + a.setVersion("1.0.0"); + a.setName("PingProcess"); + a.setTitle("PING process"); + a.setSubtitle("Communication Testing Process"); + a.setStatus(PublicationStatus.DRAFT); + a.setExperimental(true); + a.setDate(new Date()); + a.setPublisher("HiGHmed"); + a.getContactFirstRep().setName("HiGHmed").getTelecomFirstRep().setSystem(ContactPointSystem.EMAIL) + .setValue("pmo@highmed.org"); + a.setDescription( + "Process to send PING messages to remote Organizations and to receive corresponding PONG message"); + a.setKind(ActivityDefinitionKind.TASK); + + Extension e1 = a.addExtension(); + e1.setUrl("http://highmed.org/fhir/StructureDefinition/process-authorization"); + e1.addExtension("message-name", new StringType("startProcessMessage")); + e1.addExtension("authorization-role", + new Coding("http://highmed.org/fhir/CodeSystem/authorization-role", "LOCAL", null)); + Extension ot12 = e1.addExtension(); + ot12.setUrl("organization-types"); + ot12.addExtension("organization-type", + new Coding("http://highmed.org/fhir/CodeSystem/authorization-role", "TTP", null)); + ot12.addExtension("organization-type", + new Coding("http://highmed.org/fhir/CodeSystem/authorization-role", "MeDIC", null)); + e1.addExtension("task-profile", + new CanonicalType("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process")); + + Extension e2 = a.addExtension(); + e2.setUrl("http://highmed.org/fhir/StructureDefinition/process-authorization"); + e2.addExtension("message-name", new StringType("pongMessage")); + e2.addExtension("authorization-role", + new Coding("http://highmed.org/fhir/CodeSystem/authorization-role", "REMOTE", null)); + Extension ot22 = e2.addExtension(); + ot22.setUrl("organization-types"); + ot22.addExtension("organization-type", + new Coding("http://highmed.org/fhir/CodeSystem/authorization-role", "TTP", null)); + ot22.addExtension("organization-type", + new Coding("http://highmed.org/fhir/CodeSystem/authorization-role", "MeDIC", null)); + e2.addExtension("task-profile", + new CanonicalType("http://highmed.org/fhir/StructureDefinition/highmed-task-pong")); + + String xml = FhirContext.forR4().newXmlParser().setPrettyPrint(true).encodeResourceToString(a); + logger.debug(xml); + } +} From 6d73d3381e45839721e06d6402c64bc9a91ca8ec Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 3 Mar 2020 19:56:26 +0100 Subject: [PATCH 17/55] work on authorization rules, create of ping, pong and start-ping working --- .../authorization/TaskAuthorizationRule.java | 19 ++- .../dao/jdbc/ActivityDefinitionDaoJdbc.java | 4 +- ...n-PingProcess-1.0.0.xml => ping-1.0.0.xml} | 64 +++++----- ...ocess-1.0.0.xml.put => ping-1.0.0.xml.put} | 0 .../fhir/ActivityDefinition/pong-1.0.0.xml | 54 ++++++++ .../ActivityDefinition/pong-1.0.0.xml.put | 1 + .../fhir/integration/TaskIntegrationTest.java | 120 ++++++++++++++++++ 7 files changed, 221 insertions(+), 41 deletions(-) rename dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/{ActivityDefinition-PingProcess-1.0.0.xml => ping-1.0.0.xml} (66%) rename dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/{ActivityDefinition-PingProcess-1.0.0.xml.put => ping-1.0.0.xml.put} (100%) create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-1.0.0.xml create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-1.0.0.xml.put diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java index c67c48ec8..2ad171b6a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java @@ -5,7 +5,7 @@ import java.util.EnumSet; import java.util.List; import java.util.Optional; -import java.util.regex.MatchResult; +import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -189,13 +189,18 @@ private Stream<String> getBpmnMessageName(Task newResource) private boolean taskAllowedForUser(Connection connection, User user, String instantiatesUri, String messageName) { - MatchResult matchResult = INSTANTIATES_URI_PATTERN.matcher(instantiatesUri).toMatchResult(); - String processUrl = matchResult.group(1); - String processVersion = matchResult.group(2); + Matcher matcher = INSTANTIATES_URI_PATTERN.matcher(instantiatesUri); + if (matcher.matches()) + { + String processUrl = matcher.group(1); + String processVersion = matcher.group(2); - return activityDefinitionProvider - .getActivityDefinition(connection, user.getRole(), processUrl, processVersion, messageName) - .map(ad -> true).orElse(false); + return activityDefinitionProvider + .getActivityDefinition(connection, user.getRole(), processUrl, processVersion, messageName) + .map(ad -> true).orElse(false); + } + else + return false; } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java index 4d9752055..cb68b31c4 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java @@ -91,13 +91,13 @@ public Optional<ActivityDefinition> readByOrganizationTypeUserRoleProcessUrlVers + "activity_definition->'extension' @> ?::jsonb AND " + "lower(activity_definition->>'status') <> 'retired'")) { - String extension = "'[{\"url\":\"http://highmed.org/fhir/StructureDefinition/process-authorization\",\"extension\":[" + String extension = "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/process-authorization\",\"extension\":[" + "{\"url\":\"message-name\",\"valueString\":\"" + messageName + "\"}," + "{\"url\":\"authorization-role\",\"valueCoding\":{\"code\":\"" + userRole.toString() + "\",\"system\":\"http://highmed.org/fhir/CodeSystem/authorization-role\"}}," + "{\"url\":\"organization-types\",\"extension\":[{\"url\":\"organization-type\",\"valueCoding\":{\"code\":\"" + organizationType.toString() - + "\",\"system\":\"http://highmed.org/fhir/CodeSystem/authorization-role\"}}]}]}]'"; + + "\",\"system\":\"http://highmed.org/fhir/CodeSystem/authorization-role\"}}]}]}]"; statement.setString(1, processUrl); statement.setString(2, processVersion); diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ActivityDefinition-PingProcess-1.0.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-1.0.0.xml similarity index 66% rename from dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ActivityDefinition-PingProcess-1.0.0.xml rename to dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-1.0.0.xml index f546869d2..a63a9d27b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ActivityDefinition-PingProcess-1.0.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-1.0.0.xml @@ -1,82 +1,82 @@ <ActivityDefinition xmlns="http://hl7.org/fhir"> <meta> <tag> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> - <code value="REMOTE"/> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> </tag> </meta> <extension url="http://highmed.org/fhir/StructureDefinition/process-authorization"> <extension url="message-name"> - <valueString value="startProcessMessage"/> + <valueString value="startProcessMessage" /> </extension> <extension url="authorization-role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> - <code value="LOCAL"/> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="LOCAL" /> </valueCoding> </extension> <extension url="organization-types"> <extension url="organization-type"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> - <code value="TTP"/> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="TTP" /> </valueCoding> </extension> <extension url="organization-type"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> - <code value="MeDIC"/> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="MeDIC" /> </valueCoding> </extension> </extension> <extension url="task-profile"> - <valueCanonical value="http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"/> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/highmed-task-start-process" /> </extension> </extension> <extension url="http://highmed.org/fhir/StructureDefinition/process-authorization"> <extension url="message-name"> - <valueString value="pongMessage"/> + <valueString value="pongMessage" /> </extension> <extension url="authorization-role"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> - <code value="REMOTE"/> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> </valueCoding> </extension> <extension url="organization-types"> <extension url="organization-type"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> - <code value="TTP"/> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="TTP" /> </valueCoding> </extension> <extension url="organization-type"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> - <code value="MeDIC"/> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="MeDIC" /> </valueCoding> </extension> </extension> <extension url="task-profile"> - <valueCanonical value="http://highmed.org/fhir/StructureDefinition/highmed-task-pong"/> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/highmed-task-pong" /> </extension> </extension> - <url value="http://highmed.org/bpe/Process/ping"/> - <version value="1.0.0"/> - <name value="PingProcess"/> - <title value="PING process"/> - <subtitle value="Communication Testing Process"/> - <status value="draft"/> - <experimental value="true"/> - <date value="2020-03-03T10:14:14+01:00"/> - <publisher value="HiGHmed"/> + <url value="http://highmed.org/bpe/Process/ping" /> + <version value="1.0.0" /> + <name value="PingProcess" /> + <title value="PING process" /> + <subtitle value="Communication Testing Process" /> + <status value="draft" /> + <experimental value="true" /> + <date value="2020-03-03T10:14:14+01:00" /> + <publisher value="HiGHmed" /> <contact> - <name value="HiGHmed"/> + <name value="HiGHmed" /> <telecom> - <system value="email"/> - <value value="pmo@highmed.org"/> + <system value="email" /> + <value value="pmo@highmed.org" /> </telecom> </contact> - <description value="Process to send PING messages to remote Organizations and to receive corresponding PONG message"/> - <kind value="Task"/> + <description value="Process to send PING messages to remote Organizations and to receive corresponding PONG message" /> + <kind value="Task" /> </ActivityDefinition> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ActivityDefinition-PingProcess-1.0.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-1.0.0.xml.put similarity index 100% rename from dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ActivityDefinition-PingProcess-1.0.0.xml.put rename to dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-1.0.0.xml.put diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-1.0.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-1.0.0.xml new file mode 100644 index 000000000..72b3a1355 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-1.0.0.xml @@ -0,0 +1,54 @@ +<ActivityDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </tag> + </meta> + <extension url="http://highmed.org/fhir/StructureDefinition/process-authorization"> + <extension url="message-name"> + <valueString value="pingMessage" /> + </extension> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </valueCoding> + </extension> + <extension url="organization-types"> + <extension url="organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="TTP" /> + </valueCoding> + </extension> + <extension url="organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/highmed-task-ping" /> + </extension> + </extension> + <url value="http://highmed.org/bpe/Process/pong" /> + <version value="1.0.0" /> + <name value="PongProcess" /> + <title value="PONG process" /> + <subtitle value="Communication Testing Process" /> + <status value="draft" /> + <experimental value="true" /> + <date value="2020-03-03T10:14:14+01:00" /> + <publisher value="HiGHmed" /> + <contact> + <name value="HiGHmed" /> + <telecom> + <system value="email" /> + <value value="pmo@highmed.org" /> + </telecom> + </contact> + <description value="Process startet by PING messages and to send corresponding PONG messages back remote Organizations" /> + <kind value="Task" /> +</ActivityDefinition> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-1.0.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-1.0.0.xml.put new file mode 100644 index 000000000..b931cf16f --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-1.0.0.xml.put @@ -0,0 +1 @@ +ActivityDefinition?url=http://highmed.org/bpe/Process/pong&version=1.0.0 \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java index 82877e9db..be3241d65 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java @@ -5,17 +5,25 @@ import static org.junit.Assert.assertTrue; import java.nio.file.Paths; +import java.util.Date; import java.util.List; import java.util.concurrent.BlockingDeque; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Response.Status; + +import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.fhir.client.WebsocketClient; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.DomainResource; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.StringType; import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.Task.TaskIntent; +import org.hl7.fhir.r4.model.Task.TaskStatus; import org.junit.Test; public class TaskIntegrationTest extends AbstractIntegrationTest @@ -122,4 +130,116 @@ public void testOutputTransactionReferenceResolver() throws Exception websocketClient.disconnect(); } } + + @Test + public void testCreateTaskStartPingProcess() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/1.0.0"); + t.setStatus(TaskStatus.REQUESTED); + t.setIntent(TaskIntent.ORDER); + t.setAuthoredOn(new Date()); + Reference localOrg = new Reference(organizationProvider.getLocalOrganization().get()); + t.setRequester(localOrg); + t.getRestriction().addRecipient(localOrg); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("startProcessMessage")); + + getWebserviceClient().create(t); + } + + @Test(expected = WebApplicationException.class) + public void testCreateTaskStartPingProcessNotAllowedForRemoteUser() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/1.0.0"); + t.setStatus(TaskStatus.REQUESTED); + t.setIntent(TaskIntent.ORDER); + t.setAuthoredOn(new Date()); + + Reference requester = new Reference().setType("Organization"); + requester.getIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier") + .setValue("External_Test_Organization"); + t.setRequester(requester); + + t.getRestriction().addRecipient(new Reference(organizationProvider.getLocalOrganization().get())); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("startProcessMessage")); + + try + { + getExternalWebserviceClient().create(t); + } + catch (WebApplicationException e) + { + assertEquals(Status.FORBIDDEN.getStatusCode(), e.getResponse().getStatus()); + throw e; + } + } + + @Test + public void testCreateTaskStartPongProcessAllowedForRemoteUser() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-ping"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/pong/1.0.0"); + t.setStatus(TaskStatus.REQUESTED); + t.setIntent(TaskIntent.ORDER); + t.setAuthoredOn(new Date()); + + Reference requester = new Reference().setType("Organization"); + requester.getIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier") + .setValue("External_Test_Organization"); + t.setRequester(requester); + + t.getRestriction().addRecipient(new Reference(organizationProvider.getLocalOrganization().get())); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("pingMessage")); + + getExternalWebserviceClient().create(t); + } + + @Test + public void testCreateTaskContinuePingProcessAllowedForRemoteUser() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-pong"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/1.0.0"); + t.setStatus(TaskStatus.REQUESTED); + t.setIntent(TaskIntent.ORDER); + t.setAuthoredOn(new Date()); + + Reference requester = new Reference().setType("Organization"); + requester.getIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier") + .setValue("External_Test_Organization"); + t.setRequester(requester); + + t.getRestriction().addRecipient(new Reference(organizationProvider.getLocalOrganization().get())); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("pongMessage")); + + getExternalWebserviceClient().create(t); + } } From 447fe46507923ad1f37250aadae538a57ba68fd3 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 3 Mar 2020 23:06:39 +0100 Subject: [PATCH 18/55] work on authorization rules, Task authorization -> update --- .../authorization/TaskAuthorizationRule.java | 85 ++++++++++++++++++- .../fhir/integration/TaskIntegrationTest.java | 59 +++++++++++++ 2 files changed, 142 insertions(+), 2 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java index 2ad171b6a..424dc3ba6 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java @@ -262,8 +262,49 @@ else if (isLocalUser(user) && isCurrentUserPartOfReferencedOrganization(connection, user, "task.restriction.recipient", oldResource.getRestriction().getRecipientFirstRep())) { - // TODO - return Optional.empty(); + Optional<String> same = reasonNotSame(oldResource, newResource); + if (same.isEmpty()) + { + // REQUESTED -> INPROGRESS + if (TaskStatus.REQUESTED.equals(oldResource.getStatus()) + && TaskStatus.INPROGRESS.equals(newResource.getStatus())) + { + if (!newResource.hasOutput()) + { + logger.info( + "local user (user is part of task.restriction.recipient organization), task.status inprogress, properties task.instantiatesUri, task.requester, task.restriction, task.input not changed"); + return Optional.of( + "local user (user part of task.restriction.recipient), task.status inprogress, properties task.instantiatesUri, task.requester, task.restriction, task.input not changed"); + } + else + { + logger.warn("Update of Task unauthorized, task.output not expected"); + return Optional.empty(); + } + } + // INPROGRESS -> COMPLETED or FAILED + else if (TaskStatus.INPROGRESS.equals(oldResource.getStatus()) + && (TaskStatus.COMPLETED.equals(newResource.getStatus()) + || TaskStatus.FAILED.equals(newResource.getStatus()))) + { + // might have output + logger.info( + "local user (user is part of task.restriction.recipient organization), task.status completed or failed, properties task.instantiatesUri, task.requester, task.restriction, task.input not changed"); + return Optional.of( + "local user (user part of task.restriction.recipient), task.status completed or failed, properties task.instantiatesUri, task.requester, task.restriction, task.input not changed"); + } + else + { + logger.warn("Update of Task unauthorized, task.status change {} -> {} not allowed", + oldResource.getStatus(), newResource.getStatus()); + return Optional.empty(); + } + } + else + { + logger.warn("Update of Task unauthorized, task properties {} changed", same.get()); + return Optional.empty(); + } } else { @@ -279,6 +320,46 @@ && isCurrentUserPartOfReferencedOrganization(connection, user, "task.restriction } } + private Optional<String> reasonNotSame(Task oldResource, Task newResource) + { + List<String> errors = new ArrayList<String>(); + if (!oldResource.getRequester().equalsDeep(newResource.getRequester())) + { + errors.add("task.requester"); + } + + if (!oldResource.getRestriction().equalsDeep(newResource.getRestriction())) + { + errors.add("task.restriction"); + } + + if (!oldResource.getInstantiatesUri().equals(newResource.getInstantiatesUri())) + { + errors.add("task.instantiatesUri"); + } + + if (oldResource.getInput().size() != newResource.getInput().size()) + { + errors.add("task.input"); + } + else + { + for (int i = 0; i < oldResource.getInput().size(); i++) + { + if (!oldResource.getInput().get(i).equalsDeep(newResource.getInput().get(i))) + { + errors.add("task.input[" + i + "]"); + break; + } + } + } + + if (errors.isEmpty()) + return Optional.empty(); + else + return Optional.of(errors.stream().collect(Collectors.joining(", "))); + } + @Override public Optional<String> reasonDeleteAllowed(Connection connection, User user, Task oldResource) { diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java index be3241d65..fb3b942cb 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java @@ -15,6 +15,7 @@ import javax.ws.rs.core.Response.Status; import org.highmed.dsf.fhir.authentication.OrganizationProvider; +import org.highmed.dsf.fhir.dao.TaskDao; import org.highmed.fhir.client.WebsocketClient; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.DomainResource; @@ -242,4 +243,62 @@ public void testCreateTaskContinuePingProcessAllowedForRemoteUser() throws Excep getExternalWebserviceClient().create(t); } + + @Test + public void testUpdateTaskStartPingProcessStatusRequestedToInProgress() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/1.0.0"); + t.setStatus(TaskStatus.REQUESTED); + t.setIntent(TaskIntent.ORDER); + t.setAuthoredOn(new Date()); + Reference localOrg = new Reference() + .setReferenceElement(organizationProvider.getLocalOrganization().get().getIdElement().toVersionless()); + t.setRequester(localOrg); + t.getRestriction().addRecipient(localOrg); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("startProcessMessage")); + + TaskDao dao = getSpringWebApplicationContext().getBean(TaskDao.class); + Task created = dao.create(t); + + created.setStatus(TaskStatus.INPROGRESS); + + getWebserviceClient().update(created); + } + + @Test + public void testUpdateTaskStartPingProcessStatusInProgressToCompleted() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/1.0.0"); + t.setStatus(TaskStatus.INPROGRESS); + t.setIntent(TaskIntent.ORDER); + t.setAuthoredOn(new Date()); + Reference localOrg = new Reference() + .setReferenceElement(organizationProvider.getLocalOrganization().get().getIdElement().toVersionless()); + t.setRequester(localOrg); + t.getRestriction().addRecipient(localOrg); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("startProcessMessage")); + + TaskDao dao = getSpringWebApplicationContext().getBean(TaskDao.class); + Task created = dao.create(t); + + created.setStatus(TaskStatus.COMPLETED); + + getWebserviceClient().update(created); + } } From 64bd431acf506423d6d2b69021273623d0b6cdba Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Mon, 9 Mar 2020 00:14:32 +0100 Subject: [PATCH 19/55] work on authorization rules, more rules not tested yet ResearchStudy, Practitioner, PractitionerRole --- .../highmed/dsf/fhir/authentication/User.java | 6 + .../AbstractAuthorizationRule.java | 37 +- .../BinaryAuthorizationRule.java | 19 +- .../EndpointAuthorizationRule.java | 15 +- .../OrganizationAuthorizationRule.java | 18 +- .../PractitionerAuthorizationRule.java | 132 ++++++- .../PractitionerRoleAuthorizationRule.java | 198 +++++++++- .../ResearchStudyAuthorizationRule.java | 365 +++++++++++++++++- .../authorization/ResearchStudyHelper.java | 29 ++ .../dsf/fhir/dao/ResearchStudyDao.java | 9 + .../dao/jdbc/PractitionerRoleDaoJdbc.java | 6 +- .../fhir/dao/jdbc/ResearchStudyDaoJdbc.java | 71 +++- .../highmed/dsf/fhir/search/SearchQuery.java | 2 +- .../fhir/search/SearchQueryUserFilter.java | 8 +- .../parameters/EndpointOrganization.java | 6 +- .../PractitionerRoleOrganization.java | 196 ++++++++++ .../PractitionerRolePractitioner.java | 196 ++++++++++ .../ResearchStudyPrincipalInvestigator.java | 230 +++++++++++ .../fhir/search/parameters/TaskRequester.java | 20 +- .../user/PractitionerRoleUserFilter.java | 54 ++- .../user/PractitionerUserFilter.java | 57 ++- .../user/ResearchStudyUserFilter.java | 46 ++- .../impl/ConformanceServiceImpl.java | 12 +- .../NamingSystem/highmed-research-study.xml | 22 ++ .../highmed-research-study.xml.put | 1 + ...ed-extension-participating-medic-0.1.0.xml | 84 ++-- ...hmed-extension-participating-ttp-0.1.0.xml | 44 +++ ...-extension-participating-ttp-0.1.0.xml.put | 1 + .../highmed-research-study-0.1.0.xml | 156 +++++--- .../dsf/fhir/dao/ResearchStudyDaoTest.java | 41 ++ .../dsf/fhir/hapi/ResearchStudyTest.java | 31 ++ 31 files changed, 1895 insertions(+), 217 deletions(-) create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyHelper.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PractitionerRoleOrganization.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PractitionerRolePractitioner.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ResearchStudyPrincipalInvestigator.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-research-study.xml create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-research-study.xml.put create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-ttp-0.1.0.xml create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-ttp-0.1.0.xml.put create mode 100644 dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/ResearchStudyTest.java diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/User.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/User.java index 4f92ce8ec..dafca7ea9 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/User.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authentication/User.java @@ -1,5 +1,6 @@ package org.highmed.dsf.fhir.authentication; +import org.highmed.dsf.fhir.OrganizationType; import org.hl7.fhir.r4.model.Organization; public class User @@ -23,6 +24,11 @@ public Organization getOrganization() return organization; } + public OrganizationType getOrganizationType() + { + return OrganizationType.fromString(organization.getTypeFirstRep().getCodingFirstRep().getCode()).orElseThrow(); + } + public String getName() { return organization == null ? "null" : organization.getName(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java index 071f5ab09..b0f22ec18 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java @@ -6,7 +6,9 @@ import java.util.EnumSet; import java.util.Objects; import java.util.Optional; +import java.util.stream.Stream; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.authentication.UserRole; @@ -140,6 +142,16 @@ protected final boolean isRemoteUser(User user) return user != null && UserRole.REMOTE.equals(user.getRole()); } + protected final boolean isUserPartOfMeDic(User user) + { + return user != null && OrganizationType.MeDIC.equals(user.getOrganizationType()); + } + + protected final boolean isUserPartOfTtp(User user) + { + return user != null && OrganizationType.TTP.equals(user.getOrganizationType()); + } + protected final boolean hasLocalOrRemoteAuthorizationRole(Resource resource) { return resource.hasMeta() && resource.getMeta().getTag().stream() @@ -167,7 +179,13 @@ private boolean hasAuthorizationRole(Resource resource, String role) protected final boolean isCurrentUserPartOfReferencedOrganizations(Connection connection, User user, String referenceLocation, Collection<? extends Reference> references) { - return references.stream() + return isCurrentUserPartOfReferencedOrganizations(connection, user, referenceLocation, references.stream()); + } + + protected final boolean isCurrentUserPartOfReferencedOrganizations(Connection connection, User user, + String referenceLocation, Stream<? extends Reference> references) + { + return references .anyMatch(r -> isCurrentUserPartOfReferencedOrganization(connection, user, referenceLocation, r)); } @@ -221,4 +239,21 @@ protected final boolean isLocalOrganization(Organization organization) return organizationProvider.getLocalOrganization() .map(localOrg -> localOrg.getIdElement().equals(organization.getIdElement())).orElse(false); } + + @SafeVarargs + protected final Optional<ResourceReference> createIfLiteralInternalOrLogicalReference(String referenceLocation, + Reference reference, Class<? extends Resource>... referenceTypes) + { + ResourceReference r = new ResourceReference(referenceLocation, reference, referenceTypes); + if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL).contains(r.getType(serverBase))) + return Optional.of(r); + else + return Optional.empty(); + } + + protected final Optional<Resource> resolveReference(Connection connection, User user, + Optional<ResourceReference> reference) + { + return reference.flatMap(ref -> referenceResolver.resolveReference(user, ref, connection)); + } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java index c8f30cab2..f7012ba20 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/BinaryAuthorizationRule.java @@ -34,13 +34,11 @@ public Optional<String> reasonCreateAllowed(Connection connection, User user, Bi { if (newResource.hasData() && newResource.hasContentType() && newResource.hasSecurityContext()) { - ResourceReference reference = new ResourceReference("Binary.SecurityContext", - newResource.getSecurityContext(), Organization.class); - if (EnumSet.of(ReferenceType.LITERAL_INTERNAL, ReferenceType.LOGICAL) - .contains(reference.getType(serverBase))) + Optional<ResourceReference> reference = createIfLiteralInternalOrLogicalReference( + "Binary.SecurityContext", newResource.getSecurityContext(), Organization.class); + if (reference.isPresent()) { - Optional<Resource> securityContext = referenceResolver.resolveReference(user, reference, - connection); + Optional<Resource> securityContext = resolveReference(connection, user, reference); if (securityContext.isPresent()) { if (securityContext.get() instanceof Organization) @@ -91,13 +89,14 @@ public Optional<String> reasonReadAllowed(Connection connection, User user, Bina logger.info("Read of Binary authorized for local user '{}'", user.getName()); return Optional.of("local user"); } - else if (isCurrentUserPartOfReferencedOrganization(connection, user, "Binary.SecurityContext", - existingResource.getSecurityContext())) + else if ((isLocalUser(user) || isRemoteUser(user)) && isCurrentUserPartOfReferencedOrganization(connection, + user, "Binary.securityContext", existingResource.getSecurityContext())) { logger.info( - "Read of Binary authorized, Binary.SecurityContext reference could be resolved and user '{}' is part of referenced organization", + "Read of Binary authorized, Binary.securityContext reference could be resolved and user '{}' is part of referenced organization", user.getName()); - return Optional.of("Binary.SecurityContext resolved and user part of referenced organization"); + return Optional.of( + "local or remote user, Binary.securityContext resolved and user part of referenced organization"); } else { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java index c7c1fd504..7cab96325 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java @@ -76,27 +76,27 @@ private Optional<String> newResourceOk(Endpoint newResource) if (newResource.hasIdentifier()) { if (newResource.getIdentifier().stream() - .map(i -> i.hasSystem() && i.hasValue() && IDENTIFIER_SYSTEM.equals(i.getSystem())).count() != 1) + .filter(i -> i.hasSystem() && i.hasValue() && IDENTIFIER_SYSTEM.equals(i.getSystem())).count() != 1) { errors.add( - "endpoint.identifier one with system '" + IDENTIFIER_SYSTEM + "' and non empty value expected"); + "Endpoint.identifier one with system '" + IDENTIFIER_SYSTEM + "' and non empty value expected"); } } else { - errors.add("endpoint.identifier missing"); + errors.add("Endpoint.identifier missing"); } if (newResource.hasAddress()) { if (!ENDPOINT_ADDRESS_PATTERN.matcher(newResource.getAddress()).matches()) { - errors.add("endpoint.address not matching " + ENDPOINT_ADDRESS_PATTERN_STRING + " pattern"); + errors.add("Endpoint.address not matching " + ENDPOINT_ADDRESS_PATTERN_STRING + " pattern"); } } else { - errors.add("endpoint.address missing"); + errors.add("Endpoint.address missing"); } if (!hasLocalOrRemoteAuthorizationRole(newResource)) @@ -113,7 +113,8 @@ private Optional<String> newResourceOk(Endpoint newResource) private boolean resourceExists(Connection connection, Endpoint newResource) { String identifierValue = newResource.getIdentifier().stream() - .filter(i -> IDENTIFIER_SYSTEM.equals(i.getSystem())).map(i -> i.getValue()).findFirst().orElseThrow(); + .filter(i -> i.hasSystem() && i.hasValue() && IDENTIFIER_SYSTEM.equals(i.getSystem())) + .map(i -> i.getValue()).findFirst().orElseThrow(); return endpointWithAddressExists(connection, newResource.getAddress()) || endpointWithIdentifierExists(connection, identifierValue); @@ -124,7 +125,7 @@ private boolean endpointWithIdentifierExists(Connection connection, String ident Map<String, List<String>> queryParameters = Map.of("identifier", Collections.singletonList(IDENTIFIER_SYSTEM + "|" + identifierValue)); EndpointDao dao = getDao(); - SearchQuery<Endpoint> query = dao.createSearchQueryWithoutUserFilter(1, 1).configureParameters(queryParameters); + SearchQuery<Endpoint> query = dao.createSearchQueryWithoutUserFilter(0, 0).configureParameters(queryParameters); try { PartialResult<Endpoint> result = dao.searchWithTransaction(connection, query); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java index 1b4f497dc..507d84002 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java @@ -81,15 +81,15 @@ private Optional<String> newResourceOk(Organization newResource) if (newResource.hasIdentifier()) { if (newResource.getIdentifier().stream() - .map(i -> i.hasSystem() && i.hasValue() && IDENTIFIER_SYSTEM.equals(i.getSystem())).count() != 1) + .filter(i -> i.hasSystem() && i.hasValue() && IDENTIFIER_SYSTEM.equals(i.getSystem())).count() != 1) { - errors.add("organization.identifier one with system '" + IDENTIFIER_SYSTEM + errors.add("Organization.identifier one with system '" + IDENTIFIER_SYSTEM + "' and non empty value expected"); } } else { - errors.add("organization.identifier missing"); + errors.add("Organization.identifier missing"); } if (newResource.hasExtension()) @@ -98,13 +98,13 @@ private Optional<String> newResourceOk(Organization newResource) && (e.getValue() instanceof StringType) && EXTENSION_THUMBPRINT_URL.equals(e.getUrl()) && EXTENSION_THUMBPRINT_VALUE_PATTERN.matcher(((StringType) e.getValue()).getValue()).matches())) { - errors.add("organization.extension missing extension with url '" + EXTENSION_THUMBPRINT_URL + errors.add("Organization.extension missing extension with url '" + EXTENSION_THUMBPRINT_URL + "' and value matching " + EXTENSION_THUMBPRINT_VALUE_PATTERN_STRING + " pattern"); } } else { - errors.add("organization.extension missing"); + errors.add("Organization.extension missing"); } if (!hasLocalOrRemoteAuthorizationRole(newResource)) @@ -121,9 +121,11 @@ private Optional<String> newResourceOk(Organization newResource) private boolean resourceExists(Connection connection, Organization newResource) { String identifierValue = newResource.getIdentifier().stream() - .filter(i -> IDENTIFIER_SYSTEM.equals(i.getSystem())).map(i -> i.getValue()).findFirst().orElseThrow(); + .filter(i -> i.hasSystem() && i.hasValue() && IDENTIFIER_SYSTEM.equals(i.getSystem())) + .map(i -> i.getValue()).findFirst().orElseThrow(); String thumbprintValue = newResource.getExtension().stream() - .filter(e -> EXTENSION_THUMBPRINT_URL.equals(e.getUrl())) + .filter(e -> e.hasUrl() && e.hasValue() && (e.getValue() instanceof StringType) + && EXTENSION_THUMBPRINT_URL.equals(e.getUrl())) .map(e -> ((StringType) e.getValue()).getValue()).findFirst().orElseThrow(); return organizationWithThumbPrintExists(connection, thumbprintValue) @@ -149,7 +151,7 @@ private boolean organizationWithIdentifierExists(Connection connection, String i Map<String, List<String>> queryParameters = Map.of("identifier", Collections.singletonList(IDENTIFIER_SYSTEM + "|" + identifierValue)); OrganizationDao dao = getDao(); - SearchQuery<Organization> query = dao.createSearchQueryWithoutUserFilter(1, 1) + SearchQuery<Organization> query = dao.createSearchQueryWithoutUserFilter(0, 0) .configureParameters(queryParameters); try { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java index 1c1b30fa4..ad64ca14e 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java @@ -1,17 +1,30 @@ package org.highmed.dsf.fhir.authorization; import java.sql.Connection; +import java.sql.SQLException; +import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.Optional; import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.PractitionerDao; +import org.highmed.dsf.fhir.dao.PractitionerRoleDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.search.PartialResult; +import org.highmed.dsf.fhir.search.SearchQuery; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Practitioner; +import org.hl7.fhir.r4.model.PractitionerRole; +import org.hl7.fhir.r4.model.ResearchStudy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class PractitionerAuthorizationRule extends AbstractAuthorizationRule<Practitioner, PractitionerDao> { + private static final Logger logger = LoggerFactory.getLogger(PractitionerAuthorizationRule.class); + public PractitionerAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { @@ -21,36 +34,135 @@ public PractitionerAuthorizationRule(DaoProvider daoProvider, String serverBase, @Override public Optional<String> reasonCreateAllowed(Connection connection, User user, Practitioner newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Create of Practitioner authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Create of Practitioner unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonReadAllowed(Connection connection, User user, Practitioner existingResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Read of Practitioner authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else if (isRemoteUser(user)) + { + if (researchStudyWithPrincipalInvestigatorAndUsersOrganizationExists(connection, user, existingResource)) + { + logger.info( + "Read of Practitioner authorized for remote user '{}', ResearchStudy with principalInvestigator equal to this Practitioner and users organization part of ResearchStudy", + user.getName()); + return Optional.of( + "remote user, users organization part of ResearchStudy with principal investigator equal to this Practitioner"); + } + // TODO ResearchStudy with users organization and principalInvestigator set to PractitionerRole and + // PractitionerRoles practitioner set to this Practitioner + else if (practitionerRoleWithPractitionerAndUsersOrganizationExists(connection, user, existingResource)) + { + logger.info( + "Read of Practitioner authorized for remote user '{}', PractitionerRole with organization equal to users organization and practitioner equal to this Practitioner"); + return Optional.of("remote user, PractitionerRole with users organizatio and this Practitioner"); + } + else + { + logger.warn( + "PractitionerRole or ResearchStudy with this Practitioner and users Organization not found"); + return Optional.empty(); + } + } + else + { + logger.warn("Read of Practitioner unauthorized, not a local or remote user"); + return Optional.empty(); + } + } + + private boolean researchStudyWithPrincipalInvestigatorAndUsersOrganizationExists(Connection connection, User user, + Practitioner existingResource) + { + try + { + List<ResearchStudy> studies = daoProvider.getResearchStudyDao() + .readByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationIdWithTransaction(connection, + existingResource.getIdElement(), user.getOrganizationType(), + user.getOrganization().getIdElement()); + return !studies.isEmpty(); + } + catch (SQLException e) + { + logger.warn("Error while searching for research studies", e); + return false; + } + } + + private boolean practitionerRoleWithPractitionerAndUsersOrganizationExists(Connection connection, User user, + Practitioner existingResource) + { + try + { + PractitionerRoleDao dao = daoProvider.getPractitionerRoleDao(); + SearchQuery<PractitionerRole> query = dao.createSearchQueryWithoutUserFilter(0, 0) + .configureParameters(Map.of("practitioner", + Collections + .singletonList(existingResource.getIdElement().toVersionless().getValueAsString()), + "organization", Collections.singletonList( + user.getOrganization().getIdElement().toVersionless().getValueAsString()))); + PartialResult<PractitionerRole> result = dao.searchWithTransaction(connection, query); + return result.getOverallCount() > 0; + } + catch (SQLException e) + { + logger.warn("Error while searching for research studies", e); + return false; + } } @Override public Optional<String> reasonUpdateAllowed(Connection connection, User user, Practitioner oldResource, Practitioner newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Update of Practitioner authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + + } + else + { + logger.warn("Update of Practitioner unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonDeleteAllowed(Connection connection, User user, Practitioner oldResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Delete of Practitioner authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Delete of Practitioner unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonSearchAllowed(Connection connection, User user) { - // TODO Auto-generated method stub - return Optional.empty(); + logger.info("Search of Practitioner authorized for {} user '{}', will be fitered by users organization {}", + user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString()); + return Optional.of("Allowed for all, filtered by users organization"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java index 36aea6baf..06fb4ef6b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java @@ -1,17 +1,31 @@ package org.highmed.dsf.fhir.authorization; import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.PractitionerRoleDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.service.ReferenceResolver; +import org.highmed.dsf.fhir.service.ResourceReference; +import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.Practitioner; import org.hl7.fhir.r4.model.PractitionerRole; +import org.hl7.fhir.r4.model.ResearchStudy; +import org.hl7.fhir.r4.model.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class PractitionerRoleAuthorizationRule extends AbstractAuthorizationRule<PractitionerRole, PractitionerRoleDao> { + private static final Logger logger = LoggerFactory.getLogger(PractitionerRoleAuthorizationRule.class); + public PractitionerRoleAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { @@ -21,36 +35,200 @@ public PractitionerRoleAuthorizationRule(DaoProvider daoProvider, String serverB @Override public Optional<String> reasonCreateAllowed(Connection connection, User user, PractitionerRole newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + Optional<String> errors = newResourceOk(connection, user, newResource); + if (errors.isEmpty()) + { + logger.info( + "Create of PractitionerRole authorized for local user '{}', practitioner and organization references resolved", + user.getName()); + return Optional.of("local user; practitioner and organization resolved"); + } + else + { + logger.warn("Create of PractitionerRole unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else + { + logger.warn("Create of PractitionerRole unauthorized, not a local user"); + return Optional.empty(); + } + } + + private Optional<String> newResourceOk(Connection connection, User user, PractitionerRole newResource) + { + List<String> errors = new ArrayList<String>(); + + if (newResource.hasOrganization()) + { + Optional<ResourceReference> organizationReference = createIfLiteralInternalOrLogicalReference( + "PractitionerRole.organization", newResource.getOrganization(), Organization.class); + if (organizationReference.isPresent()) + { + Optional<Resource> organization = resolveReference(connection, user, organizationReference); + if (!organization.isPresent()) + { + errors.add("PractitionerRole.organization could not be resolved"); + } + } + else + { + errors.add("PractitionerRole.organization not a literal internal or logical reference"); + } + } + else + { + errors.add("PractitionerRole.organization missing"); + } + + if (newResource.hasPractitioner()) + { + Optional<ResourceReference> practitionerReference = createIfLiteralInternalOrLogicalReference( + "PractitionerRole.practitioner", newResource.getPractitioner(), Practitioner.class); + if (practitionerReference.isPresent()) + { + Optional<Resource> practitioner = resolveReference(connection, user, practitionerReference); + if (!practitioner.isPresent()) + { + errors.add("PractitionerRole.practitioner could not be resolved"); + } + } + else + { + errors.add("PractitionerRole.practitioner not a literal internal or logical reference"); + } + } + else + { + errors.add("PractitionerRole.practitioner missing"); + } + + if (errors.isEmpty()) + return Optional.empty(); + else + return Optional.of(errors.stream().collect(Collectors.joining(", "))); } @Override public Optional<String> reasonReadAllowed(Connection connection, User user, PractitionerRole existingResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Read of PractitionerRole authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else if (isRemoteUser(user)) + { + if (isCurrentUserPartOfReferencedOrganization(connection, user, "PractitionerRole.organization", + existingResource.getOrganization())) + { + logger.info( + "Read of PractitionerRole authorized, PractitionerRole.organization reference could be resolved and user '{}' is part of referenced organization", + user.getName()); + return Optional.of( + "remote user, PractitionerRole.organization resolved and user part of referenced organization"); + } + else if (researchStudyWithPrincipalInvestigatorAndUsersOrganizationExists(connection, user, + existingResource.getIdElement())) + { + logger.warn( + "Read of PractitionerRole authorized, remote user '{}' part of ResearchStudy with this PractitionerRole as principal investigator", + user.getName()); + return Optional.of( + "remote user, users organization part of ResearchStudies principal investigator equal to this PractitionerRole"); + + } + else if (researchStudyWithPrincipalInvestigatorAndUsersOrganizationExists(connection, user, + new IdType(existingResource.getPractitioner().getReference()))) + { + logger.warn( + "Read of PractitionerRole authorized, remote user '{}' part of ResearchStudy with this PractitionerRoles Practitioner as principal investigator", + user.getName()); + return Optional.of( + "remote user, users organization part of ResearchStudy and principal investigator equal to this PractitionerRoles Practitioner"); + } + else + { + logger.warn( + "Read of PractitionerRole unauthorized, remote user '{}' not part of PractitionerRoles organization or not part of ResearchStudy with this PractitionerRole as principal investigator or not part of ResearchStudy with this PractitionerRoles Practitioner as principal investigator", + user.getName()); + return Optional.empty(); + } + } + else + { + logger.warn("Read of PractitionerRole unauthorized, not a local or remote user"); + return Optional.empty(); + } + } + + private boolean researchStudyWithPrincipalInvestigatorAndUsersOrganizationExists(Connection connection, User user, + IdType principalInvestigatorId) + { + try + { + List<ResearchStudy> studies = daoProvider.getResearchStudyDao() + .readByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationIdWithTransaction(connection, + principalInvestigatorId, user.getOrganizationType(), user.getOrganization().getIdElement()); + return !studies.isEmpty(); + } + catch (SQLException e) + { + logger.warn("Error while searching for research studies", e); + return false; + } } @Override public Optional<String> reasonUpdateAllowed(Connection connection, User user, PractitionerRole oldResource, PractitionerRole newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + Optional<String> errors = newResourceOk(connection, user, newResource); + if (errors.isEmpty()) + { + logger.info( + "Update of PractitionerRole authorized for local user '{}', practitioner and organization references resolved", + user.getName()); + return Optional.of("local user; practitioner and organization resolved"); + } + else + { + logger.warn("Update of PractitionerRole unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else + { + logger.warn("Update of PractitionerRole unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonDeleteAllowed(Connection connection, User user, PractitionerRole oldResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Delete of PractitionerRole authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Delete of PractitionerRole unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonSearchAllowed(Connection connection, User user) { - // TODO Auto-generated method stub - return Optional.empty(); + logger.info("Search of PractitionerRole authorized for {} user '{}', will be fitered by users organization {}", + user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString()); + return Optional.of("Allowed for all, filtered by users organization"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java index a4d0f1f1d..9a47b4f0a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java @@ -1,17 +1,44 @@ package org.highmed.dsf.fhir.authorization; import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.dao.PractitionerRoleDao; import org.highmed.dsf.fhir.dao.ResearchStudyDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.search.PartialResult; +import org.highmed.dsf.fhir.search.SearchQuery; import org.highmed.dsf.fhir.service.ReferenceResolver; +import org.hl7.fhir.r4.model.Group; +import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.Practitioner; +import org.hl7.fhir.r4.model.PractitionerRole; +import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.ResearchStudy; +import org.hl7.fhir.r4.model.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ResearchStudyAuthorizationRule extends AbstractAuthorizationRule<ResearchStudy, ResearchStudyDao> { + private static final Logger logger = LoggerFactory.getLogger(ResearchStudyAuthorizationRule.class); + + private static final String RESEARCH_STUDY_IDENTIFIER = "http://highmed.org/fhir/NamingSystem/research-study-identifier"; + private static final String RESEARCH_STUDY_IDENTIFIER_PATTERN_STRING = "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"; + private static final Pattern RESEARCH_STUDY_IDENTIFIER_PATTERN = Pattern + .compile(RESEARCH_STUDY_IDENTIFIER_PATTERN_STRING); + public ResearchStudyAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { @@ -21,36 +48,354 @@ public ResearchStudyAuthorizationRule(DaoProvider daoProvider, String serverBase @Override public Optional<String> reasonCreateAllowed(Connection connection, User user, ResearchStudy newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + Optional<String> errors = newResourceOk(connection, user, newResource); + if (errors.isEmpty()) + { + if (!resourceExists(connection, newResource)) + { + logger.info( + "Create of ResearchStudy authorized for local user '{}', ResearchStudy with identifier does not exist", + user.getName()); + return Optional.of("local user, ResearchStudy with identifier not exist yet"); + } + else + { + logger.warn("Create of ResearchStudy unauthorized, ResearchStudy with identifier already exists"); + return Optional.empty(); + } + } + else + { + logger.warn("Create of ResearchStudy unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else + { + logger.warn("Create of ResearchStudy unauthorized, not a local user"); + return Optional.empty(); + } + } + + private Optional<String> newResourceOk(Connection connection, User user, ResearchStudy newResource) + { + List<String> errors = new ArrayList<String>(); + + if (newResource.hasIdentifier()) + { + if (newResource.getIdentifier().stream() + .filter(i -> i.hasSystem() && i.hasValue() && RESEARCH_STUDY_IDENTIFIER.equals(i.getSystem()) + && RESEARCH_STUDY_IDENTIFIER_PATTERN.matcher(i.getValue()).matches()) + .count() != 1) + { + errors.add("ResearchStudy.identifier one with system '" + RESEARCH_STUDY_IDENTIFIER + + "' and non empty value matching " + RESEARCH_STUDY_IDENTIFIER_PATTERN_STRING + " expected"); + } + } + else + { + errors.add("ResearchStudy.identifier missing"); + } + + Stream<Reference> participatingMedicReferences = ResearchStudyHelper + .getParticipatingMedicReferences(newResource); + if (participatingMedicReferences.count() >= 0) + { + if (!organizationsResolvable(connection, user, + "ResearchStudy.extension(url:http://highmed.org/fhir/StructureDefinition/participating-medic)", + participatingMedicReferences).allMatch(t -> t)) + { + errors.add( + "ResearchStudy.extension(url:http://highmed.org/fhir/StructureDefinition/participating-medic) one or more participating-medic Organizations not resolved"); + } + } + else + { + errors.add( + "ResearchStudy.extension(url:http://highmed.org/fhir/StructureDefinition/participating-medic) one or more participating-medic Organization references missing"); + } + + Optional<Reference> participatingTtpReference = ResearchStudyHelper.getParticipatingTtpReference(newResource); + if (participatingTtpReference.isPresent()) + { + if (!organizationResolvable(connection, user, + "ResearchStudy.extension(url:http://highmed.org/fhir/StructureDefinition/participating-ttp)", + participatingTtpReference.get())) + { + errors.add( + "ResearchStudy.extension(url:http://highmed.org/fhir/StructureDefinition/participating-ttp) participating-ttp Organization not resolved"); + } + } + else + { + errors.add( + "ResearchStudy.extension(url:http://highmed.org/fhir/StructureDefinition/participating-ttp) participating-ttp Organization references missing"); + } + + if (newResource.getEnrollment().size() >= 0) + { + if (!enrollmentsResolvable(connection, user, "ResearchStudy.enrollment", + newResource.getEnrollment().stream()).allMatch(t -> t)) + { + errors.add("ResearchStudy.enrollment one or more Groups not resolved"); + } + } + else + { + errors.add("ResearchStudy.enrollment one or more Group references missing"); + } + + if (newResource.hasPrincipalInvestigator()) + { + Optional<Resource> practitioner = resolvePractitioner(connection, user, + "ResearchStudy.principalInvestigator", newResource.getPrincipalInvestigator()); + if (practitioner.isPresent()) + { + if (!practitionerRoleExists(connection, user, practitioner.get().getIdElement())) + { + errors.add( + "ResearchStudy.principalInvestigator corresponding PractitionerRole.practitioner not found"); + } + } + else + { + errors.add("ResearchStudy.principalInvestigator not resolved"); + } + } + else + { + errors.add("ResearchStudy.principalInvestigator missing"); + } + + if (errors.isEmpty()) + return Optional.empty(); + else + return Optional.of(errors.stream().collect(Collectors.joining(", "))); + } + + private Stream<Boolean> organizationsResolvable(Connection connection, User user, String referenceLocation, + Stream<Reference> references) + { + return references.map(r -> organizationResolvable(connection, user, referenceLocation, r)); + } + + private boolean organizationResolvable(Connection connection, User user, String referenceLocation, + Reference reference) + { + var ref = createIfLiteralInternalOrLogicalReference(referenceLocation, reference, Organization.class); + return resolveReference(connection, user, ref).isPresent(); + } + + private Stream<Boolean> enrollmentsResolvable(Connection connection, User user, String referenceLocation, + Stream<Reference> references) + { + return references.map(r -> enrollmentResolvable(connection, user, referenceLocation, r)); + } + + private boolean enrollmentResolvable(Connection connection, User user, String referenceLocation, + Reference reference) + { + var ref = createIfLiteralInternalOrLogicalReference(referenceLocation, reference, Group.class); + return resolveReference(connection, user, ref).isPresent(); + } + + private Optional<Resource> resolvePractitioner(Connection connection, User user, String referenceLocation, + Reference reference) + { + var ref = createIfLiteralInternalOrLogicalReference(referenceLocation, reference, Practitioner.class); + return resolveReference(connection, user, ref); + } + + private boolean practitionerRoleExists(Connection connection, User user, IdType practitionerId) + { + PractitionerRoleDao dao = daoProvider.getPractitionerRoleDao(); + SearchQuery<PractitionerRole> query = dao.createSearchQuery(user, 0, 0).configureParameters( + Map.of("practitioner", Collections.singletonList("Practitioner/" + practitionerId.getIdPart()), + "active", Collections.singletonList("true"))); + + try + { + return dao.search(query).getOverallCount() == 1; + } + catch (SQLException e) + { + logger.warn("Error while searching for PractitionerRole", e); + return false; + } + } + + private boolean resourceExists(Connection connection, ResearchStudy newResource) + { + String identifierValue = newResource.getIdentifier().stream() + .filter(i -> i.hasSystem() && i.hasValue() && RESEARCH_STUDY_IDENTIFIER.equals(i.getSystem())) + .map(i -> i.getValue()).findFirst().orElseThrow(); + + return researchStudyWithIdentifierExists(connection, identifierValue); + } + + private boolean researchStudyWithIdentifierExists(Connection connection, String identifierValue) + { + Map<String, List<String>> queryParameters = Map.of("identifier", + Collections.singletonList(RESEARCH_STUDY_IDENTIFIER + "|" + identifierValue)); + ResearchStudyDao dao = getDao(); + SearchQuery<ResearchStudy> query = dao.createSearchQueryWithoutUserFilter(0, 0) + .configureParameters(queryParameters); + try + { + PartialResult<ResearchStudy> result = dao.searchWithTransaction(connection, query); + return result.getOverallCount() >= 1; + } + catch (SQLException e) + { + logger.warn("Error while searching for ResearchStudy with identifier", e); + return false; + } } @Override public Optional<String> reasonReadAllowed(Connection connection, User user, ResearchStudy existingResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Read of ResearchStudy authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else if (isRemoteUser(user)) + { + if (isUserPartOfMeDic(user)) + { + if (isCurrentUserPartOfReferencedOrganizations(connection, user, + "ResearchStudy.extension(url:" + ResearchStudyHelper.PARTICIPATING_MEDIC_EXTENSION_URL + ")", + ResearchStudyHelper.getParticipatingMedicReferences(existingResource))) + { + logger.info("Read of ResearchStudy authorized, ResearchStudy.extension(url:" + + ResearchStudyHelper.PARTICIPATING_MEDIC_EXTENSION_URL + + ") reference could be resolved and remote user '{}' part of referenced MeDIC organization", + user.getName()); + return Optional.of("remote user, ResearchStudy.extension(url:" + + ResearchStudyHelper.PARTICIPATING_MEDIC_EXTENSION_URL + + ") resolved and user part of referenced MeDIC organization"); + } + else + { + logger.warn( + "Read of ResearchStudy unauthorized, user not part of referenced MeDIC or reference in extension could not be resolved"); + return Optional.empty(); + } + } + else if (isUserPartOfTtp(user)) + { + if (isCurrentUserPartOfReferencedOrganization(connection, user, + "ResearchStudy.extension(url:" + ResearchStudyHelper.PARTICIPATING_TTP_EXTENSION_URL + ")", + ResearchStudyHelper.getParticipatingTtpReference(existingResource).orElse(null))) + { + logger.info("Read of ResearchStudy authorized, ResearchStudy.extension(url:" + + ResearchStudyHelper.PARTICIPATING_TTP_EXTENSION_URL + + ") reference could be resolved and remote user '{}' part of referenced TTP organization", + user.getName()); + return Optional.of("remote user, ResearchStudy.extension(url:" + + ResearchStudyHelper.PARTICIPATING_TTP_EXTENSION_URL + + ") resolved and user part of referenced TTP organization"); + } + else + { + logger.warn( + "Read of ResearchStudy unauthorized, user not part of referenced TTP or reference in extension could not be resolved"); + return Optional.empty(); + } + } + else + { + logger.warn("Read of ResearchStudy unauthorized, user not part of MeDIC or TTP"); + return Optional.empty(); + } + } + else + { + logger.warn("Read of ResearchStudy unauthorized, not a local or remote user"); + return Optional.empty(); + } } @Override public Optional<String> reasonUpdateAllowed(Connection connection, User user, ResearchStudy oldResource, ResearchStudy newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + Optional<String> errors = newResourceOk(connection, user, newResource); + if (errors.isEmpty()) + { + if (isSame(oldResource, newResource)) + { + logger.info( + "Update of ResearchStudy authorized for local user '{}', identifier same as existing ResearchStudy", + user.getName()); + return Optional.of("local user; identifier same as existing ResearchStudy"); + + } + else if (!resourceExists(connection, newResource)) + { + logger.info( + "Update of ResearchStudy authorized for local user '{}', other ResearchStudy with identifier does not exist", + user.getName()); + return Optional.of("local user; other ResearchStudy with identifier does not exist yet"); + } + else + { + logger.warn( + "Update of ResearchStudy unauthorized, other ResearchStudy with identifier already exists"); + return Optional.empty(); + } + } + else + { + logger.warn("Update of ResearchStudy unauthorized, " + errors.get()); + return Optional.empty(); + } + } + else + { + logger.warn("Update of ResearchStudy unauthorized, not a local user"); + return Optional.empty(); + } + } + + private boolean isSame(ResearchStudy oldResource, ResearchStudy newResource) + { + String oldIdentifierValue = oldResource.getIdentifier().stream() + .filter(i -> RESEARCH_STUDY_IDENTIFIER.equals(i.getSystem())).map(i -> i.getValue()).findFirst() + .orElseThrow(); + + String newIdentifierValue = newResource.getIdentifier().stream() + .filter(i -> RESEARCH_STUDY_IDENTIFIER.equals(i.getSystem())).map(i -> i.getValue()).findFirst() + .orElseThrow(); + + return oldIdentifierValue.equals(newIdentifierValue); } @Override public Optional<String> reasonDeleteAllowed(Connection connection, User user, ResearchStudy oldResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Delete of ResearchStudy authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Delete of ResearchStudy unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonSearchAllowed(Connection connection, User user) { - // TODO Auto-generated method stub - return Optional.empty(); + logger.info("Search of ResearchStudy authorized for {} user '{}', will be fitered by users organization {}", + user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString()); + return Optional.of("Allowed for all, filtered by users organization"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyHelper.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyHelper.java new file mode 100644 index 000000000..2f47ddeeb --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyHelper.java @@ -0,0 +1,29 @@ +package org.highmed.dsf.fhir.authorization; + +import java.util.Optional; +import java.util.stream.Stream; + +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ResearchStudy; + +final class ResearchStudyHelper +{ + public static final String PARTICIPATING_MEDIC_EXTENSION_URL = "http://highmed.org/fhir/StructureDefinition/participating-medic"; + public static final String PARTICIPATING_TTP_EXTENSION_URL = "http://highmed.org/fhir/StructureDefinition/participating-ttp"; + + private ResearchStudyHelper() + { + } + + static Stream<Reference> getParticipatingMedicReferences(ResearchStudy resource) + { + return resource.getExtensionsByUrl(PARTICIPATING_MEDIC_EXTENSION_URL).stream().map(e -> e.getValue()) + .filter(t -> t instanceof Reference).map(t -> ((Reference) t)); + } + + static Optional<Reference> getParticipatingTtpReference(ResearchStudy resource) + { + return Optional.ofNullable(resource.getExtensionByUrl(PARTICIPATING_TTP_EXTENSION_URL)).map(e -> e.getValue()) + .filter(t -> t instanceof Reference).map(t -> ((Reference) t)); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResearchStudyDao.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResearchStudyDao.java index 70a999477..168f5176c 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResearchStudyDao.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResearchStudyDao.java @@ -1,7 +1,16 @@ package org.highmed.dsf.fhir.dao; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.List; + +import org.highmed.dsf.fhir.OrganizationType; +import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.ResearchStudy; public interface ResearchStudyDao extends ResourceDao<ResearchStudy> { + List<ResearchStudy> readByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationIdWithTransaction( + Connection connection, IdType principalInvestigatorId, OrganizationType organizationType, + IdType organizationId) throws SQLException; } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerRoleDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerRoleDaoJdbc.java index d5a056297..7b857ca96 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerRoleDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerRoleDaoJdbc.java @@ -4,6 +4,8 @@ import org.highmed.dsf.fhir.dao.PractitionerRoleDao; import org.highmed.dsf.fhir.search.parameters.PractitionerRoleActive; import org.highmed.dsf.fhir.search.parameters.PractitionerRoleIdentifier; +import org.highmed.dsf.fhir.search.parameters.PractitionerRoleOrganization; +import org.highmed.dsf.fhir.search.parameters.PractitionerRolePractitioner; import org.highmed.dsf.fhir.search.parameters.user.PractitionerRoleUserFilter; import org.hl7.fhir.r4.model.PractitionerRole; @@ -15,7 +17,9 @@ public PractitionerRoleDaoJdbc(BasicDataSource dataSource, FhirContext fhirConte { super(dataSource, fhirContext, PractitionerRole.class, "practitioner_roles", "practitioner_role", "practitioner_role_id", PractitionerRoleUserFilter::new, - with(PractitionerRoleIdentifier::new, PractitionerRoleActive::new), with()); + with(PractitionerRoleActive::new, PractitionerRoleIdentifier::new, PractitionerRoleOrganization::new, + PractitionerRolePractitioner::new), + with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java index bbe888f09..183fd230a 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java @@ -1,20 +1,37 @@ package org.highmed.dsf.fhir.dao.jdbc; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.ResearchStudyDao; import org.highmed.dsf.fhir.search.parameters.ResearchStudyEnrollment; import org.highmed.dsf.fhir.search.parameters.ResearchStudyIdentifier; +import org.highmed.dsf.fhir.search.parameters.ResearchStudyPrincipalInvestigator; import org.highmed.dsf.fhir.search.parameters.user.ResearchStudyUserFilter; +import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.ResearchStudy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import ca.uhn.fhir.context.FhirContext; public class ResearchStudyDaoJdbc extends AbstractResourceDaoJdbc<ResearchStudy> implements ResearchStudyDao { + private static final Logger logger = LoggerFactory.getLogger(ResearchStudyDaoJdbc.class); + public ResearchStudyDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, ResearchStudy.class, "research_studies", "research_study", "research_study_id", - ResearchStudyUserFilter::new, with(ResearchStudyIdentifier::new, ResearchStudyEnrollment::new), with()); + ResearchStudyUserFilter::new, with(ResearchStudyIdentifier::new, ResearchStudyEnrollment::new, + ResearchStudyPrincipalInvestigator::new), + with()); } @Override @@ -22,4 +39,56 @@ protected ResearchStudy copy(ResearchStudy resource) { return resource.copy(); } + + @Override + public List<ResearchStudy> readByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationIdWithTransaction( + Connection connection, IdType principalInvestigatorId, OrganizationType organizationType, + IdType organizationId) throws SQLException + { + Objects.requireNonNull(connection, "connection"); + Objects.requireNonNull(principalInvestigatorId, "principalInvestigatorId"); + Objects.requireNonNull(organizationType, "organizationType"); + Objects.requireNonNull(organizationId, "organizationId"); + + try (PreparedStatement statement = connection + .prepareStatement("SELECT research_study FROM current_research_studies WHERE " + + "(research_study->'principalInvestigator'->>'reference' = ? OR research_study->'principalInvestigator'->>'reference' = ?) AND " + + "(research_study->'extension' @> ?::jsonb OR research_study->'extension' @> ?::jsonb)")) + { + statement.setString(1, principalInvestigatorId.getValue()); + statement.setString(2, principalInvestigatorId.toVersionless().getValue()); + + switch (organizationType) + { + case MeDIC: + statement.setString(3, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-medic\",\"valueReference\":{\"reference\":\"" + + organizationId.getValue() + "\"}}]"); + statement.setString(4, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-medic\",\"valueReference\":{\"reference\":\"" + + organizationId.toVersionless().getValue() + "\"}}]"); + break; + + case TTP: + statement.setString(3, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-ttp\",\"valueReference\":{\"reference\":\"" + + organizationId.getValue() + "\"}}]"); + statement.setString(4, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-ttp\",\"valueReference\":{\"reference\":\"" + + organizationId.toVersionless().getValue() + "\"}}]"); + break; + } + + logger.trace("Executing query '{}'", statement); + try (ResultSet result = statement.executeQuery()) + { + List<ResearchStudy> results = new ArrayList<>(); + + while (result.next()) + results.add(getResource(result, 1)); + + return results; + } + } + } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQuery.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQuery.java index d67760d8c..d01b7b3df 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQuery.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQuery.java @@ -175,7 +175,7 @@ private String createFilterQuery() Stream<String> elements = searchParameters.stream().filter(SearchQueryParameter::isDefined) .map(SearchQueryParameter::getFilterQuery); - if (userFilter != null) + if (userFilter != null && !userFilter.getFilterQuery().isEmpty()) elements = Stream.concat(Stream.of(userFilter.getFilterQuery()), elements); return elements.collect(Collectors.joining(" AND ")); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQueryUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQueryUserFilter.java index cefe3d02c..007159f8b 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQueryUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/SearchQueryUserFilter.java @@ -9,9 +9,15 @@ public interface SearchQueryUserFilter String AUTHORIZATION_ROLE_VALUE_REMOTE = "REMOTE"; String AUTHORIZATION_ROLE_VALUE_LOCAL = "LOCAL"; + /** + * @return not <code>null</code>, empty {@link String} if resources should not be filtered + */ String getFilterQuery(); + /** + * @return >= 0, 0 if {@link #getFilterQuery()} returns empty {@link String} + */ int getSqlParameterCount(); - + void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException; } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointOrganization.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointOrganization.java index 2987bf942..3f9abf018 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointOrganization.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointOrganization.java @@ -28,7 +28,7 @@ public class EndpointOrganization extends AbstractReferenceParameter<Endpoint> public static final String PARAMETER_NAME = "organization"; private static final String TARGET_RESOURCE_TYPE_NAME = "Organization"; - private static final String ORGANIZATION_IDENTIFIERS_SUBQUERY = "(SELECT organization->'identifier' FROM current_organizations" + private static final String IDENTIFIERS_SUBQUERY = "(SELECT organization->'identifier' FROM current_organizations" + " WHERE concat('Organization/', organization->>'id') = endpoint->'managingOrganization'->>'reference')"; public EndpointOrganization() @@ -52,9 +52,9 @@ public String getFilterQuery() case CODE: case CODE_AND_SYSTEM: case SYSTEM: - return ORGANIZATION_IDENTIFIERS_SUBQUERY + " @> ?::jsonb"; + return IDENTIFIERS_SUBQUERY + " @> ?::jsonb"; case CODE_AND_NO_SYSTEM_PROPERTY: - return "(SELECT count(*) FROM jsonb_array_elements(" + ORGANIZATION_IDENTIFIERS_SUBQUERY + return "(SELECT count(*) FROM jsonb_array_elements(" + IDENTIFIERS_SUBQUERY + ") identifier WHERE identifier->>'value' = ? AND NOT (identifier ?? 'system')) > 0"; } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PractitionerRoleOrganization.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PractitionerRoleOrganization.java new file mode 100644 index 000000000..1cab775c0 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PractitionerRoleOrganization.java @@ -0,0 +1,196 @@ +package org.highmed.dsf.fhir.search.parameters; + +import java.sql.Array; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.UUID; + +import org.highmed.dsf.fhir.dao.OrganizationDao; +import org.highmed.dsf.fhir.dao.exception.ResourceDeletedException; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.function.BiFunctionWithSqlException; +import org.highmed.dsf.fhir.search.IncludeParts; +import org.highmed.dsf.fhir.search.SearchQueryParameter.SearchParameterDefinition; +import org.highmed.dsf.fhir.search.parameters.basic.AbstractIdentifierParameter; +import org.highmed.dsf.fhir.search.parameters.basic.AbstractReferenceParameter; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.r4.model.Enumerations.SearchParamType; +import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.PractitionerRole; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.Resource; + +@SearchParameterDefinition(name = PractitionerRoleOrganization.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/PractitionerRole-organization", type = SearchParamType.REFERENCE, documentation = "The identity of the organization the practitioner represents / acts on behalf of") +public class PractitionerRoleOrganization extends AbstractReferenceParameter<PractitionerRole> +{ + private static final String RESOURCE_TYPE_NAME = "PractitionerRole"; + public static final String PARAMETER_NAME = "organization"; + private static final String TARGET_RESOURCE_TYPE_NAME = "Organization"; + + private static final String PRACTITIONER_IDENTIFIERS_SUBQUERY = "(SELECT organization->'identifier' FROM current_organizations" + + " WHERE concat('Organization/', organization->>'id') = practitioner_role->'organization'->>'reference')"; + + public PractitionerRoleOrganization() + { + super(PractitionerRole.class, RESOURCE_TYPE_NAME, PARAMETER_NAME, TARGET_RESOURCE_TYPE_NAME); + } + + @Override + public String getFilterQuery() + { + switch (valueAndType.type) + { + case ID: + case RESOURCE_NAME_AND_ID: + case URL: + return "practitioner_role->'organization'->>'reference' = ?"; + case IDENTIFIER: + { + switch (valueAndType.identifier.type) + { + case CODE: + case CODE_AND_SYSTEM: + case SYSTEM: + return PRACTITIONER_IDENTIFIERS_SUBQUERY + " @> ?::jsonb"; + case CODE_AND_NO_SYSTEM_PROPERTY: + return "(SELECT count(*) FROM jsonb_array_elements(" + PRACTITIONER_IDENTIFIERS_SUBQUERY + + ") identifier WHERE identifier->>'value' = ? AND NOT (identifier ?? 'system')) > 0"; + } + } + } + + return ""; + } + + @Override + public int getSqlParameterCount() + { + return 1; + } + + @Override + public void modifyStatement(int parameterIndex, int subqueryParameterIndex, PreparedStatement statement, + BiFunctionWithSqlException<String, Object[], Array> arrayCreator) throws SQLException + { + switch (valueAndType.type) + { + case ID: + statement.setString(parameterIndex, TARGET_RESOURCE_TYPE_NAME + "/" + valueAndType.id); + break; + case RESOURCE_NAME_AND_ID: + statement.setString(parameterIndex, valueAndType.resourceName + "/" + valueAndType.id); + break; + case URL: + statement.setString(parameterIndex, valueAndType.url); + break; + case IDENTIFIER: + { + switch (valueAndType.identifier.type) + { + case CODE: + statement.setString(parameterIndex, + "[{\"value\": \"" + valueAndType.identifier.codeValue + "\"}]"); + break; + case CODE_AND_SYSTEM: + statement.setString(parameterIndex, "[{\"value\": \"" + valueAndType.identifier.codeValue + + "\", \"system\": \"" + valueAndType.identifier.systemValue + "\"}]"); + break; + case CODE_AND_NO_SYSTEM_PROPERTY: + statement.setString(parameterIndex, valueAndType.identifier.codeValue); + break; + case SYSTEM: + statement.setString(parameterIndex, + "[{\"system\": \"" + valueAndType.identifier.systemValue + "\"}]"); + break; + } + } + } + } + + @Override + protected void doResolveReferencesForMatching(PractitionerRole resource, DaoProvider daoProvider) + throws SQLException + { + OrganizationDao dao = daoProvider.getOrganizationDao(); + Reference reference = resource.getOrganization(); + IIdType idType = reference.getReferenceElement(); + + if (idType.hasVersionIdPart()) + { + dao.readVersion(UUID.fromString(idType.getIdPart()), idType.getVersionIdPartAsLong()) + .ifPresent(reference::setResource); + } + else + { + try + { + dao.read(UUID.fromString(idType.getIdPart())).ifPresent(reference::setResource); + } + catch (ResourceDeletedException e) + { + // ignore while matching, will result in a non match if this would have been the matching resource + } + } + } + + @Override + public boolean matches(Resource resource) + { + if (!isDefined()) + throw notDefined(); + + if (!(resource instanceof PractitionerRole)) + return false; + + PractitionerRole pR = (PractitionerRole) resource; + + if (ReferenceSearchType.IDENTIFIER.equals(valueAndType.type)) + { + if (pR.getOrganization().getResource() instanceof Organization) + { + Organization o = (Organization) pR.getOrganization().getResource(); + return o.getIdentifier().stream() + .anyMatch(i -> AbstractIdentifierParameter.identifierMatches(valueAndType.identifier, i)); + } + else + return false; + } + else + { + String ref = pR.getOrganization().getReference(); + switch (valueAndType.type) + { + case ID: + return ref.equals(TARGET_RESOURCE_TYPE_NAME + "/" + valueAndType.id); + case RESOURCE_NAME_AND_ID: + return ref.equals(valueAndType.resourceName + "/" + valueAndType.id); + case URL: + return ref.equals(valueAndType.url); + default: + return false; + } + } + } + + @Override + protected String getSortSql(String sortDirectionWithSpacePrefix) + { + return "practitioner_role->'organization'->>'reference'"; + } + + @Override + protected String getIncludeSql(IncludeParts includeParts) + { + if (includeParts.matches(RESOURCE_TYPE_NAME, PARAMETER_NAME, TARGET_RESOURCE_TYPE_NAME)) + return "(SELECT jsonb_build_array(organization) FROM current_organizations WHERE concat('Organization/', organization->>'id') = practitioner_role->'organization'->>'reference') AS organizations"; + else + return null; + } + + @Override + protected void modifyIncludeResource(IncludeParts includeParts, Resource resource, Connection connection) + { + // Nothing to do for organizations + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PractitionerRolePractitioner.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PractitionerRolePractitioner.java new file mode 100644 index 000000000..468fa775a --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PractitionerRolePractitioner.java @@ -0,0 +1,196 @@ +package org.highmed.dsf.fhir.search.parameters; + +import java.sql.Array; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.UUID; + +import org.highmed.dsf.fhir.dao.PractitionerDao; +import org.highmed.dsf.fhir.dao.exception.ResourceDeletedException; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.function.BiFunctionWithSqlException; +import org.highmed.dsf.fhir.search.IncludeParts; +import org.highmed.dsf.fhir.search.SearchQueryParameter.SearchParameterDefinition; +import org.highmed.dsf.fhir.search.parameters.basic.AbstractIdentifierParameter; +import org.highmed.dsf.fhir.search.parameters.basic.AbstractReferenceParameter; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.r4.model.Enumerations.SearchParamType; +import org.hl7.fhir.r4.model.Practitioner; +import org.hl7.fhir.r4.model.PractitionerRole; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.Resource; + +@SearchParameterDefinition(name = PractitionerRolePractitioner.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/PractitionerRole-practitioner", type = SearchParamType.REFERENCE, documentation = "Practitioner that is able to provide the defined services for the organization") +public class PractitionerRolePractitioner extends AbstractReferenceParameter<PractitionerRole> +{ + private static final String RESOURCE_TYPE_NAME = "PractitionerRole"; + public static final String PARAMETER_NAME = "practitioner"; + private static final String TARGET_RESOURCE_TYPE_NAME = "Practitioner"; + + private static final String PRACTITIONER_IDENTIFIERS_SUBQUERY = "(SELECT practitioner->'identifier' FROM current_practitioners" + + " WHERE concat('Practitioner/', practitioner->>'id') = practitioner_role->'practitioner'->>'reference')"; + + public PractitionerRolePractitioner() + { + super(PractitionerRole.class, RESOURCE_TYPE_NAME, PARAMETER_NAME, TARGET_RESOURCE_TYPE_NAME); + } + + @Override + public String getFilterQuery() + { + switch (valueAndType.type) + { + case ID: + case RESOURCE_NAME_AND_ID: + case URL: + return "practitioner_role->'practitioner'->>'reference' = ?"; + case IDENTIFIER: + { + switch (valueAndType.identifier.type) + { + case CODE: + case CODE_AND_SYSTEM: + case SYSTEM: + return PRACTITIONER_IDENTIFIERS_SUBQUERY + " @> ?::jsonb"; + case CODE_AND_NO_SYSTEM_PROPERTY: + return "(SELECT count(*) FROM jsonb_array_elements(" + PRACTITIONER_IDENTIFIERS_SUBQUERY + + ") identifier WHERE identifier->>'value' = ? AND NOT (identifier ?? 'system')) > 0"; + } + } + } + + return ""; + } + + @Override + public int getSqlParameterCount() + { + return 1; + } + + @Override + public void modifyStatement(int parameterIndex, int subqueryParameterIndex, PreparedStatement statement, + BiFunctionWithSqlException<String, Object[], Array> arrayCreator) throws SQLException + { + switch (valueAndType.type) + { + case ID: + statement.setString(parameterIndex, TARGET_RESOURCE_TYPE_NAME + "/" + valueAndType.id); + break; + case RESOURCE_NAME_AND_ID: + statement.setString(parameterIndex, valueAndType.resourceName + "/" + valueAndType.id); + break; + case URL: + statement.setString(parameterIndex, valueAndType.url); + break; + case IDENTIFIER: + { + switch (valueAndType.identifier.type) + { + case CODE: + statement.setString(parameterIndex, + "[{\"value\": \"" + valueAndType.identifier.codeValue + "\"}]"); + break; + case CODE_AND_SYSTEM: + statement.setString(parameterIndex, "[{\"value\": \"" + valueAndType.identifier.codeValue + + "\", \"system\": \"" + valueAndType.identifier.systemValue + "\"}]"); + break; + case CODE_AND_NO_SYSTEM_PROPERTY: + statement.setString(parameterIndex, valueAndType.identifier.codeValue); + break; + case SYSTEM: + statement.setString(parameterIndex, + "[{\"system\": \"" + valueAndType.identifier.systemValue + "\"}]"); + break; + } + } + } + } + + @Override + protected void doResolveReferencesForMatching(PractitionerRole resource, DaoProvider daoProvider) + throws SQLException + { + PractitionerDao dao = daoProvider.getPractitionerDao(); + Reference reference = resource.getPractitioner(); + IIdType idType = reference.getReferenceElement(); + + if (idType.hasVersionIdPart()) + { + dao.readVersion(UUID.fromString(idType.getIdPart()), idType.getVersionIdPartAsLong()) + .ifPresent(reference::setResource); + } + else + { + try + { + dao.read(UUID.fromString(idType.getIdPart())).ifPresent(reference::setResource); + } + catch (ResourceDeletedException e) + { + // ignore while matching, will result in a non match if this would have been the matching resource + } + } + } + + @Override + public boolean matches(Resource resource) + { + if (!isDefined()) + throw notDefined(); + + if (!(resource instanceof PractitionerRole)) + return false; + + PractitionerRole pR = (PractitionerRole) resource; + + if (ReferenceSearchType.IDENTIFIER.equals(valueAndType.type)) + { + if (pR.getPractitioner().getResource() instanceof Practitioner) + { + Practitioner p = (Practitioner) pR.getPractitioner().getResource(); + return p.getIdentifier().stream() + .anyMatch(i -> AbstractIdentifierParameter.identifierMatches(valueAndType.identifier, i)); + } + else + return false; + } + else + { + String ref = pR.getPractitioner().getReference(); + switch (valueAndType.type) + { + case ID: + return ref.equals(TARGET_RESOURCE_TYPE_NAME + "/" + valueAndType.id); + case RESOURCE_NAME_AND_ID: + return ref.equals(valueAndType.resourceName + "/" + valueAndType.id); + case URL: + return ref.equals(valueAndType.url); + default: + return false; + } + } + } + + @Override + protected String getSortSql(String sortDirectionWithSpacePrefix) + { + return "practitioner_role->'practitioner'->>'reference'"; + } + + @Override + protected String getIncludeSql(IncludeParts includeParts) + { + if (includeParts.matches(RESOURCE_TYPE_NAME, PARAMETER_NAME, TARGET_RESOURCE_TYPE_NAME)) + return "(SELECT jsonb_build_array(practitioner) FROM current_practitioners WHERE concat('Practitioner/', practitioner->>'id') = practitioner_role->'practitioner'->>'reference') AS practitioners"; + else + return null; + } + + @Override + protected void modifyIncludeResource(IncludeParts includeParts, Resource resource, Connection connection) + { + // Nothing to do for practitioners + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ResearchStudyPrincipalInvestigator.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ResearchStudyPrincipalInvestigator.java new file mode 100644 index 000000000..a9a5c109d --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ResearchStudyPrincipalInvestigator.java @@ -0,0 +1,230 @@ +package org.highmed.dsf.fhir.search.parameters; + +import java.sql.Array; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.UUID; + +import org.highmed.dsf.fhir.dao.ResourceDao; +import org.highmed.dsf.fhir.dao.exception.ResourceDeletedException; +import org.highmed.dsf.fhir.dao.provider.DaoProvider; +import org.highmed.dsf.fhir.function.BiFunctionWithSqlException; +import org.highmed.dsf.fhir.search.IncludeParts; +import org.highmed.dsf.fhir.search.SearchQueryParameter.SearchParameterDefinition; +import org.highmed.dsf.fhir.search.parameters.basic.AbstractIdentifierParameter; +import org.highmed.dsf.fhir.search.parameters.basic.AbstractReferenceParameter; +import org.hl7.fhir.instance.model.api.IIdType; +import org.hl7.fhir.r4.model.Enumerations.SearchParamType; +import org.hl7.fhir.r4.model.Practitioner; +import org.hl7.fhir.r4.model.PractitionerRole; +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ResearchStudy; +import org.hl7.fhir.r4.model.Resource; + +@SearchParameterDefinition(name = ResearchStudyPrincipalInvestigator.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ResearchStudy-principalinvestigator", type = SearchParamType.REFERENCE, documentation = "Researcher who oversees multiple aspects of the study") +public class ResearchStudyPrincipalInvestigator extends AbstractReferenceParameter<ResearchStudy> +{ + private static final String RESOURCE_TYPE_NAME = "ResearchStudy"; + public static final String PARAMETER_NAME = "principalinvestigator"; + private static final String[] TARGET_RESOURCE_TYPE_NAMES = { "Practitioner", "PractitionerRole" }; + + private static final String IDENTIFIERS_SUBQUERY = "(SELECT practitioner->'identifier' FROM current_practitioners " + + "WHERE concat('Practitioner/', practitioner->>'id') = research_study->'principalInvestigator'->>'reference' " + + "UNION SELECT practitioner_role->'identifier' FROM current_practitioner_roles " + + "WHERE concat('PractitionerRole/', practitioner_role->>'id') = research_study->'principalInvestigator'->>'reference')"; + + public ResearchStudyPrincipalInvestigator() + { + super(ResearchStudy.class, RESOURCE_TYPE_NAME, PARAMETER_NAME, TARGET_RESOURCE_TYPE_NAMES); + } + + @Override + public String getFilterQuery() + { + switch (valueAndType.type) + { + case ID: + return "research_study->'principalInvestigator'->>'reference' IN ?"; + case RESOURCE_NAME_AND_ID: + case URL: + return "research_study->'principalInvestigator'->>'reference' = ?"; + case IDENTIFIER: + { + switch (valueAndType.identifier.type) + { + case CODE: + case CODE_AND_SYSTEM: + case SYSTEM: + return IDENTIFIERS_SUBQUERY + " @> ?::jsonb"; + case CODE_AND_NO_SYSTEM_PROPERTY: + return "(SELECT count(*) FROM jsonb_array_elements(" + IDENTIFIERS_SUBQUERY + + ") identifier WHERE identifier->>'value' = ? AND NOT (identifier ?? 'system')) > 0"; + } + } + } + + return ""; + } + + @Override + public int getSqlParameterCount() + { + return 1; + } + + @Override + public void modifyStatement(int parameterIndex, int subqueryParameterIndex, PreparedStatement statement, + BiFunctionWithSqlException<String, Object[], Array> arrayCreator) throws SQLException + { + switch (valueAndType.type) + { + case ID: + statement.setString(parameterIndex, TARGET_RESOURCE_TYPE_NAMES + "/" + valueAndType.id); + break; + case RESOURCE_NAME_AND_ID: + statement.setString(parameterIndex, valueAndType.resourceName + "/" + valueAndType.id); + break; + case URL: + statement.setString(parameterIndex, valueAndType.url); + break; + case IDENTIFIER: + { + switch (valueAndType.identifier.type) + { + case CODE: + statement.setString(parameterIndex, + "[{\"value\": \"" + valueAndType.identifier.codeValue + "\"}]"); + break; + case CODE_AND_SYSTEM: + statement.setString(parameterIndex, "[{\"value\": \"" + valueAndType.identifier.codeValue + + "\", \"system\": \"" + valueAndType.identifier.systemValue + "\"}]"); + break; + case CODE_AND_NO_SYSTEM_PROPERTY: + statement.setString(parameterIndex, valueAndType.identifier.codeValue); + break; + case SYSTEM: + statement.setString(parameterIndex, + "[{\"system\": \"" + valueAndType.identifier.systemValue + "\"}]"); + break; + } + } + } + } + + @Override + protected void doResolveReferencesForMatching(ResearchStudy resource, DaoProvider daoProvider) throws SQLException + { + Reference reference = resource.getPrincipalInvestigator(); + IIdType idType = reference.getReferenceElement(); + + if (idType.hasResourceType()) + { + if ("Practitioner".equals(idType.getResourceType())) + setResource(reference, idType, daoProvider.getPractitionerDao()); + else if ("PractitionerRole".equals(idType.getResourceType())) + setResource(reference, idType, daoProvider.getPractitionerRoleDao()); + } + } + + private void setResource(Reference reference, IIdType idType, ResourceDao<?> dao) throws SQLException + { + if (idType.hasVersionIdPart()) + { + dao.readVersion(UUID.fromString(idType.getIdPart()), idType.getVersionIdPartAsLong()) + .ifPresent(reference::setResource); + } + else + { + try + { + dao.read(UUID.fromString(idType.getIdPart())).ifPresent(reference::setResource); + } + catch (ResourceDeletedException e) + { + // ignore while matching, will result in a non match if this would have been the matching resource + } + } + } + + @Override + public boolean matches(Resource resource) + { + if (!isDefined()) + throw notDefined(); + + if (!(resource instanceof ResearchStudy)) + return false; + + ResearchStudy r = (ResearchStudy) resource; + + if (ReferenceSearchType.IDENTIFIER.equals(valueAndType.type)) + { + if (r.getPrincipalInvestigator().getResource() instanceof Practitioner) + { + Practitioner p = (Practitioner) r.getPrincipalInvestigator().getResource(); + return p.getIdentifier().stream() + .anyMatch(i -> AbstractIdentifierParameter.identifierMatches(valueAndType.identifier, i)); + } + else if (r.getPrincipalInvestigator().getResource() instanceof PractitionerRole) + { + PractitionerRole p = (PractitionerRole) r.getPrincipalInvestigator().getResource(); + return p.getIdentifier().stream() + .anyMatch(i -> AbstractIdentifierParameter.identifierMatches(valueAndType.identifier, i)); + } + else + return false; + } + else + { + String ref = r.getPrincipalInvestigator().getReference(); + switch (valueAndType.type) + { + case ID: + return ref.equals("Practitioner" + "/" + valueAndType.id) + || ref.equals("PractitionerRole" + "/" + valueAndType.id); + case RESOURCE_NAME_AND_ID: + return ref.equals(valueAndType.resourceName + "/" + valueAndType.id); + case URL: + return ref.equals(valueAndType.url); + default: + return false; + } + } + } + + @Override + protected String getSortSql(String sortDirectionWithSpacePrefix) + { + return "research_study->'principalInvestigator'->>'reference'"; + } + + @Override + protected String getIncludeSql(IncludeParts includeParts) + { + if (RESOURCE_TYPE_NAME.equals(includeParts.getSourceResourceTypeName()) + && PARAMETER_NAME.equals(includeParts.getSearchParameterName()) + && Arrays.stream(TARGET_RESOURCE_TYPE_NAMES) + .anyMatch(n -> n.equals(includeParts.getTargetResourceTypeName()))) + switch (includeParts.getTargetResourceTypeName()) + { + case "Practitioner": + return "(SELECT jsonb_build_array(practitioner) FROM current_practitioners" + + " WHERE concat('Practitioner/', practitioner->>'id') = research_study->'principalInvestigator'->>'reference') AS practitioners"; + case "PractitionerRole": + return "(SELECT jsonb_build_array(practitioner_role) FROM current_practitioner_roles" + + " WHERE concat('PractitionerRole/', practitioner_role->>'id') = research_study->'principalInvestigator'->>'reference') AS practitioner_roles"; + default: + return null; + } + else + return null; + } + + @Override + protected void modifyIncludeResource(IncludeParts includeParts, Resource resource, Connection connection) + { + // Nothing to do for practitioners + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/TaskRequester.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/TaskRequester.java index a9d9a616c..a2ea2caab 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/TaskRequester.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/TaskRequester.java @@ -35,14 +35,14 @@ public class TaskRequester extends AbstractReferenceParameter<Task> "PractitionerRole" }; // TODO add Device, RelatedPerson if supported, see also doResolveReferencesForMatching, matches, getIncludeSql - private static final String ORGANIZATION_IDENTIFIERS_SUBQUERY = "(SELECT practitioner->'identifier' FROM current_practitioners" - + " WHERE concat('Practitioner/', practitioner->>'id') = task->'requester'->>'reference' " - + " UNION SELECT organization->'identifier' FROM current_organizations" - + " WHERE concat('Organization/', organization->>'id') = task->'requester'->>'reference' " - + " UNION SELECT patient->'identifier' FROM current_patients" - + " WHERE concat('Patient/', patient->>'id') = task->'requester'->>'reference' " - + " UNION SELECT practitioner_role->'identifier' FROM current_practitioner_roles" - + " WHERE concat('PractitionerRole/', practitioner_role->>'id') = task->'requester'->>'reference')"; + private static final String IDENTIFIERS_SUBQUERY = "(SELECT practitioner->'identifier' FROM current_practitioners " + + "WHERE concat('Practitioner/', practitioner->>'id') = task->'requester'->>'reference' " + + "UNION SELECT organization->'identifier' FROM current_organizations " + + "WHERE concat('Organization/', organization->>'id') = task->'requester'->>'reference' " + + "UNION SELECT patient->'identifier' FROM current_patients " + + "WHERE concat('Patient/', patient->>'id') = task->'requester'->>'reference' " + + "UNION SELECT practitioner_role->'identifier' FROM current_practitioner_roles " + + "WHERE concat('PractitionerRole/', practitioner_role->>'id') = task->'requester'->>'reference')"; public TaskRequester() { @@ -66,9 +66,9 @@ public String getFilterQuery() case CODE: case CODE_AND_SYSTEM: case SYSTEM: - return ORGANIZATION_IDENTIFIERS_SUBQUERY + " @> ?::jsonb"; + return IDENTIFIERS_SUBQUERY + " @> ?::jsonb"; case CODE_AND_NO_SYSTEM_PROPERTY: - return "(SELECT count(*) FROM jsonb_array_elements(" + ORGANIZATION_IDENTIFIERS_SUBQUERY + return "(SELECT count(*) FROM jsonb_array_elements(" + IDENTIFIERS_SUBQUERY + ") identifier WHERE identifier->>'value' = ? AND NOT (identifier ?? 'system')) > 0"; } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerRoleUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerRoleUserFilter.java index b8a22499a..fb2e03dc0 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerRoleUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerRoleUserFilter.java @@ -4,13 +4,10 @@ import java.sql.SQLException; import org.highmed.dsf.fhir.authentication.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.highmed.dsf.fhir.authentication.UserRole; public class PractitionerRoleUserFilter extends AbstractUserFilter { - private static final Logger logger = LoggerFactory.getLogger(PractitionerRoleUserFilter.class); - public PractitionerRoleUserFilter(User user) { super(user); @@ -19,24 +16,57 @@ public PractitionerRoleUserFilter(User user) @Override public String getFilterQuery() { - // TODO implement - - logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); - return "false"; + if (UserRole.LOCAL.equals(user.getRole())) + return ""; + else + // user part of PractitionerRoles Organization or + // PractitionerRoles Practitioner part of ResearchStudy as principal investigator and + // users Organization part of ResearchStudy + return "(practitioner_role->'organization'->>'reference' = ? OR practitioner_role->'organization'->>'reference' = ? OR " + + "practitioner_role->'practitioner'->>'reference' IN (SELECT research_study->'principalInvestigator'->>'reference' FROM " + + "current_research_studies WHERE current_research_studies WHERE research_study->'extension' @> ?::jsonb OR research_study->'extension' @> ?::jsonb))"; } @Override public int getSqlParameterCount() { - logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); - return 0; + return UserRole.LOCAL.equals(user.getRole()) ? 0 : 4; } @Override public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException { - // TODO implement + if (!UserRole.LOCAL.equals(user.getRole())) + { + if (parameterIndex == 1) + statement.setString(parameterIndex, user.getOrganization().getIdElement().getValue()); + else if (parameterIndex == 2) + statement.setString(parameterIndex, user.getOrganization().getIdElement().toVersionless().getValue()); - logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + switch (user.getOrganizationType()) + { + case MeDIC: + if (parameterIndex == 3) + statement.setString(parameterIndex, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-medic\",\"valueReference\":{\"reference\":\"" + + user.getOrganization().getIdElement().getValue() + "\"}}]"); + else if (parameterIndex == 4) + statement.setString(parameterIndex, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-medic\",\"valueReference\":{\"reference\":\"" + + user.getOrganization().getIdElement().toVersionless().getValue() + "\"}}]"); + break; + + case TTP: + if (parameterIndex == 3) + statement.setString(parameterIndex, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-ttp\",\"valueReference\":{\"reference\":\"" + + user.getOrganization().getIdElement().getValue() + "\"}}]"); + else if (parameterIndex == 4) + statement.setString(parameterIndex, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-ttp\",\"valueReference\":{\"reference\":\"" + + user.getOrganization().getIdElement().toVersionless().getValue() + "\"}}]"); + break; + } + } } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerUserFilter.java index 7547e51a1..537c30749 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerUserFilter.java @@ -4,13 +4,10 @@ import java.sql.SQLException; import org.highmed.dsf.fhir.authentication.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.highmed.dsf.fhir.authentication.UserRole; public class PractitionerUserFilter extends AbstractUserFilter { - private static final Logger logger = LoggerFactory.getLogger(PractitionerUserFilter.class); - public PractitionerUserFilter(User user) { super(user); @@ -19,24 +16,60 @@ public PractitionerUserFilter(User user) @Override public String getFilterQuery() { - // TODO implement - - logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); - return "false"; + if (UserRole.LOCAL.equals(user.getRole())) + return ""; + else + // Practitioner part of ResearchStudy as principal investigator and users Organization part of same + // ResearchStudy or + // Practitioner part of PractitionerRole and users Organization part of same PractitionerRole + return "(concat('Practitioner/', practitioner->>'id') IN (" + + "SELECT research_study->'principalInvestigator'->>'reference' FROM current_research_studies WHERE " + + "research_study->'extension' @> ?::jsonb OR research_study->'extension' @> ?::jsonb) OR " + + "concat('Practitioner/', practitioner->>'id') IN (" + + "SELECT practitioner_role->'practitioner'->>'reference' FROM current_practitioner_roles WHERE " + + "practitioner_role->'organization'->>'reference' = ? OR practitioner_role->'organization'->>'reference' = ?))"; } @Override public int getSqlParameterCount() { - logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); - return 0; + return UserRole.LOCAL.equals(user.getRole()) ? 0 : 4; } @Override public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException { - // TODO implement + if (!UserRole.LOCAL.equals(user.getRole())) + { + switch (user.getOrganizationType()) + { + case MeDIC: + if (parameterIndex == 1) + statement.setString(parameterIndex, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-medic\",\"valueReference\":{\"reference\":\"" + + user.getOrganization().getIdElement().getValue() + "\"}}]"); + else if (parameterIndex == 2) + statement.setString(parameterIndex, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-medic\",\"valueReference\":{\"reference\":\"" + + user.getOrganization().getIdElement().toVersionless().getValue() + "\"}}]"); + break; + + case TTP: + if (parameterIndex == 1) + statement.setString(parameterIndex, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-ttp\",\"valueReference\":{\"reference\":\"" + + user.getOrganization().getIdElement().getValue() + "\"}}]"); + else if (parameterIndex == 2) + statement.setString(parameterIndex, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-ttp\",\"valueReference\":{\"reference\":\"" + + user.getOrganization().getIdElement().toVersionless().getValue() + "\"}}]"); + break; + } - logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + if (parameterIndex == 3) + statement.setString(parameterIndex, user.getOrganization().getIdElement().getValue()); + else if (parameterIndex == 4) + statement.setString(parameterIndex, user.getOrganization().getIdElement().toVersionless().getValue()); + } } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ResearchStudyUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ResearchStudyUserFilter.java index fa212ed28..90683814d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ResearchStudyUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ResearchStudyUserFilter.java @@ -4,13 +4,10 @@ import java.sql.SQLException; import org.highmed.dsf.fhir.authentication.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.highmed.dsf.fhir.authentication.UserRole; public class ResearchStudyUserFilter extends AbstractUserFilter { - private static final Logger logger = LoggerFactory.getLogger(ResearchStudyUserFilter.class); - public ResearchStudyUserFilter(User user) { super(user); @@ -19,24 +16,47 @@ public ResearchStudyUserFilter(User user) @Override public String getFilterQuery() { - // TODO implement - - logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); - return "false"; + if (UserRole.LOCAL.equals(user.getRole())) + return ""; + else + return "(research_study->'extension' @> ?::jsonb OR research_study->'extension' @> ?::jsonb)"; } @Override public int getSqlParameterCount() { - logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); - return 0; + return UserRole.LOCAL.equals(user.getRole()) ? 0 : 2; } @Override public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException { - // TODO implement - - logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + if (!UserRole.LOCAL.equals(user.getRole())) + { + switch (user.getOrganizationType()) + { + case MeDIC: + if (parameterIndex == 1) + statement.setString(parameterIndex, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-medic\",\"valueReference\":{\"reference\":\"" + + user.getOrganization().getIdElement().getValue() + "\"}}]"); + else if (parameterIndex == 2) + statement.setString(parameterIndex, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-medic\",\"valueReference\":{\"reference\":\"" + + user.getOrganization().getIdElement().toVersionless().getValue() + "\"}}]"); + break; + + case TTP: + if (parameterIndex == 1) + statement.setString(parameterIndex, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-ttp\",\"valueReference\":{\"reference\":\"" + + user.getOrganization().getIdElement().getValue() + "\"}}]"); + else if (parameterIndex == 2) + statement.setString(parameterIndex, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-ttp\",\"valueReference\":{\"reference\":\"" + + user.getOrganization().getIdElement().toVersionless().getValue() + "\"}}]"); + break; + } + } } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java index 1e2f13cb2..2a2f029ce 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java @@ -48,8 +48,11 @@ import org.highmed.dsf.fhir.search.parameters.PractitionerIdentifier; import org.highmed.dsf.fhir.search.parameters.PractitionerRoleActive; import org.highmed.dsf.fhir.search.parameters.PractitionerRoleIdentifier; +import org.highmed.dsf.fhir.search.parameters.PractitionerRoleOrganization; +import org.highmed.dsf.fhir.search.parameters.PractitionerRolePractitioner; import org.highmed.dsf.fhir.search.parameters.ResearchStudyEnrollment; import org.highmed.dsf.fhir.search.parameters.ResearchStudyIdentifier; +import org.highmed.dsf.fhir.search.parameters.ResearchStudyPrincipalInvestigator; import org.highmed.dsf.fhir.search.parameters.ResourceId; import org.highmed.dsf.fhir.search.parameters.ResourceLastUpdated; import org.highmed.dsf.fhir.search.parameters.StructureDefinitionIdentifier; @@ -265,11 +268,16 @@ private CapabilityStatement createCapabilityStatement(String serverBase, int def var practitionerRoleActive = createSearchParameter(PractitionerRoleActive.class); var practitionerRoleIdentifier = createSearchParameter(PractitionerRoleIdentifier.class); - searchParameters.put(PractitionerRole.class, Arrays.asList(practitionerRoleActive, practitionerRoleIdentifier)); + var practitionerRoleOrganization = createSearchParameter(PractitionerRoleOrganization.class); + var practitionerRolePractitioner = createSearchParameter(PractitionerRolePractitioner.class); + searchParameters.put(PractitionerRole.class, Arrays.asList(practitionerRoleActive, practitionerRoleIdentifier, + practitionerRoleOrganization, practitionerRolePractitioner)); var researchStudyIdentifier = createSearchParameter(ResearchStudyIdentifier.class); var researchStudyEnrollment = createSearchParameter(ResearchStudyEnrollment.class); - searchParameters.put(ResearchStudy.class, Arrays.asList(researchStudyIdentifier, researchStudyEnrollment)); + var researchStudyPrincipalInvestigator = createSearchParameter(ResearchStudyPrincipalInvestigator.class); + searchParameters.put(ResearchStudy.class, + Arrays.asList(researchStudyIdentifier, researchStudyEnrollment, researchStudyPrincipalInvestigator)); var structureDefinitionIdentifier = createSearchParameter(StructureDefinitionIdentifier.class); var structureDefinitionStatus = createSearchParameter(StructureDefinitionStatus.class); diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-research-study.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-research-study.xml new file mode 100644 index 000000000..2660b1ec2 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-research-study.xml @@ -0,0 +1,22 @@ +<NamingSystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://hl7.org/fhir" + xsi:schemaLocation="http://hl7.org/fhir http://www.hl7.org/fhir/fhir-base.xsd"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> + <name value="HiGHmed_ResearchStudy_Identifier"/> + <status value="active"/> + <kind value="identifier"/> + <date value="2015-08-31"/> + <publisher value="HiGHmed"/> + <responsible value="HiGHmed"/> + <description + value="UUID used to identify a ResearchStudy"/> + <usage value="Used withing HiGHmed to identify research studies"/> + <uniqueId> + <type value="uuid"/> + <value value="http://highmed.org/fhir/NamingSystem/research-study-identifier"/> + </uniqueId> +</NamingSystem> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-research-study.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-research-study.xml.put new file mode 100644 index 000000000..701aa10b9 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/NamingSystem/highmed-research-study.xml.put @@ -0,0 +1 @@ +NamingSystem?name=HiGHmed_ResearchStudy_Identifier \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-medic-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-medic-0.1.0.xml index f37f0d554..d214997da 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-medic-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-medic-0.1.0.xml @@ -1,46 +1,44 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> - <meta> - <tag> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> - <code value="REMOTE"/> - </tag> - </meta> - <url value="http://highmed.org/fhir/StructureDefinition/participating-medic"/> - <version value="0.1.0"/> - <name value="ParticipatingMedic"/> - <status value="draft"/> - <date value="2019-08-05"/> - <fhirVersion value="4.0.0"/> - <kind value="complex-type"/> - <abstract value="false"/> - <context> - <type value="element"/> - <expression value="ResearchStudy"/> - </context> - <type value="Extension"/> - <baseDefinition value="http://hl7.org/fhir/StructureDefinition/Extension"/> - <derivation value="constraint"/> - <differential> - <element id="Extension"> - <path value="Extension"/> - <short value="ParticipatingMedic"/> - <definition - value="Used to denote the medic organizations that are requested to supply data for the study at hand."/> - </element> - <element id="Extension.value[x]"> - <path value="Extension.value[x]"/> - <short value="ParticipatingMedic"/> - <definition - value="Organization reference used to denote the medic organizations that are requested to supply data for the study at hand."/> - <type> - <code value="Reference"/> - <targetProfile value="http://highmed.org/fhir/StructureDefinition/highmed-organization"/> - </type> - </element> - <element id="Extension.value[x].reference"> - <path value="Extension.value[x].reference"/> - <min value="1"/> - </element> - </differential> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/participating-medic" /> + <version value="0.1.0" /> + <name value="ParticipatingMedic" /> + <status value="draft" /> + <date value="2019-08-05" /> + <fhirVersion value="4.0.0" /> + <kind value="complex-type" /> + <abstract value="false" /> + <context> + <type value="element" /> + <expression value="ResearchStudy" /> + </context> + <type value="Extension" /> + <baseDefinition value="http://hl7.org/fhir/StructureDefinition/Extension" /> + <derivation value="constraint" /> + <differential> + <element id="Extension"> + <path value="Extension" /> + <short value="ParticipatingMedic" /> + <definition value="Used to denote the medic organizations that are requested to supply data for the study at hand." /> + </element> + <element id="Extension.url"> + <path value="Extension.url" /> + <fixedUri value="http://highmed.org/fhir/StructureDefinition/participating-medic" /> + </element> + <element id="Extension.value[x]"> + <path value="Extension.value[x]" /> + <short value="ParticipatingMedic" /> + <definition value="Organization reference used to denote the medic organizations that are requested to supply data for the study at hand." /> + <type> + <code value="Reference" /> + <targetProfile value="http://highmed.org/fhir/StructureDefinition/highmed-organization" /> + </type> + </element> + </differential> </StructureDefinition> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-ttp-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-ttp-0.1.0.xml new file mode 100644 index 000000000..fbf697cbd --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-ttp-0.1.0.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<StructureDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/participating-ttp" /> + <version value="0.1.0" /> + <name value="ParticipatingTtp" /> + <status value="draft" /> + <date value="2020-03-04" /> + <fhirVersion value="4.0.0" /> + <kind value="complex-type" /> + <abstract value="false" /> + <context> + <type value="element" /> + <expression value="ResearchStudy" /> + </context> + <type value="Extension" /> + <baseDefinition value="http://hl7.org/fhir/StructureDefinition/Extension" /> + <derivation value="constraint" /> + <differential> + <element id="Extension"> + <path value="Extension" /> + <short value="ParticipatingTtp" /> + <definition value="Used to denote the TTP organization that is used to record link and pseudonymize data." /> + </element> + <element id="Extension.url"> + <path value="Extension.url" /> + <fixedUri value="http://highmed.org/fhir/StructureDefinition/participating-ttp" /> + </element> + <element id="Extension.value[x]"> + <path value="Extension.value[x]" /> + <short value="ParticipatingMedic" /> + <definition value="Organization reference used to denote the TTP organization that is used to record link and pseudonymize data." /> + <type> + <code value="Reference" /> + <targetProfile value="http://highmed.org/fhir/StructureDefinition/highmed-organization" /> + </type> + </element> + </differential> +</StructureDefinition> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-ttp-0.1.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-ttp-0.1.0.xml.put new file mode 100644 index 000000000..e5994fc5f --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-participating-ttp-0.1.0.xml.put @@ -0,0 +1 @@ +StructureDefinition?url=http://highmed.org/fhir/StructureDefinition/participating-ttp&version=0.1.0 \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-research-study-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-research-study-0.1.0.xml index 8eab7dc16..0bd8076c8 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-research-study-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-research-study-0.1.0.xml @@ -1,65 +1,97 @@ <?xml version="1.0" encoding="utf-8"?> <StructureDefinition xmlns="http://hl7.org/fhir"> - <meta> - <tag> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> - <code value="REMOTE"/> - </tag> - </meta> - <url value="http://highmed.org/fhir/StructureDefinition/highmed-research-study"/> - <version value="0.1.0"/> - <name value="ResearchStudy"/> - <status value="draft"/> - <fhirVersion value="4.0.0"/> - <kind value="resource"/> - <abstract value="false"/> - <type value="ResearchStudy"/> - <baseDefinition value="http://hl7.org/fhir/StructureDefinition/ResearchStudy"/> - <derivation value="constraint"/> - <differential> - <element id="ResearchStudy.extension"> - <path value="ResearchStudy.extension"/> - <slicing> - <discriminator> - <type value="value"/> - <path value="url"/> - </discriminator> - <rules value="open"/> - </slicing> - </element> - <element id="ResearchStudy.extension:participatingMedic"> - <path value="ResearchStudy.extension"/> - <sliceName value="participatingMedic"/> - <min value="1"/> - <type> - <code value="Extension"/> - <profile value="http://highmed.org/fhir/StructureDefinition/participating-medic"/> - </type> - </element> - <element id="ResearchStudy.description"> - <path value="ResearchStudy.description"/> - <min value="1"/> - </element> - <element id="ResearchStudy.enrollment"> - <path value="ResearchStudy.enrollment"/> - <min value="1"/> - <type> - <code value="Reference"/> - <targetProfile value="http://highmed.org/fhir/StructureDefinition/highmed-group"/> - </type> - </element> - <element id="ResearchStudy.enrollment.reference"> - <path value="ResearchStudy.enrollment.reference"/> - <min value="1"/> - </element> - <element id="ResearchStudy.principalInvestigator"> - <path value="ResearchStudy.principalInvestigator"/> - <min value="1"/> - <type> - <code value="Reference"/> - <targetProfile value="http://highmed.org/fhir/StructureDefinition/highmed-practitioner"/> - <targetProfile value="http://highmed.org/fhir/StructureDefinition/highmed-practitioner-role"/> - </type> - </element> - </differential> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </tag> + </meta> + <url value="http://highmed.org/fhir/StructureDefinition/highmed-research-study" /> + <version value="0.1.0" /> + <name value="ResearchStudy" /> + <status value="draft" /> + <fhirVersion value="4.0.0" /> + <kind value="resource" /> + <abstract value="false" /> + <type value="ResearchStudy" /> + <baseDefinition value="http://hl7.org/fhir/StructureDefinition/ResearchStudy" /> + <derivation value="constraint" /> + <differential> + <element id="ResearchStudy.extension"> + <path value="ResearchStudy.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> + </element> + <element id="ResearchStudy.extension:participating-ttp"> + <path value="ResearchStudy.extension" /> + <sliceName value="participating-ttp" /> + <min value="1" /> + <max value="1" /> + <type> + <code value="Extension" /> + <profile value="http://highmed.org/fhir/StructureDefinition/participating-ttp" /> + </type> + </element> + <element id="ResearchStudy.extension:participating-medic"> + <path value="ResearchStudy.extension" /> + <sliceName value="participating-medic" /> + <min value="1" /> + <max value="*" /> + <type> + <code value="Extension" /> + <profile value="http://highmed.org/fhir/StructureDefinition/participating-medic" /> + </type> + </element> + <element id="ResearchStudy.identifier"> + <path value="ResearchStudy.identifier" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="system" /> + </discriminator> + <rules value="open" /> + </slicing> + <min value="1" /> + </element> + <element id="ResearchStudy.identifier:highmedIdentifier"> + <path value="ResearchStudy.identifier" /> + <sliceName value="highmedIdentifier" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="ResearchStudy.identifier:highmedIdentifier.system"> + <path value="ResearchStudy.identifier.system" /> + <fixedUri value="http://highmed.org/fhir/NamingSystem/research-study-identifier" /> + </element> + <element id="ResearchStudy.description"> + <path value="ResearchStudy.description" /> + <min value="1" /> + </element> + <element id="ResearchStudy.enrollment"> + <path value="ResearchStudy.enrollment" /> + <min value="1" /> + <type> + <code value="Reference" /> + <targetProfile value="http://highmed.org/fhir/StructureDefinition/highmed-group" /> + </type> + </element> + <element id="ResearchStudy.enrollment.reference"> + <path value="ResearchStudy.enrollment.reference" /> + <min value="1" /> + </element> + <element id="ResearchStudy.principalInvestigator"> + <path value="ResearchStudy.principalInvestigator" /> + <min value="1" /> + <type> + <code value="Reference" /> + <targetProfile value="http://highmed.org/fhir/StructureDefinition/highmed-practitioner" /> + <targetProfile value="http://highmed.org/fhir/StructureDefinition/highmed-practitioner-role" /> + </type> + </element> + </differential> </StructureDefinition> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ResearchStudyDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ResearchStudyDaoTest.java index 6a8ca974a..c50d44f59 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ResearchStudyDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ResearchStudyDaoTest.java @@ -1,19 +1,31 @@ package org.highmed.dsf.fhir.dao; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import java.sql.Connection; import java.util.Date; import java.util.GregorianCalendar; +import java.util.List; +import java.util.UUID; import org.apache.commons.dbcp2.BasicDataSource; +import org.highmed.dsf.fhir.OrganizationType; import org.highmed.dsf.fhir.dao.jdbc.ResearchStudyDaoJdbc; +import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.Period; +import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.ResearchStudy; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import ca.uhn.fhir.context.FhirContext; public class ResearchStudyDaoTest extends AbstractResourceDaoTest<ResearchStudy, ResearchStudyDao> { + private static final Logger logger = LoggerFactory.getLogger(ResearchStudyDaoTest.class); + private static final String title = "Demo Research Study"; private final Date periodStart = new GregorianCalendar(2019, 0, 1).getTime(); private final Date periodEnd = new GregorianCalendar(2021, 11, 31).getTime(); @@ -56,4 +68,33 @@ protected void checkUpdates(ResearchStudy resource) assertEquals(periodStart, resource.getPeriod().getStart()); assertEquals(periodEnd, resource.getPeriod().getEnd()); } + + @Test + public void testReadByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationIdWithTransaction() throws Exception + { + String piReference = "Practitioner/" + UUID.randomUUID().toString(); + String orgReference = "Organization/" + UUID.randomUUID().toString(); + + ResearchStudy r = new ResearchStudy(); + r.setPrincipalInvestigator(new Reference(piReference)); + r.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-ttp") + .setValue(new Reference(orgReference)); + r.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-medic") + .setValue(new Reference("Organization/" + UUID.randomUUID().toString())); + r.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-medic") + .setValue(new Reference("Organization/" + UUID.randomUUID().toString())); + + logger.debug(fhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(r)); + + dao.create(r); + + try (Connection connection = dao.newReadWriteTransaction()) + { + List<ResearchStudy> rss = dao + .readByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationIdWithTransaction(connection, + new IdType(piReference), OrganizationType.TTP, new IdType(orgReference)); + assertNotNull(rss); + assertEquals(1, rss.size()); + } + } } diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/ResearchStudyTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/ResearchStudyTest.java new file mode 100644 index 000000000..de4dce724 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/hapi/ResearchStudyTest.java @@ -0,0 +1,31 @@ +package org.highmed.dsf.fhir.hapi; + +import static org.junit.Assert.assertTrue; + +import java.util.UUID; + +import org.hl7.fhir.r4.model.Reference; +import org.hl7.fhir.r4.model.ResearchStudy; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ca.uhn.fhir.context.FhirContext; + +public class ResearchStudyTest +{ + private static final Logger logger = LoggerFactory.getLogger(ResearchStudyTest.class); + + @Test + public void testReferenceExtension() throws Exception + { + ResearchStudy r = new ResearchStudy(); + r.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-medic") + .setValue(new Reference().setReference("Organization/" + UUID.randomUUID().toString())); + + logger.debug(FhirContext.forR4().newXmlParser().setPrettyPrint(true).encodeResourceToString(r)); + + assertTrue(r.getExtensionByUrl("http://highmed.org/fhir/StructureDefinition/participating-medic") + .getValue() instanceof Reference); + } +} From 7e2a13065e043b0daafe72d3cb323a36433e7ba5 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Mon, 9 Mar 2020 21:48:34 +0100 Subject: [PATCH 20/55] work on authorization rules, i.a. requestSimpleFeasibility bundle test --- .../authorization/GroupAuthorizationRule.java | 16 +- .../ResearchStudyAuthorizationRule.java | 10 +- .../fhir/dao/command/CommandFactoryImpl.java | 16 +- .../dsf/fhir/dao/command/CreateCommand.java | 18 +- .../CreateStructureDefinitionCommand.java | 8 +- .../dao/command/ResolveReferencesCommand.java | 67 +--- .../dao/command/ResolveReferencesHelper.java | 110 ++++++ .../dsf/fhir/dao/command/UpdateCommand.java | 25 +- .../UpdateStructureDefinitionCommand.java | 8 +- .../dao/jdbc/AbstractResourceDaoJdbc.java | 9 +- .../requestSimpleFeasibility-1.0.0.xml | 70 ++++ .../requestSimpleFeasibility-1.0.0.xml.put | 1 + .../fhir/integration/TaskIntegrationTest.java | 54 +-- .../resources/integration/task-bundle.json | 321 ++++++++++++++---- 14 files changed, 531 insertions(+), 202 deletions(-) create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesHelper.java create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-1.0.0.xml create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-1.0.0.xml.put diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java index b7b546d3b..678252784 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java @@ -9,9 +9,13 @@ import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Group; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class GroupAuthorizationRule extends AbstractAuthorizationRule<Group, GroupDao> { + private static final Logger logger = LoggerFactory.getLogger(GroupAuthorizationRule.class); + public GroupAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { @@ -21,8 +25,16 @@ public GroupAuthorizationRule(DaoProvider daoProvider, String serverBase, Refere @Override public Optional<String> reasonCreateAllowed(Connection connection, User user, Group newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Create of Group authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Create of Group unauthorized, not a local user"); + return Optional.empty(); + } } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java index 9a47b4f0a..b42359963 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java @@ -99,13 +99,11 @@ private Optional<String> newResourceOk(Connection connection, User user, Researc errors.add("ResearchStudy.identifier missing"); } - Stream<Reference> participatingMedicReferences = ResearchStudyHelper - .getParticipatingMedicReferences(newResource); - if (participatingMedicReferences.count() >= 0) + if (ResearchStudyHelper.getParticipatingMedicReferences(newResource).count() >= 0) { if (!organizationsResolvable(connection, user, "ResearchStudy.extension(url:http://highmed.org/fhir/StructureDefinition/participating-medic)", - participatingMedicReferences).allMatch(t -> t)) + ResearchStudyHelper.getParticipatingMedicReferences(newResource)).allMatch(t -> t)) { errors.add( "ResearchStudy.extension(url:http://highmed.org/fhir/StructureDefinition/participating-medic) one or more participating-medic Organizations not resolved"); @@ -131,7 +129,7 @@ private Optional<String> newResourceOk(Connection connection, User user, Researc else { errors.add( - "ResearchStudy.extension(url:http://highmed.org/fhir/StructureDefinition/participating-ttp) participating-ttp Organization references missing"); + "ResearchStudy.extension(url:http://highmed.org/fhir/StructureDefinition/participating-ttp) participating-ttp Organization reference missing"); } if (newResource.getEnrollment().size() >= 0) @@ -217,7 +215,7 @@ private boolean practitionerRoleExists(Connection connection, User user, IdType try { - return dao.search(query).getOverallCount() == 1; + return dao.searchWithTransaction(connection, query).getOverallCount() == 1; } catch (SQLException e) { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CommandFactoryImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CommandFactoryImpl.java index c51367ceb..3b5b31273 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CommandFactoryImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CommandFactoryImpl.java @@ -108,13 +108,14 @@ private <R extends Resource> Command post(int index, User user, Bundle bundle, B if (resource instanceof StructureDefinition) return new CreateStructureDefinitionCommand(index, user, bundle, entry, serverBase, authorizationHelper, (StructureDefinition) resource, (StructureDefinitionDao) dao.get(), exceptionHandler, - parameterConverter, responseGenerator, eventManager, eventGenerator, - daoProvider.getStructureDefinitionSnapshotDao(), snapshotGenerator, snapshotDependencyAnalyzer); + parameterConverter, responseGenerator, referenceExtractor, referenceResolver, eventManager, + eventGenerator, daoProvider.getStructureDefinitionSnapshotDao(), snapshotGenerator, + snapshotDependencyAnalyzer); else return dao .map(d -> new CreateCommand<R, ResourceDao<R>>(index, user, bundle, entry, serverBase, authorizationHelper, resource, d, exceptionHandler, parameterConverter, - responseGenerator, eventManager, eventGenerator)) + responseGenerator, referenceExtractor, referenceResolver, eventManager, eventGenerator)) .orElseThrow(() -> new IllegalStateException( "Resource of type " + resource.getClass().getName() + " not supported")); } @@ -137,13 +138,14 @@ private <R extends Resource> Command put(int index, User user, Bundle bundle, Bu if (resource instanceof StructureDefinition) return new UpdateStructureDefinitionCommand(index, user, bundle, entry, serverBase, authorizationHelper, (StructureDefinition) resource, (StructureDefinitionDao) dao.get(), exceptionHandler, - parameterConverter, responseGenerator, eventManager, eventGenerator, - daoProvider.getStructureDefinitionSnapshotDao(), snapshotGenerator, snapshotDependencyAnalyzer); + parameterConverter, responseGenerator, referenceExtractor, referenceResolver, eventManager, + eventGenerator, daoProvider.getStructureDefinitionSnapshotDao(), snapshotGenerator, + snapshotDependencyAnalyzer); else return dao .map(d -> new UpdateCommand<R, ResourceDao<R>>(index, user, bundle, entry, serverBase, authorizationHelper, resource, d, exceptionHandler, parameterConverter, - responseGenerator, eventManager, eventGenerator)) + responseGenerator, referenceExtractor, referenceResolver, eventManager, eventGenerator)) .orElseThrow(() -> new IllegalStateException( "Resource of type " + resource.getClass().getName() + " not supported")); } @@ -249,7 +251,7 @@ private <R extends Resource> Stream<Command> resolveReferences(Command cmd, int .map(d -> Stream.of(cmd, new ResolveReferencesCommand<R, ResourceDao<R>>(index, user, bundle, entry, serverBase, authorizationHelper, resource, d, exceptionHandler, parameterConverter, - referenceExtractor, responseGenerator, referenceResolver))) + responseGenerator, referenceExtractor, referenceResolver))) .orElseThrow(() -> new IllegalStateException( "Resource of type " + resource.getClass().getName() + " not supported")); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateCommand.java index 86fde63a2..b7abadc48 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateCommand.java @@ -26,6 +26,8 @@ import org.highmed.dsf.fhir.search.PartialResult; import org.highmed.dsf.fhir.search.SearchQuery; import org.highmed.dsf.fhir.search.SearchQueryParameterError; +import org.highmed.dsf.fhir.service.ReferenceExtractor; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r4.model.Bundle.BundleEntryResponseComponent; @@ -44,7 +46,9 @@ public class CreateCommand<R extends Resource, D extends ResourceDao<R>> extends { private static final Logger logger = LoggerFactory.getLogger(CreateCommand.class); - protected final ResponseGenerator responseGenerator; + private final ResponseGenerator responseGenerator; + private final ResolveReferencesHelper<R> resolveReferencesHelper; + protected final EventManager eventManager; protected final EventGenerator eventGenerator; @@ -52,14 +56,18 @@ public class CreateCommand<R extends Resource, D extends ResourceDao<R>> extends protected Response responseResult; public CreateCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, - AuthorizationHelper authorizationHelper, R resource, D dao, - ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, - ResponseGenerator responseGenerator, EventManager eventManager, EventGenerator eventGenerator) + AuthorizationHelper authorizationHelper, R resource, D dao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter, ResponseGenerator responseGenerator, + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, EventManager eventManager, + EventGenerator eventGenerator) { super(2, index, user, bundle, entry, serverBase, authorizationHelper, resource, dao, exceptionHandler, parameterConverter); this.responseGenerator = responseGenerator; + resolveReferencesHelper = new ResolveReferencesHelper<R>(index, user, serverBase, referenceExtractor, + referenceResolver, responseGenerator); + this.eventManager = eventManager; this.eventGenerator = eventGenerator; } @@ -93,6 +101,8 @@ else if (resource.hasIdElement() && !entry.getFullUrl().equals(resource.getIdEle public void execute(Map<String, IdType> idTranslationTable, Connection connection) throws SQLException, WebApplicationException { + resolveReferencesHelper.resolveReferencesIgnoreAndLogExceptions(idTranslationTable, connection, resource); + authorizationHelper.checkCreateAllowed(connection, user, resource); Optional<Resource> exists = checkAlreadyExists(connection, entry.getRequest().getIfNoneExist(), diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateStructureDefinitionCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateStructureDefinitionCommand.java index 0fa9dff5c..a622476f5 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateStructureDefinitionCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/CreateStructureDefinitionCommand.java @@ -13,6 +13,8 @@ import org.highmed.dsf.fhir.help.ExceptionHandler; import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceExtractor; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.service.SnapshotDependencies; import org.highmed.dsf.fhir.service.SnapshotDependencyAnalyzer; import org.highmed.dsf.fhir.service.SnapshotGenerator; @@ -38,12 +40,14 @@ public class CreateStructureDefinitionCommand extends CreateCommand<StructureDef public CreateStructureDefinitionCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, AuthorizationHelper authorizationHelper, StructureDefinition resource, StructureDefinitionDao dao, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, - ResponseGenerator responseGenerator, EventManager eventManager, EventGenerator eventGenerator, + ResponseGenerator responseGenerator, ReferenceExtractor referenceExtractor, + ReferenceResolver referenceResolver, EventManager eventManager, EventGenerator eventGenerator, StructureDefinitionSnapshotDao snapshotDao, SnapshotGenerator snapshotGenerator, SnapshotDependencyAnalyzer snapshotDependencyAnalyzer) { super(index, user, bundle, entry, serverBase, authorizationHelper, resource, dao, exceptionHandler, - parameterConverter, responseGenerator, eventManager, eventGenerator); + parameterConverter, responseGenerator, referenceExtractor, referenceResolver, eventManager, + eventGenerator); this.snapshotDao = snapshotDao; this.snapshotGenerator = snapshotGenerator; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java index 5c37ddeb0..aa9dc4d55 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesCommand.java @@ -2,10 +2,8 @@ import java.sql.Connection; import java.sql.SQLException; -import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.stream.Collectors; import javax.ws.rs.WebApplicationException; @@ -18,7 +16,6 @@ import org.highmed.dsf.fhir.help.ResponseGenerator; import org.highmed.dsf.fhir.service.ReferenceExtractor; import org.highmed.dsf.fhir.service.ReferenceResolver; -import org.highmed.dsf.fhir.service.ResourceReference; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r4.model.IdType; @@ -27,22 +24,18 @@ public class ResolveReferencesCommand<R extends Resource, D extends ResourceDao<R>> extends AbstractCommandWithResource<R, D> implements Command { - private final ReferenceExtractor referenceExtractor; - private final ResponseGenerator responseGenerator; - private final ReferenceResolver referenceResolver; + private final ResolveReferencesHelper<R> resolveReferencesHelper; public ResolveReferencesCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, - AuthorizationHelper authorizationHelper, R resource, D dao, - ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, - ReferenceExtractor referenceExtractor, ResponseGenerator responseGenerator, - ReferenceResolver referenceResolver) + AuthorizationHelper authorizationHelper, R resource, D dao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter, ResponseGenerator responseGenerator, + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver) { super(4, index, user, bundle, entry, serverBase, authorizationHelper, resource, dao, exceptionHandler, parameterConverter); - this.referenceExtractor = referenceExtractor; - this.responseGenerator = responseGenerator; - this.referenceResolver = referenceResolver; + resolveReferencesHelper = new ResolveReferencesHelper<R>(index, user, serverBase, referenceExtractor, + referenceResolver, responseGenerator); } @Override @@ -56,16 +49,8 @@ public void execute(Map<String, IdType> idTranslationTable, Connection connectio { R latest = latestOrErrorIfDeletedOrNotFound(idTranslationTable, connection); - boolean resourceNeedsUpdated = false; - List<ResourceReference> references = referenceExtractor.getReferences(latest).collect(Collectors.toList()); - // Don't use stream.map(...).anyMatch(b -> b), anyMatch is a shortcut operation stopping after first match - for (ResourceReference ref : references) - { - boolean needsUpdate = resolveReference(idTranslationTable, connection, ref); - if (needsUpdate) - resourceNeedsUpdated = true; - } - + boolean resourceNeedsUpdated = resolveReferencesHelper.resolveReferences(idTranslationTable, connection, + latest); if (resourceNeedsUpdated) { try @@ -94,42 +79,6 @@ private R latestOrErrorIfDeletedOrNotFound(Map<String, IdType> idTranslationTabl } } - private boolean resolveReference(Map<String, IdType> idTranslationTable, Connection connection, - ResourceReference resourceReference) throws WebApplicationException - { - switch (resourceReference.getType(serverBase)) - { - case TEMPORARY: - return resolveTemporaryReference(resourceReference, idTranslationTable); - case LITERAL_INTERNAL: - return referenceResolver.resolveLiteralInternalReference(resource, index, resourceReference, - connection); - case LITERAL_EXTERNAL: - return referenceResolver.resolveLiteralExternalReference(resource, index, resourceReference); - case CONDITIONAL: - return referenceResolver.resolveConditionalReference(user, resource, index, resourceReference, - connection); - case LOGICAL: - return referenceResolver.resolveLogicalReference(user, resource, index, resourceReference, connection); - case UNKNOWN: - default: - throw new WebApplicationException( - responseGenerator.unknownReference(index, resource, resourceReference)); - } - } - - private boolean resolveTemporaryReference(ResourceReference resourceReference, - Map<String, IdType> idTranslationTable) - { - IdType newId = idTranslationTable.get(resourceReference.getReference().getReference()); - if (newId == null) - throw new WebApplicationException(responseGenerator.unknownReference(index, resource, resourceReference)); - else - resourceReference.getReference().setReferenceElement(newId); - - return true; // throws exception if reference could not be resolved - } - @Override public Optional<BundleEntryComponent> postExecute(Connection connection) { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesHelper.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesHelper.java new file mode 100644 index 000000000..443b1f8e9 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/ResolveReferencesHelper.java @@ -0,0 +1,110 @@ +package org.highmed.dsf.fhir.dao.command; + +import java.sql.Connection; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import javax.ws.rs.WebApplicationException; + +import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceExtractor; +import org.highmed.dsf.fhir.service.ReferenceResolver; +import org.highmed.dsf.fhir.service.ResourceReference; +import org.hl7.fhir.r4.model.IdType; +import org.hl7.fhir.r4.model.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public final class ResolveReferencesHelper<R extends Resource> +{ + private static final Logger logger = LoggerFactory.getLogger(ResolveReferencesHelper.class); + + private final int index; + private final User user; + private final String serverBase; + private final ReferenceExtractor referenceExtractor; + private final ReferenceResolver referenceResolver; + private final ResponseGenerator responseGenerator; + + public ResolveReferencesHelper(int index, User user, String serverBase, ReferenceExtractor referenceExtractor, + ReferenceResolver referenceResolver, ResponseGenerator responseGenerator) + { + this.index = index; + this.user = user; + this.serverBase = serverBase; + this.referenceExtractor = referenceExtractor; + this.referenceResolver = referenceResolver; + this.responseGenerator = responseGenerator; + } + + public boolean resolveReferences(Map<String, IdType> idTranslationTable, Connection connection, R resource) + throws WebApplicationException + { + boolean resourceNeedsUpdated = false; + List<ResourceReference> references = referenceExtractor.getReferences(resource).collect(Collectors.toList()); + // Don't use stream.map(...).anyMatch(b -> b), anyMatch is a shortcut operation stopping after first match + for (ResourceReference ref : references) + { + boolean needsUpdate = resolveReference(idTranslationTable, connection, resource, ref); + if (needsUpdate) + resourceNeedsUpdated = true; + } + return resourceNeedsUpdated; + } + + public void resolveReferencesIgnoreAndLogExceptions(Map<String, IdType> idTranslationTable, Connection connection, + R resource) throws WebApplicationException + { + List<ResourceReference> references = referenceExtractor.getReferences(resource).collect(Collectors.toList()); + // Don't use stream.map(...).anyMatch(b -> b), anyMatch is a shortcut operation stopping after first match + for (ResourceReference ref : references) + { + try + { + resolveReference(idTranslationTable, connection, resource, ref); + } + catch (WebApplicationException e) + { + logger.warn("Error while resolving reference {}", e.getMessage()); + } + } + } + + private boolean resolveReference(Map<String, IdType> idTranslationTable, Connection connection, R resource, + ResourceReference resourceReference) throws WebApplicationException + { + switch (resourceReference.getType(serverBase)) + { + case TEMPORARY: + return resolveTemporaryReference(resourceReference, idTranslationTable, resource); + case LITERAL_INTERNAL: + return referenceResolver.resolveLiteralInternalReference(resource, index, resourceReference, + connection); + case LITERAL_EXTERNAL: + return referenceResolver.resolveLiteralExternalReference(resource, index, resourceReference); + case CONDITIONAL: + return referenceResolver.resolveConditionalReference(user, resource, index, resourceReference, + connection); + case LOGICAL: + return referenceResolver.resolveLogicalReference(user, resource, index, resourceReference, connection); + case UNKNOWN: + default: + throw new WebApplicationException( + responseGenerator.unknownReference(index, resource, resourceReference)); + } + } + + private boolean resolveTemporaryReference(ResourceReference resourceReference, + Map<String, IdType> idTranslationTable, R resource) + { + IdType newId = idTranslationTable.get(resourceReference.getReference().getReference()); + if (newId == null) + throw new WebApplicationException(responseGenerator.unknownReference(index, resource, resourceReference)); + else + resourceReference.getReference().setReferenceElement(newId); + + return true; // throws exception if reference could not be resolved + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java index 756b1dabc..bb96cd75f 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateCommand.java @@ -26,6 +26,8 @@ import org.highmed.dsf.fhir.search.PartialResult; import org.highmed.dsf.fhir.search.SearchQuery; import org.highmed.dsf.fhir.search.SearchQueryParameterError; +import org.highmed.dsf.fhir.service.ReferenceExtractor; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r4.model.Bundle.BundleEntryResponseComponent; @@ -42,7 +44,9 @@ public class UpdateCommand<R extends Resource, D extends ResourceDao<R>> extends { private static final Logger logger = LoggerFactory.getLogger(UpdateCommand.class); - protected final ResponseGenerator responseGenerator; + private final ResponseGenerator responseGenerator; + private final ResolveReferencesHelper<R> resolveReferencesHelper; + protected final EventManager eventManager; protected final EventGenerator eventGenerator; @@ -50,14 +54,18 @@ public class UpdateCommand<R extends Resource, D extends ResourceDao<R>> extends protected R updatedResource; public UpdateCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, - AuthorizationHelper authorizationHelper, R resource, D dao, - ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, - ResponseGenerator responseGenerator, EventManager eventManager, EventGenerator eventGenerator) + AuthorizationHelper authorizationHelper, R resource, D dao, ExceptionHandler exceptionHandler, + ParameterConverter parameterConverter, ResponseGenerator responseGenerator, + ReferenceExtractor referenceExtractor, ReferenceResolver referenceResolver, EventManager eventManager, + EventGenerator eventGenerator) { super(3, index, user, bundle, entry, serverBase, authorizationHelper, resource, dao, exceptionHandler, parameterConverter); this.responseGenerator = responseGenerator; + resolveReferencesHelper = new ResolveReferencesHelper<R>(index, user, serverBase, referenceExtractor, + referenceResolver, responseGenerator); + this.eventManager = eventManager; this.eventGenerator = eventGenerator; } @@ -146,7 +154,7 @@ private void updateById(Map<String, IdType> idTranslationTable, Connection conne throw new WebApplicationException(responseGenerator.nonMatchingResourceTypeAndRequestUrlInBundle(index, resourceTypeName, entry.getRequest().getUrl())); - checkUpdateAllowed(user, connection, resource); + checkUpdateAllowed(idTranslationTable, connection, user, resource); Optional<Long> ifMatch = Optional.ofNullable(entry.getRequest().getIfMatch()) .flatMap(parameterConverter::toEntityTag).flatMap(parameterConverter::toVersion); @@ -155,7 +163,8 @@ private void updateById(Map<String, IdType> idTranslationTable, Connection conne () -> dao.updateWithTransaction(connection, resource, ifMatch.orElse(null))); } - private void checkUpdateAllowed(User user, Connection connection, Resource newResource) + private void checkUpdateAllowed(Map<String, IdType> idTranslationTable, Connection connection, User user, + R newResource) { String resourceTypeName = newResource.getResourceType().name(); String id = newResource.getIdElement().getIdPart(); @@ -172,6 +181,8 @@ private void checkUpdateAllowed(User user, Connection connection, Resource newRe } else { + resolveReferencesHelper.resolveReferencesIgnoreAndLogExceptions(idTranslationTable, connection, resource); + R oldResource = dbResource.get(); authorizationHelper.checkUpdateAllowed(connection, user, oldResource, newResource); } @@ -208,6 +219,8 @@ private void updateByCondition(Map<String, IdType> idTranslationTable, Connectio if (result.getOverallCount() <= 0 && (!resource.hasId() || resource.getIdElement().getValue().startsWith(URL_UUID_PREFIX))) { + resolveReferencesHelper.resolveReferencesIgnoreAndLogExceptions(idTranslationTable, connection, resource); + authorizationHelper.checkCreateAllowed(connection, user, resource); id = UUID.randomUUID(); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateStructureDefinitionCommand.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateStructureDefinitionCommand.java index 7c6d6f8ce..49c01f01e 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateStructureDefinitionCommand.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/command/UpdateStructureDefinitionCommand.java @@ -13,6 +13,8 @@ import org.highmed.dsf.fhir.help.ExceptionHandler; import org.highmed.dsf.fhir.help.ParameterConverter; import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.highmed.dsf.fhir.service.ReferenceExtractor; +import org.highmed.dsf.fhir.service.ReferenceResolver; import org.highmed.dsf.fhir.service.SnapshotDependencies; import org.highmed.dsf.fhir.service.SnapshotDependencyAnalyzer; import org.highmed.dsf.fhir.service.SnapshotGenerator; @@ -39,12 +41,14 @@ public class UpdateStructureDefinitionCommand extends UpdateCommand<StructureDef public UpdateStructureDefinitionCommand(int index, User user, Bundle bundle, BundleEntryComponent entry, String serverBase, AuthorizationHelper authorizationHelper, StructureDefinition resource, StructureDefinitionDao dao, ExceptionHandler exceptionHandler, ParameterConverter parameterConverter, - ResponseGenerator responseGenerator, EventManager eventManager, EventGenerator eventGenerator, + ResponseGenerator responseGenerator, ReferenceExtractor referenceExtractor, + ReferenceResolver referenceResolver, EventManager eventManager, EventGenerator eventGenerator, StructureDefinitionSnapshotDao snapshotDao, SnapshotGenerator snapshotGenerator, SnapshotDependencyAnalyzer snapshotDependencyAnalyzer) { super(index, user, bundle, entry, serverBase, authorizationHelper, resource, dao, exceptionHandler, - parameterConverter, responseGenerator, eventManager, eventGenerator); + parameterConverter, responseGenerator, referenceExtractor, referenceResolver, eventManager, + eventGenerator); this.snapshotDao = snapshotDao; this.snapshotGenerator = snapshotGenerator; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java index f383e2d08..61f9c94bd 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/AbstractResourceDaoJdbc.java @@ -283,14 +283,13 @@ protected R getResource(ResultSet result, int index) throws SQLException } /* caution: only works because we set all versions as deleted or not deleted in method markDeleted */ - public final boolean hasNonDeletedResource(UUID uuid) throws SQLException + public final boolean hasNonDeletedResource(Connection connection, UUID uuid) throws SQLException { if (uuid == null) return false; - try (Connection connection = dataSource.getConnection(); - PreparedStatement statement = connection.prepareStatement("SELECT count(*) FROM " + resourceTable - + " WHERE " + resourceIdColumn + " = ? AND NOT deleted")) + try (PreparedStatement statement = connection.prepareStatement( + "SELECT count(*) FROM " + resourceTable + " WHERE " + resourceIdColumn + " = ? AND NOT deleted")) { statement.setObject(1, preparedStatementFactory.uuidToPgObject(uuid)); @@ -454,7 +453,7 @@ public boolean existsNotDeletedWithTransaction(Connection connection, String idS return false; if (versionString == null || versionString.isBlank()) - return hasNonDeletedResource(uuid); + return hasNonDeletedResource(connection, uuid); else { Long version = toLong(versionString); diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-1.0.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-1.0.0.xml new file mode 100644 index 000000000..0fe350027 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-1.0.0.xml @@ -0,0 +1,70 @@ +<ActivityDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </tag> + </meta> + <extension url="http://highmed.org/fhir/StructureDefinition/process-authorization"> + <extension url="message-name"> + <valueString value="requestSimpleFeasibilityMessage" /> + </extension> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="LOCAL" /> + </valueCoding> + </extension> + <extension url="organization-types"> + <extension url="organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/highmed-task-request-simple-feasibility" /> + </extension> + </extension> + <extension url="http://highmed.org/fhir/StructureDefinition/process-authorization"> + <extension url="message-name"> + <valueString value="resultMultiMedicSimpleFeasibilityMessage" /> + </extension> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </valueCoding> + </extension> + <extension url="organization-types"> + <extension url="organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="TTP" /> + </valueCoding> + </extension> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/highmed-task-multi-medic-result-simple-feasibility" /> + </extension> + </extension> + <url value="http://highmed.org/bpe/Process/requestSimpleFeasibility" /> + <version value="1.0.0" /> + <name value="RequestSimpleFeasibility" /> + <title value="Request simple feasibility" /> + <subtitle value="Feasibility Request Process" /> + <status value="draft" /> + <experimental value="true" /> + <date value="2020-03-09T21:07:00+01:00" /> + <publisher value="HiGHmed" /> + <contact> + <name value="HiGHmed" /> + <telecom> + <system value="email" /> + <value value="pmo@highmed.org" /> + </telecom> + </contact> + <description value="Process to start a simple feasibility, process sends messages to all MeDICs and a TTP, receives result from TTP" /> + <kind value="Task" /> +</ActivityDefinition> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-1.0.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-1.0.0.xml.put new file mode 100644 index 000000000..4ec0093b4 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-1.0.0.xml.put @@ -0,0 +1 @@ +ActivityDefinition?url=http://highmed.org/bpe/Process/requestSimpleFeasibility&version=1.0.0 \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java index fb3b942cb..f3a10b5b9 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java @@ -37,7 +37,7 @@ private List<Bundle.BundleEntryComponent> createTaskBundle() } @Test - public void testInputTransactionReferenceResolver() throws Exception + public void testHandleBundleForRequestSimpleFeasibility() throws Exception { WebsocketClient websocketClient = getWebsocketClient(); assertNotNull(websocketClient); @@ -50,7 +50,7 @@ public void testInputTransactionReferenceResolver() throws Exception { List<Bundle.BundleEntryComponent> resultBundleEntries = createTaskBundle(); - String taskId = new IdType(resultBundleEntries.get(1).getFullUrl()).getIdPart(); + String taskId = new IdType(resultBundleEntries.get(5).getFullUrl()).getIdPart(); Task task = getWebserviceClient().read(Task.class, taskId); Task.ParameterComponent input = task.getInput().stream() @@ -58,7 +58,7 @@ public void testInputTransactionReferenceResolver() throws Exception .findFirst().orElse(new Task.ParameterComponent()); IdType taskInputResearchStudyId = new IdType(((Reference) input.getValue()).getReference()); - IdType researchStudyId = new IdType(resultBundleEntries.get(0).getFullUrl()); + IdType researchStudyId = new IdType(resultBundleEntries.get(4).getFullUrl()); assertEquals(researchStudyId.getResourceType(), taskInputResearchStudyId.getResourceType()); assertEquals(researchStudyId.getIdPart(), taskInputResearchStudyId.getIdPart()); @@ -84,54 +84,6 @@ public void testInputTransactionReferenceResolver() throws Exception } } - @Test - public void testOutputTransactionReferenceResolver() throws Exception - { - WebsocketClient websocketClient = getWebsocketClient(); - assertNotNull(websocketClient); - - BlockingDeque<DomainResource> events = new LinkedBlockingDeque<>(); - websocketClient.setDomainResourceHandler(events::add, AbstractIntegrationTest::newJsonParser); - websocketClient.connect(); - - try - { - List<Bundle.BundleEntryComponent> resultBundleEntries = createTaskBundle(); - - String taskId = new IdType(resultBundleEntries.get(1).getFullUrl()).getIdPart(); - Task task = getWebserviceClient().read(Task.class, taskId); - - Task.TaskOutputComponent output = task.getOutput().stream() - .filter(c -> c.getType().getCoding().get(0).getCode().equals("research-study-reference")) - .findFirst().orElse(new Task.TaskOutputComponent()); - - IdType taskOutputResearchStudyId = new IdType(((Reference) output.getValue()).getReference()); - IdType researchStudyId = new IdType(resultBundleEntries.get(0).getFullUrl()); - - assertEquals(researchStudyId.getResourceType(), taskOutputResearchStudyId.getResourceType()); - assertEquals(researchStudyId.getIdPart(), taskOutputResearchStudyId.getIdPart()); - - DomainResource event = events.pollFirst(5, TimeUnit.SECONDS); - assertNotNull(event); - assertTrue(event instanceof Task); - - Task taskViaWebsocket = (Task) event; - Task.TaskOutputComponent outputViaWebsocket = taskViaWebsocket.getOutput().stream() - .filter(c -> c.getType().getCoding().get(0).getCode().equals("research-study-reference")) - .findFirst().orElse(new Task.TaskOutputComponent()); - - IdType taskOutputResearchStudyIdViaWebsocket = new IdType( - ((Reference) outputViaWebsocket.getValue()).getReference()); - assertEquals(researchStudyId.getResourceType(), taskOutputResearchStudyIdViaWebsocket.getResourceType()); - assertEquals(researchStudyId.getIdPart(), taskOutputResearchStudyIdViaWebsocket.getIdPart()); - } - finally - { - if (websocketClient != null) - websocketClient.disconnect(); - } - } - @Test public void testCreateTaskStartPingProcess() throws Exception { diff --git a/dsf-fhir/dsf-fhir-server/src/test/resources/integration/task-bundle.json b/dsf-fhir/dsf-fhir-server/src/test/resources/integration/task-bundle.json index d9644e09c..7aba09dc8 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/resources/integration/task-bundle.json +++ b/dsf-fhir/dsf-fhir-server/src/test/resources/integration/task-bundle.json @@ -1,60 +1,265 @@ { - "resourceType": "Bundle", - "type": "transaction", - "entry": [ - { - "fullUrl": "urn:uuid:aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", - "resource": { - "resourceType": "ResearchStudy", - "status": "active" - }, - "request": { - "method": "POST", - "url": "ResearchStudy" - } - }, - { - "fullUrl": "urn:uuid:bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", - "resource": { - "resourceType": "Task", - "instantiatesUri": "http://highmed.org/bpe/Process/requestSimpleCohortSizeQuery/1.0.0", - "status": "requested", - "intent": "order", - "input": [ - { - "type": { - "coding": [ - { - "system": "http://highmed.org/fhir/CodeSystem/bpmn-message", - "code": "research-study-reference" - } - ] - }, - "valueReference": { - "reference": "urn:uuid:aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" - } - } - ], - "output": [ - { - "type": { - "coding": [ - { - "system": "http://highmed.org/fhir/CodeSystem/bpmn-message", - "code": "research-study-reference" - } - ] - }, - "valueReference": { - "reference": "urn:uuid:aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" - } - } - ] - }, - "request": { - "method": "POST", - "url": "Task" - } - } - ] + "resourceType": "Bundle", + "type": "transaction", + "entry": [ + { + "fullUrl": "urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8aa", + "resource": { + "resourceType": "Group", + "meta": { + "profile": "http://highmed.org/fhir/StructureDefinition/highmed-group" + }, + "text": { + "div": "This is the description", + "status": "additional" + }, + "type": "person", + "actual": true, + "extension": [ + { + "url": "http://highmed.org/fhir/StructureDefinition/query", + "valueExpression": [ + { + "language": "application/x-aql-query", + "expression": "SELECT COUNT(e) FROM EHR e" + } + ] + } + ] + }, + "request": { + "method": "POST", + "url": "Group" + } + }, + { + "fullUrl": "urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8bb", + "resource": { + "resourceType": "Group", + "meta": { + "profile": "http://highmed.org/fhir/StructureDefinition/highmed-group" + }, + "text": { + "div": "This is the description", + "status": "additional" + }, + "type": "person", + "actual": true, + "extension": [ + { + "url": "http://highmed.org/fhir/StructureDefinition/query", + "valueExpression": [ + { + "language": "application/x-aql-query", + "expression": "SELECT COUNT(e) FROM EHR e" + } + ] + } + ] + }, + "request": { + "method": "POST", + "url": "Group" + } + }, + { + "fullUrl": "urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8xx", + "resource": { + "resourceType": "Practitioner", + "meta": { + "profile": "http://highmed.org/fhir/StructureDefinition/highmed-practitioner" + }, + "name": [ + { + "family": "HiGHmed", + "given": [ + "Test" + ] + } + ], + "telecom": [ + { + "system": "phone", + "value": "+491710001122" + }, + { + "system": "email", + "value": "test-practitioner@highmed.org" + } + ], + "address": [ + { + "line": [ + "Highmedstraße 12" + ], + "city": "Berlin", + "postalCode": "10115", + "country": "DE" + } + ] + }, + "request": { + "method": "POST", + "url": "Practitioner" + } + }, + { + "fullUrl": "urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8yy", + "resource": { + "resourceType": "PractitionerRole", + "meta": { + "profile": "http://highmed.org/fhir/StructureDefinition/highmed-practitioner-role" + }, + "active": true, + "practitioner": { + "reference": "urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8xx" + }, + "organization": { + "identifier": { + "system": "http://highmed.org/fhir/NamingSystem/organization-identifier", + "value": "Test_Organization" + }, + "type": "Organization" + } + }, + "request": { + "method": "POST", + "url": "PractitionerRole" + } + }, + { + "fullUrl": "urn:uuid:aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", + "resource": { + "resourceType": "ResearchStudy", + "meta": { + "profile": "http://highmed.org/fhir/StructureDefinition/highmed-research-study" + }, + "identifier": [ + { + "value": "c4d3e590-890a-4840-848f-412cf4b7f1fa", + "system": "http://highmed.org/fhir/NamingSystem/research-study-identifier" + } + ], + "title": "Research Study Test", + "status": "active", + "description": "This is a test research study based on the highmed profile. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.", + "enrollment": [ + { + "reference": "urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8aa" + }, + { + "reference": "urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8bb" + } + ], + "principalInvestigator": { + "reference": "urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8xx" + }, + "extension": [ + { + "url": "http://highmed.org/fhir/StructureDefinition/participating-medic", + "valueReference": { + "identifier": { + "system": "http://highmed.org/fhir/NamingSystem/organization-identifier", + "value": "Test_Organization" + }, + "type": "Organization" + } + }, + { + "url": "http://highmed.org/fhir/StructureDefinition/participating-ttp", + "valueReference": { + "identifier": { + "system": "http://highmed.org/fhir/NamingSystem/organization-identifier", + "value": "External_Test_Organization" + }, + "type": "Organization" + } + } + ] + }, + "request": { + "method": "POST", + "url": "ResearchStudy" + } + }, + { + "fullUrl": "urn:uuid:bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", + "resource": { + "resourceType": "Task", + "instantiatesUri": "http://highmed.org/bpe/Process/requestSimpleFeasibility/1.0.0", + "status": "requested", + "intent": "order", + "requester": { + "identifier": { + "system": "http://highmed.org/fhir/NamingSystem/organization-identifier", + "value": "Test_Organization" + }, + "type": "Organization" + }, + "restriction": { + "recipient": [ + { + "identifier": { + "system": "http://highmed.org/fhir/NamingSystem/organization-identifier", + "value": "Test_Organization" + }, + "type": "Organization" + } + ] + }, + "input": [ + { + "type": { + "coding": [ + { + "system": "http://highmed.org/fhir/CodeSystem/bpmn-message", + "code": "message-name" + } + ] + }, + "valueString": "requestSimpleFeasibilityMessage" + }, + { + "type": { + "coding": [ + { + "system": "http://highmed.org/fhir/CodeSystem/bpmn-message", + "code": "research-study-reference" + } + ] + }, + "valueReference": { + "reference": "urn:uuid:aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" + } + }, + { + "type": { + "coding": [ + { + "system": "http://highmed.org/fhir/CodeSystem/feasibility", + "code": "needs-record-linkage" + } + ] + }, + "valueBoolean": false + }, + { + "type": { + "coding": [ + { + "system": "http://highmed.org/fhir/CodeSystem/feasibility", + "code": "needs-consent-check" + } + ] + }, + "valueBoolean": false + } + ] + }, + "request": { + "method": "POST", + "url": "Task" + } + } + ] } \ No newline at end of file From 322b9aec169e7d7eedb0990dc3574c52bb0bf276 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 01:02:09 +0100 Subject: [PATCH 21/55] work on authorization rules, i.a. GroupAuthorizationRule/GroupUserFilter --- .../authorization/GroupAuthorizationRule.java | 76 ++++++++++++++-- .../PractitionerAuthorizationRule.java | 7 +- .../PractitionerRoleAuthorizationRule.java | 6 +- .../dsf/fhir/dao/ResearchStudyDao.java | 10 ++- .../fhir/dao/jdbc/ResearchStudyDaoJdbc.java | 89 +++++++++++++------ .../parameters/user/GroupUserFilter.java | 51 ++++++++--- .../user/PractitionerUserFilter.java | 5 +- .../dsf/fhir/dao/ResearchStudyDaoTest.java | 40 +++++++-- 8 files changed, 214 insertions(+), 70 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java index 678252784..91f527cdb 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/GroupAuthorizationRule.java @@ -1,6 +1,7 @@ package org.highmed.dsf.fhir.authorization; import java.sql.Connection; +import java.sql.SQLException; import java.util.Optional; import org.highmed.dsf.fhir.authentication.OrganizationProvider; @@ -40,28 +41,87 @@ public Optional<String> reasonCreateAllowed(Connection connection, User user, Gr @Override public Optional<String> reasonReadAllowed(Connection connection, User user, Group existingResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Read of Group authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else if (isRemoteUser(user)) + { + if (researchStudyWithEnrollmentAndUsersOrganizationExists(connection, user, existingResource)) + { + logger.info( + "Read of Group authorized for remote user '{}', ResearchStudy with enrollment contains this Group and users organization part of ResearchStudy", + user.getName()); + return Optional.of( + "remote user, users organization part of ResearchStudy with enrollment contains this Group"); + } + else + { + logger.warn("ResearchStudy.enrollment containing this Group and users Organization not found"); + return Optional.empty(); + } + } + else + { + logger.warn("Read of Group unauthorized, not a local or remote user"); + return Optional.empty(); + } + } + + private boolean researchStudyWithEnrollmentAndUsersOrganizationExists(Connection connection, User user, + Group existingResource) + { + try + { + return daoProvider.getResearchStudyDao() + .existsByEnrollmentIdAndOrganizationTypeAndOrganizationIdWithTransaction(connection, + existingResource.getIdElement(), user.getOrganizationType(), + user.getOrganization().getIdElement()); + } + catch (SQLException e) + { + logger.warn("Error while searching for research studies", e); + return false; + } } @Override public Optional<String> reasonUpdateAllowed(Connection connection, User user, Group oldResource, Group newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Update of Group authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + + } + else + { + logger.warn("Update of Group unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonDeleteAllowed(Connection connection, User user, Group oldResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Delete of Group authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Delete of Group unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonSearchAllowed(Connection connection, User user) { - // TODO Auto-generated method stub - return Optional.empty(); + logger.info("Search of Group authorized for {} user '{}', will be fitered by users organization {}", + user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString()); + return Optional.of("Allowed for all, filtered by users organization"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java index ad64ca14e..8ce977c09 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java @@ -3,7 +3,6 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.Collections; -import java.util.List; import java.util.Map; import java.util.Optional; @@ -17,7 +16,6 @@ import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Practitioner; import org.hl7.fhir.r4.model.PractitionerRole; -import org.hl7.fhir.r4.model.ResearchStudy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -91,11 +89,10 @@ private boolean researchStudyWithPrincipalInvestigatorAndUsersOrganizationExists { try { - List<ResearchStudy> studies = daoProvider.getResearchStudyDao() - .readByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationIdWithTransaction(connection, + return daoProvider.getResearchStudyDao() + .existsByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationIdWithTransaction(connection, existingResource.getIdElement(), user.getOrganizationType(), user.getOrganization().getIdElement()); - return !studies.isEmpty(); } catch (SQLException e) { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java index 06fb4ef6b..e4cbec732 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerRoleAuthorizationRule.java @@ -17,7 +17,6 @@ import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Practitioner; import org.hl7.fhir.r4.model.PractitionerRole; -import org.hl7.fhir.r4.model.ResearchStudy; import org.hl7.fhir.r4.model.Resource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -170,10 +169,9 @@ private boolean researchStudyWithPrincipalInvestigatorAndUsersOrganizationExists { try { - List<ResearchStudy> studies = daoProvider.getResearchStudyDao() - .readByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationIdWithTransaction(connection, + return daoProvider.getResearchStudyDao() + .existsByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationIdWithTransaction(connection, principalInvestigatorId, user.getOrganizationType(), user.getOrganization().getIdElement()); - return !studies.isEmpty(); } catch (SQLException e) { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResearchStudyDao.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResearchStudyDao.java index 168f5176c..131b40ba2 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResearchStudyDao.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ResearchStudyDao.java @@ -2,7 +2,6 @@ import java.sql.Connection; import java.sql.SQLException; -import java.util.List; import org.highmed.dsf.fhir.OrganizationType; import org.hl7.fhir.r4.model.IdType; @@ -10,7 +9,10 @@ public interface ResearchStudyDao extends ResourceDao<ResearchStudy> { - List<ResearchStudy> readByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationIdWithTransaction( - Connection connection, IdType principalInvestigatorId, OrganizationType organizationType, - IdType organizationId) throws SQLException; + boolean existsByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationIdWithTransaction(Connection connection, + IdType principalInvestigatorId, OrganizationType organizationType, IdType organizationId) + throws SQLException; + + boolean existsByEnrollmentIdAndOrganizationTypeAndOrganizationIdWithTransaction(Connection connection, + IdType enrollmentId, OrganizationType organizationType, IdType organizationId) throws SQLException; } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java index 183fd230a..f9e862c5a 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java @@ -4,8 +4,6 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; import java.util.Objects; import org.apache.commons.dbcp2.BasicDataSource; @@ -25,7 +23,7 @@ public class ResearchStudyDaoJdbc extends AbstractResourceDaoJdbc<ResearchStudy> implements ResearchStudyDao { private static final Logger logger = LoggerFactory.getLogger(ResearchStudyDaoJdbc.class); - + public ResearchStudyDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, ResearchStudy.class, "research_studies", "research_study", "research_study_id", @@ -41,7 +39,7 @@ protected ResearchStudy copy(ResearchStudy resource) } @Override - public List<ResearchStudy> readByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationIdWithTransaction( + public boolean existsByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationIdWithTransaction( Connection connection, IdType principalInvestigatorId, OrganizationType organizationType, IdType organizationId) throws SQLException { @@ -51,44 +49,79 @@ public List<ResearchStudy> readByPrincipalInvestigatorIdAndOrganizationTypeAndOr Objects.requireNonNull(organizationId, "organizationId"); try (PreparedStatement statement = connection - .prepareStatement("SELECT research_study FROM current_research_studies WHERE " + .prepareStatement("SELECT COUNT(*) FROM current_research_studies WHERE " + "(research_study->'principalInvestigator'->>'reference' = ? OR research_study->'principalInvestigator'->>'reference' = ?) AND " + "(research_study->'extension' @> ?::jsonb OR research_study->'extension' @> ?::jsonb)")) { statement.setString(1, principalInvestigatorId.getValue()); statement.setString(2, principalInvestigatorId.toVersionless().getValue()); - switch (organizationType) + setOrganization(statement, organizationType, organizationId); + + logger.trace("Executing query '{}'", statement); + try (ResultSet result = statement.executeQuery()) { - case MeDIC: - statement.setString(3, - "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-medic\",\"valueReference\":{\"reference\":\"" - + organizationId.getValue() + "\"}}]"); - statement.setString(4, - "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-medic\",\"valueReference\":{\"reference\":\"" - + organizationId.toVersionless().getValue() + "\"}}]"); - break; - - case TTP: - statement.setString(3, - "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-ttp\",\"valueReference\":{\"reference\":\"" - + organizationId.getValue() + "\"}}]"); - statement.setString(4, - "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-ttp\",\"valueReference\":{\"reference\":\"" - + organizationId.toVersionless().getValue() + "\"}}]"); - break; + if (result.next()) + return result.getInt(1) > 0; + else + return false; } + } + } + + @Override + public boolean existsByEnrollmentIdAndOrganizationTypeAndOrganizationIdWithTransaction(Connection connection, + IdType enrollmentId, OrganizationType organizationType, IdType organizationId) throws SQLException + { + Objects.requireNonNull(connection, "connection"); + Objects.requireNonNull(enrollmentId, "enrollmentId"); + Objects.requireNonNull(organizationType, "organizationType"); + Objects.requireNonNull(organizationId, "organizationId"); + + try (PreparedStatement statement = connection + .prepareStatement("SELECT COUNT(*) FROM current_research_studies WHERE " + + "(? IN (SELECT enrollment->>'reference' FROM jsonb_array_elements(research_study->'enrollment') AS enrollment) OR " + + "? IN (SELECT enrollment->>'reference' FROM jsonb_array_elements(research_study->'enrollment') AS enrollment)) AND " + + "(research_study->'extension' @> ?::jsonb OR research_study->'extension' @> ?::jsonb)")) + { + statement.setString(1, enrollmentId.getValue()); + statement.setString(2, enrollmentId.toVersionless().getValue()); + + setOrganization(statement, organizationType, organizationId); logger.trace("Executing query '{}'", statement); try (ResultSet result = statement.executeQuery()) { - List<ResearchStudy> results = new ArrayList<>(); + if (result.next()) + return result.getInt(1) > 0; + else + return false; + } + } + } - while (result.next()) - results.add(getResource(result, 1)); + private void setOrganization(PreparedStatement statement, OrganizationType organizationType, IdType organizationId) + throws SQLException + { + switch (organizationType) + { + case MeDIC: + statement.setString(3, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-medic\",\"valueReference\":{\"reference\":\"" + + organizationId.getValue() + "\"}}]"); + statement.setString(4, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-medic\",\"valueReference\":{\"reference\":\"" + + organizationId.toVersionless().getValue() + "\"}}]"); + break; - return results; - } + case TTP: + statement.setString(3, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-ttp\",\"valueReference\":{\"reference\":\"" + + organizationId.getValue() + "\"}}]"); + statement.setString(4, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-ttp\",\"valueReference\":{\"reference\":\"" + + organizationId.toVersionless().getValue() + "\"}}]"); + break; } } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/GroupUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/GroupUserFilter.java index 7ad2da8af..32c16e539 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/GroupUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/GroupUserFilter.java @@ -4,13 +4,10 @@ import java.sql.SQLException; import org.highmed.dsf.fhir.authentication.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.highmed.dsf.fhir.authentication.UserRole; public class GroupUserFilter extends AbstractUserFilter { - private static final Logger logger = LoggerFactory.getLogger(GroupUserFilter.class); - public GroupUserFilter(User user) { super(user); @@ -19,24 +16,54 @@ public GroupUserFilter(User user) @Override public String getFilterQuery() { - // TODO implement - - logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); - return "false"; + if (UserRole.LOCAL.equals(user.getRole())) + return ""; + else + return "(concat('Group/', group->>'id') IN " + + "(SELECT enrollment->>'reference' FROM (SELECT jsonb_array_elements(research_study->'enrollment') AS enrollment FROM current_research_studies " + + "WHERE research_study->'extension' @> ?::jsonb OR research_study->'extension' @> ?::jsonb) AS enrollments))"; } @Override public int getSqlParameterCount() { - logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); - return 0; + return UserRole.LOCAL.equals(user.getRole()) ? 0 : 2; } @Override public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException { - // TODO implement + if (!UserRole.LOCAL.equals(user.getRole())) + { + switch (user.getOrganizationType()) + { + case MeDIC: + if (parameterIndex == 1) + statement.setString(parameterIndex, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-medic\",\"valueReference\":{\"reference\":\"" + + user.getOrganization().getIdElement().getValue() + "\"}}]"); + else if (parameterIndex == 2) + statement.setString(parameterIndex, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-medic\",\"valueReference\":{\"reference\":\"" + + user.getOrganization().getIdElement().toVersionless().getValue() + "\"}}]"); + break; + + case TTP: + if (parameterIndex == 1) + statement.setString(parameterIndex, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-ttp\",\"valueReference\":{\"reference\":\"" + + user.getOrganization().getIdElement().getValue() + "\"}}]"); + else if (parameterIndex == 2) + statement.setString(parameterIndex, + "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-ttp\",\"valueReference\":{\"reference\":\"" + + user.getOrganization().getIdElement().toVersionless().getValue() + "\"}}]"); + break; + } - logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + if (parameterIndex == 3) + statement.setString(parameterIndex, user.getOrganization().getIdElement().getValue()); + else if (parameterIndex == 4) + statement.setString(parameterIndex, user.getOrganization().getIdElement().toVersionless().getValue()); + } } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerUserFilter.java index 537c30749..1402f74a1 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PractitionerUserFilter.java @@ -21,10 +21,11 @@ public String getFilterQuery() else // Practitioner part of ResearchStudy as principal investigator and users Organization part of same // ResearchStudy or - // Practitioner part of PractitionerRole and users Organization part of same PractitionerRole return "(concat('Practitioner/', practitioner->>'id') IN (" + "SELECT research_study->'principalInvestigator'->>'reference' FROM current_research_studies WHERE " + "research_study->'extension' @> ?::jsonb OR research_study->'extension' @> ?::jsonb) OR " + + // Practitioner part of PractitionerRole and users Organization part of same PractitionerRole + "concat('Practitioner/', practitioner->>'id') IN (" + "SELECT practitioner_role->'practitioner'->>'reference' FROM current_practitioner_roles WHERE " + "practitioner_role->'organization'->>'reference' = ? OR practitioner_role->'organization'->>'reference' = ?))"; @@ -53,7 +54,7 @@ else if (parameterIndex == 2) "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/participating-medic\",\"valueReference\":{\"reference\":\"" + user.getOrganization().getIdElement().toVersionless().getValue() + "\"}}]"); break; - + case TTP: if (parameterIndex == 1) statement.setString(parameterIndex, diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ResearchStudyDaoTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ResearchStudyDaoTest.java index c50d44f59..4125a0fc3 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ResearchStudyDaoTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/dao/ResearchStudyDaoTest.java @@ -1,12 +1,11 @@ package org.highmed.dsf.fhir.dao; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import java.sql.Connection; import java.util.Date; import java.util.GregorianCalendar; -import java.util.List; import java.util.UUID; import org.apache.commons.dbcp2.BasicDataSource; @@ -90,11 +89,38 @@ public void testReadByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationI try (Connection connection = dao.newReadWriteTransaction()) { - List<ResearchStudy> rss = dao - .readByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationIdWithTransaction(connection, - new IdType(piReference), OrganizationType.TTP, new IdType(orgReference)); - assertNotNull(rss); - assertEquals(1, rss.size()); + boolean exists = dao.existsByPrincipalInvestigatorIdAndOrganizationTypeAndOrganizationIdWithTransaction( + connection, new IdType(piReference), OrganizationType.TTP, new IdType(orgReference)); + assertTrue(exists); + } + } + + @Test + public void testReadByEnrollmentIdAndOrganizationTypeAndOrganizationIdWithTransaction() throws Exception + { + String enrollmentReference1 = "Group/" + UUID.randomUUID().toString(); + String enrollmentReference2 = "Group/" + UUID.randomUUID().toString(); + String orgReference = "Organization/" + UUID.randomUUID().toString(); + + ResearchStudy r = new ResearchStudy(); + r.addEnrollment(new Reference(enrollmentReference1)); + r.addEnrollment(new Reference(enrollmentReference2)); + r.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-ttp") + .setValue(new Reference("Organization/" + UUID.randomUUID().toString())); + r.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-medic") + .setValue(new Reference(orgReference)); + r.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-medic") + .setValue(new Reference("Organization/" + UUID.randomUUID().toString())); + + logger.debug(fhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(r)); + + dao.create(r); + + try (Connection connection = dao.newReadWriteTransaction()) + { + boolean exists = dao.existsByEnrollmentIdAndOrganizationTypeAndOrganizationIdWithTransaction(connection, + new IdType(enrollmentReference1), OrganizationType.MeDIC, new IdType(orgReference)); + assertTrue(exists); } } } From e68d34223c8519c6c5e406bb4e21b9b9693ec18d Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 12:35:24 +0100 Subject: [PATCH 22/55] ActivityDefinitions for all processes, requesting/receiving org type Process authorization extension now differentiates between requesting and receiving organization type, this allows for specifying the organization type that can execute a process --- .../resources/computeSimpleFeasibility.bpmn | 102 ++++++------ .../resources/executeSimpleFeasibility.bpmn | 156 +++++++++--------- .../resources/requestSimpleFeasibility.bpmn | 56 +++---- .../src/main/resources/ping.bpmn | 4 +- .../src/main/resources/pong.bpmn | 4 +- .../resources/executeUpdateResources.bpmn | 15 +- .../resources/requestUpdateResources.bpmn | 4 +- .../src/main/resources/updateWhiteListe.bpmn | 4 +- .../ActivityDefinitionProvider.java | 4 +- .../ActivityDefinitionProviderImpl.java | 38 ++++- .../authorization/TaskAuthorizationRule.java | 4 +- .../dsf/fhir/dao/ActivityDefinitionDao.java | 5 +- .../dao/jdbc/ActivityDefinitionDaoJdbc.java | 17 +- .../computeSimpleFeasibility-0.1.0.xml | 86 ++++++++++ ...=> computeSimpleFeasibility-0.1.0.xml.put} | 2 +- .../executeSimpleFeasibility-0.1.0.xml | 56 +++++++ .../executeSimpleFeasibility-0.1.0.xml.put | 1 + .../executeUpdateResources-0.1.0.xml | 62 +++++++ .../executeUpdateResources-0.1.0.xml.put | 1 + .../{ping-1.0.0.xml => ping-0.1.0.xml} | 50 ++++-- ...{ping-1.0.0.xml.put => ping-0.1.0.xml.put} | 2 +- .../{pong-1.0.0.xml => pong-0.1.0.xml} | 26 ++- .../ActivityDefinition/pong-0.1.0.xml.put | 1 + ...xml => requestSimpleFeasibility-0.1.0.xml} | 30 +++- ...=> requestSimpleFeasibility-0.1.0.xml.put} | 2 +- .../requestUpdateResources-0.1.0.xml | 56 +++++++ .../requestUpdateResources-0.1.0.xml.put | 1 + .../updateWhiteList-0.1.0.xml | 56 +++++++ .../updateWhiteList-0.1.0.xml.put | 1 + ...-extension-process-authorization-0.1.0.xml | 77 +++++++-- .../fhir/integration/TaskIntegrationTest.java | 12 +- .../resources/integration/task-bundle.json | 2 +- 32 files changed, 691 insertions(+), 246 deletions(-) create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/computeSimpleFeasibility-0.1.0.xml rename dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/{pong-1.0.0.xml.put => computeSimpleFeasibility-0.1.0.xml.put} (88%) create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeSimpleFeasibility-0.1.0.xml create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeSimpleFeasibility-0.1.0.xml.put create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml.put rename dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/{ping-1.0.0.xml => ping-0.1.0.xml} (58%) rename dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/{ping-1.0.0.xml.put => ping-0.1.0.xml.put} (88%) rename dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/{pong-1.0.0.xml => pong-0.1.0.xml} (64%) create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-0.1.0.xml.put rename dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/{requestSimpleFeasibility-1.0.0.xml => requestSimpleFeasibility-0.1.0.xml} (70%) rename dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/{requestSimpleFeasibility-1.0.0.xml.put => requestSimpleFeasibility-0.1.0.xml.put} (69%) create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestUpdateResources-0.1.0.xml create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestUpdateResources-0.1.0.xml.put create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/updateWhiteList-0.1.0.xml create mode 100644 dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/updateWhiteList-0.1.0.xml.put diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/computeSimpleFeasibility.bpmn b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/computeSimpleFeasibility.bpmn index 57484c1e7..bf23ee2a0 100644 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/computeSimpleFeasibility.bpmn +++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/computeSimpleFeasibility.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1yff9tp" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="2.2.4"> - <bpmn:process id="computeSimpleFeasibility" isExecutable="true" camunda:versionTag="1.0.0"> +<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1yff9tp" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.5.0"> + <bpmn:process id="computeSimpleFeasibility" isExecutable="true" camunda:versionTag="0.1.0"> <bpmn:subProcess id="SubProcess_1gopxt4"> <bpmn:incoming>SequenceFlow_1lfe4wr</bpmn:incoming> <bpmn:outgoing>SequenceFlow_0xxpamp</bpmn:outgoing> @@ -103,122 +103,122 @@ <bpmndi:BPMNDiagram id="BPMNDiagram_1"> <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="computeSimpleFeasibility"> <bpmndi:BPMNShape id="SubProcess_1gopxt4_di" bpmnElement="SubProcess_1gopxt4" isExpanded="true"> - <dc:Bounds x="289" y="65" width="498" height="134" /> + <dc:Bounds x="469" y="175" width="498" height="134" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="ServiceTask_1ae0fdh_di" bpmnElement="calculateMultimedicCohortSize"> - <dc:Bounds x="1369" y="92" width="100" height="80" /> + <dc:Bounds x="1549" y="202" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="BoundaryEvent_1g0rcyp_di" bpmnElement="BoundaryEvent_1g0rcyp"> - <dc:Bounds x="769" y="181" width="36" height="36" /> + <dc:Bounds x="949" y="291" width="36" height="36" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="EndEvent_01cb50v_di" bpmnElement="EndEvent_01cb50v"> - <dc:Bounds x="714" y="116" width="36" height="36" /> + <dc:Bounds x="894" y="226" width="36" height="36" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="ServiceTask_0yjis46_di" bpmnElement="temporarillyStoreQueryResults"> - <dc:Bounds x="566" y="94" width="100" height="80" /> + <dc:Bounds x="746" y="204" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="ReceiveTask_0533fm9_di" bpmnElement="receiveQueryResultsFromMeDIC"> - <dc:Bounds x="403" y="94" width="100" height="80" /> + <dc:Bounds x="583" y="204" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="StartEvent_17r90ez_di" bpmnElement="SubStartEvent"> - <dc:Bounds x="313" y="116" width="36" height="36" /> + <dc:Bounds x="493" y="226" width="36" height="36" /> <bpmndi:BPMNLabel> <dc:Bounds x="320" y="159" width="22" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_0qjt33w_di" bpmnElement="SequenceFlow_0qjt33w"> - <di:waypoint x="349" y="134" /> - <di:waypoint x="403" y="134" /> + <di:waypoint x="529" y="244" /> + <di:waypoint x="583" y="244" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_0by0at7_di" bpmnElement="SequenceFlow_0by0at7"> - <di:waypoint x="503" y="134" /> - <di:waypoint x="566" y="134" /> + <di:waypoint x="683" y="244" /> + <di:waypoint x="746" y="244" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_0mj024w_di" bpmnElement="SequenceFlow_0mj024w"> - <di:waypoint x="666" y="134" /> - <di:waypoint x="714" y="134" /> + <di:waypoint x="846" y="244" /> + <di:waypoint x="894" y="244" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="StartEvent_1skbvzb_di" bpmnElement="StartEvent"> - <dc:Bounds x="-21" y="114" width="36" height="36" /> + <dc:Bounds x="159" y="224" width="36" height="36" /> <bpmndi:BPMNLabel> - <dc:Bounds x="-14" y="157" width="22" height="14" /> + <dc:Bounds x="166" y="267" width="23" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="EndEvent_0xh5o35_di" bpmnElement="EndEvent"> - <dc:Bounds x="1758" y="114" width="36" height="36" /> + <dc:Bounds x="1938" y="224" width="36" height="36" /> <bpmndi:BPMNLabel> - <dc:Bounds x="1734" y="157" width="85" height="27" /> + <dc:Bounds x="1914" y="267" width="85" height="27" /> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_0ru8qx9_di" bpmnElement="SequenceFlow_0ru8qx9"> - <di:waypoint x="1469" y="132" /> - <di:waypoint x="1552" y="132" /> + <di:waypoint x="1649" y="242" /> + <di:waypoint x="1732" y="242" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_01pjftq_di" bpmnElement="SequenceFlow_01pjftq"> - <di:waypoint x="15" y="132" /> - <di:waypoint x="99" y="132" /> + <di:waypoint x="195" y="242" /> + <di:waypoint x="279" y="242" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_1lfe4wr_di" bpmnElement="SequenceFlow_1lfe4wr"> - <di:waypoint x="199" y="132" /> - <di:waypoint x="289" y="132" /> + <di:waypoint x="379" y="242" /> + <di:waypoint x="469" y="242" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="ExclusiveGateway_07e71aa_di" bpmnElement="ExclusiveGateway_07e71aa" isMarkerVisible="true"> - <dc:Bounds x="893" y="107" width="50" height="50" /> + <dc:Bounds x="1073" y="217" width="50" height="50" /> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_0xxpamp_di" bpmnElement="SequenceFlow_0xxpamp"> - <di:waypoint x="787" y="132" /> - <di:waypoint x="893" y="132" /> + <di:waypoint x="967" y="242" /> + <di:waypoint x="1073" y="242" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_0h3to47_di" bpmnElement="SequenceFlow_0h3to47"> - <di:waypoint x="805" y="199" /> - <di:waypoint x="918" y="199" /> - <di:waypoint x="918" y="157" /> + <di:waypoint x="985" y="309" /> + <di:waypoint x="1098" y="309" /> + <di:waypoint x="1098" y="267" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_0t4lx4v_di" bpmnElement="SequenceFlow_0t4lx4v"> - <di:waypoint x="943" y="132" /> - <di:waypoint x="1226" y="132" /> + <di:waypoint x="1123" y="242" /> + <di:waypoint x="1406" y="242" /> <bpmndi:BPMNLabel> - <dc:Bounds x="948" y="114" width="21" height="14" /> + <dc:Bounds x="1128" y="224" width="21" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_0calilw_di" bpmnElement="SequenceFlow_0calilw"> - <di:waypoint x="918" y="107" /> - <di:waypoint x="918" y="16" /> - <di:waypoint x="1015" y="16" /> + <di:waypoint x="1098" y="217" /> + <di:waypoint x="1098" y="126" /> + <di:waypoint x="1195" y="126" /> <bpmndi:BPMNLabel> - <dc:Bounds x="923" y="23" width="65" height="27" /> + <dc:Bounds x="1103" y="133" width="65" height="27" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="ServiceTask_093hq2s_di" bpmnElement="executeEpiLink"> - <dc:Bounds x="1015" y="-24" width="100" height="80" /> + <dc:Bounds x="1195" y="86" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_02zmrer_di" bpmnElement="SequenceFlow_02zmrer"> - <di:waypoint x="1115" y="16" /> - <di:waypoint x="1201" y="16" /> + <di:waypoint x="1295" y="126" /> + <di:waypoint x="1381" y="126" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="ServiceTask_1rlgjc0_di" bpmnElement="countIds"> - <dc:Bounds x="1201" y="-24" width="100" height="80" /> + <dc:Bounds x="1381" y="86" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="ExclusiveGateway_1r8ow3i_di" bpmnElement="ExclusiveGateway_1r8ow3i" isMarkerVisible="true"> - <dc:Bounds x="1226" y="107" width="50" height="50" /> + <dc:Bounds x="1406" y="217" width="50" height="50" /> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_1lu3gr1_di" bpmnElement="SequenceFlow_1lu3gr1"> - <di:waypoint x="1276" y="132" /> - <di:waypoint x="1369" y="132" /> + <di:waypoint x="1456" y="242" /> + <di:waypoint x="1549" y="242" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_1sevjlz_di" bpmnElement="SequenceFlow_1sevjlz"> - <di:waypoint x="1251" y="56" /> - <di:waypoint x="1251" y="107" /> + <di:waypoint x="1431" y="166" /> + <di:waypoint x="1431" y="217" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="ServiceTask_0bw310g_di" bpmnElement="storeCorrelationKeys"> - <dc:Bounds x="99" y="92" width="100" height="80" /> + <dc:Bounds x="279" y="202" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_0brvdlv_di" bpmnElement="SequenceFlow_0brvdlv"> - <di:waypoint x="1652" y="132" /> - <di:waypoint x="1758" y="132" /> + <di:waypoint x="1832" y="242" /> + <di:waypoint x="1938" y="242" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="ServiceTask_0uk3eyz_di" bpmnElement="selectResponseTargetMedic"> - <dc:Bounds x="1552" y="92" width="100" height="80" /> + <dc:Bounds x="1732" y="202" width="100" height="80" /> </bpmndi:BPMNShape> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/executeSimpleFeasibility.bpmn b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/executeSimpleFeasibility.bpmn index be91156ff..27749ab15 100755 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/executeSimpleFeasibility.bpmn +++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/executeSimpleFeasibility.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0drkcb5" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="2.2.4"> - <bpmn:process id="executeSimpleFeasibility" isExecutable="true" camunda:versionTag="1.0.0"> +<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0drkcb5" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.5.0"> + <bpmn:process id="executeSimpleFeasibility" isExecutable="true" camunda:versionTag="0.1.0"> <bpmn:serviceTask id="checkResults" name="check results" camunda:class="org.highmed.dsf.bpe.service.CheckSingleMedicResults"> <bpmn:incoming>SequenceFlow_0q803rh</bpmn:incoming> <bpmn:outgoing>SequenceFlow_04ouilq</bpmn:outgoing> @@ -134,180 +134,180 @@ <bpmndi:BPMNDiagram id="BPMNDiagram_1"> <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="executeSimpleFeasibility"> <bpmndi:BPMNShape id="ServiceTask_0t2s0v7_di" bpmnElement="checkResults"> - <dc:Bounds x="1450" y="102" width="100" height="80" /> + <dc:Bounds x="1820" y="232" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="ServiceTask_0jna5l2_di" bpmnElement="checkFeasibilityResources"> - <dc:Bounds x="100" y="102" width="100" height="80" /> + <dc:Bounds x="470" y="232" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="StartEvent_1fzso6r_di" bpmnElement="StartEvent"> - <dc:Bounds x="-209" y="124" width="36" height="36" /> + <dc:Bounds x="161" y="254" width="36" height="36" /> <bpmndi:BPMNLabel> - <dc:Bounds x="-202" y="167" width="22" height="14" /> + <dc:Bounds x="168" y="297" width="23" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="TextAnnotation_0euut3n_di" bpmnElement="TextAnnotation_0euut3n"> - <dc:Bounds x="16" y="22" width="267" height="56" /> + <dc:Bounds x="386" y="152" width="267" height="56" /> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_1rmqv20_di" bpmnElement="SequenceFlow_1rmqv20"> - <di:waypoint x="826" y="142" /> - <di:waypoint x="878" y="142" /> + <di:waypoint x="1196" y="272" /> + <di:waypoint x="1248" y="272" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_1wwn9pl_di" bpmnElement="SequenceFlow_1wwn9pl"> - <di:waypoint x="200" y="142" /> - <di:waypoint x="289" y="142" /> + <di:waypoint x="570" y="272" /> + <di:waypoint x="659" y="272" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_14cn0vs_di" bpmnElement="SequenceFlow_14cn0vs"> - <di:waypoint x="-173" y="142" /> - <di:waypoint x="-80" y="142" /> + <di:waypoint x="197" y="272" /> + <di:waypoint x="290" y="272" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Association_1ncewqu_di" bpmnElement="Association_1ncewqu"> - <di:waypoint x="150" y="102" /> - <di:waypoint x="150" y="78" /> + <di:waypoint x="520" y="232" /> + <di:waypoint x="520" y="208" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_1etju4m_di" bpmnElement="SequenceFlow_1etju4m"> - <di:waypoint x="20" y="142" /> - <di:waypoint x="100" y="142" /> + <di:waypoint x="390" y="272" /> + <di:waypoint x="470" y="272" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="ServiceTask_0b8j3ka_di" bpmnElement="downloadFeasibilityResources"> - <dc:Bounds x="-80" y="102" width="100" height="80" /> + <dc:Bounds x="290" y="232" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="EndEvent_10xdh63_di" bpmnElement="EndEvent"> - <dc:Bounds x="1831" y="124" width="36" height="36" /> + <dc:Bounds x="2201" y="254" width="36" height="36" /> <bpmndi:BPMNLabel> - <dc:Bounds x="1804" y="167" width="90" height="14" /> + <dc:Bounds x="2186" y="297" width="67" height="27" /> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_04ouilq_di" bpmnElement="SequenceFlow_04ouilq"> - <di:waypoint x="1550" y="142" /> - <di:waypoint x="1636" y="142" /> + <di:waypoint x="1920" y="272" /> + <di:waypoint x="2006" y="272" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_07wtgee_di" bpmnElement="SequenceFlow_07wtgee"> - <di:waypoint x="389" y="142" /> - <di:waypoint x="457" y="142" /> + <di:waypoint x="759" y="272" /> + <di:waypoint x="827" y="272" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="ServiceTask_1pt9xhp_di" bpmnElement="checkQueries"> - <dc:Bounds x="289" y="102" width="100" height="80" /> + <dc:Bounds x="659" y="232" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="ExclusiveGateway_1dln3in_di" bpmnElement="ExclusiveGateway_1dln3in" isMarkerVisible="true"> - <dc:Bounds x="457" y="117" width="50" height="50" /> + <dc:Bounds x="827" y="247" width="50" height="50" /> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_0zlq6j4_di" bpmnElement="SequenceFlow_0zlq6j4"> - <di:waypoint x="507" y="142" /> - <di:waypoint x="613" y="142" /> + <di:waypoint x="877" y="272" /> + <di:waypoint x="983" y="272" /> <bpmndi:BPMNLabel> - <dc:Bounds x="512" y="124" width="21" height="14" /> + <dc:Bounds x="882" y="254" width="21" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_0yqpkri_di" bpmnElement="SequenceFlow_0yqpkri"> - <di:waypoint x="482" y="117" /> - <di:waypoint x="482" y="11" /> - <di:waypoint x="588" y="11" /> + <di:waypoint x="852" y="247" /> + <di:waypoint x="852" y="141" /> + <di:waypoint x="958" y="141" /> <bpmndi:BPMNLabel> - <dc:Bounds x="492" y="16" width="72" height="40" /> + <dc:Bounds x="862" y="146" width="73" height="40" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="ServiceTask_02nwn9u_di" bpmnElement="replaceCountpartWithIdSelection"> - <dc:Bounds x="588" y="-29" width="100" height="80" /> + <dc:Bounds x="958" y="101" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="ExclusiveGateway_1r4c9fx_di" bpmnElement="ExclusiveGateway_1r4c9fx" isMarkerVisible="true"> - <dc:Bounds x="613" y="117" width="50" height="50" /> + <dc:Bounds x="983" y="247" width="50" height="50" /> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_0bwn08k_di" bpmnElement="SequenceFlow_0bwn08k"> - <di:waypoint x="663" y="142" /> - <di:waypoint x="726" y="142" /> + <di:waypoint x="1033" y="272" /> + <di:waypoint x="1096" y="272" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_1u1p9j2_di" bpmnElement="SequenceFlow_1u1p9j2"> - <di:waypoint x="638" y="51" /> - <di:waypoint x="638" y="117" /> + <di:waypoint x="1008" y="181" /> + <di:waypoint x="1008" y="247" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="ExclusiveGateway_0bq7zdz_di" bpmnElement="ExclusiveGateway_0bq7zdz" isMarkerVisible="true"> - <dc:Bounds x="878" y="117" width="50" height="50" /> + <dc:Bounds x="1248" y="247" width="50" height="50" /> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_05r9whd_di" bpmnElement="SequenceFlow_05r9whd"> - <di:waypoint x="928" y="142" /> - <di:waypoint x="1029" y="142" /> + <di:waypoint x="1298" y="272" /> + <di:waypoint x="1399" y="272" /> <bpmndi:BPMNLabel> - <dc:Bounds x="932" y="125" width="21" height="14" /> + <dc:Bounds x="1302" y="255" width="21" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_0isxkuy_di" bpmnElement="SequenceFlow_0isxkuy"> - <di:waypoint x="903" y="167" /> - <di:waypoint x="903" y="285" /> - <di:waypoint x="1004" y="285" /> + <di:waypoint x="1273" y="297" /> + <di:waypoint x="1273" y="415" /> + <di:waypoint x="1374" y="415" /> <bpmndi:BPMNLabel> - <dc:Bounds x="912" y="253" width="72" height="27" /> + <dc:Bounds x="1282" y="383" width="73" height="27" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="ServiceTask_0l3b9as_di" bpmnElement="filterByConsent"> - <dc:Bounds x="1004" y="245" width="100" height="80" /> + <dc:Bounds x="1374" y="375" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="ExclusiveGateway_0lecmy5_di" bpmnElement="ExclusiveGateway_0lecmy5" isMarkerVisible="true"> - <dc:Bounds x="1029" y="117" width="50" height="50" /> + <dc:Bounds x="1399" y="247" width="50" height="50" /> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_1b4h5qz_di" bpmnElement="SequenceFlow_1b4h5qz"> - <di:waypoint x="1079" y="142" /> - <di:waypoint x="1163" y="142" /> + <di:waypoint x="1449" y="272" /> + <di:waypoint x="1533" y="272" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_0kzp6tl_di" bpmnElement="SequenceFlow_0kzp6tl"> - <di:waypoint x="1054" y="245" /> - <di:waypoint x="1054" y="167" /> + <di:waypoint x="1424" y="375" /> + <di:waypoint x="1424" y="297" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="ExclusiveGateway_0sff9xb_di" bpmnElement="ExclusiveGateway_0sff9xb" isMarkerVisible="true"> - <dc:Bounds x="1163" y="117" width="50" height="50" /> + <dc:Bounds x="1533" y="247" width="50" height="50" /> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_17otl7p_di" bpmnElement="SequenceFlow_17otl7p"> - <di:waypoint x="1213" y="142" /> - <di:waypoint x="1316" y="142" /> + <di:waypoint x="1583" y="272" /> + <di:waypoint x="1686" y="272" /> <bpmndi:BPMNLabel> - <dc:Bounds x="1215" y="124" width="21" height="14" /> + <dc:Bounds x="1585" y="254" width="21" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_1futlo2_di" bpmnElement="SequenceFlow_1futlo2"> - <di:waypoint x="1188" y="167" /> - <di:waypoint x="1188" y="285" /> - <di:waypoint x="1291" y="285" /> + <di:waypoint x="1558" y="297" /> + <di:waypoint x="1558" y="415" /> + <di:waypoint x="1661" y="415" /> <bpmndi:BPMNLabel> - <dc:Bounds x="1195" y="250" width="65" height="27" /> + <dc:Bounds x="1565" y="380" width="65" height="27" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="ServiceTask_0akkess_di" bpmnElement="generateBloomFilters"> - <dc:Bounds x="1291" y="245" width="100" height="80" /> + <dc:Bounds x="1661" y="375" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="ExclusiveGateway_002t87f_di" bpmnElement="ExclusiveGateway_002t87f" isMarkerVisible="true"> - <dc:Bounds x="1316" y="117" width="50" height="50" /> + <dc:Bounds x="1686" y="247" width="50" height="50" /> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_0q803rh_di" bpmnElement="SequenceFlow_0q803rh"> - <di:waypoint x="1366" y="142" /> - <di:waypoint x="1450" y="142" /> + <di:waypoint x="1736" y="272" /> + <di:waypoint x="1820" y="272" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_1ug2kru_di" bpmnElement="SequenceFlow_1ug2kru"> - <di:waypoint x="1341" y="245" /> - <di:waypoint x="1341" y="167" /> + <di:waypoint x="1711" y="375" /> + <di:waypoint x="1711" y="297" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_0kfeekm_di" bpmnElement="SequenceFlow_0kfeekm"> - <di:waypoint x="1188" y="117" /> - <di:waypoint x="1188" y="-10" /> - <di:waypoint x="1291" y="-10" /> + <di:waypoint x="1558" y="247" /> + <di:waypoint x="1558" y="120" /> + <di:waypoint x="1661" y="120" /> <bpmndi:BPMNLabel> - <dc:Bounds x="1194" y="-5" width="72" height="40" /> + <dc:Bounds x="1564" y="125" width="73" height="40" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_1kpvsx9_di" bpmnElement="SequenceFlow_1kpvsx9"> - <di:waypoint x="1341" y="30" /> - <di:waypoint x="1341" y="117" /> + <di:waypoint x="1711" y="160" /> + <di:waypoint x="1711" y="247" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="ServiceTask_17kpyle_di" bpmnElement="countIds"> - <dc:Bounds x="1291" y="-50" width="100" height="80" /> + <dc:Bounds x="1661" y="80" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_0ascyjc_di" bpmnElement="SequenceFlow_0ascyjc"> - <di:waypoint x="1736" y="142" /> - <di:waypoint x="1831" y="142" /> + <di:waypoint x="2106" y="272" /> + <di:waypoint x="2201" y="272" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="ServiceTask_15aifhd_di" bpmnElement="selectResponseTargetTtp"> - <dc:Bounds x="1636" y="102" width="100" height="80" /> + <dc:Bounds x="2006" y="232" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="ServiceTask_0u5pb4i_di" bpmnElement="executeQueries"> - <dc:Bounds x="726" y="102" width="100" height="80" /> + <dc:Bounds x="1096" y="232" width="100" height="80" /> </bpmndi:BPMNShape> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/requestSimpleFeasibility.bpmn b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/requestSimpleFeasibility.bpmn index d7d18df3d..63cb4ee07 100755 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/requestSimpleFeasibility.bpmn +++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/requestSimpleFeasibility.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0inb4ax" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="2.2.4"> - <bpmn:process id="requestSimpleFeasibility" isExecutable="true" camunda:versionTag="1.0.0"> +<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0inb4ax" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.5.0"> + <bpmn:process id="requestSimpleFeasibility" isExecutable="true" camunda:versionTag="0.1.0"> <bpmn:startEvent id="StartEvent" name="start"> <bpmn:outgoing>SequenceFlow_11k77gx</bpmn:outgoing> <bpmn:messageEventDefinition id="MessageEventDefinition_10c2suu" messageRef="Message_1pq9qxp" /> @@ -75,67 +75,67 @@ <bpmndi:BPMNDiagram id="BPMNDiagram_1"> <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="requestSimpleFeasibility"> <bpmndi:BPMNShape id="StartEvent_1ozsjmr_di" bpmnElement="StartEvent"> - <dc:Bounds x="-108" y="117" width="36" height="36" /> + <dc:Bounds x="152" y="117" width="36" height="36" /> <bpmndi:BPMNLabel> - <dc:Bounds x="-101" y="160" width="22" height="14" /> + <dc:Bounds x="159" y="160" width="23" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="ServiceTask_0vfud44_di" bpmnElement="selectRequestTargetsAndGenerateKeys"> - <dc:Bounds x="221" y="95" width="100" height="80" /> + <dc:Bounds x="481" y="95" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="SendTask_1pu8i9n_di" bpmnElement="sendRequestToMedics"> - <dc:Bounds x="535" y="95" width="100" height="80" /> + <dc:Bounds x="795" y="95" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="ServiceTask_00phx5l_di" bpmnElement="checkFinalResult"> - <dc:Bounds x="865" y="95" width="100" height="80" /> + <dc:Bounds x="1125" y="95" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_11k77gx_di" bpmnElement="SequenceFlow_11k77gx"> - <di:waypoint x="-72" y="135" /> - <di:waypoint x="31" y="135" /> + <di:waypoint x="188" y="135" /> + <di:waypoint x="291" y="135" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_0b5s4ef_di" bpmnElement="SequenceFlow_0b5s4ef"> - <di:waypoint x="321" y="135" /> - <di:waypoint x="405" y="135" /> + <di:waypoint x="581" y="135" /> + <di:waypoint x="665" y="135" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_0h6ci9o_di" bpmnElement="SequenceFlow_0h6ci9o"> - <di:waypoint x="965" y="135" /> - <di:waypoint x="1067" y="135" /> + <di:waypoint x="1225" y="135" /> + <di:waypoint x="1327" y="135" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="ServiceTask_052xqjx_di" bpmnElement="downloadResearchStudyResource"> - <dc:Bounds x="31" y="95" width="100" height="80" /> + <dc:Bounds x="291" y="95" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="EndEvent_18syky8_di" bpmnElement="EndEvent"> - <dc:Bounds x="1067" y="117" width="36" height="36" /> + <dc:Bounds x="1327" y="117" width="36" height="36" /> <bpmndi:BPMNLabel> - <dc:Bounds x="1065" y="160" width="40" height="14" /> + <dc:Bounds x="1325" y="160" width="40" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_18ajfnh_di" bpmnElement="SequenceFlow_18ajfnh"> - <di:waypoint x="131" y="135" /> - <di:waypoint x="221" y="135" /> + <di:waypoint x="391" y="135" /> + <di:waypoint x="481" y="135" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_035oihl_di" bpmnElement="SequenceFlow_035oihl"> - <di:waypoint x="441" y="135" /> - <di:waypoint x="535" y="135" /> + <di:waypoint x="701" y="135" /> + <di:waypoint x="795" y="135" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="IntermediateThrowEvent_1yqfh9l_di" bpmnElement="sendCorreltationKeysToTTP"> - <dc:Bounds x="405" y="117" width="36" height="36" /> + <dc:Bounds x="665" y="117" width="36" height="36" /> <bpmndi:BPMNLabel> - <dc:Bounds x="384" y="160" width="79" height="27" /> + <dc:Bounds x="644" y="160" width="79" height="27" /> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="SequenceFlow_08xvdjp_di" bpmnElement="SequenceFlow_08xvdjp"> - <di:waypoint x="635" y="135" /> - <di:waypoint x="741" y="135" /> + <di:waypoint x="895" y="135" /> + <di:waypoint x="1001" y="135" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_0c2loil_di" bpmnElement="SequenceFlow_0c2loil"> - <di:waypoint x="777" y="135" /> - <di:waypoint x="865" y="135" /> + <di:waypoint x="1037" y="135" /> + <di:waypoint x="1125" y="135" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="IntermediateCatchEvent_1mozzkz_di" bpmnElement="receiveFinalResultFromTTP"> - <dc:Bounds x="741" y="117" width="36" height="36" /> + <dc:Bounds x="1001" y="117" width="36" height="36" /> <bpmndi:BPMNLabel> - <dc:Bounds x="721" y="160" width="76" height="27" /> + <dc:Bounds x="981" y="160" width="77" height="27" /> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> </bpmndi:BPMNPlane> diff --git a/dsf-bpe/dsf-bpe-process-ping/src/main/resources/ping.bpmn b/dsf-bpe/dsf-bpe-process-ping/src/main/resources/ping.bpmn index c5ed3cb6b..75ffb5316 100755 --- a/dsf-bpe/dsf-bpe-process-ping/src/main/resources/ping.bpmn +++ b/dsf-bpe/dsf-bpe-process-ping/src/main/resources/ping.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0azvmx1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="2.2.4"> - <bpmn:process id="ping" isExecutable="true" camunda:versionTag="1.0.0"> +<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_0azvmx1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.5.0"> + <bpmn:process id="ping" isExecutable="true" camunda:versionTag="0.1.0"> <bpmn:sequenceFlow id="SequenceFlow_0k1j79c" sourceRef="StartEvent_1" targetRef="selectTargets" /> <bpmn:sequenceFlow id="SequenceFlow_05ia6lz" sourceRef="selectTargets" targetRef="sendPing" /> <bpmn:serviceTask id="selectTargets" name="selectTargets" camunda:class="org.highmed.dsf.bpe.service.SelectPingTargets"> diff --git a/dsf-bpe/dsf-bpe-process-ping/src/main/resources/pong.bpmn b/dsf-bpe/dsf-bpe-process-ping/src/main/resources/pong.bpmn index 4a5a922d9..228eb1954 100755 --- a/dsf-bpe/dsf-bpe-process-ping/src/main/resources/pong.bpmn +++ b/dsf-bpe/dsf-bpe-process-ping/src/main/resources/pong.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_15v05m6" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="2.2.4"> - <bpmn:process id="pong" isExecutable="true" camunda:versionTag="1.0.0"> +<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_15v05m6" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.5.0"> + <bpmn:process id="pong" isExecutable="true" camunda:versionTag="0.1.0"> <bpmn:startEvent id="StartEvent_1"> <bpmn:outgoing>SequenceFlow_07w11cw</bpmn:outgoing> <bpmn:messageEventDefinition messageRef="Message_0u91abp" /> diff --git a/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/executeUpdateResources.bpmn b/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/executeUpdateResources.bpmn index a69cea747..7b323f8d6 100755 --- a/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/executeUpdateResources.bpmn +++ b/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/executeUpdateResources.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_0k0v4i2" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="2.2.4"> - <bpmn:process id="executeUpdateResources" isExecutable="true" camunda:versionTag="1.0.0"> +<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_0k0v4i2" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.5.0"> + <bpmn:process id="executeUpdateResources" isExecutable="true" camunda:versionTag="0.1.0"> <bpmn:startEvent id="StartEvent_1"> <bpmn:outgoing>SequenceFlow_0djh0eg</bpmn:outgoing> <bpmn:messageEventDefinition messageRef="Message_1r6vnvn" /> @@ -19,10 +19,6 @@ <bpmn:incoming>SequenceFlow_0djh0eg</bpmn:incoming> <bpmn:outgoing>SequenceFlow_141lpsf</bpmn:outgoing> </bpmn:serviceTask> - <bpmn:textAnnotation id="TextAnnotation_0rr4guv"> - <bpmn:text>TODO: add step to check requesting organization is of type TTP</bpmn:text> - </bpmn:textAnnotation> - <bpmn:association id="Association_1sc5e0d" sourceRef="updateResources" targetRef="TextAnnotation_0rr4guv" /> </bpmn:process> <bpmn:message id="Message_1r6vnvn" name="executeUpdateResourcesMessage" /> <bpmndi:BPMNDiagram id="BPMNDiagram_1"> @@ -44,13 +40,6 @@ <di:waypoint x="533" y="121" /> <di:waypoint x="622" y="121" /> </bpmndi:BPMNEdge> - <bpmndi:BPMNShape id="TextAnnotation_0rr4guv_di" bpmnElement="TextAnnotation_0rr4guv"> - <dc:Bounds x="357" y="189" width="228" height="43" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNEdge id="Association_1sc5e0d_di" bpmnElement="Association_1sc5e0d"> - <di:waypoint x="478" y="161" /> - <di:waypoint x="474" y="189" /> - </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="SequenceFlow_141lpsf_di" bpmnElement="SequenceFlow_141lpsf"> <di:waypoint x="357" y="121" /> <di:waypoint x="433" y="121" /> diff --git a/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/requestUpdateResources.bpmn b/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/requestUpdateResources.bpmn index 9d1d35224..9824b606f 100755 --- a/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/requestUpdateResources.bpmn +++ b/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/requestUpdateResources.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_0os0n0z" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="2.2.4"> - <bpmn:process id="requestUpdateResources" isExecutable="true" camunda:versionTag="1.0.0"> +<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_0os0n0z" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.5.0"> + <bpmn:process id="requestUpdateResources" isExecutable="true" camunda:versionTag="0.1.0"> <bpmn:sequenceFlow id="SequenceFlow_1ryplwc" sourceRef="StartEvent_1" targetRef="selectResourceAndTargets" /> <bpmn:sequenceFlow id="SequenceFlow_1u4zxix" sourceRef="selectResourceAndTargets" targetRef="sendRequest" /> <bpmn:endEvent id="EndEvent_1f9cjs7"> diff --git a/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/resources/updateWhiteListe.bpmn b/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/resources/updateWhiteListe.bpmn index 95321df87..96ee697b9 100755 --- a/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/resources/updateWhiteListe.bpmn +++ b/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/resources/updateWhiteListe.bpmn @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> -<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1yb5vw3" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="2.2.4"> - <bpmn:process id="updateWhiteList" isExecutable="true" camunda:versionTag="1.0.0"> +<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1yb5vw3" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.5.0"> + <bpmn:process id="updateWhiteList" isExecutable="true" camunda:versionTag="0.1.0"> <bpmn:sequenceFlow id="SequenceFlow_0bbhq2r" sourceRef="StartEvent_1" targetRef="updateWhiteListTask" /> <bpmn:endEvent id="EndEvent_0xd0x8k"> <bpmn:incoming>SequenceFlow_0oyvmcd</bpmn:incoming> diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProvider.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProvider.java index 6c884888e..abe3f4f42 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProvider.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProvider.java @@ -3,11 +3,11 @@ import java.sql.Connection; import java.util.Optional; -import org.highmed.dsf.fhir.authentication.UserRole; +import org.highmed.dsf.fhir.authentication.User; import org.hl7.fhir.r4.model.ActivityDefinition; public interface ActivityDefinitionProvider { - Optional<ActivityDefinition> getActivityDefinition(Connection connection, UserRole userRole, String processUrl, + Optional<ActivityDefinition> getActivityDefinition(Connection connection, User user, String processUrl, String processVersion, String messageName); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProviderImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProviderImpl.java index 200696b1b..d2a1a7405 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProviderImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProviderImpl.java @@ -6,7 +6,7 @@ import java.util.Optional; import org.highmed.dsf.fhir.OrganizationType; -import org.highmed.dsf.fhir.authentication.UserRole; +import org.highmed.dsf.fhir.authentication.User; import org.highmed.dsf.fhir.dao.ActivityDefinitionDao; import org.hl7.fhir.r4.model.ActivityDefinition; import org.slf4j.Logger; @@ -34,23 +34,45 @@ public void afterPropertiesSet() throws Exception } @Override - public Optional<ActivityDefinition> getActivityDefinition(Connection connection, UserRole userRole, - String processUrl, String processVersion, String messageName) + public Optional<ActivityDefinition> getActivityDefinition(Connection connection, User user, String processUrl, + String processVersion, String messageName) { + Objects.requireNonNull(connection, "connection"); + Objects.requireNonNull(user, "user"); + + if (processUrl == null || processUrl.isBlank()) + { + logger.warn("processUrl null or blank"); + return Optional.empty(); + } + else if (processVersion == null || processVersion.isBlank()) + { + logger.warn("processVersion null or blank"); + return Optional.empty(); + } + else if (messageName == null || messageName.isBlank()) + { + logger.warn("messageName null or blank"); + return Optional.empty(); + } + try { Optional<ActivityDefinition> optAD = dao .readByOrganizationTypeUserRoleProcessUrlVersionMessageNameAndNotRetiredWithTransaction(connection, - organizationType, userRole, processUrl, processVersion, messageName); + organizationType, user.getOrganizationType(), user.getRole(), processUrl, processVersion, + messageName); if (optAD.isPresent()) logger.debug( - "ActivityDefinition with organization-type {}, user-role {}, process-url {}, process-version {} and message-name {} found", - organizationType, userRole, processUrl, processVersion, messageName); + "ActivityDefinition with recipient-organization-type {}, requester-organization-type {}, user-role {}, process-url {}, process-version {} and message-name {} found", + organizationType, user.getOrganizationType(), user.getRole(), processUrl, processVersion, + messageName); else logger.warn( - "ActivityDefinition with organization-type {}, user-role {}, process-url {}, process-version {} and message-name {} not found", - organizationType, userRole, processUrl, processVersion, messageName); + "ActivityDefinition with recipient-organization-type {}, requester-organization-type {}, user-role {}, process-url {}, process-version {} and message-name {} not found", + organizationType, user.getOrganizationType(), user.getRole(), processUrl, processVersion, + messageName); return optAD; } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java index 424dc3ba6..64ba10025 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java @@ -196,8 +196,8 @@ private boolean taskAllowedForUser(Connection connection, User user, String inst String processVersion = matcher.group(2); return activityDefinitionProvider - .getActivityDefinition(connection, user.getRole(), processUrl, processVersion, messageName) - .map(ad -> true).orElse(false); + .getActivityDefinition(connection, user, processUrl, processVersion, messageName).map(ad -> true) + .orElse(false); } else return false; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDao.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDao.java index 04e44554a..e008d560c 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDao.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/ActivityDefinitionDao.java @@ -11,6 +11,7 @@ public interface ActivityDefinitionDao extends ResourceDao<ActivityDefinition>, ReadByUrlDao<ActivityDefinition> { Optional<ActivityDefinition> readByOrganizationTypeUserRoleProcessUrlVersionMessageNameAndNotRetiredWithTransaction( - Connection connection, OrganizationType organizationType, UserRole userRole, String processUrl, - String processVersion, String messageName) throws SQLException; + Connection connection, OrganizationType requesterOrganizationType, + OrganizationType recipientOrganizationType, UserRole userRole, String processUrl, String processVersion, + String messageName) throws SQLException; } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java index cb68b31c4..af013c443 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java @@ -69,11 +69,13 @@ public Optional<ActivityDefinition> readByUrlAndVersionWithTransaction(Connectio @Override public Optional<ActivityDefinition> readByOrganizationTypeUserRoleProcessUrlVersionMessageNameAndNotRetiredWithTransaction( - Connection connection, OrganizationType organizationType, UserRole userRole, String processUrl, - String processVersion, String messageName) throws SQLException + Connection connection, OrganizationType recipientOrganizationType, + OrganizationType requesterOrganizationType, UserRole userRole, String processUrl, String processVersion, + String messageName) throws SQLException { Objects.requireNonNull(connection, "connection"); - Objects.requireNonNull(organizationType, "organizationType"); + Objects.requireNonNull(recipientOrganizationType, "recipientOrganizationType"); + Objects.requireNonNull(requesterOrganizationType, "requesterOrganizationType"); Objects.requireNonNull(userRole, "userRole"); Objects.requireNonNull(processUrl, "processUrl"); if (processUrl.isBlank()) @@ -95,9 +97,12 @@ public Optional<ActivityDefinition> readByOrganizationTypeUserRoleProcessUrlVers + "{\"url\":\"message-name\",\"valueString\":\"" + messageName + "\"}," + "{\"url\":\"authorization-role\",\"valueCoding\":{\"code\":\"" + userRole.toString() + "\",\"system\":\"http://highmed.org/fhir/CodeSystem/authorization-role\"}}," - + "{\"url\":\"organization-types\",\"extension\":[{\"url\":\"organization-type\",\"valueCoding\":{\"code\":\"" - + organizationType.toString() - + "\",\"system\":\"http://highmed.org/fhir/CodeSystem/authorization-role\"}}]}]}]"; + + "{\"url\":\"requester-organization-types\",\"extension\":[{\"url\":\"requester-organization-type\",\"valueCoding\":{\"code\":\"" + + requesterOrganizationType.toString() + + "\",\"system\":\"http://highmed.org/fhir/CodeSystem/organization-type\"}}]}," + + "{\"url\":\"recipient-organization-types\",\"extension\":[{\"url\":\"recipient-organization-type\",\"valueCoding\":{\"code\":\"" + + recipientOrganizationType.toString() + + "\",\"system\":\"http://highmed.org/fhir/CodeSystem/organization-type\"}}]}]}]"; statement.setString(1, processUrl); statement.setString(2, processVersion); diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/computeSimpleFeasibility-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/computeSimpleFeasibility-0.1.0.xml new file mode 100644 index 000000000..7aa0529cb --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/computeSimpleFeasibility-0.1.0.xml @@ -0,0 +1,86 @@ +<ActivityDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </tag> + </meta> + <extension url="http://highmed.org/fhir/StructureDefinition/process-authorization"> + <extension url="message-name"> + <valueString value="computeSimpleFeasibilityMessage" /> + </extension> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </valueCoding> + </extension> + <extension url="requester-organization-types"> + <extension url="requester-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <extension url="recipient-organization-types"> + <extension url="recipient-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="TTP" /> + </valueCoding> + </extension> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/highmed-task-compute-simple-feasibility" /> + </extension> + </extension> + <extension url="http://highmed.org/fhir/StructureDefinition/process-authorization"> + <extension url="message-name"> + <valueString value="resultSingleMedicSimpleFeasibilityMessage" /> + </extension> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </valueCoding> + </extension> + <extension url="requester-organization-types"> + <extension url="requester-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <extension url="recipient-organization-types"> + <extension url="recipient-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="TTP" /> + </valueCoding> + </extension> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/highmed-task-single-medic-result-simple-feasibility" /> + </extension> + </extension> + <url value="http://highmed.org/bpe/Process/computeSimpleFeasibility" /> + <version value="0.1.0" /> + <name value="computeSimpleFeasibility" /> + <title value="Compute Simple Feasibility" /> + <subtitle value="Process to compute simple feasibility result" /> + <status value="draft" /> + <experimental value="true" /> + <date value="2020-03-10T12:12:12+01:00" /> + <publisher value="HiGHmed" /> + <contact> + <name value="HiGHmed" /> + <telecom> + <system value="email" /> + <value value="pmo@highmed.org" /> + </telecom> + </contact> + <description value="Process to compute a simple fesibility result and to send the result back to the requesting organization" /> + <kind value="Task" /> +</ActivityDefinition> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-1.0.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/computeSimpleFeasibility-0.1.0.xml.put similarity index 88% rename from dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-1.0.0.xml.put rename to dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/computeSimpleFeasibility-0.1.0.xml.put index b931cf16f..36a3ab2c7 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-1.0.0.xml.put +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/computeSimpleFeasibility-0.1.0.xml.put @@ -1 +1 @@ -ActivityDefinition?url=http://highmed.org/bpe/Process/pong&version=1.0.0 \ No newline at end of file +ActivityDefinition?url=http://highmed.org/bpe/Process/pong&version=0.1.0 \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeSimpleFeasibility-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeSimpleFeasibility-0.1.0.xml new file mode 100644 index 000000000..01eed0a6e --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeSimpleFeasibility-0.1.0.xml @@ -0,0 +1,56 @@ +<ActivityDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </tag> + </meta> + <extension url="http://highmed.org/fhir/StructureDefinition/process-authorization"> + <extension url="message-name"> + <valueString value="executeSimpleFeasibilityMessage" /> + </extension> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </valueCoding> + </extension> + <extension url="requester-organization-types"> + <extension url="requester-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <extension url="recipient-organization-types"> + <extension url="recipient-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/highmed-task-execute-simple-feasibility" /> + </extension> + </extension> + <url value="http://highmed.org/bpe/Process/executeSimpleFeasibility" /> + <version value="0.1.0" /> + <name value="ExecuteSimpleFeasibility" /> + <title value="Execute a Simple Feasibility" /> + <subtitle value="Process to execute a simple feasibility query" /> + <status value="draft" /> + <experimental value="true" /> + <date value="2020-03-10T12:05:00+01:00" /> + <publisher value="HiGHmed" /> + <contact> + <name value="HiGHmed" /> + <telecom> + <system value="email" /> + <value value="pmo@highmed.org" /> + </telecom> + </contact> + <description value="Process to execute a simple feasibility query received from a MeDIC and to send result to a TTP" /> + <kind value="Task" /> +</ActivityDefinition> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeSimpleFeasibility-0.1.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeSimpleFeasibility-0.1.0.xml.put new file mode 100644 index 000000000..e87d6183e --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeSimpleFeasibility-0.1.0.xml.put @@ -0,0 +1 @@ +ActivityDefinition?url=http://highmed.org/bpe/Process/executeSimpleFeasibility&version=0.1.0 \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml new file mode 100644 index 000000000..deb709504 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml @@ -0,0 +1,62 @@ +<ActivityDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </tag> + </meta> + <extension url="http://highmed.org/fhir/StructureDefinition/process-authorization"> + <extension url="message-name"> + <valueString value="updateWhitelistMessage" /> + </extension> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </valueCoding> + </extension> + <extension url="requester-organization-types"> + <extension url="requester-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="TTP" /> + </valueCoding> + </extension> + </extension> + <extension url="recipient-organization-types"> + <extension url="recipient-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="TTP" /> + </valueCoding> + </extension> + <extension url="recipient-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/highmed-task-execute-update-resources" /> + </extension> + </extension> + <url value="http://highmed.org/bpe/Process/executeUpdateResources" /> + <version value="0.1.0" /> + <name value="ExecuteUpdateResources" /> + <title value="Execute Update of Resources" /> + <subtitle value="Process to Download and Execute FHIR Bundle" /> + <status value="draft" /> + <experimental value="true" /> + <date value="2020-03-10T10:40:00+01:00" /> + <publisher value="HiGHmed" /> + <contact> + <name value="HiGHmed" /> + <telecom> + <system value="email" /> + <value value="pmo@highmed.org" /> + </telecom> + </contact> + <description value="Process to download and execute a FHIR bundle" /> + <kind value="Task" /> +</ActivityDefinition> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml.put new file mode 100644 index 000000000..c0170516e --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml.put @@ -0,0 +1 @@ +ActivityDefinition?url=http://highmed.org/bpe/Process/executeUpdateResources&version=0.1.0 \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-1.0.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-0.1.0.xml similarity index 58% rename from dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-1.0.0.xml rename to dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-0.1.0.xml index a63a9d27b..28c76c157 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-1.0.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-0.1.0.xml @@ -15,16 +15,30 @@ <code value="LOCAL" /> </valueCoding> </extension> - <extension url="organization-types"> - <extension url="organization-type"> + <extension url="requester-organization-types"> + <extension url="requester-organization-type"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> <code value="TTP" /> </valueCoding> </extension> - <extension url="organization-type"> + <extension url="requester-organization-type"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <extension url="recipient-organization-types"> + <extension url="recipient-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="TTP" /> + </valueCoding> + </extension> + <extension url="recipient-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> <code value="MeDIC" /> </valueCoding> </extension> @@ -43,16 +57,30 @@ <code value="REMOTE" /> </valueCoding> </extension> - <extension url="organization-types"> - <extension url="organization-type"> + <extension url="requester-organization-types"> + <extension url="requester-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="TTP" /> + </valueCoding> + </extension> + <extension url="requester-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <extension url="recipient-organization-types"> + <extension url="recipient-organization-type"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> <code value="TTP" /> </valueCoding> </extension> - <extension url="organization-type"> + <extension url="recipient-organization-type"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> <code value="MeDIC" /> </valueCoding> </extension> @@ -62,7 +90,7 @@ </extension> </extension> <url value="http://highmed.org/bpe/Process/ping" /> - <version value="1.0.0" /> + <version value="0.1.0" /> <name value="PingProcess" /> <title value="PING process" /> <subtitle value="Communication Testing Process" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-1.0.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-0.1.0.xml.put similarity index 88% rename from dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-1.0.0.xml.put rename to dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-0.1.0.xml.put index db076a001..f1518ab7f 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-1.0.0.xml.put +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-0.1.0.xml.put @@ -1 +1 @@ -ActivityDefinition?url=http://highmed.org/bpe/Process/ping&version=1.0.0 \ No newline at end of file +ActivityDefinition?url=http://highmed.org/bpe/Process/ping&version=0.1.0 \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-1.0.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-0.1.0.xml similarity index 64% rename from dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-1.0.0.xml rename to dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-0.1.0.xml index 72b3a1355..ee826646d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-1.0.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-0.1.0.xml @@ -15,16 +15,30 @@ <code value="REMOTE" /> </valueCoding> </extension> - <extension url="organization-types"> - <extension url="organization-type"> + <extension url="requester-organization-types"> + <extension url="requester-organization-type"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> <code value="TTP" /> </valueCoding> </extension> - <extension url="organization-type"> + <extension url="requester-organization-type"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <extension url="recipient-organization-types"> + <extension url="recipient-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="TTP" /> + </valueCoding> + </extension> + <extension url="recipient-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> <code value="MeDIC" /> </valueCoding> </extension> @@ -34,7 +48,7 @@ </extension> </extension> <url value="http://highmed.org/bpe/Process/pong" /> - <version value="1.0.0" /> + <version value="0.1.0" /> <name value="PongProcess" /> <title value="PONG process" /> <subtitle value="Communication Testing Process" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-0.1.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-0.1.0.xml.put new file mode 100644 index 000000000..36a3ab2c7 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-0.1.0.xml.put @@ -0,0 +1 @@ +ActivityDefinition?url=http://highmed.org/bpe/Process/pong&version=0.1.0 \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-1.0.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-0.1.0.xml similarity index 70% rename from dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-1.0.0.xml rename to dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-0.1.0.xml index 0fe350027..8acfc3533 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-1.0.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-0.1.0.xml @@ -15,10 +15,18 @@ <code value="LOCAL" /> </valueCoding> </extension> - <extension url="organization-types"> - <extension url="organization-type"> + <extension url="requester-organization-types"> + <extension url="requester-organization-type"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> + <extension url="recipient-organization-types"> + <extension url="recipient-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> <code value="MeDIC" /> </valueCoding> </extension> @@ -37,20 +45,28 @@ <code value="REMOTE" /> </valueCoding> </extension> - <extension url="organization-types"> - <extension url="organization-type"> + <extension url="requester-organization-types"> + <extension url="requester-organization-type"> <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> <code value="TTP" /> </valueCoding> </extension> </extension> + <extension url="recipient-organization-types"> + <extension url="recipient-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="MeDIC" /> + </valueCoding> + </extension> + </extension> <extension url="task-profile"> <valueCanonical value="http://highmed.org/fhir/StructureDefinition/highmed-task-multi-medic-result-simple-feasibility" /> </extension> </extension> <url value="http://highmed.org/bpe/Process/requestSimpleFeasibility" /> - <version value="1.0.0" /> + <version value="0.1.0" /> <name value="RequestSimpleFeasibility" /> <title value="Request simple feasibility" /> <subtitle value="Feasibility Request Process" /> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-1.0.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-0.1.0.xml.put similarity index 69% rename from dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-1.0.0.xml.put rename to dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-0.1.0.xml.put index 4ec0093b4..e2e134a4e 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-1.0.0.xml.put +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-0.1.0.xml.put @@ -1 +1 @@ -ActivityDefinition?url=http://highmed.org/bpe/Process/requestSimpleFeasibility&version=1.0.0 \ No newline at end of file +ActivityDefinition?url=http://highmed.org/bpe/Process/requestSimpleFeasibility&version=0.1.0 \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestUpdateResources-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestUpdateResources-0.1.0.xml new file mode 100644 index 000000000..ef01d0fd4 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestUpdateResources-0.1.0.xml @@ -0,0 +1,56 @@ +<ActivityDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </tag> + </meta> + <extension url="http://highmed.org/fhir/StructureDefinition/process-authorization"> + <extension url="message-name"> + <valueString value="requestUpdateResourcesMessage" /> + </extension> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="LOCAL" /> + </valueCoding> + </extension> + <extension url="requester-organization-types"> + <extension url="requester-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="TTP" /> + </valueCoding> + </extension> + </extension> + <extension url="recipient-organization-types"> + <extension url="recipient-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="TTP" /> + </valueCoding> + </extension> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/highmed-task-request-update-resources" /> + </extension> + </extension> + <url value="http://highmed.org/bpe/Process/requestUpdateResources" /> + <version value="0.1.0" /> + <name value="RequestUpdateResources" /> + <title value="Request Update of Resources" /> + <subtitle value="Process to Request a Bundle Download" /> + <status value="draft" /> + <experimental value="true" /> + <date value="2020-03-10T11:02:00+01:00" /> + <publisher value="HiGHmed" /> + <contact> + <name value="HiGHmed" /> + <telecom> + <system value="email" /> + <value value="pmo@highmed.org" /> + </telecom> + </contact> + <description value="Process to request the download of a bundle to update FHIR resources" /> + <kind value="Task" /> +</ActivityDefinition> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestUpdateResources-0.1.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestUpdateResources-0.1.0.xml.put new file mode 100644 index 000000000..0a2f93bb2 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestUpdateResources-0.1.0.xml.put @@ -0,0 +1 @@ +ActivityDefinition?url=http://highmed.org/bpe/Process/requestUpdateResources&version=0.1.0 \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/updateWhiteList-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/updateWhiteList-0.1.0.xml new file mode 100644 index 000000000..ada28c888 --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/updateWhiteList-0.1.0.xml @@ -0,0 +1,56 @@ +<ActivityDefinition xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </tag> + </meta> + <extension url="http://highmed.org/fhir/StructureDefinition/process-authorization"> + <extension url="message-name"> + <valueString value="updateWhitelistMessage" /> + </extension> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="LOCAL" /> + </valueCoding> + </extension> + <extension url="requester-organization-types"> + <extension url="requester-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="TTP" /> + </valueCoding> + </extension> + </extension> + <extension url="recipient-organization-types"> + <extension url="recipient-organization-type"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/organization-type" /> + <code value="TTP" /> + </valueCoding> + </extension> + </extension> + <extension url="task-profile"> + <valueCanonical value="http://highmed.org/fhir/StructureDefinition/highmed-task-update-whitelist" /> + </extension> + </extension> + <url value="http://highmed.org/bpe/Process/updateWhiteList" /> + <version value="0.1.0" /> + <name value="UpdateWhiteList" /> + <title value="Update White List" /> + <subtitle value="Update White List Bundle Process" /> + <status value="draft" /> + <experimental value="true" /> + <date value="2020-03-10T10:40:00+01:00" /> + <publisher value="HiGHmed" /> + <contact> + <name value="HiGHmed" /> + <telecom> + <system value="email" /> + <value value="pmo@highmed.org" /> + </telecom> + </contact> + <description value="Process to update the white list FHIR bundle" /> + <kind value="Task" /> +</ActivityDefinition> \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/updateWhiteList-0.1.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/updateWhiteList-0.1.0.xml.put new file mode 100644 index 000000000..c357f40ab --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/updateWhiteList-0.1.0.xml.put @@ -0,0 +1 @@ +ActivityDefinition?url=http://highmed.org/bpe/Process/updateWhiteList&version=1.0.0 \ No newline at end of file diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml index 1d77ca992..f7f03cefd 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml @@ -75,13 +75,13 @@ <path value="Extension.extension.value[x].code" /> <min value="1" /> </element> - <element id="Extension.extension:organization-types"> + <element id="Extension.extension:requester-organization-types"> <path value="Extension.extension" /> - <sliceName value="organization-types" /> + <sliceName value="requester-organization-types" /> <min value="1" /> <max value="1" /> </element> - <element id="Extension.extension:organization-types.extension"> + <element id="Extension.extension:requester-organization-types.extension"> <path value="Extension.extension.extension" /> <slicing> <discriminator> @@ -91,36 +91,85 @@ <rules value="open" /> </slicing> </element> - <element id="Extension.extension:organization-types.extension:organization-type"> + <element id="Extension.extension:requester-organization-types.extension:requester-organization-type"> <path value="Extension.extension.extension" /> - <sliceName value="organization-type" /> + <sliceName value="requester-organization-type" /> <min value="1" /> <max value="2" /> </element> - <element id="Extension.extension:organization-types.extension:organization-type.url"> + <element id="Extension.extension:requester-organization-types.extension:requester-organization-type.url"> <path value="Extension.extension.extension.url" /> - <fixedUri value="organization-type" /> + <fixedUri value="requester-organization-type" /> </element> - <element id="Extension.extension:organization-types.extension:organization-type.value[x]"> + <element id="Extension.extension:requester-organization-types.extension:requester-organization-type.value[x]"> <path value="Extension.extension.extension.value[x]" /> <type> <code value="Coding" /> </type> </element> - <element id="Extension.extension:organization-types.extension:organization-type.value[x].system"> + <element id="Extension.extension:requester-organization-types.extension:requester-organization-type.value[x].system"> <path value="Extension.extension.extension.value[x].system" /> <min value="1" /> - <fixedUri value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/organization-type" /> + </element> + <element id="Extension.extension:requester-organization-types.extension:requester-organization-type.value[x].code"> + <path value="Extension.extension.extension.value[x].code" /> + <min value="1" /> + </element> + <element id="Extension.extension:requester-organization-types.url"> + <path value="Extension.extension.url" /> + <fixedUri value="requester-organization-types" /> + </element> + <element id="Extension.extension:requester-organization-types.value[x]"> + <path value="Extension.extension.value[x]" /> + <max value="0" /> + </element> + <element id="Extension.extension:recipient-organization-types"> + <path value="Extension.extension" /> + <sliceName value="recipient-organization-types" /> + <min value="1" /> + <max value="1" /> + </element> + <element id="Extension.extension:recipient-organization-type.extension"> + <path value="Extension.extension.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> + </element> + <element id="Extension.extension:recipient-organization-types.extension:recipient-organization-type"> + <path value="Extension.extension.extension" /> + <sliceName value="recipient-organization-type" /> + <min value="1" /> + <max value="2" /> + </element> + <element id="Extension.extension:recipient-organization-types.extension:recipient-organization-type.url"> + <path value="Extension.extension.extension.url" /> + <fixedUri value="recipient-organization-type" /> + </element> + <element id="Extension.extension:recipient-organization-types.extension:recipient-organization-type.value[x]"> + <path value="Extension.extension.extension.value[x]" /> + <type> + <code value="Coding" /> + </type> + </element> + <element id="Extension.extension:recipient-organization-types.extension:recipient-organization-type.value[x].system"> + <path value="Extension.extension.extension.value[x].system" /> + <min value="1" /> + <fixedUri value="http://highmed.org/fhir/CodeSystem/organization-type" /> </element> - <element id="Extension.extension:organization-types.extension:organization-type.value[x].code"> + <element id="Extension.extension:recipient-organization-types.extension:recipient-organization-type.value[x].code"> <path value="Extension.extension.extension.value[x].code" /> <min value="1" /> </element> - <element id="Extension.extension:organization-types.url"> + <element id="Extension.extension:recipient-organization-types.url"> <path value="Extension.extension.url" /> - <fixedUri value="organization-types" /> + <fixedUri value="recipient-organization-types" /> </element> - <element id="Extension.extension:organization-types.value[x]"> + <element id="Extension.extension:recipient-organization-types.value[x]"> <path value="Extension.extension.value[x]" /> <max value="0" /> </element> diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java index f3a10b5b9..563c6d7f2 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java @@ -93,7 +93,7 @@ public void testCreateTaskStartPingProcess() throws Exception Task t = new Task(); t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"); - t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/1.0.0"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/0.1.0"); t.setStatus(TaskStatus.REQUESTED); t.setIntent(TaskIntent.ORDER); t.setAuthoredOn(new Date()); @@ -116,7 +116,7 @@ public void testCreateTaskStartPingProcessNotAllowedForRemoteUser() throws Excep Task t = new Task(); t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"); - t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/1.0.0"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/0.1.0"); t.setStatus(TaskStatus.REQUESTED); t.setIntent(TaskIntent.ORDER); t.setAuthoredOn(new Date()); @@ -151,7 +151,7 @@ public void testCreateTaskStartPongProcessAllowedForRemoteUser() throws Exceptio Task t = new Task(); t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-ping"); - t.setInstantiatesUri("http://highmed.org/bpe/Process/pong/1.0.0"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/pong/0.1.0"); t.setStatus(TaskStatus.REQUESTED); t.setIntent(TaskIntent.ORDER); t.setAuthoredOn(new Date()); @@ -178,7 +178,7 @@ public void testCreateTaskContinuePingProcessAllowedForRemoteUser() throws Excep Task t = new Task(); t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-pong"); - t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/1.0.0"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/0.1.0"); t.setStatus(TaskStatus.REQUESTED); t.setIntent(TaskIntent.ORDER); t.setAuthoredOn(new Date()); @@ -205,7 +205,7 @@ public void testUpdateTaskStartPingProcessStatusRequestedToInProgress() throws E Task t = new Task(); t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"); - t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/1.0.0"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/0.1.0"); t.setStatus(TaskStatus.REQUESTED); t.setIntent(TaskIntent.ORDER); t.setAuthoredOn(new Date()); @@ -234,7 +234,7 @@ public void testUpdateTaskStartPingProcessStatusInProgressToCompleted() throws E Task t = new Task(); t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"); - t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/1.0.0"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/0.1.0"); t.setStatus(TaskStatus.INPROGRESS); t.setIntent(TaskIntent.ORDER); t.setAuthoredOn(new Date()); diff --git a/dsf-fhir/dsf-fhir-server/src/test/resources/integration/task-bundle.json b/dsf-fhir/dsf-fhir-server/src/test/resources/integration/task-bundle.json index 7aba09dc8..ea4bfc76f 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/resources/integration/task-bundle.json +++ b/dsf-fhir/dsf-fhir-server/src/test/resources/integration/task-bundle.json @@ -186,7 +186,7 @@ "fullUrl": "urn:uuid:bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb", "resource": { "resourceType": "Task", - "instantiatesUri": "http://highmed.org/bpe/Process/requestSimpleFeasibility/1.0.0", + "instantiatesUri": "http://highmed.org/bpe/Process/requestSimpleFeasibility/0.1.0", "status": "requested", "intent": "order", "requester": { From 4d69aa7860d7604718ca4e6f1b43ab34f069e434 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 13:05:33 +0100 Subject: [PATCH 23/55] additional auth rules and user filters --- .../HealthcareServiceAuthorizationRule.java | 68 ++++++++++++++++--- .../LocationAuthorizationRule.java | 66 +++++++++++++++--- .../PatientAuthorizationRule.java | 58 +++++++++++++--- .../ProvenanceAuthorizationRule.java | 58 +++++++++++++--- .../parameters/user/PatientUserFilter.java | 18 ++--- .../parameters/user/ProvenanceUserFilter.java | 18 ++--- 6 files changed, 222 insertions(+), 64 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java index 04c550c59..bd3fdb272 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/HealthcareServiceAuthorizationRule.java @@ -9,10 +9,14 @@ import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.HealthcareService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class HealthcareServiceAuthorizationRule extends AbstractAuthorizationRule<HealthcareService, HealthcareServiceDao> { + private static final Logger logger = LoggerFactory.getLogger(HealthcareServiceAuthorizationRule.class); + public HealthcareServiceAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { @@ -22,36 +26,80 @@ public HealthcareServiceAuthorizationRule(DaoProvider daoProvider, String server @Override public Optional<String> reasonCreateAllowed(Connection connection, User user, HealthcareService newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Create of HealthcareService authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Create of HealthcareService unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonReadAllowed(Connection connection, User user, HealthcareService existingResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user) && hasLocalOrRemoteAuthorizationRole(existingResource)) + { + logger.info( + "Read of HealthcareService authorized for local user '{}', HealthcareService has local or remote authorization role", + user.getName()); + return Optional.of("local user, local or remote authorized HealthcareService"); + } + else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) + { + logger.info( + "Read of HealthcareService authorized for remote user '{}', HealthcareService has remote authorization role", + user.getName()); + return Optional.of("remote user, remote authorized HealthcareService"); + } + else + { + logger.warn( + "Read of HealthcareService unauthorized, no matching user role resource authorization role found"); + return Optional.empty(); + } } @Override public Optional<String> reasonUpdateAllowed(Connection connection, User user, HealthcareService oldResource, HealthcareService newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Update of HealthcareService authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + + } + else + { + logger.warn("Update of HealthcareService unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonDeleteAllowed(Connection connection, User user, HealthcareService oldResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Delete of HealthcareService authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Delete of HealthcareService unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonSearchAllowed(Connection connection, User user) { - // TODO Auto-generated method stub - return Optional.empty(); + logger.info("Search of HealthcareService authorized for {} user '{}', will be fitered by users organization {}", + user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString()); + return Optional.of("Allowed for all, filtered by users organization"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java index 4c1c96b69..38a3aa8bc 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/LocationAuthorizationRule.java @@ -9,9 +9,13 @@ import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Location; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class LocationAuthorizationRule extends AbstractAuthorizationRule<Location, LocationDao> { + private static final Logger logger = LoggerFactory.getLogger(LocationAuthorizationRule.class); + public LocationAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { @@ -21,36 +25,78 @@ public LocationAuthorizationRule(DaoProvider daoProvider, String serverBase, Ref @Override public Optional<String> reasonCreateAllowed(Connection connection, User user, Location newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Create of Location authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Create of Location unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonReadAllowed(Connection connection, User user, Location existingResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user) && hasLocalOrRemoteAuthorizationRole(existingResource)) + { + logger.info( + "Read of Location authorized for local user '{}', Location has local or remote authorization role", + user.getName()); + return Optional.of("local user, local or remote authorized Location"); + } + else if (isRemoteUser(user) && hasRemoteAuthorizationRole(existingResource)) + { + logger.info("Read of Location authorized for remote user '{}', Location has remote authorization role", + user.getName()); + return Optional.of("remote user, remote authorized Location"); + } + else + { + logger.warn("Read of Location unauthorized, no matching user role resource authorization role found"); + return Optional.empty(); + } } @Override public Optional<String> reasonUpdateAllowed(Connection connection, User user, Location oldResource, Location newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Update of Location authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + + } + else + { + logger.warn("Update of Location unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonDeleteAllowed(Connection connection, User user, Location oldResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Delete of Location authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Delete of Location unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonSearchAllowed(Connection connection, User user) { - // TODO Auto-generated method stub - return Optional.empty(); + logger.info("Search of Location authorized for {} user '{}', will be fitered by users organization {}", + user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString()); + return Optional.of("Allowed for all, filtered by users organization"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java index 777e22864..235657d8a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PatientAuthorizationRule.java @@ -9,9 +9,13 @@ import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Patient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class PatientAuthorizationRule extends AbstractAuthorizationRule<Patient, PatientDao> { + private static final Logger logger = LoggerFactory.getLogger(PatientAuthorizationRule.class); + public PatientAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { @@ -21,36 +25,70 @@ public PatientAuthorizationRule(DaoProvider daoProvider, String serverBase, Refe @Override public Optional<String> reasonCreateAllowed(Connection connection, User user, Patient newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Create of Patient authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Create of Patient unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonReadAllowed(Connection connection, User user, Patient existingResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Read of Patient authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Read of Patient unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonUpdateAllowed(Connection connection, User user, Patient oldResource, Patient newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Update of Patient authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + + } + else + { + logger.warn("Update of Patient unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonDeleteAllowed(Connection connection, User user, Patient oldResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Delete of Patient authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Delete of Patient unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonSearchAllowed(Connection connection, User user) { - // TODO Auto-generated method stub - return Optional.empty(); + logger.info("Search of Patient authorized for {} user '{}', will be fitered by users organization {}", + user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString()); + return Optional.of("Allowed for all, filtered by users organization"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java index 89f76fbe9..cbf41e9d2 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ProvenanceAuthorizationRule.java @@ -9,9 +9,13 @@ import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.service.ReferenceResolver; import org.hl7.fhir.r4.model.Provenance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ProvenanceAuthorizationRule extends AbstractAuthorizationRule<Provenance, ProvenanceDao> { + private static final Logger logger = LoggerFactory.getLogger(ProvenanceAuthorizationRule.class); + public ProvenanceAuthorizationRule(DaoProvider daoProvider, String serverBase, ReferenceResolver referenceResolver, OrganizationProvider organizationProvider) { @@ -21,36 +25,70 @@ public ProvenanceAuthorizationRule(DaoProvider daoProvider, String serverBase, R @Override public Optional<String> reasonCreateAllowed(Connection connection, User user, Provenance newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Create of Provenance authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Create of Provenance unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonReadAllowed(Connection connection, User user, Provenance existingResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Read of Provenance authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Read of Provenance unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonUpdateAllowed(Connection connection, User user, Provenance oldResource, Provenance newResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Update of Provenance authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + + } + else + { + logger.warn("Update of Provenance unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonDeleteAllowed(Connection connection, User user, Provenance oldResource) { - // TODO Auto-generated method stub - return Optional.empty(); + if (isLocalUser(user)) + { + logger.info("Delete of Provenance authorized for local user '{}'", user.getName()); + return Optional.of("local user"); + } + else + { + logger.warn("Delete of Provenance unauthorized, not a local user"); + return Optional.empty(); + } } @Override public Optional<String> reasonSearchAllowed(Connection connection, User user) { - // TODO Auto-generated method stub - return Optional.empty(); + logger.info("Search of Provenance authorized for {} user '{}', will be fitered by users organization {}", + user.getRole(), user.getName(), user.getOrganization().getIdElement().getValueAsString()); + return Optional.of("Allowed for all, filtered by users organization"); } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PatientUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PatientUserFilter.java index 06ddfe308..2b87ac849 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PatientUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/PatientUserFilter.java @@ -4,13 +4,10 @@ import java.sql.SQLException; import org.highmed.dsf.fhir.authentication.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.highmed.dsf.fhir.authentication.UserRole; public class PatientUserFilter extends AbstractUserFilter { - private static final Logger logger = LoggerFactory.getLogger(PatientUserFilter.class); - public PatientUserFilter(User user) { super(user); @@ -19,24 +16,21 @@ public PatientUserFilter(User user) @Override public String getFilterQuery() { - // TODO implement - - logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); - return "false"; + if (UserRole.LOCAL.equals(user.getRole())) + return ""; // not filtered for local users + else + return "false"; } @Override public int getSqlParameterCount() { - logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); return 0; } @Override public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException { - // TODO implement - - logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + // nothing to do } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ProvenanceUserFilter.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ProvenanceUserFilter.java index 54516617d..a8c02b680 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ProvenanceUserFilter.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/user/ProvenanceUserFilter.java @@ -4,13 +4,10 @@ import java.sql.SQLException; import org.highmed.dsf.fhir.authentication.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.highmed.dsf.fhir.authentication.UserRole; public class ProvenanceUserFilter extends AbstractUserFilter { - private static final Logger logger = LoggerFactory.getLogger(ProvenanceUserFilter.class); - public ProvenanceUserFilter(User user) { super(user); @@ -19,24 +16,21 @@ public ProvenanceUserFilter(User user) @Override public String getFilterQuery() { - // TODO implement - - logger.warn("{}#getFilterQuery not implemented yet", getClass().getName()); - return "false"; + if (UserRole.LOCAL.equals(user.getRole())) + return ""; // not filtered for local users + else + return "false"; } @Override public int getSqlParameterCount() { - logger.warn("{}#getSqlParameterCount not implemented yet", getClass().getName()); return 0; } @Override public void modifyStatement(int parameterIndex, PreparedStatement statement) throws SQLException { - // TODO implement - - logger.warn("{}#modifyStatement not implemented yet", getClass().getName()); + // nothing to do } } From 0e2c68577141385f4725e276c27cafb426a11942 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 15:53:21 +0100 Subject: [PATCH 24/55] test bundle fixes, added missing auth tags --- .../bundle-templates/medic1-bundle.xml | 18 +++++++ .../bundle-templates/medic2-bundle.xml | 18 +++++++ .../bundle-templates/medic3-bundle.xml | 18 +++++++ .../resources/bundle-templates/ttp-bundle.xml | 48 +++++++++++++++++++ 4 files changed, 102 insertions(+) diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic1-bundle.xml b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic1-bundle.xml index d422e7e18..afabce9b2 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic1-bundle.xml +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic1-bundle.xml @@ -4,6 +4,12 @@ <fullUrl value="urn:uuid:bb73165c-c7b9-4342-8e28-531f07fa7735"/> <resource> <Organization xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <extension url="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"> <valueString value="TODO"/> </extension> @@ -34,6 +40,12 @@ <fullUrl value="urn:uuid:cf62edc2-cc5d-43ed-ac0e-caf09f7326c3"/> <resource> <Organization xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <extension url="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"> <valueString value="TODO"/> </extension> @@ -60,6 +72,12 @@ <fullUrl value="urn:uuid:169e782c-2673-40e9-8b30-f1dc46dba984"/> <resource> <Endpoint xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <identifier> <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_TTP_Endpoint"/> diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic2-bundle.xml b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic2-bundle.xml index ce04e26f7..1a5eb6915 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic2-bundle.xml +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic2-bundle.xml @@ -4,6 +4,12 @@ <fullUrl value="urn:uuid:bb73165c-c7b9-4342-8e28-531f07fa7735"/> <resource> <Organization xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <extension url="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"> <valueString value="TODO"/> </extension> @@ -34,6 +40,12 @@ <fullUrl value="urn:uuid:55901940-02db-40bf-9a6e-bdfdd0ddb7bf"/> <resource> <Organization xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <extension url="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"> <valueString value="TODO"/> </extension> @@ -60,6 +72,12 @@ <fullUrl value="urn:uuid:dae83c31-e478-4bc2-a6bc-61e8b9b41fd7"/> <resource> <Endpoint xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <identifier> <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_TTP_Endpoint"/> diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic3-bundle.xml b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic3-bundle.xml index 3fe68cb49..946a1206a 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic3-bundle.xml +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/medic3-bundle.xml @@ -4,6 +4,12 @@ <fullUrl value="urn:uuid:bb73165c-c7b9-4342-8e28-531f07fa7735"/> <resource> <Organization xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <extension url="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"> <valueString value="TODO"/> </extension> @@ -34,6 +40,12 @@ <fullUrl value="urn:uuid:a49a45d2-88cc-4830-a028-413d68d9a439"/> <resource> <Organization xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <extension url="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"> <valueString value="TODO"/> </extension> @@ -60,6 +72,12 @@ <fullUrl value="urn:uuid:a3dc8452-0eba-4db7-9c18-4c2cf925b655"/> <resource> <Endpoint xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <identifier> <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_TTP_Endpoint"/> diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/ttp-bundle.xml b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/ttp-bundle.xml index c4c8fb4ab..5982c9796 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/ttp-bundle.xml +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/bundle-templates/ttp-bundle.xml @@ -4,6 +4,12 @@ <fullUrl value="urn:uuid:bb73165c-c7b9-4342-8e28-531f07fa7735"/> <resource> <Organization xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <extension url="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"> <valueString value="TODO"/> </extension> @@ -34,6 +40,12 @@ <fullUrl value="urn:uuid:cf62edc2-cc5d-43ed-ac0e-caf09f7326c3"/> <resource> <Organization xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <extension url="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"> <valueString value="TODO"/> </extension> @@ -64,6 +76,12 @@ <fullUrl value="urn:uuid:55901940-02db-40bf-9a6e-bdfdd0ddb7bf"/> <resource> <Organization xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <extension url="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"> <valueString value="TODO"/> </extension> @@ -94,6 +112,12 @@ <fullUrl value="urn:uuid:a49a45d2-88cc-4830-a028-413d68d9a439"/> <resource> <Organization xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <extension url="http://highmed.org/fhir/StructureDefinition/certificate-thumbprint"> <valueString value="TODO"/> </extension> @@ -124,6 +148,12 @@ <fullUrl value="urn:uuid:b879e904-d666-45de-a995-accdd4429b79"/> <resource> <Endpoint xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <identifier> <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_TTP_Endpoint"/> @@ -161,6 +191,12 @@ <fullUrl value="urn:uuid:6b405f8a-a201-475d-8dd7-4d73314855e1"/> <resource> <Endpoint xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <identifier> <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_MeDIC_1_Endpoint"/> @@ -198,6 +234,12 @@ <fullUrl value="urn:uuid:1712b523-1783-40fa-a317-375415686457"/> <resource> <Endpoint xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <identifier> <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_MeDIC_2_Endpoint"/> @@ -235,6 +277,12 @@ <fullUrl value="urn:uuid:1c3d45f9-5aa8-4979-892e-bf2d29b398e0"/> <resource> <Endpoint xmlns="http://hl7.org/fhir"> + <meta> + <tag> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role"/> + <code value="REMOTE"/> + </tag> + </meta> <identifier> <system value="http://highmed.org/fhir/NamingSystem/endpoint-identifier"/> <value value="Test_MeDIC_3_Endpoint"/> From 25e14fc34fa63b2639de6729c1f05f9d41631dae Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 15:53:54 +0100 Subject: [PATCH 25/55] docker-compose version upgrade --- dsf-docker-test-setup-3medic-ttp/highmed.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/dsf-docker-test-setup-3medic-ttp/highmed.yml b/dsf-docker-test-setup-3medic-ttp/highmed.yml index 95f216d6c..7e6a554bb 100755 --- a/dsf-docker-test-setup-3medic-ttp/highmed.yml +++ b/dsf-docker-test-setup-3medic-ttp/highmed.yml @@ -67,10 +67,9 @@ append: true - name: Download docker-compose get_url: - url: https://github.com/docker/compose/releases/download/v1.25.2/docker-compose-{{ ansible_system }}-{{ ansible_userspace_architecture - }} + url: https://github.com/docker/compose/releases/download/1.25.4/docker-compose-Linux-x86_64 dest: /usr/local/bin/docker-compose - checksum: sha256:786f9390aa8d72bcf34a1757df71577b7d8b7cb915205f72f12b9ee3ca0e0cc6 + checksum: sha256:542e93b1d5106d2769b325f60ba9a0ba087bb96e30dc2c1cb026f0cb642e9aed mode: '777' - name: update /etc/hosts file blockinfile: From 10758f8a0c8b358e0833d93a9a6a8f5f4a1e9240 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 15:58:14 +0100 Subject: [PATCH 26/55] added separate audit logger to log into file fhir-audit.log --- .../medic1/fhir/app/conf/log4j2.xml | 15 +++++++++++++++ .../medic2/fhir/app/conf/log4j2.xml | 15 +++++++++++++++ .../medic3/fhir/app/conf/log4j2.xml | 15 +++++++++++++++ .../ttp/fhir/app/conf/log4j2.xml | 15 +++++++++++++++ dsf-docker-test-setup/fhir/app/conf/log4j2.xml | 15 +++++++++++++++ 5 files changed, 75 insertions(+) diff --git a/dsf-docker-test-setup-3medic-ttp/medic1/fhir/app/conf/log4j2.xml b/dsf-docker-test-setup-3medic-ttp/medic1/fhir/app/conf/log4j2.xml index 72fdbac52..61f365c4c 100755 --- a/dsf-docker-test-setup-3medic-ttp/medic1/fhir/app/conf/log4j2.xml +++ b/dsf-docker-test-setup-3medic-ttp/medic1/fhir/app/conf/log4j2.xml @@ -17,6 +17,17 @@ <TimeBasedTriggeringPolicy/> </Policies> </RollingFile> + <RollingFile name="AUDIT" fileName="log/fhir-audit.log" + filePattern="log/fhir-audit_%d{MM-dd-yyyy}_%i.log.gz" + ignoreExceptions="false"> + <PatternLayout> + <Pattern>%d [%t] %-5p %c - %m%n</Pattern> + </PatternLayout> + <Policies> + <OnStartupTriggeringPolicy/> + <TimeBasedTriggeringPolicy/> + </Policies> + </RollingFile> <!-- <SMTP name="MAIL" subject="FHIR Error" to="foo@bar.de, baz@bar.de" @@ -34,6 +45,10 @@ </Appenders> <Loggers> + <Logger name="dsf-audit-logger" level="INFO"> + <AppenderRef ref="AUDIT"/> + </Logger> + <Logger name="org.highmed" level="TRACE"/> <logger name="de.rwh" level="DEBUG"/> <Logger name="org.apache" level="WARN"/> diff --git a/dsf-docker-test-setup-3medic-ttp/medic2/fhir/app/conf/log4j2.xml b/dsf-docker-test-setup-3medic-ttp/medic2/fhir/app/conf/log4j2.xml index 72fdbac52..61f365c4c 100755 --- a/dsf-docker-test-setup-3medic-ttp/medic2/fhir/app/conf/log4j2.xml +++ b/dsf-docker-test-setup-3medic-ttp/medic2/fhir/app/conf/log4j2.xml @@ -17,6 +17,17 @@ <TimeBasedTriggeringPolicy/> </Policies> </RollingFile> + <RollingFile name="AUDIT" fileName="log/fhir-audit.log" + filePattern="log/fhir-audit_%d{MM-dd-yyyy}_%i.log.gz" + ignoreExceptions="false"> + <PatternLayout> + <Pattern>%d [%t] %-5p %c - %m%n</Pattern> + </PatternLayout> + <Policies> + <OnStartupTriggeringPolicy/> + <TimeBasedTriggeringPolicy/> + </Policies> + </RollingFile> <!-- <SMTP name="MAIL" subject="FHIR Error" to="foo@bar.de, baz@bar.de" @@ -34,6 +45,10 @@ </Appenders> <Loggers> + <Logger name="dsf-audit-logger" level="INFO"> + <AppenderRef ref="AUDIT"/> + </Logger> + <Logger name="org.highmed" level="TRACE"/> <logger name="de.rwh" level="DEBUG"/> <Logger name="org.apache" level="WARN"/> diff --git a/dsf-docker-test-setup-3medic-ttp/medic3/fhir/app/conf/log4j2.xml b/dsf-docker-test-setup-3medic-ttp/medic3/fhir/app/conf/log4j2.xml index 72fdbac52..61f365c4c 100755 --- a/dsf-docker-test-setup-3medic-ttp/medic3/fhir/app/conf/log4j2.xml +++ b/dsf-docker-test-setup-3medic-ttp/medic3/fhir/app/conf/log4j2.xml @@ -17,6 +17,17 @@ <TimeBasedTriggeringPolicy/> </Policies> </RollingFile> + <RollingFile name="AUDIT" fileName="log/fhir-audit.log" + filePattern="log/fhir-audit_%d{MM-dd-yyyy}_%i.log.gz" + ignoreExceptions="false"> + <PatternLayout> + <Pattern>%d [%t] %-5p %c - %m%n</Pattern> + </PatternLayout> + <Policies> + <OnStartupTriggeringPolicy/> + <TimeBasedTriggeringPolicy/> + </Policies> + </RollingFile> <!-- <SMTP name="MAIL" subject="FHIR Error" to="foo@bar.de, baz@bar.de" @@ -34,6 +45,10 @@ </Appenders> <Loggers> + <Logger name="dsf-audit-logger" level="INFO"> + <AppenderRef ref="AUDIT"/> + </Logger> + <Logger name="org.highmed" level="TRACE"/> <logger name="de.rwh" level="DEBUG"/> <Logger name="org.apache" level="WARN"/> diff --git a/dsf-docker-test-setup-3medic-ttp/ttp/fhir/app/conf/log4j2.xml b/dsf-docker-test-setup-3medic-ttp/ttp/fhir/app/conf/log4j2.xml index 72fdbac52..61f365c4c 100755 --- a/dsf-docker-test-setup-3medic-ttp/ttp/fhir/app/conf/log4j2.xml +++ b/dsf-docker-test-setup-3medic-ttp/ttp/fhir/app/conf/log4j2.xml @@ -17,6 +17,17 @@ <TimeBasedTriggeringPolicy/> </Policies> </RollingFile> + <RollingFile name="AUDIT" fileName="log/fhir-audit.log" + filePattern="log/fhir-audit_%d{MM-dd-yyyy}_%i.log.gz" + ignoreExceptions="false"> + <PatternLayout> + <Pattern>%d [%t] %-5p %c - %m%n</Pattern> + </PatternLayout> + <Policies> + <OnStartupTriggeringPolicy/> + <TimeBasedTriggeringPolicy/> + </Policies> + </RollingFile> <!-- <SMTP name="MAIL" subject="FHIR Error" to="foo@bar.de, baz@bar.de" @@ -34,6 +45,10 @@ </Appenders> <Loggers> + <Logger name="dsf-audit-logger" level="INFO"> + <AppenderRef ref="AUDIT"/> + </Logger> + <Logger name="org.highmed" level="TRACE"/> <logger name="de.rwh" level="DEBUG"/> <Logger name="org.apache" level="WARN"/> diff --git a/dsf-docker-test-setup/fhir/app/conf/log4j2.xml b/dsf-docker-test-setup/fhir/app/conf/log4j2.xml index 72fdbac52..61f365c4c 100755 --- a/dsf-docker-test-setup/fhir/app/conf/log4j2.xml +++ b/dsf-docker-test-setup/fhir/app/conf/log4j2.xml @@ -17,6 +17,17 @@ <TimeBasedTriggeringPolicy/> </Policies> </RollingFile> + <RollingFile name="AUDIT" fileName="log/fhir-audit.log" + filePattern="log/fhir-audit_%d{MM-dd-yyyy}_%i.log.gz" + ignoreExceptions="false"> + <PatternLayout> + <Pattern>%d [%t] %-5p %c - %m%n</Pattern> + </PatternLayout> + <Policies> + <OnStartupTriggeringPolicy/> + <TimeBasedTriggeringPolicy/> + </Policies> + </RollingFile> <!-- <SMTP name="MAIL" subject="FHIR Error" to="foo@bar.de, baz@bar.de" @@ -34,6 +45,10 @@ </Appenders> <Loggers> + <Logger name="dsf-audit-logger" level="INFO"> + <AppenderRef ref="AUDIT"/> + </Logger> + <Logger name="org.highmed" level="TRACE"/> <logger name="de.rwh" level="DEBUG"/> <Logger name="org.apache" level="WARN"/> From e5b26fd375405cd878e7b7e155ec2bd0c227d5e2 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 15:58:41 +0100 Subject: [PATCH 27/55] added missing EndpointAddress search parameter --- .../java/org/highmed/dsf/fhir/dao/jdbc/EndpointDaoJdbc.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/EndpointDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/EndpointDaoJdbc.java index 377e077f6..96ba71015 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/EndpointDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/EndpointDaoJdbc.java @@ -7,6 +7,7 @@ import org.apache.commons.dbcp2.BasicDataSource; import org.highmed.dsf.fhir.dao.EndpointDao; +import org.highmed.dsf.fhir.search.parameters.EndpointAddress; import org.highmed.dsf.fhir.search.parameters.EndpointIdentifier; import org.highmed.dsf.fhir.search.parameters.EndpointName; import org.highmed.dsf.fhir.search.parameters.EndpointOrganization; @@ -26,7 +27,8 @@ public class EndpointDaoJdbc extends AbstractResourceDaoJdbc<Endpoint> implement public EndpointDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, Endpoint.class, "endpoints", "endpoint", "endpoint_id", EndpointUserFilter::new, - with(EndpointOrganization::new, EndpointIdentifier::new, EndpointName::new, EndpointStatus::new), + with(EndpointAddress::new, EndpointIdentifier::new, EndpointName::new, EndpointOrganization::new, + EndpointStatus::new), with(OrganizationEndpointRevInclude::new)); } From 0dade5ee3daf06fe04a1d4b730df7bbe7bc43314 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 15:59:11 +0100 Subject: [PATCH 28/55] added check for unsupported query parameters while executing auth rules --- .../EndpointAuthorizationRule.java | 24 ++++++++++++------- .../OrganizationAuthorizationRule.java | 4 ++++ .../PractitionerAuthorizationRule.java | 20 ++++++++++------ .../ResearchStudyAuthorizationRule.java | 14 ++++++++--- .../SubscriptionAuthorizationRule.java | 4 ++++ 5 files changed, 48 insertions(+), 18 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java index 7cab96325..0cbe6e035 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/EndpointAuthorizationRule.java @@ -120,12 +120,15 @@ private boolean resourceExists(Connection connection, Endpoint newResource) || endpointWithIdentifierExists(connection, identifierValue); } - private boolean endpointWithIdentifierExists(Connection connection, String identifierValue) + private boolean endpointWithAddressExists(Connection connection, String address) { - Map<String, List<String>> queryParameters = Map.of("identifier", - Collections.singletonList(IDENTIFIER_SYSTEM + "|" + identifierValue)); + Map<String, List<String>> queryParameters = Map.of("address", Collections.singletonList(address)); EndpointDao dao = getDao(); SearchQuery<Endpoint> query = dao.createSearchQueryWithoutUserFilter(0, 0).configureParameters(queryParameters); + + if (!query.getUnsupportedQueryParameters(queryParameters).isEmpty()) + return false; + try { PartialResult<Endpoint> result = dao.searchWithTransaction(connection, query); @@ -133,16 +136,21 @@ private boolean endpointWithIdentifierExists(Connection connection, String ident } catch (SQLException e) { - logger.warn("Error while searching for Endpoint with identifier", e); + logger.warn("Error while searching for Endpoint with address", e); return false; } } - private boolean endpointWithAddressExists(Connection connection, String address) + private boolean endpointWithIdentifierExists(Connection connection, String identifierValue) { - Map<String, List<String>> queryParameters = Map.of("address", Collections.singletonList(address)); + Map<String, List<String>> queryParameters = Map.of("identifier", + Collections.singletonList(IDENTIFIER_SYSTEM + "|" + identifierValue)); EndpointDao dao = getDao(); - SearchQuery<Endpoint> query = dao.createSearchQueryWithoutUserFilter(1, 1).configureParameters(queryParameters); + SearchQuery<Endpoint> query = dao.createSearchQueryWithoutUserFilter(0, 0).configureParameters(queryParameters); + + if (!query.getUnsupportedQueryParameters(queryParameters).isEmpty()) + return false; + try { PartialResult<Endpoint> result = dao.searchWithTransaction(connection, query); @@ -150,7 +158,7 @@ private boolean endpointWithAddressExists(Connection connection, String address) } catch (SQLException e) { - logger.warn("Error while searching for Endpoint with address", e); + logger.warn("Error while searching for Endpoint with identifier", e); return false; } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java index 507d84002..fbf4c241d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/OrganizationAuthorizationRule.java @@ -153,6 +153,10 @@ private boolean organizationWithIdentifierExists(Connection connection, String i OrganizationDao dao = getDao(); SearchQuery<Organization> query = dao.createSearchQueryWithoutUserFilter(0, 0) .configureParameters(queryParameters); + + if (!query.getUnsupportedQueryParameters(queryParameters).isEmpty()) + return false; + try { PartialResult<Organization> result = dao.searchWithTransaction(connection, query); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java index 8ce977c09..4349b2f55 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/PractitionerAuthorizationRule.java @@ -3,6 +3,7 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Optional; @@ -104,15 +105,20 @@ private boolean researchStudyWithPrincipalInvestigatorAndUsersOrganizationExists private boolean practitionerRoleWithPractitionerAndUsersOrganizationExists(Connection connection, User user, Practitioner existingResource) { + Map<String, List<String>> queryParameters = Map.of("practitioner", + Collections.singletonList(existingResource.getIdElement().toVersionless().getValueAsString()), + "organization", + Collections.singletonList(user.getOrganization().getIdElement().toVersionless().getValueAsString())); + PractitionerRoleDao dao = daoProvider.getPractitionerRoleDao(); + + SearchQuery<PractitionerRole> query = dao.createSearchQueryWithoutUserFilter(0, 0) + .configureParameters(queryParameters); + + if (!query.getUnsupportedQueryParameters(queryParameters).isEmpty()) + return false; + try { - PractitionerRoleDao dao = daoProvider.getPractitionerRoleDao(); - SearchQuery<PractitionerRole> query = dao.createSearchQueryWithoutUserFilter(0, 0) - .configureParameters(Map.of("practitioner", - Collections - .singletonList(existingResource.getIdElement().toVersionless().getValueAsString()), - "organization", Collections.singletonList( - user.getOrganization().getIdElement().toVersionless().getValueAsString()))); PartialResult<PractitionerRole> result = dao.searchWithTransaction(connection, query); return result.getOverallCount() > 0; } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java index b42359963..05762b7a0 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java @@ -208,10 +208,14 @@ private Optional<Resource> resolvePractitioner(Connection connection, User user, private boolean practitionerRoleExists(Connection connection, User user, IdType practitionerId) { + Map<String, List<String>> queryParameters = Map.of("practitioner", + Collections.singletonList("Practitioner/" + practitionerId.getIdPart()), "active", + Collections.singletonList("true")); PractitionerRoleDao dao = daoProvider.getPractitionerRoleDao(); - SearchQuery<PractitionerRole> query = dao.createSearchQuery(user, 0, 0).configureParameters( - Map.of("practitioner", Collections.singletonList("Practitioner/" + practitionerId.getIdPart()), - "active", Collections.singletonList("true"))); + SearchQuery<PractitionerRole> query = dao.createSearchQuery(user, 0, 0).configureParameters(queryParameters); + + if (!query.getUnsupportedQueryParameters(queryParameters).isEmpty()) + return false; try { @@ -240,6 +244,10 @@ private boolean researchStudyWithIdentifierExists(Connection connection, String ResearchStudyDao dao = getDao(); SearchQuery<ResearchStudy> query = dao.createSearchQueryWithoutUserFilter(0, 0) .configureParameters(queryParameters); + + if (!query.getUnsupportedQueryParameters(queryParameters).isEmpty()) + return false; + try { PartialResult<ResearchStudy> result = dao.searchWithTransaction(connection, query); diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java index 474d1213f..0acc6d1f9 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/SubscriptionAuthorizationRule.java @@ -151,6 +151,10 @@ private boolean resourceExists(Connection connection, Subscription newResource) SubscriptionDao dao = getDao(); SearchQuery<Subscription> query = dao.createSearchQueryWithoutUserFilter(1, 1) .configureParameters(queryParameters); + + if (!query.getUnsupportedQueryParameters(queryParameters).isEmpty()) + return false; + try { PartialResult<Subscription> result = dao.searchWithTransaction(connection, query); From 5fb76937410fb32fff39671769f35d9a9abdb07b Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 16:28:43 +0100 Subject: [PATCH 29/55] copy/paste error fix -> wrong url --- .../ActivityDefinition/computeSimpleFeasibility-0.1.0.xml.put | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/computeSimpleFeasibility-0.1.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/computeSimpleFeasibility-0.1.0.xml.put index 36a3ab2c7..409d243ff 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/computeSimpleFeasibility-0.1.0.xml.put +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/computeSimpleFeasibility-0.1.0.xml.put @@ -1 +1 @@ -ActivityDefinition?url=http://highmed.org/bpe/Process/pong&version=0.1.0 \ No newline at end of file +ActivityDefinition?url=http://highmed.org/bpe/Process/computeSimpleFeasibility&version=0.1.0 \ No newline at end of file From ac2f351a5d47d19713b00c6dca2579b7515f572f Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 16:29:21 +0100 Subject: [PATCH 30/55] copy/paste error fix -> warning log text --- .../fhir/authorization/ActivityDefinitionAuthorizationRule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java index 892d4581f..cbe5a5d92 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionAuthorizationRule.java @@ -185,7 +185,7 @@ else if (!resourceExists(connection, newResource)) else { logger.warn( - "Update of ActivityDefinition unauthorized, other Endpoint with address and identifier already exists"); + "Update of ActivityDefinition unauthorized, other ActivityDefinition with url and version already exists"); return Optional.empty(); } } From 82683738e0f11f6027137e3d9c101f3a60f7d5c8 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 16:29:39 +0100 Subject: [PATCH 31/55] added missing resource ActivityDefinition --- .../dsf/fhir/webservice/impl/ConformanceServiceImpl.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java index 2a2f029ce..a118ba973 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java @@ -196,10 +196,10 @@ private CapabilityStatement createCapabilityStatement(String serverBase, int def websocketExtension.setUrl("http://hl7.org/fhir/StructureDefinition/capabilitystatement-websocket"); websocketExtension.setValue(new UrlType(serverBase.replace("http", "ws") + ServerEndpoint.PATH)); - var resources = Arrays.asList(Binary.class, Bundle.class, CodeSystem.class, Endpoint.class, Group.class, - HealthcareService.class, Location.class, NamingSystem.class, Organization.class, Patient.class, - PractitionerRole.class, Practitioner.class, Provenance.class, ResearchStudy.class, - StructureDefinition.class, Subscription.class, Task.class, ValueSet.class); + var resources = Arrays.asList(ActivityDefinition.class, Binary.class, Bundle.class, CodeSystem.class, + Endpoint.class, Group.class, HealthcareService.class, Location.class, NamingSystem.class, + Organization.class, Patient.class, PractitionerRole.class, Practitioner.class, Provenance.class, + ResearchStudy.class, StructureDefinition.class, Subscription.class, Task.class, ValueSet.class); var searchParameters = new HashMap<Class<? extends Resource>, List<CapabilityStatementRestResourceSearchParamComponent>>(); var revIncludeParameters = new HashMap<Class<? extends Resource>, List<Class<? extends AbstractRevIncludeParameterFactory>>>(); From b509eb965ea1350a33e0f3021f1f24f62746f05a Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 16:36:33 +0100 Subject: [PATCH 32/55] copy/paste error fix -> wrong version --- .../fhir/ActivityDefinition/updateWhiteList-0.1.0.xml.put | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/updateWhiteList-0.1.0.xml.put b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/updateWhiteList-0.1.0.xml.put index c357f40ab..4cc51c434 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/updateWhiteList-0.1.0.xml.put +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/updateWhiteList-0.1.0.xml.put @@ -1 +1 @@ -ActivityDefinition?url=http://highmed.org/bpe/Process/updateWhiteList&version=1.0.0 \ No newline at end of file +ActivityDefinition?url=http://highmed.org/bpe/Process/updateWhiteList&version=0.1.0 \ No newline at end of file From 7062cd625ad066710e0b39892f8ebe218620acff Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 16:47:23 +0100 Subject: [PATCH 33/55] removed zero length whitespace characters --- .../fhir/search/parameters/ActivityDefinitionIdentifier.java | 2 +- .../dsf/fhir/search/parameters/ActivityDefinitionName.java | 2 +- .../dsf/fhir/search/parameters/ActivityDefinitionStatus.java | 2 +- .../dsf/fhir/search/parameters/ActivityDefinitionUrl.java | 2 +- .../dsf/fhir/search/parameters/ActivityDefinitionVersion.java | 2 +- .../highmed/dsf/fhir/search/parameters/CodeSystemStatus.java | 2 +- .../highmed/dsf/fhir/search/parameters/OrganizationType.java | 2 +- .../dsf/fhir/search/parameters/SubscriptionCriteria.java | 2 +- .../org/highmed/dsf/fhir/search/parameters/TaskIdentifier.java | 2 +- .../org/highmed/dsf/fhir/search/parameters/ValueSetStatus.java | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionIdentifier.java index 91d874e71..5017ac824 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionIdentifier.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionIdentifier.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Enumerations.SearchParamType; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.​identifier", type = SearchParamType.TOKEN, documentation = "External identifier for the activity definition") +@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.identifier", type = SearchParamType.TOKEN, documentation = "External identifier for the activity definition") public class ActivityDefinitionIdentifier extends AbstractIdentifierParameter<ActivityDefinition> { public static final String RESOURCE_COLUMN = "activity_definition"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionName.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionName.java index 281317892..c6fa89ec8 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionName.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionName.java @@ -12,7 +12,7 @@ import org.hl7.fhir.r4.model.Enumerations.SearchParamType; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = ActivityDefinitionName.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.​name", type = SearchParamType.STRING, documentation = "Computationally friendly name of the activity definition") +@SearchParameterDefinition(name = ActivityDefinitionName.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.name", type = SearchParamType.STRING, documentation = "Computationally friendly name of the activity definition") public class ActivityDefinitionName extends AbstractStringParameter<ActivityDefinition> { public static final String PARAMETER_NAME = "name"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionStatus.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionStatus.java index 5166681b7..359e40a99 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionStatus.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionStatus.java @@ -21,7 +21,7 @@ import org.hl7.fhir.r4.model.Enumerations.SearchParamType; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = ActivityDefinitionStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.​status", type = SearchParamType.TOKEN, documentation = "The current status of the activity definition") +@SearchParameterDefinition(name = ActivityDefinitionStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.status", type = SearchParamType.TOKEN, documentation = "The current status of the activity definition") public class ActivityDefinitionStatus extends AbstractTokenParameter<ActivityDefinition> { public static final String PARAMETER_NAME = "status"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionUrl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionUrl.java index 14e63831c..726bd7c15 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionUrl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionUrl.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Enumerations.SearchParamType; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = ActivityDefinitionUrl.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.​url", type = SearchParamType.URI, documentation = "The uri that identifies the activity definition") +@SearchParameterDefinition(name = ActivityDefinitionUrl.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.url", type = SearchParamType.URI, documentation = "The uri that identifies the activity definition") public class ActivityDefinitionUrl extends AbstractUrlAndVersionParameter<ActivityDefinition> { public static final String RESOURCE_COLUMN = "activity_definition"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionVersion.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionVersion.java index b4c1e31cc..07adf7785 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionVersion.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionVersion.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Enumerations.SearchParamType; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = ActivityDefinitionVersion.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.​version", type = SearchParamType.TOKEN, documentation = "The business version of the activity definition") +@SearchParameterDefinition(name = ActivityDefinitionVersion.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.version", type = SearchParamType.TOKEN, documentation = "The business version of the activity definition") public class ActivityDefinitionVersion extends AbstractVersionParameter<ActivityDefinition> { public static final String RESOURCE_COLUMN = "activity_definition"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemStatus.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemStatus.java index 713c773c1..6987f685f 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemStatus.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemStatus.java @@ -22,7 +22,7 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.ValueSet; -@SearchParameterDefinition(name = CodeSystemStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/CodeSystem.​status", type = SearchParamType.TOKEN, documentation = "The current status of the code system") +@SearchParameterDefinition(name = CodeSystemStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/CodeSystem.status", type = SearchParamType.TOKEN, documentation = "The current status of the code system") public class CodeSystemStatus extends AbstractTokenParameter<CodeSystem> { public static final String PARAMETER_NAME = "status"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationType.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationType.java index 636646a89..fa68b8b5c 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationType.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationType.java @@ -17,7 +17,7 @@ import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Organization.​type", +@SearchParameterDefinition(name = PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Organization.type", type = SearchParamType.TOKEN, documentation = "A code for the type of organization") public class OrganizationType extends AbstractTokenParameter<Organization> { diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionCriteria.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionCriteria.java index 47cf7fda6..552af7327 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionCriteria.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionCriteria.java @@ -12,7 +12,7 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.Subscription; -@SearchParameterDefinition(name = SubscriptionCriteria.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Subscription.​criteria", type = SearchParamType.STRING, documentation = "The search rules used to determine when to send a notification (always matches exact)") +@SearchParameterDefinition(name = SubscriptionCriteria.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Subscription.criteria", type = SearchParamType.STRING, documentation = "The search rules used to determine when to send a notification (always matches exact)") public class SubscriptionCriteria extends AbstractStringParameter<Subscription> { public static final String PARAMETER_NAME = "criteria"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/TaskIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/TaskIdentifier.java index cb4234e94..277e77bf9 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/TaskIdentifier.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/TaskIdentifier.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.Task; -@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Task.​identifier", type = SearchParamType.TOKEN, documentation = "Search for a task instance by its business identifier") +@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Task.identifier", type = SearchParamType.TOKEN, documentation = "Search for a task instance by its business identifier") public class TaskIdentifier extends AbstractIdentifierParameter<Task> { public static final String RESOURCE_COLUMN = "task"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetStatus.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetStatus.java index 091dbed6c..7e4f01a9a 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetStatus.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetStatus.java @@ -21,7 +21,7 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.ValueSet; -@SearchParameterDefinition(name = ValueSetStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ValueSet.​status", type = SearchParamType.TOKEN, documentation = "The current status of the value set") +@SearchParameterDefinition(name = ValueSetStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ValueSet.status", type = SearchParamType.TOKEN, documentation = "The current status of the value set") public class ValueSetStatus extends AbstractTokenParameter<ValueSet> { public static final String PARAMETER_NAME = "status"; From 0770d0d2683b711a05f7eafab933920faded2213 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 17:08:49 +0100 Subject: [PATCH 34/55] fixed search parameter definition urls and alpha. sort order in DAOs --- .../fhir/dao/jdbc/HealthcareServiceDaoJdbc.java | 2 +- .../dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java | 4 ++-- .../dsf/fhir/dao/jdbc/PatientDaoJdbc.java | 2 +- .../dsf/fhir/dao/jdbc/PractitionerDaoJdbc.java | 2 +- .../dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java | 2 +- .../dsf/fhir/dao/jdbc/SubscriptionDaoJdbc.java | 8 ++++---- .../parameters/ActivityDefinitionIdentifier.java | 2 +- .../parameters/ActivityDefinitionName.java | 2 +- .../parameters/ActivityDefinitionStatus.java | 2 +- .../search/parameters/ActivityDefinitionUrl.java | 2 +- .../parameters/ActivityDefinitionVersion.java | 2 +- .../fhir/search/parameters/BundleIdentifier.java | 2 +- .../search/parameters/CodeSystemIdentifier.java | 2 +- .../fhir/search/parameters/CodeSystemStatus.java | 2 +- .../fhir/search/parameters/CodeSystemUrl.java | 2 +- .../search/parameters/CodeSystemVersion.java | 2 +- .../search/parameters/EndpointIdentifier.java | 2 +- .../search/parameters/EndpointOrganization.java | 2 +- .../parameters/HealthcareServiceIdentifier.java | 2 +- .../search/parameters/LocationIdentifier.java | 2 +- .../search/parameters/OrganizationEndpoint.java | 2 +- .../parameters/OrganizationIdentifier.java | 2 +- .../fhir/search/parameters/OrganizationType.java | 16 +++++++--------- .../search/parameters/PatientIdentifier.java | 2 +- .../parameters/PractitionerIdentifier.java | 2 +- .../parameters/PractitionerRoleIdentifier.java | 2 +- .../parameters/ResearchStudyEnrollment.java | 2 +- .../parameters/ResearchStudyIdentifier.java | 2 +- .../StructureDefinitionIdentifier.java | 2 +- .../parameters/StructureDefinitionUrl.java | 2 +- .../parameters/StructureDefinitionVersion.java | 2 +- .../search/parameters/SubscriptionCriteria.java | 2 +- ...nnelPayload.java => SubscriptionPayload.java} | 6 +++--- .../search/parameters/SubscriptionStatus.java | 2 +- ...ionChannelType.java => SubscriptionType.java} | 6 +++--- .../fhir/search/parameters/TaskIdentifier.java | 2 +- .../search/parameters/ValueSetIdentifier.java | 2 +- .../fhir/search/parameters/ValueSetStatus.java | 2 +- .../dsf/fhir/search/parameters/ValueSetUrl.java | 2 +- .../fhir/search/parameters/ValueSetVersion.java | 2 +- .../webservice/impl/ConformanceServiceImpl.java | 12 ++++++------ 41 files changed, 60 insertions(+), 62 deletions(-) rename dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/{SubscriptionChannelPayload.java => SubscriptionPayload.java} (85%) rename dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/{SubscriptionChannelType.java => SubscriptionType.java} (87%) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/HealthcareServiceDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/HealthcareServiceDaoJdbc.java index 22305c237..168dc8430 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/HealthcareServiceDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/HealthcareServiceDaoJdbc.java @@ -15,7 +15,7 @@ public HealthcareServiceDaoJdbc(BasicDataSource dataSource, FhirContext fhirCont { super(dataSource, fhirContext, HealthcareService.class, "healthcare_services", "healthcare_service", "healthcare_service_id", HealthcareServiceUserFilter::new, - with(HealthcareServiceIdentifier::new, HealthcareServiceActive::new), with()); + with(HealthcareServiceActive::new, HealthcareServiceIdentifier::new), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java index ccfea5518..0749a6958 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/OrganizationDaoJdbc.java @@ -28,8 +28,8 @@ public class OrganizationDaoJdbc extends AbstractResourceDaoJdbc<Organization> i public OrganizationDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, Organization.class, "organizations", "organization", "organization_id", - OrganizationUserFilter::new, with(OrganizationName::new, OrganizationEndpoint::new, - OrganizationIdentifier::new, OrganizationActive::new, OrganizationType::new), + OrganizationUserFilter::new, with(OrganizationActive::new, OrganizationEndpoint::new, + OrganizationIdentifier::new, OrganizationName::new, OrganizationType::new), with(EndpointOrganizationRevInclude::new)); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PatientDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PatientDaoJdbc.java index da5c7318f..69dfd2cd9 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PatientDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PatientDaoJdbc.java @@ -14,7 +14,7 @@ public class PatientDaoJdbc extends AbstractResourceDaoJdbc<Patient> implements public PatientDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, Patient.class, "patients", "patient", "patient_id", PatientUserFilter::new, - with(PatientIdentifier::new, PatientActive::new), with()); + with(PatientActive::new, PatientIdentifier::new), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerDaoJdbc.java index a1f515860..e8d9d1d7d 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/PractitionerDaoJdbc.java @@ -14,7 +14,7 @@ public class PractitionerDaoJdbc extends AbstractResourceDaoJdbc<Practitioner> i public PractitionerDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, Practitioner.class, "practitioners", "practitioner", "practitioner_id", - PractitionerUserFilter::new, with(PractitionerIdentifier::new, PractitionerActive::new), with()); + PractitionerUserFilter::new, with(PractitionerActive::new, PractitionerIdentifier::new), with()); } @Override diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java index f9e862c5a..2c8ed0bde 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ResearchStudyDaoJdbc.java @@ -27,7 +27,7 @@ public class ResearchStudyDaoJdbc extends AbstractResourceDaoJdbc<ResearchStudy> public ResearchStudyDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, ResearchStudy.class, "research_studies", "research_study", "research_study_id", - ResearchStudyUserFilter::new, with(ResearchStudyIdentifier::new, ResearchStudyEnrollment::new, + ResearchStudyUserFilter::new, with(ResearchStudyEnrollment::new, ResearchStudyIdentifier::new, ResearchStudyPrincipalInvestigator::new), with()); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/SubscriptionDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/SubscriptionDaoJdbc.java index 46c4d6137..6604d846a 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/SubscriptionDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/SubscriptionDaoJdbc.java @@ -10,10 +10,10 @@ import org.apache.commons.dbcp2.BasicDataSource; import org.highmed.dsf.fhir.dao.SubscriptionDao; -import org.highmed.dsf.fhir.search.parameters.SubscriptionChannelPayload; -import org.highmed.dsf.fhir.search.parameters.SubscriptionChannelType; import org.highmed.dsf.fhir.search.parameters.SubscriptionCriteria; +import org.highmed.dsf.fhir.search.parameters.SubscriptionPayload; import org.highmed.dsf.fhir.search.parameters.SubscriptionStatus; +import org.highmed.dsf.fhir.search.parameters.SubscriptionType; import org.highmed.dsf.fhir.search.parameters.user.SubscriptionUserFilter; import org.hl7.fhir.r4.model.Subscription; import org.slf4j.Logger; @@ -28,8 +28,8 @@ public class SubscriptionDaoJdbc extends AbstractResourceDaoJdbc<Subscription> i public SubscriptionDaoJdbc(BasicDataSource dataSource, FhirContext fhirContext) { super(dataSource, fhirContext, Subscription.class, "subscriptions", "subscription", "subscription_id", - SubscriptionUserFilter::new, with(SubscriptionCriteria::new, SubscriptionStatus::new, - SubscriptionChannelType::new, SubscriptionChannelPayload::new), + SubscriptionUserFilter::new, with(SubscriptionCriteria::new, SubscriptionPayload::new, + SubscriptionStatus::new, SubscriptionType::new), with()); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionIdentifier.java index 5017ac824..6136106eb 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionIdentifier.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionIdentifier.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Enumerations.SearchParamType; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.identifier", type = SearchParamType.TOKEN, documentation = "External identifier for the activity definition") +@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition-identifier", type = SearchParamType.TOKEN, documentation = "External identifier for the activity definition") public class ActivityDefinitionIdentifier extends AbstractIdentifierParameter<ActivityDefinition> { public static final String RESOURCE_COLUMN = "activity_definition"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionName.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionName.java index c6fa89ec8..74f01d8f4 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionName.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionName.java @@ -12,7 +12,7 @@ import org.hl7.fhir.r4.model.Enumerations.SearchParamType; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = ActivityDefinitionName.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.name", type = SearchParamType.STRING, documentation = "Computationally friendly name of the activity definition") +@SearchParameterDefinition(name = ActivityDefinitionName.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition-name", type = SearchParamType.STRING, documentation = "Computationally friendly name of the activity definition") public class ActivityDefinitionName extends AbstractStringParameter<ActivityDefinition> { public static final String PARAMETER_NAME = "name"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionStatus.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionStatus.java index 359e40a99..f44d84aef 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionStatus.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionStatus.java @@ -21,7 +21,7 @@ import org.hl7.fhir.r4.model.Enumerations.SearchParamType; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = ActivityDefinitionStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.status", type = SearchParamType.TOKEN, documentation = "The current status of the activity definition") +@SearchParameterDefinition(name = ActivityDefinitionStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition-status", type = SearchParamType.TOKEN, documentation = "The current status of the activity definition") public class ActivityDefinitionStatus extends AbstractTokenParameter<ActivityDefinition> { public static final String PARAMETER_NAME = "status"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionUrl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionUrl.java index 726bd7c15..cf622a83d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionUrl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionUrl.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Enumerations.SearchParamType; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = ActivityDefinitionUrl.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.url", type = SearchParamType.URI, documentation = "The uri that identifies the activity definition") +@SearchParameterDefinition(name = ActivityDefinitionUrl.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition-url", type = SearchParamType.URI, documentation = "The uri that identifies the activity definition") public class ActivityDefinitionUrl extends AbstractUrlAndVersionParameter<ActivityDefinition> { public static final String RESOURCE_COLUMN = "activity_definition"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionVersion.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionVersion.java index 07adf7785..ff6a6cc37 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionVersion.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ActivityDefinitionVersion.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Enumerations.SearchParamType; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = ActivityDefinitionVersion.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition.version", type = SearchParamType.TOKEN, documentation = "The business version of the activity definition") +@SearchParameterDefinition(name = ActivityDefinitionVersion.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ActivityDefinition-version", type = SearchParamType.TOKEN, documentation = "The business version of the activity definition") public class ActivityDefinitionVersion extends AbstractVersionParameter<ActivityDefinition> { public static final String RESOURCE_COLUMN = "activity_definition"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/BundleIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/BundleIdentifier.java index fdb805834..e35d46fe5 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/BundleIdentifier.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/BundleIdentifier.java @@ -13,7 +13,7 @@ import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = BundleIdentifier.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Bundle.identifier", type = SearchParamType.TOKEN, documentation = "Persistent identifier for the bundle") +@SearchParameterDefinition(name = BundleIdentifier.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Bundle-identifier", type = SearchParamType.TOKEN, documentation = "Persistent identifier for the bundle") public class BundleIdentifier extends AbstractTokenParameter<Bundle> { public static final String PARAMETER_NAME = "identifier"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemIdentifier.java index 77b65ff28..c54bcfb09 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemIdentifier.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemIdentifier.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Enumerations.SearchParamType; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/CodeSystem.identifier", type = SearchParamType.TOKEN, documentation = "External identifier for the code system") +@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/CodeSystem-identifier", type = SearchParamType.TOKEN, documentation = "External identifier for the code system") public class CodeSystemIdentifier extends AbstractIdentifierParameter<CodeSystem> { public static final String RESOURCE_COLUMN = "code_system"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemStatus.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemStatus.java index 6987f685f..c04618d9d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemStatus.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemStatus.java @@ -22,7 +22,7 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.ValueSet; -@SearchParameterDefinition(name = CodeSystemStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/CodeSystem.status", type = SearchParamType.TOKEN, documentation = "The current status of the code system") +@SearchParameterDefinition(name = CodeSystemStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/CodeSystem-status", type = SearchParamType.TOKEN, documentation = "The current status of the code system") public class CodeSystemStatus extends AbstractTokenParameter<CodeSystem> { public static final String PARAMETER_NAME = "status"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemUrl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemUrl.java index c99884529..d2d7092eb 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemUrl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemUrl.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Enumerations.SearchParamType; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = CodeSystemUrl.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/CodeSystem.url", type = SearchParamType.URI, documentation = "The uri that identifies the code system") +@SearchParameterDefinition(name = CodeSystemUrl.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/CodeSystem-url", type = SearchParamType.URI, documentation = "The uri that identifies the code system") public class CodeSystemUrl extends AbstractUrlAndVersionParameter<CodeSystem> { public static final String RESOURCE_COLUMN = "code_system"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemVersion.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemVersion.java index 51b9ee890..24185bd54 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemVersion.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/CodeSystemVersion.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Enumerations.SearchParamType; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = CodeSystemVersion.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/CodeSystem.version", type = SearchParamType.TOKEN, documentation = "The business version of the code system") +@SearchParameterDefinition(name = CodeSystemVersion.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/CodeSystem-version", type = SearchParamType.TOKEN, documentation = "The business version of the code system") public class CodeSystemVersion extends AbstractVersionParameter<CodeSystem> { public static final String RESOURCE_COLUMN = "code_system"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointIdentifier.java index 0ed2ef685..d07222ce8 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointIdentifier.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointIdentifier.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Enumerations.SearchParamType; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Endpoint.identifier", type = SearchParamType.TOKEN, documentation = "Identifies this endpoint across multiple systems") +@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Endpoint-identifier", type = SearchParamType.TOKEN, documentation = "Identifies this endpoint across multiple systems") public class EndpointIdentifier extends AbstractIdentifierParameter<Endpoint> { public static final String RESOURCE_COLUMN = "endpoint"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointOrganization.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointOrganization.java index 3f9abf018..37faa148c 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointOrganization.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/EndpointOrganization.java @@ -21,7 +21,7 @@ import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = EndpointOrganization.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Endpoint.managingOrganization", type = SearchParamType.REFERENCE, documentation = "The organization that is managing the endpoint, search by identifier is supported") +@SearchParameterDefinition(name = EndpointOrganization.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Endpoint-organization", type = SearchParamType.REFERENCE, documentation = "The organization that is managing the endpoint") public class EndpointOrganization extends AbstractReferenceParameter<Endpoint> { private static final String RESOURCE_TYPE_NAME = "Endpoint"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/HealthcareServiceIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/HealthcareServiceIdentifier.java index d1fe6ff1d..92d3e0eb6 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/HealthcareServiceIdentifier.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/HealthcareServiceIdentifier.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.HealthcareService; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/HealthcareService.identifier", type = SearchParamType.TOKEN, documentation = "External identifiers for this item") +@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/HealthcareService-identifier", type = SearchParamType.TOKEN, documentation = "External identifiers for this item") public class HealthcareServiceIdentifier extends AbstractIdentifierParameter<HealthcareService> { public static final String RESOURCE_COLUMN = "healthcare_service"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/LocationIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/LocationIdentifier.java index c161046ee..cefb682ef 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/LocationIdentifier.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/LocationIdentifier.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Location; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Location.identifier", type = SearchParamType.TOKEN, documentation = "An identifier for the location") +@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Location-identifier", type = SearchParamType.TOKEN, documentation = "An identifier for the location") public class LocationIdentifier extends AbstractIdentifierParameter<Location> { public static final String RESOURCE_COLUMN = "location"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationEndpoint.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationEndpoint.java index 61f63b722..5add3d3bf 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationEndpoint.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationEndpoint.java @@ -21,7 +21,7 @@ import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = OrganizationEndpoint.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Organization.endpoint", type = SearchParamType.REFERENCE, documentation = "Technical endpoints providing access to services operated for the organization") +@SearchParameterDefinition(name = OrganizationEndpoint.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Organization-endpoint", type = SearchParamType.REFERENCE, documentation = "Technical endpoints providing access to services operated for the organization") public class OrganizationEndpoint extends AbstractReferenceParameter<Organization> { private static final String RESOURCE_TYPE_NAME = "Organization"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationIdentifier.java index 9aa9773d6..785ae5da3 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationIdentifier.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationIdentifier.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Organization.identifier", type = SearchParamType.TOKEN, documentation = "Any identifier for the organization (not the accreditation issuer's identifier)") +@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Organization-identifier", type = SearchParamType.TOKEN, documentation = "Any identifier for the organization (not the accreditation issuer's identifier)") public class OrganizationIdentifier extends AbstractIdentifierParameter<Organization> { public static final String RESOURCE_COLUMN = "organization"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationType.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationType.java index fa68b8b5c..e049bd1ab 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationType.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/OrganizationType.java @@ -17,8 +17,7 @@ import org.hl7.fhir.r4.model.Organization; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Organization.type", - type = SearchParamType.TOKEN, documentation = "A code for the type of organization") +@SearchParameterDefinition(name = PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Organization-type", type = SearchParamType.TOKEN, documentation = "A code for the type of organization") public class OrganizationType extends AbstractTokenParameter<Organization> { public static final String PARAMETER_NAME = "type"; @@ -64,9 +63,8 @@ public void modifyStatement(int parameterIndex, int subqueryParameterIndex, Prep statement.setString(parameterIndex, "[{\"code\": \"" + valueAndType.codeValue + "\"}]"); return; case CODE_AND_SYSTEM: - statement.setString(parameterIndex, - "[{\"code\": \"" + valueAndType.codeValue + "\", \"system\": \"" + valueAndType.systemValue - + "\"}]"); + statement.setString(parameterIndex, "[{\"code\": \"" + valueAndType.codeValue + "\", \"system\": \"" + + valueAndType.systemValue + "\"}]"); return; case CODE_AND_NO_SYSTEM_PROPERTY: statement.setString(parameterIndex, valueAndType.codeValue); @@ -89,11 +87,11 @@ public static boolean codingMatches(TokenValueAndSearchType valueAndType, Identi case CODE: return Objects.equals(valueAndType.codeValue, identifier.getValue()); case CODE_AND_SYSTEM: - return Objects.equals(valueAndType.codeValue, identifier.getValue()) && Objects - .equals(valueAndType.systemValue, identifier.getSystem()); + return Objects.equals(valueAndType.codeValue, identifier.getValue()) + && Objects.equals(valueAndType.systemValue, identifier.getSystem()); case CODE_AND_NO_SYSTEM_PROPERTY: - return Objects.equals(valueAndType.codeValue, identifier.getValue()) && (identifier.getSystem() == null - || identifier.getSystem().isBlank()); + return Objects.equals(valueAndType.codeValue, identifier.getValue()) + && (identifier.getSystem() == null || identifier.getSystem().isBlank()); case SYSTEM: return Objects.equals(valueAndType.systemValue, identifier.getSystem()); default: diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PatientIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PatientIdentifier.java index c5d25da1d..f76c3960e 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PatientIdentifier.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PatientIdentifier.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Patient; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Patient.identifier", type = SearchParamType.TOKEN, documentation = "A patient identifier") +@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Patient-identifier", type = SearchParamType.TOKEN, documentation = "A patient identifier") public class PatientIdentifier extends AbstractIdentifierParameter<Patient> { public static final String RESOURCE_COLUMN = "patient"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PractitionerIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PractitionerIdentifier.java index 4b5b9203d..7a932926b 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PractitionerIdentifier.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PractitionerIdentifier.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Practitioner; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Practitioner.identifier", type = SearchParamType.TOKEN, documentation = "A practitioner's Identifier") +@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Practitioner-identifier", type = SearchParamType.TOKEN, documentation = "A practitioner's Identifier") public class PractitionerIdentifier extends AbstractIdentifierParameter<Practitioner> { public static final String RESOURCE_COLUMN = "practitioner"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PractitionerRoleIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PractitionerRoleIdentifier.java index af473ee7e..c9b9e79a1 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PractitionerRoleIdentifier.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/PractitionerRoleIdentifier.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.PractitionerRole; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/PractitionerRole.identifier", type = SearchParamType.TOKEN, documentation = "A practitioner's Identifier") +@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/PractitionerRole-identifier", type = SearchParamType.TOKEN, documentation = "A practitioner's Identifier") public class PractitionerRoleIdentifier extends AbstractIdentifierParameter<PractitionerRole> { public static final String RESOURCE_COLUMN = "practitioner_role"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ResearchStudyEnrollment.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ResearchStudyEnrollment.java index 28aff6c39..db91aeec8 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ResearchStudyEnrollment.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ResearchStudyEnrollment.java @@ -21,7 +21,7 @@ import org.hl7.fhir.r4.model.ResearchStudy; import org.hl7.fhir.r4.model.Resource; -@SearchQueryParameter.SearchParameterDefinition(name = ResearchStudyEnrollment.PARAMETER_NAME, definition = "http://highmed.org/fhir/SearchParameter/research-study-enrollment", type = Enumerations.SearchParamType.REFERENCE, documentation = "Search by research study enrollment") +@SearchQueryParameter.SearchParameterDefinition(name = ResearchStudyEnrollment.PARAMETER_NAME, definition = "http://highmed.org/fhir/SearchParameter/ResearchStudy-enrollment", type = Enumerations.SearchParamType.REFERENCE, documentation = "Search by research study enrollment") public class ResearchStudyEnrollment extends AbstractReferenceParameter<ResearchStudy> { private static final String RESOURCE_TYPE_NAME = "ResearchStudy"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ResearchStudyIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ResearchStudyIdentifier.java index 26e7e9747..c692f8c15 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ResearchStudyIdentifier.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ResearchStudyIdentifier.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.ResearchStudy; import org.hl7.fhir.r4.model.Resource; -@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ResearchStudy.identifier", type = SearchParamType.TOKEN, documentation = "Business Identifier for study") +@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ResearchStudy-identifier", type = SearchParamType.TOKEN, documentation = "Business Identifier for study") public class ResearchStudyIdentifier extends AbstractIdentifierParameter<ResearchStudy> { public static final String RESOURCE_COLUMN = "research_study"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/StructureDefinitionIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/StructureDefinitionIdentifier.java index 0e209fcc9..06fecac2e 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/StructureDefinitionIdentifier.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/StructureDefinitionIdentifier.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.StructureDefinition; -@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/StructureDefinition.identifier", type = SearchParamType.TOKEN, documentation = "External identifier for the structure definition") +@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/StructureDefinition-identifier", type = SearchParamType.TOKEN, documentation = "External identifier for the structure definition") public class StructureDefinitionIdentifier extends AbstractIdentifierParameter<StructureDefinition> { public static final String RESOURCE_COLUMN = "structure_definition"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/StructureDefinitionUrl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/StructureDefinitionUrl.java index 532bdabf3..ec5b11bce 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/StructureDefinitionUrl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/StructureDefinitionUrl.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.StructureDefinition; -@SearchParameterDefinition(name = StructureDefinitionUrl.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/StructureDefinition.url", type = SearchParamType.URI, documentation = "The uri that identifies the structure definition") +@SearchParameterDefinition(name = StructureDefinitionUrl.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/StructureDefinition-url", type = SearchParamType.URI, documentation = "The uri that identifies the structure definition") public class StructureDefinitionUrl extends AbstractUrlAndVersionParameter<StructureDefinition> { public static final String RESOURCE_COLUMN = "structure_definition"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/StructureDefinitionVersion.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/StructureDefinitionVersion.java index 50a6f2285..a9a9885a7 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/StructureDefinitionVersion.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/StructureDefinitionVersion.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.StructureDefinition; -@SearchParameterDefinition(name = StructureDefinitionVersion.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/StructureDefinition.version", type = SearchParamType.TOKEN, documentation = "The business version of the structure definition") +@SearchParameterDefinition(name = StructureDefinitionVersion.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/StructureDefinition-version", type = SearchParamType.TOKEN, documentation = "The business version of the structure definition") public class StructureDefinitionVersion extends AbstractVersionParameter<StructureDefinition> { public static final String RESOURCE_COLUMN = "structure_definition"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionCriteria.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionCriteria.java index 552af7327..e3a64bd4a 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionCriteria.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionCriteria.java @@ -12,7 +12,7 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.Subscription; -@SearchParameterDefinition(name = SubscriptionCriteria.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Subscription.criteria", type = SearchParamType.STRING, documentation = "The search rules used to determine when to send a notification (always matches exact)") +@SearchParameterDefinition(name = SubscriptionCriteria.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Subscription-criteria", type = SearchParamType.STRING, documentation = "The search rules used to determine when to send a notification (always matches exact)") public class SubscriptionCriteria extends AbstractStringParameter<Subscription> { public static final String PARAMETER_NAME = "criteria"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionChannelPayload.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionPayload.java similarity index 85% rename from dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionChannelPayload.java rename to dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionPayload.java index 841da7c86..341bf2252 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionChannelPayload.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionPayload.java @@ -17,14 +17,14 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.Subscription; -@SearchParameterDefinition(name = SubscriptionChannelPayload.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Subscription.channel.payload", type = SearchParamType.TOKEN, documentation = "The mime-type of the notification payload") -public class SubscriptionChannelPayload extends AbstractTokenParameter<Subscription> +@SearchParameterDefinition(name = SubscriptionPayload.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Subscription-payload", type = SearchParamType.TOKEN, documentation = "The mime-type of the notification payload") +public class SubscriptionPayload extends AbstractTokenParameter<Subscription> { public static final String PARAMETER_NAME = "payload"; private String payloadMimeType; - public SubscriptionChannelPayload() + public SubscriptionPayload() { super(PARAMETER_NAME); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionStatus.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionStatus.java index ae93490a6..df7d60cf5 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionStatus.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionStatus.java @@ -18,7 +18,7 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.Subscription; -@SearchParameterDefinition(name = SubscriptionStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Subscription.status", type = SearchParamType.TOKEN, documentation = "Search by subscription status") +@SearchParameterDefinition(name = SubscriptionStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Subscription-status", type = SearchParamType.TOKEN, documentation = "Search by subscription status") public class SubscriptionStatus extends AbstractTokenParameter<Subscription> { public static final String PARAMETER_NAME = "status"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionChannelType.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionType.java similarity index 87% rename from dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionChannelType.java rename to dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionType.java index 63d830ef6..406d2f15f 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionChannelType.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/SubscriptionType.java @@ -18,14 +18,14 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.Subscription; -@SearchParameterDefinition(name = SubscriptionChannelType.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Subscription.channel.type", type = SearchParamType.TOKEN, documentation = "The type of channel for the sent notifications") -public class SubscriptionChannelType extends AbstractTokenParameter<Subscription> +@SearchParameterDefinition(name = SubscriptionType.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Subscription-type", type = SearchParamType.TOKEN, documentation = "The type of channel for the sent notifications") +public class SubscriptionType extends AbstractTokenParameter<Subscription> { public static final String PARAMETER_NAME = "type"; private org.hl7.fhir.r4.model.Subscription.SubscriptionChannelType channelType; - public SubscriptionChannelType() + public SubscriptionType() { super(PARAMETER_NAME); } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/TaskIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/TaskIdentifier.java index 277e77bf9..9305e06fe 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/TaskIdentifier.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/TaskIdentifier.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.Task; -@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Task.identifier", type = SearchParamType.TOKEN, documentation = "Search for a task instance by its business identifier") +@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/Task-identifier", type = SearchParamType.TOKEN, documentation = "Search for a task instance by its business identifier") public class TaskIdentifier extends AbstractIdentifierParameter<Task> { public static final String RESOURCE_COLUMN = "task"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetIdentifier.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetIdentifier.java index 73d9dac49..2aee1fdfd 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetIdentifier.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetIdentifier.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.ValueSet; -@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ValueSet.identifier", type = SearchParamType.TOKEN, documentation = "External identifier for the value set") +@SearchParameterDefinition(name = AbstractIdentifierParameter.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ValueSet-identifier", type = SearchParamType.TOKEN, documentation = "External identifier for the value set") public class ValueSetIdentifier extends AbstractIdentifierParameter<ValueSet> { public static final String RESOURCE_COLUMN = "value_set"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetStatus.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetStatus.java index 7e4f01a9a..1c5e25250 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetStatus.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetStatus.java @@ -21,7 +21,7 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.ValueSet; -@SearchParameterDefinition(name = ValueSetStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ValueSet.status", type = SearchParamType.TOKEN, documentation = "The current status of the value set") +@SearchParameterDefinition(name = ValueSetStatus.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ValueSet-status", type = SearchParamType.TOKEN, documentation = "The current status of the value set") public class ValueSetStatus extends AbstractTokenParameter<ValueSet> { public static final String PARAMETER_NAME = "status"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetUrl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetUrl.java index 501d044cd..1714d0b35 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetUrl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetUrl.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.ValueSet; -@SearchParameterDefinition(name = ValueSetUrl.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ValueSet.url", type = SearchParamType.URI, documentation = "The uri that identifies the value set") +@SearchParameterDefinition(name = ValueSetUrl.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ValueSet-url", type = SearchParamType.URI, documentation = "The uri that identifies the value set") public class ValueSetUrl extends AbstractUrlAndVersionParameter<ValueSet> { public static final String RESOURCE_COLUMN = "value_set"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetVersion.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetVersion.java index b801ee51e..6ce05a651 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetVersion.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/search/parameters/ValueSetVersion.java @@ -6,7 +6,7 @@ import org.hl7.fhir.r4.model.Resource; import org.hl7.fhir.r4.model.ValueSet; -@SearchParameterDefinition(name = ValueSetVersion.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ValueSet.version", type = SearchParamType.TOKEN, documentation = "The business version of the value set") +@SearchParameterDefinition(name = ValueSetVersion.PARAMETER_NAME, definition = "http://hl7.org/fhir/SearchParameter/ValueSet-version", type = SearchParamType.TOKEN, documentation = "The business version of the value set") public class ValueSetVersion extends AbstractVersionParameter<ValueSet> { public static final String RESOURCE_COLUMN = "value_set"; diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java index a118ba973..ae3051490 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/impl/ConformanceServiceImpl.java @@ -59,10 +59,10 @@ import org.highmed.dsf.fhir.search.parameters.StructureDefinitionStatus; import org.highmed.dsf.fhir.search.parameters.StructureDefinitionUrl; import org.highmed.dsf.fhir.search.parameters.StructureDefinitionVersion; -import org.highmed.dsf.fhir.search.parameters.SubscriptionChannelPayload; -import org.highmed.dsf.fhir.search.parameters.SubscriptionChannelType; import org.highmed.dsf.fhir.search.parameters.SubscriptionCriteria; +import org.highmed.dsf.fhir.search.parameters.SubscriptionPayload; import org.highmed.dsf.fhir.search.parameters.SubscriptionStatus; +import org.highmed.dsf.fhir.search.parameters.SubscriptionType; import org.highmed.dsf.fhir.search.parameters.TaskIdentifier; import org.highmed.dsf.fhir.search.parameters.TaskRequester; import org.highmed.dsf.fhir.search.parameters.TaskStatus; @@ -287,11 +287,11 @@ private CapabilityStatement createCapabilityStatement(String serverBase, int def structureDefinitionStatus, structureDefinitionUrl, structureDefinitionVersion)); var subscriptionCriteria = createSearchParameter(SubscriptionCriteria.class); + var subscriptionPayload = createSearchParameter(SubscriptionPayload.class); var subscriptionStatus = createSearchParameter(SubscriptionStatus.class); - var subscriptionChannelPayload = createSearchParameter(SubscriptionChannelPayload.class); - var subscriptionChannelType = createSearchParameter(SubscriptionChannelType.class); - searchParameters.put(Subscription.class, Arrays.asList(subscriptionCriteria, subscriptionStatus, - subscriptionChannelPayload, subscriptionChannelType)); + var subscriptionType = createSearchParameter(SubscriptionType.class); + searchParameters.put(Subscription.class, + Arrays.asList(subscriptionCriteria, subscriptionPayload, subscriptionStatus, subscriptionType)); var taskIdentifier = createSearchParameter(TaskIdentifier.class); var taskRequester = createSearchParameter(TaskRequester.class); From 4c7454511692208849b244942bf121b66136cb25 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 17:17:20 +0100 Subject: [PATCH 35/55] added authorization tag to created whitelist transaction bundle --- .../dsf/bpe/service/UpdateWhiteList.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/service/UpdateWhiteList.java b/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/service/UpdateWhiteList.java index f5a6eeb16..e366732f9 100755 --- a/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/service/UpdateWhiteList.java +++ b/dsf-bpe/dsf-bpe-process-update-whitelist/src/main/java/org/highmed/dsf/bpe/service/UpdateWhiteList.java @@ -59,15 +59,17 @@ public void doExecute(DelegateExecution execution) throws Exception Collections.singletonList("Organization:endpoint"))); Bundle transaction = new Bundle().setType(BundleType.TRANSACTION); + transaction.getMeta().addTag().setSystem("http://highmed.org/fhir/CodeSystem/authorization-role") + .setCode("REMOTE"); transaction.getIdentifier().setSystem(Constants.CODESYSTEM_HIGHMED_UPDATE_WHITELIST) .setValue(Constants.CODESYSTEM_HIGHMED_UPDATE_WHITELIST_VALUE_WHITE_LIST); searchSet.getEntry().stream() .filter(e -> e.hasSearch() && SearchEntryMode.MATCH.equals(e.getSearch().getMode()) && e.hasResource() - && e.getResource() instanceof Organization).map(e -> (Organization) e.getResource()) - .forEach(addWhiteListEntry(transaction, searchSet)); + && e.getResource() instanceof Organization) + .map(e -> (Organization) e.getResource()).forEach(addWhiteListEntry(transaction, searchSet)); - Bundle result = client.updateConditionaly(transaction, Map.of("identifier", Collections.singletonList( - Constants.CODESYSTEM_HIGHMED_UPDATE_WHITELIST + "|" + Bundle result = client.updateConditionaly(transaction, + Map.of("identifier", Collections.singletonList(Constants.CODESYSTEM_HIGHMED_UPDATE_WHITELIST + "|" + Constants.CODESYSTEM_HIGHMED_UPDATE_WHITELIST_VALUE_WHITE_LIST))); setTaskOutput(result, execution); @@ -75,7 +77,8 @@ public void doExecute(DelegateExecution execution) throws Exception private Consumer<? super Organization> addWhiteListEntry(Bundle transaction, Bundle searchSet) { - return organization -> { + return organization -> + { Identifier identifier = getDefaultIdentifier(organization).get(); BundleEntryComponent organizationEntry = transaction.addEntry(); @@ -97,7 +100,8 @@ private Consumer<? super Organization> addWhiteListEntry(Bundle transaction, Bun private Function<Reference, Optional<Reference>> addWhiteListEntryReturnReference(Bundle transaction, String organizationId, Bundle searchSet) { - return endpointRef -> getEndpoint(endpointRef, searchSet).map(endpoint -> { + return endpointRef -> getEndpoint(endpointRef, searchSet).map(endpoint -> + { Identifier identifier = getDefaultIdentifier(endpoint).get(); BundleEntryComponent endpointEntry = transaction.addEntry(); @@ -130,8 +134,9 @@ private Optional<Identifier> getDefaultIdentifier(Endpoint ept) private Optional<Endpoint> getEndpoint(Reference endpoint, Bundle searchSet) { return searchSet.getEntry().stream() - .filter(e -> e.hasResource() && e.getResource() instanceof Endpoint && e.getFullUrl() - .endsWith(endpoint.getReference())).map(e -> (Endpoint) e.getResource()).findFirst(); + .filter(e -> e.hasResource() && e.getResource() instanceof Endpoint + && e.getFullUrl().endsWith(endpoint.getReference())) + .map(e -> (Endpoint) e.getResource()).findFirst(); } private void setTaskOutput(Bundle result, DelegateExecution execution) From 7f71f9eecaa3d2afe6cd93a550e60977d36d6e43 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 17:18:05 +0100 Subject: [PATCH 36/55] fixed message name (case sensitive) and process version (now 0.1.0) --- .../dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java | 4 ++-- .../src/test/resources/update-whitelist-task.example.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java b/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java index de3234cac..def693de8 100644 --- a/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/java/org/highmed/dsf/bpe/start/UpdateWhiteList3MedicTtpExampleStarter.java @@ -39,7 +39,7 @@ public static void main(String[] args) Task task = new Task(); task.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-update-whitelist"); - task.setInstantiatesUri("http://highmed.org/bpe/Process/updateWhiteList/1.0.0"); + task.setInstantiatesUri("http://highmed.org/bpe/Process/updateWhiteList/0.1.0"); task.setStatus(TaskStatus.REQUESTED); task.setIntent(TaskIntent.ORDER); task.setAuthoredOn(new Date()); @@ -48,7 +48,7 @@ public static void main(String[] args) task.getRestriction().addRecipient().setType("Organization").getIdentifier() .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_TTP"); - task.addInput().setValue(new StringType("updateWhiteListMessage")).getType().addCoding() + task.addInput().setValue(new StringType("updateWhitelistMessage")).getType().addCoding() .setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message").setCode("message-name"); client.create(task); diff --git a/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/resources/update-whitelist-task.example.json b/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/resources/update-whitelist-task.example.json index c7a54d9d2..7504fa3c7 100755 --- a/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/resources/update-whitelist-task.example.json +++ b/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/resources/update-whitelist-task.example.json @@ -3,7 +3,7 @@ "meta":{ "profile":"http://highmed.org/fhir/StructureDefinition/highmed-task-update-whitelist" }, - "instantiatesUri":"http://highmed.org/bpe/Process/updateWhiteList/1.0.0", + "instantiatesUri":"http://highmed.org/bpe/Process/updateWhiteList/0.1.0", "status":"requested", "intent":"order", "authoredOn":"2019-10-21", @@ -35,7 +35,7 @@ } ] }, - "valueString":"updateWhiteListMessage" + "valueString":"updateWhitelistMessage" } ] } \ No newline at end of file From 03cf9c152d6494bf24ed88b8a9c68da3114e222d Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 17:30:58 +0100 Subject: [PATCH 37/55] process version number changes 1.0.0 -> 0.1.0 --- .../src/main/resources/computeSimpleFeasibility.bpmn | 2 +- .../src/main/resources/executeSimpleFeasibility.bpmn | 2 +- .../src/main/resources/requestSimpleFeasibility.bpmn | 4 ++-- ...estSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java | 2 +- dsf-bpe/dsf-bpe-process-ping/src/main/resources/ping.bpmn | 2 +- dsf-bpe/dsf-bpe-process-ping/src/main/resources/pong.bpmn | 2 +- .../dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java | 2 +- .../src/main/resources/requestUpdateResources.bpmn | 2 +- .../dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/computeSimpleFeasibility.bpmn b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/computeSimpleFeasibility.bpmn index bf23ee2a0..8d9ce9c61 100644 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/computeSimpleFeasibility.bpmn +++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/computeSimpleFeasibility.bpmn @@ -47,7 +47,7 @@ <camunda:inputOutput> <camunda:inputParameter name="processDefinitionKey">requestSimpleFeasibility</camunda:inputParameter> <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/highmed-task-result-multi-medic-simple-feasibility</camunda:inputParameter> - <camunda:inputParameter name="versionTag">1.0.0</camunda:inputParameter> + <camunda:inputParameter name="versionTag">0.1.0</camunda:inputParameter> <camunda:inputParameter name="messageName">resultMultiMedicSimpleFeasibilityMessage</camunda:inputParameter> </camunda:inputOutput> </bpmn:extensionElements> diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/executeSimpleFeasibility.bpmn b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/executeSimpleFeasibility.bpmn index 27749ab15..826722289 100755 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/executeSimpleFeasibility.bpmn +++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/executeSimpleFeasibility.bpmn @@ -25,7 +25,7 @@ <bpmn:extensionElements> <camunda:inputOutput> <camunda:inputParameter name="messageName">resultSingleMedicSimpleFeasibilityMessage</camunda:inputParameter> - <camunda:inputParameter name="versionTag">1.0.0</camunda:inputParameter> + <camunda:inputParameter name="versionTag">0.1.0</camunda:inputParameter> <camunda:inputParameter name="processDefinitionKey">computeSimpleFeasibility</camunda:inputParameter> <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/highmed-task-result-single-medic-simple-feasibility</camunda:inputParameter> </camunda:inputOutput> diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/requestSimpleFeasibility.bpmn b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/requestSimpleFeasibility.bpmn index 63cb4ee07..9a78de695 100755 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/requestSimpleFeasibility.bpmn +++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/resources/requestSimpleFeasibility.bpmn @@ -13,7 +13,7 @@ <bpmn:extensionElements> <camunda:inputOutput> <camunda:inputParameter name="processDefinitionKey">executeSimpleFeasibility</camunda:inputParameter> - <camunda:inputParameter name="versionTag">1.0.0</camunda:inputParameter> + <camunda:inputParameter name="versionTag">0.1.0</camunda:inputParameter> <camunda:inputParameter name="messageName">executeSimpleFeasibilityMessage</camunda:inputParameter> <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/highmed-task-execute-simple-feasibility</camunda:inputParameter> </camunda:inputOutput> @@ -42,7 +42,7 @@ <bpmn:extensionElements> <camunda:inputOutput> <camunda:inputParameter name="processDefinitionKey">computeSimpleFeasibility</camunda:inputParameter> - <camunda:inputParameter name="versionTag">1.0.0</camunda:inputParameter> + <camunda:inputParameter name="versionTag">0.1.0</camunda:inputParameter> <camunda:inputParameter name="messageName">computeSimpleFeasibilityMessage</camunda:inputParameter> <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/highmed-task-compute-simple-feasibility</camunda:inputParameter> </camunda:inputOutput> diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java b/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java index 59099dc20..381914044 100644 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java @@ -174,7 +174,7 @@ private static Task createTask(Practitioner practitioner, ResearchStudy research task.getMeta() .addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-request-simple-feasibility"); - task.setInstantiatesUri("http://highmed.org/bpe/Process/requestSimpleFeasibility/1.0.0"); + task.setInstantiatesUri("http://highmed.org/bpe/Process/requestSimpleFeasibility/0.1.0"); task.setStatus(TaskStatus.REQUESTED); task.setIntent(TaskIntent.ORDER); task.setAuthoredOn(new Date()); diff --git a/dsf-bpe/dsf-bpe-process-ping/src/main/resources/ping.bpmn b/dsf-bpe/dsf-bpe-process-ping/src/main/resources/ping.bpmn index 75ffb5316..4b064775d 100755 --- a/dsf-bpe/dsf-bpe-process-ping/src/main/resources/ping.bpmn +++ b/dsf-bpe/dsf-bpe-process-ping/src/main/resources/ping.bpmn @@ -11,7 +11,7 @@ <bpmn:extensionElements> <camunda:inputOutput> <camunda:inputParameter name="processDefinitionKey">pong</camunda:inputParameter> - <camunda:inputParameter name="versionTag">1.0.0</camunda:inputParameter> + <camunda:inputParameter name="versionTag">0.1.0</camunda:inputParameter> <camunda:inputParameter name="messageName">pingMessage</camunda:inputParameter> <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/highmed-task-ping</camunda:inputParameter> </camunda:inputOutput> diff --git a/dsf-bpe/dsf-bpe-process-ping/src/main/resources/pong.bpmn b/dsf-bpe/dsf-bpe-process-ping/src/main/resources/pong.bpmn index 228eb1954..d13a47ae0 100755 --- a/dsf-bpe/dsf-bpe-process-ping/src/main/resources/pong.bpmn +++ b/dsf-bpe/dsf-bpe-process-ping/src/main/resources/pong.bpmn @@ -10,7 +10,7 @@ <bpmn:extensionElements> <camunda:inputOutput> <camunda:inputParameter name="messageName">pongMessage</camunda:inputParameter> - <camunda:inputParameter name="versionTag">1.0.0</camunda:inputParameter> + <camunda:inputParameter name="versionTag">0.1.0</camunda:inputParameter> <camunda:inputParameter name="processDefinitionKey">ping</camunda:inputParameter> <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/highmed-task-pong</camunda:inputParameter> </camunda:inputOutput> diff --git a/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java b/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java index 2e6c37da5..182ffc78c 100644 --- a/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-ping/src/test/java/org/highmed/dsf/bpe/start/Ping3MedicFromTtpExampleStarter.java @@ -39,7 +39,7 @@ public static void main(String[] args) Task task = new Task(); task.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"); - task.setInstantiatesUri("http://highmed.org/bpe/Process/ping/1.0.0"); + task.setInstantiatesUri("http://highmed.org/bpe/Process/ping/0.1.0"); task.setStatus(TaskStatus.REQUESTED); task.setIntent(TaskIntent.ORDER); task.setAuthoredOn(new Date()); diff --git a/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/requestUpdateResources.bpmn b/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/requestUpdateResources.bpmn index 9824b606f..5fe0830b9 100755 --- a/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/requestUpdateResources.bpmn +++ b/dsf-bpe/dsf-bpe-process-update-resources/src/main/resources/requestUpdateResources.bpmn @@ -11,7 +11,7 @@ <bpmn:extensionElements> <camunda:inputOutput> <camunda:inputParameter name="processDefinitionKey">executeUpdateResources</camunda:inputParameter> - <camunda:inputParameter name="versionTag">1.0.0</camunda:inputParameter> + <camunda:inputParameter name="versionTag">0.1.0</camunda:inputParameter> <camunda:inputParameter name="messageName">executeUpdateResourcesMessage</camunda:inputParameter> <camunda:inputParameter name="profile">http://highmed.org/fhir/StructureDefinition/highmed-task-execute-update-resources</camunda:inputParameter> </camunda:inputOutput> diff --git a/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java b/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java index ed6327ae1..3b9f4c732 100644 --- a/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-update-resources/src/test/java/org/highmed/dsf/bpe/start/UpdateResource3MedicTtpExampleStarter.java @@ -49,7 +49,7 @@ public static void main(String[] args) Task task = new Task(); task.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-request-update-resources"); - task.setInstantiatesUri("http://highmed.org/bpe/Process/requestUpdateResources/1.0.0"); + task.setInstantiatesUri("http://highmed.org/bpe/Process/requestUpdateResources/0.1.0"); task.setStatus(TaskStatus.REQUESTED); task.setIntent(TaskIntent.ORDER); task.setAuthoredOn(new Date()); From 89fd23544b420d9e135fa5d8fc5a8e4ab420ffb9 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 17:39:54 +0100 Subject: [PATCH 38/55] fixed message-names --- .../fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml | 2 +- .../highmed-task-request-update-resources-0.1.0.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml index deb709504..8a05e4a75 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml @@ -7,7 +7,7 @@ </meta> <extension url="http://highmed.org/fhir/StructureDefinition/process-authorization"> <extension url="message-name"> - <valueString value="updateWhitelistMessage" /> + <valueString value="executeUpdateResourcesMessage" /> </extension> <extension url="authorization-role"> <valueCoding> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-update-resources-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-update-resources-0.1.0.xml index 12617d40b..0ccda7d46 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-update-resources-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-task-request-update-resources-0.1.0.xml @@ -39,7 +39,7 @@ </element> <element id="Task.input:message-name.value[x]"> <path value="Task.input.value[x]" /> - <fixedString value="requestUpdateResourcesMessage" /> + <fixedString value="executeUpdateResourcesMessage" /> </element> <element id="Task.input:business-key"> <path value="Task.input" /> From 2d138449aa5e570fa335644ba52932a7f62c627c Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 19:44:44 +0100 Subject: [PATCH 39/55] increased remote read and connection timeouts --- .../medic1/bpe/app/conf/config.properties | 80 +++++++++---------- .../medic2/bpe/app/conf/config.properties | 80 +++++++++---------- .../medic3/bpe/app/conf/config.properties | 80 +++++++++---------- .../ttp/bpe/app/conf/config.properties | 80 +++++++++---------- .../docker-test-medic1-fhir-config.properties | 4 +- .../docker-test-medic2-fhir-config.properties | 4 +- .../docker-test-medic3-fhir-config.properties | 4 +- .../docker-test-ttp-fhir-config.properties | 4 +- 8 files changed, 168 insertions(+), 168 deletions(-) diff --git a/dsf-docker-test-setup-3medic-ttp/medic1/bpe/app/conf/config.properties b/dsf-docker-test-setup-3medic-ttp/medic1/bpe/app/conf/config.properties index d10f17116..a7ae8f282 100755 --- a/dsf-docker-test-setup-3medic-ttp/medic1/bpe/app/conf/config.properties +++ b/dsf-docker-test-setup-3medic-ttp/medic1/bpe/app/conf/config.properties @@ -1,41 +1,41 @@ -org.highmed.dsf.bpe.db.driver=org.postgresql.Driver -org.highmed.dsf.bpe.db.url=jdbc:postgresql://db/bpe -org.highmed.dsf.bpe.db.liquibase_user=liquibase_user -org.highmed.dsf.bpe.db.liquibase_user_password=jgp9LnFnJhzrbXqpR9ZqG87H9p2N7dK3chpSq5StemTqWebzSAwYCFCqERWkFKKp - -org.highmed.dsf.bpe.db.server_users_group=bpe_users -org.highmed.dsf.bpe.db.server_user=bpe_server_user -org.highmed.dsf.bpe.db.server_user_password=wM3CEsfak2SyzSsEudxgRs7uB6n3vM7B - -org.highmed.dsf.bpe.db.camunda_users_group=camunda_users -org.highmed.dsf.bpe.db.camunda_user=camunda_server_user -org.highmed.dsf.bpe.db.camunda_user_password=wpBFyZHCxBdHxNWTUz53MYY9Z5Mn1QKd - -org.highmed.dsf.bpe.fhir.organization.identifier.localValue=Test_MeDIC_1 - -org.highmed.dsf.bpe.fhir.local.webservice.baseUrl=https://medic1/fhir -org.highmed.dsf.bpe.fhir.local.webservice.keystore.p12file=conf/medic1-client_certificate.p12 -org.highmed.dsf.bpe.fhir.local.webservice.keystore.password=password -org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=1500 -org.highmed.dsf.bpe.fhir.local.webservice.connectTimeout=500 - -org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=2500 -org.highmed.dsf.bpe.fhir.remote.webservice.connectTimeout=1500 -#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password= -#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username= -#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.schemeHostPort= - -org.highmed.dsf.bpe.fhir.local.websocket.url=wss://medic1/fhir/ws -org.highmed.dsf.bpe.fhir.local.websocket.keystore.p12file=conf/medic1-client_certificate.p12 -org.highmed.dsf.bpe.fhir.local.websocket.keystore.password=password - -org.highmed.dsf.bpe.fhir.task.subscription.searchParameter=?criteria=Task%3Fstatus%3Drequested&status=active&type=websocket&payload=application/fhir%2Bjson -org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile=last_event/time.file - -org.highmed.dsf.bpe.openehr.webservice.baseUrl=https://openehr/rest/openehr/v1 -org.highmed.dsf.bpe.openehr.webservice.basicAuthUsername=username -org.highmed.dsf.bpe.openehr.webservice.basicAuthPassword=password -org.highmed.dsf.bpe.openehr.webservice.connectionTimeout=1500 -org.highmed.dsf.bpe.openehr.webservice.readTimeout=2500 - +org.highmed.dsf.bpe.db.driver=org.postgresql.Driver +org.highmed.dsf.bpe.db.url=jdbc:postgresql://db/bpe +org.highmed.dsf.bpe.db.liquibase_user=liquibase_user +org.highmed.dsf.bpe.db.liquibase_user_password=jgp9LnFnJhzrbXqpR9ZqG87H9p2N7dK3chpSq5StemTqWebzSAwYCFCqERWkFKKp + +org.highmed.dsf.bpe.db.server_users_group=bpe_users +org.highmed.dsf.bpe.db.server_user=bpe_server_user +org.highmed.dsf.bpe.db.server_user_password=wM3CEsfak2SyzSsEudxgRs7uB6n3vM7B + +org.highmed.dsf.bpe.db.camunda_users_group=camunda_users +org.highmed.dsf.bpe.db.camunda_user=camunda_server_user +org.highmed.dsf.bpe.db.camunda_user_password=wpBFyZHCxBdHxNWTUz53MYY9Z5Mn1QKd + +org.highmed.dsf.bpe.fhir.organization.identifier.localValue=Test_MeDIC_1 + +org.highmed.dsf.bpe.fhir.local.webservice.baseUrl=https://medic1/fhir +org.highmed.dsf.bpe.fhir.local.webservice.keystore.p12file=conf/medic1-client_certificate.p12 +org.highmed.dsf.bpe.fhir.local.webservice.keystore.password=password +org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=2000 +org.highmed.dsf.bpe.fhir.local.webservice.connectTimeout=500 + +org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=5000 +org.highmed.dsf.bpe.fhir.remote.webservice.connectTimeout=2000 +#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password= +#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username= +#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.schemeHostPort= + +org.highmed.dsf.bpe.fhir.local.websocket.url=wss://medic1/fhir/ws +org.highmed.dsf.bpe.fhir.local.websocket.keystore.p12file=conf/medic1-client_certificate.p12 +org.highmed.dsf.bpe.fhir.local.websocket.keystore.password=password + +org.highmed.dsf.bpe.fhir.task.subscription.searchParameter=?criteria=Task%3Fstatus%3Drequested&status=active&type=websocket&payload=application/fhir%2Bjson +org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile=last_event/time.file + +org.highmed.dsf.bpe.openehr.webservice.baseUrl=https://openehr/rest/openehr/v1 +org.highmed.dsf.bpe.openehr.webservice.basicAuthUsername=username +org.highmed.dsf.bpe.openehr.webservice.basicAuthPassword=password +org.highmed.dsf.bpe.openehr.webservice.connectionTimeout=1500 +org.highmed.dsf.bpe.openehr.webservice.readTimeout=2500 + org.highmed.dsf.bpe.cors.origins= \ No newline at end of file diff --git a/dsf-docker-test-setup-3medic-ttp/medic2/bpe/app/conf/config.properties b/dsf-docker-test-setup-3medic-ttp/medic2/bpe/app/conf/config.properties index f38f2bc2f..5922d5d4b 100755 --- a/dsf-docker-test-setup-3medic-ttp/medic2/bpe/app/conf/config.properties +++ b/dsf-docker-test-setup-3medic-ttp/medic2/bpe/app/conf/config.properties @@ -1,41 +1,41 @@ -org.highmed.dsf.bpe.db.driver=org.postgresql.Driver -org.highmed.dsf.bpe.db.url=jdbc:postgresql://db/bpe -org.highmed.dsf.bpe.db.liquibase_user=liquibase_user -org.highmed.dsf.bpe.db.liquibase_user_password=9Ed2h5kAqSFm9xYWm2Cv248ELJVq24asKr4nwp8uxFHnfWuB5PCPgFkg42T5HgvL - -org.highmed.dsf.bpe.db.server_users_group=bpe_users -org.highmed.dsf.bpe.db.server_user=bpe_server_user -org.highmed.dsf.bpe.db.server_user_password=RvDe9MXeq3UyTJMXszLQWZ2WJpDF26Gr - -org.highmed.dsf.bpe.db.camunda_users_group=camunda_users -org.highmed.dsf.bpe.db.camunda_user=camunda_server_user -org.highmed.dsf.bpe.db.camunda_user_password=emYKsWgEMa2RMeSKfE9wCJMxnTfAafXb - -org.highmed.dsf.bpe.fhir.organization.identifier.localValue=Test_MeDIC_2 - -org.highmed.dsf.bpe.fhir.local.webservice.baseUrl=https://medic2/fhir -org.highmed.dsf.bpe.fhir.local.webservice.keystore.p12file=conf/medic2-client_certificate.p12 -org.highmed.dsf.bpe.fhir.local.webservice.keystore.password=password -org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=1500 -org.highmed.dsf.bpe.fhir.local.webservice.connectTimeout=500 - -org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=2500 -org.highmed.dsf.bpe.fhir.remote.webservice.connectTimeout=1500 -#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password= -#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username= -#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.schemeHostPort= - -org.highmed.dsf.bpe.fhir.local.websocket.url=wss://medic2/fhir/ws -org.highmed.dsf.bpe.fhir.local.websocket.keystore.p12file=conf/medic2-client_certificate.p12 -org.highmed.dsf.bpe.fhir.local.websocket.keystore.password=password - -org.highmed.dsf.bpe.fhir.task.subscription.searchParameter=?criteria=Task%3Fstatus%3Drequested&status=active&type=websocket&payload=application/fhir%2Bjson -org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile=last_event/time.file - -org.highmed.dsf.bpe.openehr.webservice.baseUrl=https://openehr/rest/openehr/v1 -org.highmed.dsf.bpe.openehr.webservice.basicAuthUsername=username -org.highmed.dsf.bpe.openehr.webservice.basicAuthPassword=password -org.highmed.dsf.bpe.openehr.webservice.connectionTimeout=1500 -org.highmed.dsf.bpe.openehr.webservice.readTimeout=2500 - +org.highmed.dsf.bpe.db.driver=org.postgresql.Driver +org.highmed.dsf.bpe.db.url=jdbc:postgresql://db/bpe +org.highmed.dsf.bpe.db.liquibase_user=liquibase_user +org.highmed.dsf.bpe.db.liquibase_user_password=9Ed2h5kAqSFm9xYWm2Cv248ELJVq24asKr4nwp8uxFHnfWuB5PCPgFkg42T5HgvL + +org.highmed.dsf.bpe.db.server_users_group=bpe_users +org.highmed.dsf.bpe.db.server_user=bpe_server_user +org.highmed.dsf.bpe.db.server_user_password=RvDe9MXeq3UyTJMXszLQWZ2WJpDF26Gr + +org.highmed.dsf.bpe.db.camunda_users_group=camunda_users +org.highmed.dsf.bpe.db.camunda_user=camunda_server_user +org.highmed.dsf.bpe.db.camunda_user_password=emYKsWgEMa2RMeSKfE9wCJMxnTfAafXb + +org.highmed.dsf.bpe.fhir.organization.identifier.localValue=Test_MeDIC_2 + +org.highmed.dsf.bpe.fhir.local.webservice.baseUrl=https://medic2/fhir +org.highmed.dsf.bpe.fhir.local.webservice.keystore.p12file=conf/medic2-client_certificate.p12 +org.highmed.dsf.bpe.fhir.local.webservice.keystore.password=password +org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=2000 +org.highmed.dsf.bpe.fhir.local.webservice.connectTimeout=500 + +org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=5000 +org.highmed.dsf.bpe.fhir.remote.webservice.connectTimeout=2000 +#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password= +#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username= +#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.schemeHostPort= + +org.highmed.dsf.bpe.fhir.local.websocket.url=wss://medic2/fhir/ws +org.highmed.dsf.bpe.fhir.local.websocket.keystore.p12file=conf/medic2-client_certificate.p12 +org.highmed.dsf.bpe.fhir.local.websocket.keystore.password=password + +org.highmed.dsf.bpe.fhir.task.subscription.searchParameter=?criteria=Task%3Fstatus%3Drequested&status=active&type=websocket&payload=application/fhir%2Bjson +org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile=last_event/time.file + +org.highmed.dsf.bpe.openehr.webservice.baseUrl=https://openehr/rest/openehr/v1 +org.highmed.dsf.bpe.openehr.webservice.basicAuthUsername=username +org.highmed.dsf.bpe.openehr.webservice.basicAuthPassword=password +org.highmed.dsf.bpe.openehr.webservice.connectionTimeout=1500 +org.highmed.dsf.bpe.openehr.webservice.readTimeout=2500 + org.highmed.dsf.bpe.cors.origins= \ No newline at end of file diff --git a/dsf-docker-test-setup-3medic-ttp/medic3/bpe/app/conf/config.properties b/dsf-docker-test-setup-3medic-ttp/medic3/bpe/app/conf/config.properties index b3f47a092..c8614100f 100755 --- a/dsf-docker-test-setup-3medic-ttp/medic3/bpe/app/conf/config.properties +++ b/dsf-docker-test-setup-3medic-ttp/medic3/bpe/app/conf/config.properties @@ -1,41 +1,41 @@ -org.highmed.dsf.bpe.db.driver=org.postgresql.Driver -org.highmed.dsf.bpe.db.url=jdbc:postgresql://db/bpe -org.highmed.dsf.bpe.db.liquibase_user=liquibase_user -org.highmed.dsf.bpe.db.liquibase_user_password=nb8HHtsk7SB5kt4VEBssyF8qJ7ButmL8pghTE3sJP5MfVNf49NzhG5LqeaYAUqYE - -org.highmed.dsf.bpe.db.server_users_group=bpe_users -org.highmed.dsf.bpe.db.server_user=bpe_server_user -org.highmed.dsf.bpe.db.server_user_password=GBhkf7rDjX6YW9KWh6SkB6eynjN7WZdC - -org.highmed.dsf.bpe.db.camunda_users_group=camunda_users -org.highmed.dsf.bpe.db.camunda_user=camunda_server_user -org.highmed.dsf.bpe.db.camunda_user_password=H2ydwDcA3Ptey2saa7MjpXEjS3d3XENM - -org.highmed.dsf.bpe.fhir.organization.identifier.localValue=Test_MeDIC_3 - -org.highmed.dsf.bpe.fhir.local.webservice.baseUrl=https://medic3/fhir -org.highmed.dsf.bpe.fhir.local.webservice.keystore.p12file=conf/medic3-client_certificate.p12 -org.highmed.dsf.bpe.fhir.local.webservice.keystore.password=password -org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=1500 -org.highmed.dsf.bpe.fhir.local.webservice.connectTimeout=500 - -org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=2500 -org.highmed.dsf.bpe.fhir.remote.webservice.connectTimeout=1500 -#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password= -#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username= -#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.schemeHostPort= - -org.highmed.dsf.bpe.fhir.local.websocket.url=wss://medic3/fhir/ws -org.highmed.dsf.bpe.fhir.local.websocket.keystore.p12file=conf/medic3-client_certificate.p12 -org.highmed.dsf.bpe.fhir.local.websocket.keystore.password=password - -org.highmed.dsf.bpe.fhir.task.subscription.searchParameter=?criteria=Task%3Fstatus%3Drequested&status=active&type=websocket&payload=application/fhir%2Bjson -org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile=last_event/time.file - -org.highmed.dsf.bpe.openehr.webservice.baseUrl=https://openehr/rest/openehr/v1 -org.highmed.dsf.bpe.openehr.webservice.basicAuthUsername=username -org.highmed.dsf.bpe.openehr.webservice.basicAuthPassword=password -org.highmed.dsf.bpe.openehr.webservice.connectionTimeout=1500 -org.highmed.dsf.bpe.openehr.webservice.readTimeout=2500 - +org.highmed.dsf.bpe.db.driver=org.postgresql.Driver +org.highmed.dsf.bpe.db.url=jdbc:postgresql://db/bpe +org.highmed.dsf.bpe.db.liquibase_user=liquibase_user +org.highmed.dsf.bpe.db.liquibase_user_password=nb8HHtsk7SB5kt4VEBssyF8qJ7ButmL8pghTE3sJP5MfVNf49NzhG5LqeaYAUqYE + +org.highmed.dsf.bpe.db.server_users_group=bpe_users +org.highmed.dsf.bpe.db.server_user=bpe_server_user +org.highmed.dsf.bpe.db.server_user_password=GBhkf7rDjX6YW9KWh6SkB6eynjN7WZdC + +org.highmed.dsf.bpe.db.camunda_users_group=camunda_users +org.highmed.dsf.bpe.db.camunda_user=camunda_server_user +org.highmed.dsf.bpe.db.camunda_user_password=H2ydwDcA3Ptey2saa7MjpXEjS3d3XENM + +org.highmed.dsf.bpe.fhir.organization.identifier.localValue=Test_MeDIC_3 + +org.highmed.dsf.bpe.fhir.local.webservice.baseUrl=https://medic3/fhir +org.highmed.dsf.bpe.fhir.local.webservice.keystore.p12file=conf/medic3-client_certificate.p12 +org.highmed.dsf.bpe.fhir.local.webservice.keystore.password=password +org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=2000 +org.highmed.dsf.bpe.fhir.local.webservice.connectTimeout=500 + +org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=5000 +org.highmed.dsf.bpe.fhir.remote.webservice.connectTimeout=2000 +#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password= +#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username= +#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.schemeHostPort= + +org.highmed.dsf.bpe.fhir.local.websocket.url=wss://medic3/fhir/ws +org.highmed.dsf.bpe.fhir.local.websocket.keystore.p12file=conf/medic3-client_certificate.p12 +org.highmed.dsf.bpe.fhir.local.websocket.keystore.password=password + +org.highmed.dsf.bpe.fhir.task.subscription.searchParameter=?criteria=Task%3Fstatus%3Drequested&status=active&type=websocket&payload=application/fhir%2Bjson +org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile=last_event/time.file + +org.highmed.dsf.bpe.openehr.webservice.baseUrl=https://openehr/rest/openehr/v1 +org.highmed.dsf.bpe.openehr.webservice.basicAuthUsername=username +org.highmed.dsf.bpe.openehr.webservice.basicAuthPassword=password +org.highmed.dsf.bpe.openehr.webservice.connectionTimeout=1500 +org.highmed.dsf.bpe.openehr.webservice.readTimeout=2500 + org.highmed.dsf.bpe.cors.origins= \ No newline at end of file diff --git a/dsf-docker-test-setup-3medic-ttp/ttp/bpe/app/conf/config.properties b/dsf-docker-test-setup-3medic-ttp/ttp/bpe/app/conf/config.properties index 8fab329b7..e1c20401c 100755 --- a/dsf-docker-test-setup-3medic-ttp/ttp/bpe/app/conf/config.properties +++ b/dsf-docker-test-setup-3medic-ttp/ttp/bpe/app/conf/config.properties @@ -1,41 +1,41 @@ -org.highmed.dsf.bpe.db.driver=org.postgresql.Driver -org.highmed.dsf.bpe.db.url=jdbc:postgresql://db/bpe -org.highmed.dsf.bpe.db.liquibase_user=liquibase_user -org.highmed.dsf.bpe.db.liquibase_user_password=7nak4DxNE4mCfPbvhCTmVSYH9zWg7W6GkzYn4jc43mmFhkRj9k7s7RpEB5UPFTA7 - -org.highmed.dsf.bpe.db.server_users_group=bpe_users -org.highmed.dsf.bpe.db.server_user=bpe_server_user -org.highmed.dsf.bpe.db.server_user_password=HvqZ7VnVt9dh57vnhebCcwsgbKqB8CXZ - -org.highmed.dsf.bpe.db.camunda_users_group=camunda_users -org.highmed.dsf.bpe.db.camunda_user=camunda_server_user -org.highmed.dsf.bpe.db.camunda_user_password=e8xNIurHV2YAhEq3gvmt3aRcAMf5jGtp - -org.highmed.dsf.bpe.fhir.organization.identifier.localValue=Test_TTP - -org.highmed.dsf.bpe.fhir.local.webservice.baseUrl=https://ttp/fhir -org.highmed.dsf.bpe.fhir.local.webservice.keystore.p12file=conf/ttp-client_certificate.p12 -org.highmed.dsf.bpe.fhir.local.webservice.keystore.password=password -org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=1500 -org.highmed.dsf.bpe.fhir.local.webservice.connectTimeout=500 - -org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=2500 -org.highmed.dsf.bpe.fhir.remote.webservice.connectTimeout=1500 -#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password= -#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username= -#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.schemeHostPort= - -org.highmed.dsf.bpe.fhir.local.websocket.url=wss://ttp/fhir/ws -org.highmed.dsf.bpe.fhir.local.websocket.keystore.p12file=conf/ttp-client_certificate.p12 -org.highmed.dsf.bpe.fhir.local.websocket.keystore.password=password - -org.highmed.dsf.bpe.fhir.task.subscription.searchParameter=?criteria=Task%3Fstatus%3Drequested&status=active&type=websocket&payload=application/fhir%2Bjson -org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile=last_event/time.file - -org.highmed.dsf.bpe.openehr.webservice.baseUrl=https://openehr/rest/openehr/v1 -org.highmed.dsf.bpe.openehr.webservice.basicAuthUsername=username -org.highmed.dsf.bpe.openehr.webservice.basicAuthPassword=password -org.highmed.dsf.bpe.openehr.webservice.connectionTimeout=1500 -org.highmed.dsf.bpe.openehr.webservice.readTimeout=2500 - +org.highmed.dsf.bpe.db.driver=org.postgresql.Driver +org.highmed.dsf.bpe.db.url=jdbc:postgresql://db/bpe +org.highmed.dsf.bpe.db.liquibase_user=liquibase_user +org.highmed.dsf.bpe.db.liquibase_user_password=7nak4DxNE4mCfPbvhCTmVSYH9zWg7W6GkzYn4jc43mmFhkRj9k7s7RpEB5UPFTA7 + +org.highmed.dsf.bpe.db.server_users_group=bpe_users +org.highmed.dsf.bpe.db.server_user=bpe_server_user +org.highmed.dsf.bpe.db.server_user_password=HvqZ7VnVt9dh57vnhebCcwsgbKqB8CXZ + +org.highmed.dsf.bpe.db.camunda_users_group=camunda_users +org.highmed.dsf.bpe.db.camunda_user=camunda_server_user +org.highmed.dsf.bpe.db.camunda_user_password=e8xNIurHV2YAhEq3gvmt3aRcAMf5jGtp + +org.highmed.dsf.bpe.fhir.organization.identifier.localValue=Test_TTP + +org.highmed.dsf.bpe.fhir.local.webservice.baseUrl=https://ttp/fhir +org.highmed.dsf.bpe.fhir.local.webservice.keystore.p12file=conf/ttp-client_certificate.p12 +org.highmed.dsf.bpe.fhir.local.webservice.keystore.password=password +org.highmed.dsf.bpe.fhir.local.webservice.readTimeout=2000 +org.highmed.dsf.bpe.fhir.local.webservice.connectTimeout=500 + +org.highmed.dsf.bpe.fhir.remote.webservice.readTimeout=5000 +org.highmed.dsf.bpe.fhir.remote.webservice.connectTimeout=2000 +#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.password= +#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.username= +#org.highmed.dsf.bpe.fhir.remote.webservice.proxy.schemeHostPort= + +org.highmed.dsf.bpe.fhir.local.websocket.url=wss://ttp/fhir/ws +org.highmed.dsf.bpe.fhir.local.websocket.keystore.p12file=conf/ttp-client_certificate.p12 +org.highmed.dsf.bpe.fhir.local.websocket.keystore.password=password + +org.highmed.dsf.bpe.fhir.task.subscription.searchParameter=?criteria=Task%3Fstatus%3Drequested&status=active&type=websocket&payload=application/fhir%2Bjson +org.highmed.dsf.bpe.fhir.task.subscription.lastEventTimeFile=last_event/time.file + +org.highmed.dsf.bpe.openehr.webservice.baseUrl=https://openehr/rest/openehr/v1 +org.highmed.dsf.bpe.openehr.webservice.basicAuthUsername=username +org.highmed.dsf.bpe.openehr.webservice.basicAuthPassword=password +org.highmed.dsf.bpe.openehr.webservice.connectionTimeout=1500 +org.highmed.dsf.bpe.openehr.webservice.readTimeout=2500 + org.highmed.dsf.bpe.cors.origins= \ No newline at end of file diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic1-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic1-fhir-config.properties index 4f7b4fb6a..f4d5d6f4d 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic1-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic1-fhir-config.properties @@ -18,7 +18,7 @@ org.highmed.dsf.fhir.init.bundle.file=conf/bundle.xml org.highmed.dsf.fhir.webservice.keystore.p12file=conf/medic1-client_certificate.p12 org.highmed.dsf.fhir.webservice.keystore.password=password -org.highmed.dsf.fhir.remote.webservice.readTimeout=2500 -org.highmed.dsf.fhir.remote.webservice.connectTimeout=1500 +org.highmed.dsf.fhir.remote.webservice.readTimeout=5000 +org.highmed.dsf.fhir.remote.webservice.connectTimeout=2000 org.highmed.dsf.fhir.cors.origins=http://localhost:8080 \ No newline at end of file diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic2-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic2-fhir-config.properties index 47e74e931..9a31cd851 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic2-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic2-fhir-config.properties @@ -18,7 +18,7 @@ org.highmed.dsf.fhir.init.bundle.file=conf/bundle.xml org.highmed.dsf.fhir.webservice.keystore.p12file=conf/medic2-client_certificate.p12 org.highmed.dsf.fhir.webservice.keystore.password=password -org.highmed.dsf.fhir.remote.webservice.readTimeout=2500 -org.highmed.dsf.fhir.remote.webservice.connectTimeout=1500 +org.highmed.dsf.fhir.remote.webservice.readTimeout=5000 +org.highmed.dsf.fhir.remote.webservice.connectTimeout=2000 org.highmed.dsf.fhir.cors.origins=http://localhost:8080 \ No newline at end of file diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic3-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic3-fhir-config.properties index 28b26bdb8..a373390f0 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic3-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-medic3-fhir-config.properties @@ -18,7 +18,7 @@ org.highmed.dsf.fhir.init.bundle.file=conf/bundle.xml org.highmed.dsf.fhir.webservice.keystore.p12file=conf/medic3-client_certificate.p12 org.highmed.dsf.fhir.webservice.keystore.password=password -org.highmed.dsf.fhir.remote.webservice.readTimeout=2500 -org.highmed.dsf.fhir.remote.webservice.connectTimeout=1500 +org.highmed.dsf.fhir.remote.webservice.readTimeout=5000 +org.highmed.dsf.fhir.remote.webservice.connectTimeout=2000 org.highmed.dsf.fhir.cors.origins=http://localhost:8080 \ No newline at end of file diff --git a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-ttp-fhir-config.properties b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-ttp-fhir-config.properties index 034998645..a2592c9e7 100755 --- a/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-ttp-fhir-config.properties +++ b/dsf-tools/dsf-tools-test-data-generator/src/main/resources/config-templates/docker-test-ttp-fhir-config.properties @@ -18,7 +18,7 @@ org.highmed.dsf.fhir.init.bundle.file=conf/bundle.xml org.highmed.dsf.fhir.webservice.keystore.p12file=conf/ttp-client_certificate.p12 org.highmed.dsf.fhir.webservice.keystore.password=password -org.highmed.dsf.fhir.remote.webservice.readTimeout=2500 -org.highmed.dsf.fhir.remote.webservice.connectTimeout=1500 +org.highmed.dsf.fhir.remote.webservice.readTimeout=5000 +org.highmed.dsf.fhir.remote.webservice.connectTimeout=2000 org.highmed.dsf.fhir.cors.origins=http://localhost:8080 \ No newline at end of file From c124041197f9dfe0fa466fc9f2ccc457b13c3d0f Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 20:33:17 +0100 Subject: [PATCH 40/55] additional practitioner.active = true check --- .../fhir/authorization/ResearchStudyAuthorizationRule.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java index 05762b7a0..92fe9c4c7 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ResearchStudyAuthorizationRule.java @@ -149,7 +149,8 @@ private Optional<String> newResourceOk(Connection connection, User user, Researc { Optional<Resource> practitioner = resolvePractitioner(connection, user, "ResearchStudy.principalInvestigator", newResource.getPrincipalInvestigator()); - if (practitioner.isPresent()) + if (practitioner.isPresent() && practitioner.get() instanceof Practitioner + && ((Practitioner) practitioner.get()).getActive()) { if (!practitionerRoleExists(connection, user, practitioner.get().getIdElement())) { @@ -159,7 +160,8 @@ private Optional<String> newResourceOk(Connection connection, User user, Researc } else { - errors.add("ResearchStudy.principalInvestigator not resolved"); + errors.add( + "ResearchStudy.principalInvestigator not resolved or not instance of Practitioner or not active"); } } else From 8824195df5f9845fb39a0a2b4e2f94f00d84859d Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 10 Mar 2020 20:33:57 +0100 Subject: [PATCH 41/55] removed old comment, added debug old/new resource as json log entry --- .../fhir/authorization/TaskAuthorizationRule.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java index 64ba10025..3a66050de 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java @@ -24,6 +24,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import ca.uhn.fhir.context.FhirContext; + public class TaskAuthorizationRule extends AbstractAuthorizationRule<Task, TaskDao> { private static final Logger logger = LoggerFactory.getLogger(TaskAuthorizationRule.class); @@ -234,11 +236,6 @@ else if (isLocalUser(user) && isCurrentUserPartOfReferencedOrganization(connecti @Override public Optional<String> reasonUpdateAllowed(Connection connection, User user, Task oldResource, Task newResource) { - // allowed status change from draft to requested for remote users - // update only allowed at status draft for remote users - // task.requester must be organization of current user or local user - // only update of tasks with requester = current user allowed for remote users - if (isRemoteUser(user) || isLocalUser(user)) { if (TaskStatus.DRAFT.equals(oldResource.getStatus()) && isCurrentUserPartOfReferencedOrganization( @@ -357,7 +354,13 @@ private Optional<String> reasonNotSame(Task oldResource, Task newResource) if (errors.isEmpty()) return Optional.empty(); else + { + logger.debug("Old Task: {}", FhirContext.forR4().newJsonParser().setStripVersionsFromReferences(false) + .encodeResourceToString(oldResource)); + logger.debug("New Task: {}", FhirContext.forR4().newJsonParser().setStripVersionsFromReferences(false) + .encodeResourceToString(newResource)); return Optional.of(errors.stream().collect(Collectors.joining(", "))); + } } @Override From 71eee5138e00f98f4e81739e2ddae2c501bdd94c Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Wed, 11 Mar 2020 02:41:44 +0100 Subject: [PATCH 42/55] isCurrentUserPartOfReferencedOrganization now only checks id not version same organizations check now based on id of the organization resources only --- .../dsf/fhir/authorization/AbstractAuthorizationRule.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java index b0f22ec18..69f0711db 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/AbstractAuthorizationRule.java @@ -212,7 +212,9 @@ protected final boolean isCurrentUserPartOfReferencedOrganization(Connection con Optional<Resource> resource = referenceResolver.resolveReference(user, resReference, connection); if (resource.isPresent() && resource.get() instanceof Organization) { - boolean sameOrganization = user.getOrganization().getIdElement().equals(resource.get().getIdElement()); + // ignoring updates (version changes) to the organization id + boolean sameOrganization = user.getOrganization().getIdElement().getIdPart() + .equals(resource.get().getIdElement().getIdPart()); if (!sameOrganization) logger.warn( "Current user not part of organization {} while checking if user part of referenced organization", From a79a6703ac3fc90d5b268ae47e0f9e1c863911a2 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Wed, 11 Mar 2020 02:42:34 +0100 Subject: [PATCH 43/55] logging fix --- .../secure/AbstractResourceServiceSecure.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java index 8c2d3b5f9..8d43d281c 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/webservice/secure/AbstractResourceServiceSecure.java @@ -94,7 +94,16 @@ public Response create(R resource, UriInfo uri, HttpHeaders headers) { audit.info("Create of resource {} allowed for user '{}': {}", resourceTypeName, getCurrentUser().getName(), reasonCreateAllowed.get()); - return delegate.create(resource, uri, headers); + + Response created = delegate.create(resource, uri, headers); + + if (created.hasEntity() && !resourceType.isInstance(created.getEntity()) + && !(created.getEntity() instanceof OperationOutcome)) + logger.warn("Update returned with entity of type {}", created.getEntity().getClass().getName()); + else if (!created.hasEntity()) + logger.info("Update returned with status {}, but no entity", created.getStatus()); + + return created; } } @@ -237,14 +246,15 @@ private Response update(String id, R newResource, UriInfo uri, HttpHeaders heade audit.info("Update of resource {} allowed for user '{}': {}", oldResource.getIdElement().getValue(), getCurrentUser().getName(), reasonUpdateAllowed.get()); - Response update = delegate.update(id, newResource, uri, headers); + Response updated = delegate.update(id, newResource, uri, headers); - if (update.hasEntity() && !(update.getEntity() instanceof OperationOutcome)) - logger.warn("Update returned with entity of type {}", update.getEntity().getClass().getName()); - else - logger.info("Update returned with status {}, but no entity", update.getStatus()); + if (updated.hasEntity() && !resourceType.isInstance(updated.getEntity()) + && !(updated.getEntity() instanceof OperationOutcome)) + logger.warn("Update returned with entity of type {}", updated.getEntity().getClass().getName()); + else if (!updated.hasEntity()) + logger.info("Update returned with status {}, but no entity", updated.getStatus()); - return update; + return updated; } } From c11cda284dee549c4f5748d0eb8e3c3a05067841 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Wed, 11 Mar 2020 02:45:50 +0100 Subject: [PATCH 44/55] EventManager now checks if resource can be read before sending event now checks if the contained resource can be read (authorization rule read allowed) by users, skips user if not allowed fixes fhir parser config -> strip versions false --- .../dsf/fhir/event/EventManagerImpl.java | 67 +++++++++++++++---- .../dsf/fhir/spring/config/EventConfig.java | 5 +- 2 files changed, 59 insertions(+), 13 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/event/EventManagerImpl.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/event/EventManagerImpl.java index 6b1c54ce8..764087987 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/event/EventManagerImpl.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/event/EventManagerImpl.java @@ -18,6 +18,8 @@ import javax.websocket.RemoteEndpoint.Async; import org.highmed.dsf.fhir.authentication.User; +import org.highmed.dsf.fhir.authorization.AuthorizationRule; +import org.highmed.dsf.fhir.authorization.AuthorizationRuleProvider; import org.highmed.dsf.fhir.dao.SubscriptionDao; import org.highmed.dsf.fhir.dao.provider.DaoProvider; import org.highmed.dsf.fhir.help.ExceptionHandler; @@ -32,6 +34,7 @@ import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.api.annotation.ResourceDef; +import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.rest.api.Constants; public class EventManagerImpl implements EventManager, InitializingBean, DisposableBean @@ -114,6 +117,7 @@ else if (!sessionId.equals(other.sessionId)) private final ExceptionHandler exceptionHandler; private final MatcherFactory matcherFactory; private final FhirContext fhirContext; + private final AuthorizationRuleProvider authorizationRuleProvider; private final AtomicBoolean firstCall = new AtomicBoolean(true); private final ReadWriteMap<String, Subscription> subscriptionsByIdPart = new ReadWriteMap<>(); @@ -121,23 +125,25 @@ else if (!sessionId.equals(other.sessionId)) private final ReadWriteMap<String, List<SessionIdAndRemoteAsync>> asyncRemotesBySubscriptionIdPart = new ReadWriteMap<>(); public EventManagerImpl(DaoProvider daoProvider, ExceptionHandler exceptionHandler, MatcherFactory matcherFactory, - FhirContext fhirContext) + FhirContext fhirContext, AuthorizationRuleProvider authorizationRuleProvider) { this.daoProvider = daoProvider; this.subscriptionDao = daoProvider.getSubscriptionDao(); this.exceptionHandler = exceptionHandler; this.matcherFactory = matcherFactory; this.fhirContext = fhirContext; + this.authorizationRuleProvider = authorizationRuleProvider; } @Override public void afterPropertiesSet() throws Exception { + Objects.requireNonNull(daoProvider, "daoProvider"); Objects.requireNonNull(subscriptionDao, "subscriptionDao"); Objects.requireNonNull(exceptionHandler, "exceptionHandler"); Objects.requireNonNull(matcherFactory, "matcherFactory"); Objects.requireNonNull(fhirContext, "fhirContext"); - Objects.requireNonNull(daoProvider, "daoProvider"); + Objects.requireNonNull(authorizationRuleProvider, "authorizationRuleProvider"); } private void refreshMatchers() @@ -266,9 +272,9 @@ private void doHandleEventWithSubscription(Subscription s, Event event) final String text; if (Constants.CT_FHIR_JSON_NEW.equals(s.getChannel().getPayload())) - text = fhirContext.newJsonParser().encodeResourceToString(event.getResource()); + text = newJsonParser().encodeResourceToString(event.getResource()); else if (Constants.CT_FHIR_XML_NEW.contentEquals(s.getChannel().getPayload())) - text = fhirContext.newXmlParser().encodeResourceToString(event.getResource()); + text = newXmlParser().encodeResourceToString(event.getResource()); else text = "ping " + s.getIdElement().getIdPart(); @@ -277,19 +283,56 @@ else if (Constants.CT_FHIR_XML_NEW.contentEquals(s.getChannel().getPayload())) // defensive copy because list could be changed by other threads while we are reading List<SessionIdAndRemoteAsync> remotes = new ArrayList<>(optRemotes.get()); - remotes.stream().filter(r -> filterByReadAccess(r, event)).forEach(r -> send(r, text)); + remotes.stream().filter(r -> userHasReadAccess(r, event)).forEach(r -> send(r, text)); + } + + private IParser newXmlParser() + { + return configureParser(fhirContext.newXmlParser()); } - private boolean filterByReadAccess(SessionIdAndRemoteAsync sessionAndRemote, Event event) + private IParser newJsonParser() { - // TODO Filter by read access + return configureParser(fhirContext.newJsonParser()); + } - User user = sessionAndRemote.user; - logger.warn("Implement filter by read access in EventManagerImpl for user '{}' and event {} with resource {}", - user.getName(), event.getClass().getName(), event.getResource() == null ? "" - : event.getResource().getClass().getAnnotation(ResourceDef.class).name()); + private IParser configureParser(IParser p) + { + p.setStripVersionsFromReferences(false); + p.setOverrideResourceIdWithBundleEntryFullUrl(false); + return p; + } + + private boolean userHasReadAccess(SessionIdAndRemoteAsync sessionAndRemote, Event event) + { + Optional<AuthorizationRule<?>> optRule = authorizationRuleProvider + .getAuthorizationRule(event.getResourceType()); + if (optRule.isPresent()) + { + @SuppressWarnings("unchecked") + AuthorizationRule<Resource> rule = (AuthorizationRule<Resource>) optRule.get(); + Optional<String> optReason = rule.reasonReadAllowed(sessionAndRemote.user, event.getResource()); - return true; + if (optReason.isPresent()) + { + logger.info("Sending event {} to user {}, read of {} allowed {}", event.getClass().getSimpleName(), + sessionAndRemote.user.getName(), event.getResourceType().getSimpleName(), optReason.get()); + return true; + } + else + { + logger.warn("Skipping event {} for user {}, read of {} not allowed", event.getClass().getSimpleName(), + sessionAndRemote.user.getName(), event.getResourceType().getSimpleName()); + return false; + } + } + else + { + logger.warn("Skipping event {} for user {}, no authorization rule for resource of type {} found", + event.getClass().getSimpleName(), sessionAndRemote.user.getName(), + event.getResourceType().getSimpleName()); + return false; + } } private void send(SessionIdAndRemoteAsync sessionAndRemote, String text) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/EventConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/EventConfig.java index c41a630bf..433f45588 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/EventConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/EventConfig.java @@ -25,6 +25,9 @@ public class EventConfig @Autowired private FhirConfig fhirConfig; + @Autowired + private AuthorizationConfig authorizationConfig; + @Bean public MatcherFactory matcherFactory() { @@ -57,7 +60,7 @@ private void put(Map<String, ? super ResourceDao<? extends DomainResource>> daos public EventManager eventManager() { return new EventManagerImpl(daoConfig.daoProvider(), helperConfig.exceptionHandler(), matcherFactory(), - fhirConfig.fhirContext()); + fhirConfig.fhirContext(), authorizationConfig.authorizationRuleProvider()); } @Bean From 54b1a47f2880b715c36249355c5ea18f6bc353e0 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Wed, 11 Mar 2020 02:49:33 +0100 Subject: [PATCH 45/55] removed not neede constructor param, fhir parser config fix fixes fhir parser config -> strip versions false --- .../dsf/fhir/client/FhirClientProviderImpl.java | 2 +- .../org/highmed/dsf/fhir/websocket/FhirConnector.java | 11 +++++++++-- .../dsf/fhir/integration/AbstractIntegrationTest.java | 7 +++---- .../dsf/fhir/integration/TaskIntegrationTest.java | 2 ++ .../org/highmed/fhir/client/WebsocketClientTyrus.java | 5 ++--- .../highmed/fhir/client/TestFhirWebsocketClient.java | 4 ++-- 6 files changed, 19 insertions(+), 12 deletions(-) diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirClientProviderImpl.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirClientProviderImpl.java index 35a10d9b4..8552722db 100755 --- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirClientProviderImpl.java +++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/client/FhirClientProviderImpl.java @@ -214,7 +214,7 @@ public WebsocketClient getLocalWebsocketClient(String subscriptionId) { if (!websocketClientsBySubscriptionId.containsKey(subscriptionId)) { - WebsocketClientTyrus client = new WebsocketClientTyrus(fhirContext, URI.create(localWebsocketUrl), + WebsocketClientTyrus client = new WebsocketClientTyrus(URI.create(localWebsocketUrl), localWebsocketTrustStore, localWebsocketKeyStore, localWebsocketKeyStorePassword, subscriptionId); websocketClientsBySubscriptionId.put(subscriptionId, client); return client; diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/FhirConnector.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/FhirConnector.java index b3a761d95..4c9e74bb4 100755 --- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/FhirConnector.java +++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/websocket/FhirConnector.java @@ -172,11 +172,18 @@ private Supplier<IParser> createParserFactory(EventType eventType, FhirContext f switch (eventType) { case XML: - return () -> fhirContext.newXmlParser(); + return () -> configureParser(fhirContext.newXmlParser()); case JSON: - return () -> fhirContext.newJsonParser(); + return () -> configureParser(fhirContext.newJsonParser()); default: throw new RuntimeException("EventType " + eventType + " not supported"); } } + + private IParser configureParser(IParser p) + { + p.setStripVersionsFromReferences(false); + p.setOverrideResourceIdWithBundleEntryFullUrl(false); + return p; + } } diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java index 0b8367c39..0dc2c1e43 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/AbstractIntegrationTest.java @@ -137,9 +137,9 @@ private static FhirWebserviceClient createWebserviceClient(KeyStore trustStore, } private static WebsocketClient createWebsocketClient(KeyStore trustStore, KeyStore keyStore, - char[] keyStorePassword, FhirContext fhirContext, String subscriptionIdPart) + char[] keyStorePassword, String subscriptionIdPart) { - return new WebsocketClientTyrus(fhirContext, URI.create(WEBSOCKET_URL), trustStore, keyStore, keyStorePassword, + return new WebsocketClientTyrus(URI.create(WEBSOCKET_URL), trustStore, keyStore, keyStorePassword, subscriptionIdPart); } @@ -391,7 +391,6 @@ protected static WebsocketClient getWebsocketClient() return createWebsocketClient(certificates.getClientCertificate().getTrustStore(), certificates.getClientCertificate().getKeyStore(), - certificates.getClientCertificate().getKeyStorePassword(), fhirContext, - subscription.getIdElement().getIdPart()); + certificates.getClientCertificate().getKeyStorePassword(), subscription.getIdElement().getIdPart()); } } diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java index 563c6d7f2..5c482061a 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java @@ -62,6 +62,7 @@ public void testHandleBundleForRequestSimpleFeasibility() throws Exception assertEquals(researchStudyId.getResourceType(), taskInputResearchStudyId.getResourceType()); assertEquals(researchStudyId.getIdPart(), taskInputResearchStudyId.getIdPart()); + assertEquals(researchStudyId.getVersionIdPart(), taskInputResearchStudyId.getVersionIdPart()); DomainResource event = events.pollFirst(5, TimeUnit.SECONDS); assertNotNull(event); @@ -76,6 +77,7 @@ public void testHandleBundleForRequestSimpleFeasibility() throws Exception ((Reference) inputViaWebsocket.getValue()).getReference()); assertEquals(researchStudyId.getResourceType(), taskInputResearchStudyIdViaWebsocket.getResourceType()); assertEquals(researchStudyId.getIdPart(), taskInputResearchStudyIdViaWebsocket.getIdPart()); + assertEquals(researchStudyId.getVersionIdPart(), taskInputResearchStudyIdViaWebsocket.getVersionIdPart()); } finally { diff --git a/dsf-fhir/dsf-fhir-websocket-client/src/main/java/org/highmed/fhir/client/WebsocketClientTyrus.java b/dsf-fhir/dsf-fhir-websocket-client/src/main/java/org/highmed/fhir/client/WebsocketClientTyrus.java index d99f9f059..d71503cd0 100755 --- a/dsf-fhir/dsf-fhir-websocket-client/src/main/java/org/highmed/fhir/client/WebsocketClientTyrus.java +++ b/dsf-fhir/dsf-fhir-websocket-client/src/main/java/org/highmed/fhir/client/WebsocketClientTyrus.java @@ -20,7 +20,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.parser.IParser; public class WebsocketClientTyrus implements WebsocketClient @@ -53,8 +52,8 @@ public boolean onDisconnect(CloseReason closeReason) private Session connection; private volatile boolean closed; - public WebsocketClientTyrus(FhirContext fhirContext, URI wsUri, KeyStore trustStore, KeyStore keyStore, - char[] keyStorePassword, String subscriptionIdPart) + public WebsocketClientTyrus(URI wsUri, KeyStore trustStore, KeyStore keyStore, char[] keyStorePassword, + String subscriptionIdPart) { this.wsUri = wsUri; diff --git a/dsf-fhir/dsf-fhir-websocket-client/src/test/java/org/highmed/fhir/client/TestFhirWebsocketClient.java b/dsf-fhir/dsf-fhir-websocket-client/src/test/java/org/highmed/fhir/client/TestFhirWebsocketClient.java index 46ac66b3a..99ee8ec8e 100755 --- a/dsf-fhir/dsf-fhir-websocket-client/src/test/java/org/highmed/fhir/client/TestFhirWebsocketClient.java +++ b/dsf-fhir/dsf-fhir-websocket-client/src/test/java/org/highmed/fhir/client/TestFhirWebsocketClient.java @@ -30,8 +30,8 @@ public static void main(String[] args) FhirContext fhirContext = FhirContext.forR4(); - WebsocketClientTyrus client = new WebsocketClientTyrus(fhirContext, URI.create("wss://localhost:8443/fhir/ws"), - trustStore, keyStore, keyStorePassword, "f4243759-47c7-4344-a030-94ef039bbd4f"); + WebsocketClientTyrus client = new WebsocketClientTyrus(URI.create("wss://localhost:8443/fhir/ws"), trustStore, + keyStore, keyStorePassword, "f4243759-47c7-4344-a030-94ef039bbd4f"); // WebsocketClientTyrus client = new WebsocketClientTyrus(fhirContext, // URI.create("wss://localhost:8001/fhir/ws"), // trustStore, keyStore, keyStorePassword, "4e19853d-82cb-4509-b2cf-b5b86f70ae91"); From 06e697f86e5f86346e6fe639a771eb26339f17e9 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Wed, 11 Mar 2020 02:50:18 +0100 Subject: [PATCH 46/55] missing active=true for test Practitioner resource --- .../src/test/resources/integration/task-bundle.json | 1 + 1 file changed, 1 insertion(+) diff --git a/dsf-fhir/dsf-fhir-server/src/test/resources/integration/task-bundle.json b/dsf-fhir/dsf-fhir-server/src/test/resources/integration/task-bundle.json index ea4bfc76f..834783617 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/resources/integration/task-bundle.json +++ b/dsf-fhir/dsf-fhir-server/src/test/resources/integration/task-bundle.json @@ -69,6 +69,7 @@ "meta": { "profile": "http://highmed.org/fhir/StructureDefinition/highmed-practitioner" }, + "active": true, "name": [ { "family": "HiGHmed", From d028c4ca9c94f5491dbb92e5c1f08179a0392e92 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Wed, 11 Mar 2020 02:51:53 +0100 Subject: [PATCH 47/55] changed authorization extension to support multiple authorization-roles --- ...finitionProcessAuthorizationExtension.java | 73 +++++++++++++++---- ...initionProcessAuthorizationExtensions.java | 2 +- .../dao/jdbc/ActivityDefinitionDaoJdbc.java | 5 +- .../computeSimpleFeasibility-0.1.0.xml | 24 +++--- .../executeSimpleFeasibility-0.1.0.xml | 18 +++-- .../executeUpdateResources-0.1.0.xml | 12 +-- .../fhir/ActivityDefinition/ping-0.1.0.xml | 24 +++--- .../fhir/ActivityDefinition/pong-0.1.0.xml | 12 +-- .../requestSimpleFeasibility-0.1.0.xml | 24 +++--- .../requestUpdateResources-0.1.0.xml | 12 +-- .../updateWhiteList-0.1.0.xml | 12 +-- ...-extension-process-authorization-0.1.0.xml | 46 +++++++++--- 12 files changed, 180 insertions(+), 84 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProcessAuthorizationExtension.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProcessAuthorizationExtension.java index f85b72137..bc29860ea 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProcessAuthorizationExtension.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProcessAuthorizationExtension.java @@ -11,13 +11,20 @@ import org.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.Extension; import org.hl7.fhir.r4.model.StringType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ActivityDefinitionProcessAuthorizationExtension { + private static final Logger logger = LoggerFactory.getLogger(ActivityDefinitionProcessAuthorizationExtension.class); + public static final String MESSAGE_NAME_EXTENSION_URL = "message-name"; + public static final String AUTHORIZATION_ROLES_EXTENSION_URL = "authorization-roles"; public static final String AUTHORIZATION_ROLE_EXTENSION_URL = "authorization-role"; - public static final String ORGANIZATION_TYPES_EXTENSION_URL = "organization-types"; - public static final String ORGANIZATION_TYPE_EXTENSION_URL = "organization-type"; + public static final String REQUESTER_ORGANIZATION_TYPES_EXTENSION_URL = "requester-organization-types"; + public static final String REQUESTER_ORGANIZATION_TYPE_EXTENSION_URL = "requester-organization-type"; + public static final String RECIPIENT_ORGANIZATION_TYPES_EXTENSION_URL = "recipient-organization-types"; + public static final String RECIPIENT_ORGANIZATION_TYPE_EXTENSION_URL = "recipient-organization-type"; public static final String TASK_PROFILE_EXTENSION_URL = "task-profile"; private final Extension processAuthorizationExtension; @@ -29,10 +36,19 @@ public ActivityDefinitionProcessAuthorizationExtension(Extension processAuthoriz public boolean isValid() { - return doGetMessageName().isPresent() && doGetAuthorizationRole().isPresent() - && (getOrganizationTypes().size() == 1 || (getOrganizationTypes().size() == 2 - && !getOrganizationTypes().get(0).equals(getOrganizationTypes().get(1)))) + boolean valid = doGetMessageName().isPresent() + && (getAuthorizationRoles().size() == 1 || (getAuthorizationRoles().size() == 2 + && !getAuthorizationRoles().get(0).equals(getAuthorizationRoles().get(1)))) + && (getRequesterOrganizationTypes().size() == 1 || (getRequesterOrganizationTypes().size() == 2 + && !getRequesterOrganizationTypes().get(0).equals(getRequesterOrganizationTypes().get(1)))) + && (getRecipientOrganizationTypes().size() == 1 || (getRecipientOrganizationTypes().size() == 2 + && !getRecipientOrganizationTypes().get(0).equals(getRecipientOrganizationTypes().get(1)))) && doGetTaskProfile().isPresent(); + + if (!valid) + logger.warn("Not valid: {}", this); + + return valid; } public String getMessageName() @@ -46,22 +62,34 @@ private Optional<String> doGetMessageName() .map(e -> e.getValue()).filter(t -> t instanceof StringType).map(t -> ((StringType) t).getValue()); } - public AuthorizationRole getAuthorizationRole() + public List<AuthorizationRole> getAuthorizationRoles() + { + return Optional.ofNullable(processAuthorizationExtension.getExtensionByUrl(AUTHORIZATION_ROLES_EXTENSION_URL)) + .map(e -> e.getExtensionsByUrl(AUTHORIZATION_ROLE_EXTENSION_URL).stream() + .flatMap(this::getAuthorizationRole).collect(Collectors.toList())) + .orElseGet(Collections::emptyList); + } + + private Stream<AuthorizationRole> getAuthorizationRole(Extension authorizationRole) { - return doGetAuthorizationRole().orElseThrow(); + return Optional.ofNullable(authorizationRole).map(ex -> ex.getValue()).filter(t -> t instanceof Coding) + .map(t -> ((Coding) t).getCode()).flatMap(AuthorizationRole::fromString).stream(); } - private Optional<AuthorizationRole> doGetAuthorizationRole() + public List<OrganizationType> getRequesterOrganizationTypes() { - return Optional.ofNullable(processAuthorizationExtension.getExtensionByUrl(AUTHORIZATION_ROLE_EXTENSION_URL)) - .map(e -> e.getValue()).filter(t -> t instanceof Coding).map(t -> ((Coding) t).getCode()) - .flatMap(AuthorizationRole::fromString); + return Optional + .ofNullable(processAuthorizationExtension.getExtensionByUrl(REQUESTER_ORGANIZATION_TYPES_EXTENSION_URL)) + .map(e -> e.getExtensionsByUrl(REQUESTER_ORGANIZATION_TYPE_EXTENSION_URL).stream() + .flatMap(this::getOrganizationType).collect(Collectors.toList())) + .orElseGet(Collections::emptyList); } - public List<OrganizationType> getOrganizationTypes() + public List<OrganizationType> getRecipientOrganizationTypes() { - return Optional.ofNullable(processAuthorizationExtension.getExtensionByUrl(ORGANIZATION_TYPES_EXTENSION_URL)) - .map(e -> e.getExtensionsByUrl(ORGANIZATION_TYPE_EXTENSION_URL).stream() + return Optional + .ofNullable(processAuthorizationExtension.getExtensionByUrl(RECIPIENT_ORGANIZATION_TYPES_EXTENSION_URL)) + .map(e -> e.getExtensionsByUrl(RECIPIENT_ORGANIZATION_TYPE_EXTENSION_URL).stream() .flatMap(this::getOrganizationType).collect(Collectors.toList())) .orElseGet(Collections::emptyList); } @@ -79,9 +107,24 @@ public String getTaskProfile() private Optional<String> doGetTaskProfile() { - Optional<String> taskProfile = Optional.ofNullable(processAuthorizationExtension.getExtensionByUrl(TASK_PROFILE_EXTENSION_URL)) + Optional<String> taskProfile = Optional + .ofNullable(processAuthorizationExtension.getExtensionByUrl(TASK_PROFILE_EXTENSION_URL)) .map(e -> e.getValue()).filter(t -> t instanceof CanonicalType) .map(t -> ((CanonicalType) t).getValue()); return taskProfile; } + + @Override + public String toString() + { + StringBuilder b = new StringBuilder(); + b.append(MESSAGE_NAME_EXTENSION_URL).append(": ").append(doGetMessageName().orElse("")); + b.append(", ").append(AUTHORIZATION_ROLES_EXTENSION_URL).append(": ").append(getAuthorizationRoles()); + b.append(", ").append(REQUESTER_ORGANIZATION_TYPES_EXTENSION_URL).append(": ") + .append(getRequesterOrganizationTypes()); + b.append(", ").append(RECIPIENT_ORGANIZATION_TYPES_EXTENSION_URL).append(": ") + .append(getRecipientOrganizationTypes()); + b.append(", ").append(TASK_PROFILE_EXTENSION_URL).append(": ").append(doGetTaskProfile().orElse("")); + return b.toString(); + } } diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProcessAuthorizationExtensions.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProcessAuthorizationExtensions.java index fcc565e15..8cd14c76c 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProcessAuthorizationExtensions.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/ActivityDefinitionProcessAuthorizationExtensions.java @@ -19,7 +19,7 @@ public ActivityDefinitionProcessAuthorizationExtensions(ActivityDefinition activ public boolean isValid() { - return doGetExtensions().map(ActivityDefinitionProcessAuthorizationExtension::isValid).count() >= 1; + return doGetExtensions().allMatch(ActivityDefinitionProcessAuthorizationExtension::isValid); } public List<ActivityDefinitionProcessAuthorizationExtension> getExtensions() diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java index af013c443..5be6d907d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/dao/jdbc/ActivityDefinitionDaoJdbc.java @@ -95,8 +95,9 @@ public Optional<ActivityDefinition> readByOrganizationTypeUserRoleProcessUrlVers { String extension = "[{\"url\":\"http://highmed.org/fhir/StructureDefinition/process-authorization\",\"extension\":[" + "{\"url\":\"message-name\",\"valueString\":\"" + messageName + "\"}," - + "{\"url\":\"authorization-role\",\"valueCoding\":{\"code\":\"" + userRole.toString() - + "\",\"system\":\"http://highmed.org/fhir/CodeSystem/authorization-role\"}}," + + "{\"url\":\"authorization-roles\",\"extension\":[{\"url\":\"authorization-role\",\"valueCoding\":{\"code\":\"" + + userRole.toString() + + "\",\"system\":\"http://highmed.org/fhir/CodeSystem/authorization-role\"}}]}," + "{\"url\":\"requester-organization-types\",\"extension\":[{\"url\":\"requester-organization-type\",\"valueCoding\":{\"code\":\"" + requesterOrganizationType.toString() + "\",\"system\":\"http://highmed.org/fhir/CodeSystem/organization-type\"}}]}," diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/computeSimpleFeasibility-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/computeSimpleFeasibility-0.1.0.xml index 7aa0529cb..1a138ee6d 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/computeSimpleFeasibility-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/computeSimpleFeasibility-0.1.0.xml @@ -9,11 +9,13 @@ <extension url="message-name"> <valueString value="computeSimpleFeasibilityMessage" /> </extension> - <extension url="authorization-role"> - <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> - <code value="REMOTE" /> - </valueCoding> + <extension url="authorization-roles"> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </valueCoding> + </extension> </extension> <extension url="requester-organization-types"> <extension url="requester-organization-type"> @@ -39,11 +41,13 @@ <extension url="message-name"> <valueString value="resultSingleMedicSimpleFeasibilityMessage" /> </extension> - <extension url="authorization-role"> - <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> - <code value="REMOTE" /> - </valueCoding> + <extension url="authorization-roles"> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </valueCoding> + </extension> </extension> <extension url="requester-organization-types"> <extension url="requester-organization-type"> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeSimpleFeasibility-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeSimpleFeasibility-0.1.0.xml index 01eed0a6e..a162028bf 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeSimpleFeasibility-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeSimpleFeasibility-0.1.0.xml @@ -9,11 +9,19 @@ <extension url="message-name"> <valueString value="executeSimpleFeasibilityMessage" /> </extension> - <extension url="authorization-role"> - <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> - <code value="REMOTE" /> - </valueCoding> + <extension url="authorization-roles"> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="LOCAL" /> + </valueCoding> + </extension> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </valueCoding> + </extension> </extension> <extension url="requester-organization-types"> <extension url="requester-organization-type"> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml index 8a05e4a75..c5c0652f1 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/executeUpdateResources-0.1.0.xml @@ -9,11 +9,13 @@ <extension url="message-name"> <valueString value="executeUpdateResourcesMessage" /> </extension> - <extension url="authorization-role"> - <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> - <code value="REMOTE" /> - </valueCoding> + <extension url="authorization-roles"> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </valueCoding> + </extension> </extension> <extension url="requester-organization-types"> <extension url="requester-organization-type"> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-0.1.0.xml index 28c76c157..8fd0d75ff 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/ping-0.1.0.xml @@ -9,11 +9,13 @@ <extension url="message-name"> <valueString value="startProcessMessage" /> </extension> - <extension url="authorization-role"> - <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> - <code value="LOCAL" /> - </valueCoding> + <extension url="authorization-roles"> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="LOCAL" /> + </valueCoding> + </extension> </extension> <extension url="requester-organization-types"> <extension url="requester-organization-type"> @@ -51,11 +53,13 @@ <extension url="message-name"> <valueString value="pongMessage" /> </extension> - <extension url="authorization-role"> - <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> - <code value="REMOTE" /> - </valueCoding> + <extension url="authorization-roles"> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </valueCoding> + </extension> </extension> <extension url="requester-organization-types"> <extension url="requester-organization-type"> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-0.1.0.xml index ee826646d..7c0d53f24 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/pong-0.1.0.xml @@ -9,11 +9,13 @@ <extension url="message-name"> <valueString value="pingMessage" /> </extension> - <extension url="authorization-role"> - <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> - <code value="REMOTE" /> - </valueCoding> + <extension url="authorization-roles"> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </valueCoding> + </extension> </extension> <extension url="requester-organization-types"> <extension url="requester-organization-type"> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-0.1.0.xml index 8acfc3533..fa0abc6cc 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestSimpleFeasibility-0.1.0.xml @@ -9,11 +9,13 @@ <extension url="message-name"> <valueString value="requestSimpleFeasibilityMessage" /> </extension> - <extension url="authorization-role"> - <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> - <code value="LOCAL" /> - </valueCoding> + <extension url="authorization-roles"> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="LOCAL" /> + </valueCoding> + </extension> </extension> <extension url="requester-organization-types"> <extension url="requester-organization-type"> @@ -39,11 +41,13 @@ <extension url="message-name"> <valueString value="resultMultiMedicSimpleFeasibilityMessage" /> </extension> - <extension url="authorization-role"> - <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> - <code value="REMOTE" /> - </valueCoding> + <extension url="authorization-roles"> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="REMOTE" /> + </valueCoding> + </extension> </extension> <extension url="requester-organization-types"> <extension url="requester-organization-type"> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestUpdateResources-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestUpdateResources-0.1.0.xml index ef01d0fd4..eb90b56af 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestUpdateResources-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/requestUpdateResources-0.1.0.xml @@ -9,11 +9,13 @@ <extension url="message-name"> <valueString value="requestUpdateResourcesMessage" /> </extension> - <extension url="authorization-role"> - <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> - <code value="LOCAL" /> - </valueCoding> + <extension url="authorization-roles"> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="LOCAL" /> + </valueCoding> + </extension> </extension> <extension url="requester-organization-types"> <extension url="requester-organization-type"> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/updateWhiteList-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/updateWhiteList-0.1.0.xml index ada28c888..6cbdeea6f 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/updateWhiteList-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/ActivityDefinition/updateWhiteList-0.1.0.xml @@ -9,11 +9,13 @@ <extension url="message-name"> <valueString value="updateWhitelistMessage" /> </extension> - <extension url="authorization-role"> - <valueCoding> - <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> - <code value="LOCAL" /> - </valueCoding> + <extension url="authorization-roles"> + <extension url="authorization-role"> + <valueCoding> + <system value="http://highmed.org/fhir/CodeSystem/authorization-role" /> + <code value="LOCAL" /> + </valueCoding> + </extension> </extension> <extension url="requester-organization-types"> <extension url="requester-organization-type"> diff --git a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml index f7f03cefd..1c6e98e33 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml +++ b/dsf-fhir/dsf-fhir-server/src/main/resources/fhir/StructureDefinition/highmed-extension-process-authorization-0.1.0.xml @@ -50,31 +50,55 @@ <code value="string" /> </type> </element> - <element id="Extension.extension:authorization-role"> + <element id="Extension.extension:authorization-roles"> <path value="Extension.extension" /> - <sliceName value="authorization-role" /> + <sliceName value="authorization-roles" /> <min value="1" /> <max value="1" /> </element> - <element id="Extension.extension:authorization-role.url"> - <path value="Extension.extension.url" /> + <element id="Extension.extension:authorization-roles.extension"> + <path value="Extension.extension.extension" /> + <slicing> + <discriminator> + <type value="value" /> + <path value="url" /> + </discriminator> + <rules value="open" /> + </slicing> + </element> + <element id="Extension.extension:authorization-roles.extension:authorization-role"> + <path value="Extension.extension.extension" /> + <sliceName value="authorization-role" /> + <min value="1" /> + <max value="2" /> + </element> + <element id="Extension.extension:authorization-roles.extension:authorization-role.url"> + <path value="Extension.extension.extension.url" /> <fixedUri value="authorization-role" /> </element> - <element id="Extension.extension:authorization-role.value[x]"> - <path value="Extension.extension.value[x]" /> + <element id="Extension.extension:authorization-roles.extension:authorization-role.value[x]"> + <path value="Extension.extension.extension.value[x]" /> <type> <code value="Coding" /> </type> </element> - <element id="Extension.extension:authorization-role.value[x].system"> - <path value="Extension.extension.value[x].system" /> + <element id="Extension.extension:authorization-roles.extension:authorization-role.value[x].system"> + <path value="Extension.extension.extension.value[x].system" /> <min value="1" /> <fixedUri value="http://highmed.org/fhir/CodeSystem/authorization-role" /> </element> - <element id="Extension.extension:authorization-role.value[x].code"> - <path value="Extension.extension.value[x].code" /> + <element id="Extension.extension:authorization-roles.extension:authorization-role.value[x].code"> + <path value="Extension.extension.extension.value[x].code" /> <min value="1" /> </element> + <element id="Extension.extension:authorization-roles.url"> + <path value="Extension.extension.url" /> + <fixedUri value="authorization-roles" /> + </element> + <element id="Extension.extension:authorization-roles.value[x]"> + <path value="Extension.extension.value[x]" /> + <max value="0" /> + </element> <element id="Extension.extension:requester-organization-types"> <path value="Extension.extension" /> <sliceName value="requester-organization-types" /> @@ -130,7 +154,7 @@ <min value="1" /> <max value="1" /> </element> - <element id="Extension.extension:recipient-organization-type.extension"> + <element id="Extension.extension:recipient-organization-types.extension"> <path value="Extension.extension.extension" /> <slicing> <discriminator> From edf7293b46bef90aca7547bd70bae836293c27d9 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Wed, 11 Mar 2020 02:52:51 +0100 Subject: [PATCH 48/55] fixed starter to conform to resource validation --- ...lityFromMedicsViaMedic1ExampleStarter.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java b/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java index 381914044..70c5e175a 100644 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java +++ b/dsf-bpe/dsf-bpe-process-feasibility/src/test/java/org/highmed/dsf/bpe/start/RequestSimpleFeasibilityFromMedicsViaMedic1ExampleStarter.java @@ -118,6 +118,7 @@ private static Practitioner createPractitioner() { Practitioner practitioner = new Practitioner(); practitioner.setIdElement(new IdType("urn:uuid:" + UUID.randomUUID().toString())); + practitioner.setActive(true); practitioner.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-practitioner"); practitioner.getNameFirstRep().setFamily("HiGHmed").addGiven("Test"); @@ -129,10 +130,10 @@ private static PractitionerRole createPractitionerRole(Practitioner practitioner { PractitionerRole practitionerRole = new PractitionerRole(); practitionerRole.setIdElement(new IdType("urn:uuid:" + UUID.randomUUID().toString())); + practitionerRole.setActive(true); practitioner.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-practitioner-role"); - practitionerRole.getPractitioner().setReference(practitioner.getIdElement().getIdPart()) - .setType("Practitioner"); + practitionerRole.getPractitioner().setReference(practitioner.getIdElement().getIdPart()); practitionerRole.getOrganization().setType("Organization").getIdentifier() .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_MeDIC_1"); @@ -145,14 +146,15 @@ private static ResearchStudy createResearchStudy(Group group1, Group group2, Pra researchStudy.setIdElement(new IdType("urn:uuid:" + UUID.randomUUID().toString())); researchStudy.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-research-study"); + researchStudy.addIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/research-study-identifier") + .setValue(UUID.randomUUID().toString()); researchStudy.setTitle("Research Study Test"); researchStudy.setStatus(ResearchStudyStatus.ACTIVE); researchStudy.setDescription( "This is a test research study based on the highmed profile. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua."); - researchStudy.addEnrollment().setReference(group1.getIdElement().getIdPart()).setType("Group"); - researchStudy.addEnrollment().setReference(group2.getIdElement().getIdPart()).setType("Group"); - researchStudy.getPrincipalInvestigator().setReference(practitioner.getIdElement().getIdPart()) - .setType("Practitioner"); + researchStudy.addEnrollment().setReference(group1.getIdElement().getIdPart()); + researchStudy.addEnrollment().setReference(group2.getIdElement().getIdPart()); + researchStudy.getPrincipalInvestigator().setReference(practitioner.getIdElement().getIdPart()); researchStudy.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-medic") .setValue(new Reference().setType("Organization").setIdentifier(new Identifier() @@ -163,6 +165,9 @@ private static ResearchStudy createResearchStudy(Group group1, Group group2, Pra researchStudy.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-medic") .setValue(new Reference().setType("Organization").setIdentifier(new Identifier() .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_MeDIC_3"))); + researchStudy.addExtension().setUrl("http://highmed.org/fhir/StructureDefinition/participating-ttp") + .setValue(new Reference().setType("Organization").setIdentifier(new Identifier() + .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_TTP"))); return researchStudy; } @@ -178,7 +183,8 @@ private static Task createTask(Practitioner practitioner, ResearchStudy research task.setStatus(TaskStatus.REQUESTED); task.setIntent(TaskIntent.ORDER); task.setAuthoredOn(new Date()); - task.getRequester().setType("Practitioner").setReference(practitioner.getIdElement().getIdPart()); + task.getRequester().setType("Organization").getIdentifier() + .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_MeDIC_1"); task.getRestriction().addRecipient().setType("Organization").getIdentifier() .setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier").setValue("Test_MeDIC_1"); From 3a5fb73eddb7ba193e46f3645daca2417e2187d7 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Wed, 11 Mar 2020 02:54:59 +0100 Subject: [PATCH 49/55] fixed serialization issues, feasibility process works with new authoriz. added new BPMN container for lists of fhir resources simple feasibility process now works in 3medic/ttp docker test setup with new authorization rules --- .../variables/DomainResourceSerializer.java | 84 ------------------ .../fhir/variables/DomainResourceValues.java | 55 ------------ .../FeasibilityQueryResultSerializer.java | 15 ++-- .../FeasibilityQueryResultsSerializer.java | 15 ++-- .../dsf/fhir/variables/FhirPlugin.java | 10 +-- ...a => FhirResourceJacksonDeserializer.java} | 19 ++-- ...ava => FhirResourceJacksonSerializer.java} | 19 ++-- .../variables/FhirResourceSerializer.java | 87 +++++++++++++++++++ .../fhir/variables/FhirResourceValues.java | 54 ++++++++++++ .../dsf/fhir/variables/FhirResourcesList.java | 40 +++++++++ .../FhirResourcesListSerializer.java | 79 +++++++++++++++++ .../variables/FhirResourcesListValues.java | 72 +++++++++++++++ .../service/CheckFeasibilityResources.java | 5 +- .../highmed/dsf/bpe/service/CheckQueries.java | 15 ++-- .../service/DownloadFeasibilityResources.java | 41 ++++----- .../DownloadResearchStudyResource.java | 34 ++++---- .../dsf/bpe/spring/config/FhirConfig.java | 37 ++++---- .../highmed/dsf/fhir/task/TaskHandler.java | 4 +- 18 files changed, 447 insertions(+), 238 deletions(-) delete mode 100755 dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/DomainResourceSerializer.java delete mode 100755 dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/DomainResourceValues.java rename dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/{OrganizationDeserializer.java => FhirResourceJacksonDeserializer.java} (52%) mode change 100755 => 100644 rename dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/{OrganizationSerializer.java => FhirResourceJacksonSerializer.java} (50%) mode change 100755 => 100644 create mode 100644 dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceSerializer.java create mode 100644 dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceValues.java create mode 100644 dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourcesList.java create mode 100644 dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourcesListSerializer.java create mode 100644 dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourcesListValues.java diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/DomainResourceSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/DomainResourceSerializer.java deleted file mode 100755 index a59344681..000000000 --- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/DomainResourceSerializer.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.highmed.dsf.fhir.variables; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; -import java.nio.charset.StandardCharsets; -import java.util.Objects; - -import org.camunda.bpm.engine.impl.variable.serializer.PrimitiveValueSerializer; -import org.camunda.bpm.engine.impl.variable.serializer.ValueFields; -import org.camunda.bpm.engine.variable.impl.value.UntypedValueImpl; -import org.highmed.dsf.fhir.variables.DomainResourceValues.DomainResourceValue; -import org.hl7.fhir.r4.model.DomainResource; -import org.springframework.beans.factory.InitializingBean; - -import ca.uhn.fhir.context.FhirContext; -import ca.uhn.fhir.parser.DataFormatException; - -public class DomainResourceSerializer extends PrimitiveValueSerializer<DomainResourceValue> implements InitializingBean -{ - private final FhirContext fhirContext; - - public DomainResourceSerializer(FhirContext fhirContext) - { - super(DomainResourceValues.VALUE_TYPE); - - this.fhirContext = fhirContext; - } - - @Override - public void afterPropertiesSet() throws Exception - { - Objects.requireNonNull(fhirContext, "fhirContext"); - } - - @Override - public void writeValue(DomainResourceValue value, ValueFields valueFields) - { - DomainResource resource = value.getValue(); - try - { - if (resource != null) - { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - OutputStreamWriter writer = new OutputStreamWriter(out, StandardCharsets.UTF_8); - fhirContext.newJsonParser().encodeResourceToWriter(resource, writer); - - valueFields.setTextValue(resource.getClass().getName()); - valueFields.setByteArrayValue(out.toByteArray()); - } - } - catch (IOException e) - { - throw new RuntimeException(e); - } - } - - @Override - public DomainResourceValue convertToTypedValue(UntypedValueImpl untypedValue) - { - return DomainResourceValues.create((DomainResource) untypedValue.getValue()); - } - - @Override - public DomainResourceValue readValue(ValueFields valueFields) - { - String className = valueFields.getTextValue(); - byte[] bytes = valueFields.getByteArrayValue(); - - try - { - @SuppressWarnings("unchecked") - Class<DomainResource> clazz = (Class<DomainResource>) Class.forName(className); - DomainResource resource = fhirContext.newJsonParser().parseResource(clazz, new ByteArrayInputStream(bytes)); - - return DomainResourceValues.create(resource); - } - catch (ClassNotFoundException | DataFormatException e) - { - throw new RuntimeException(e); - } - } -} diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/DomainResourceValues.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/DomainResourceValues.java deleted file mode 100755 index 83a1f5235..000000000 --- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/DomainResourceValues.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.highmed.dsf.fhir.variables; - -import java.util.Map; - -import org.camunda.bpm.engine.variable.impl.type.PrimitiveValueTypeImpl; -import org.camunda.bpm.engine.variable.impl.value.PrimitiveTypeValueImpl; -import org.camunda.bpm.engine.variable.type.PrimitiveValueType; -import org.camunda.bpm.engine.variable.value.PrimitiveValue; -import org.camunda.bpm.engine.variable.value.TypedValue; -import org.hl7.fhir.r4.model.DomainResource; - -public final class DomainResourceValues -{ - public static interface DomainResourceValue extends PrimitiveValue<DomainResource> - { - } - - private static class DomainResourceValueImpl extends PrimitiveTypeValueImpl<DomainResource> - implements DomainResourceValue - { - private static final long serialVersionUID = 1L; - - public DomainResourceValueImpl(DomainResource value, PrimitiveValueType type) - { - super(value, type); - } - } - - public static class DomainResourceTypeImpl extends PrimitiveValueTypeImpl - { - private static final long serialVersionUID = 1L; - - private DomainResourceTypeImpl() - { - super(DomainResource.class); - } - - @Override - public TypedValue createValue(Object value, Map<String, Object> valueInfo) - { - return new DomainResourceValueImpl((DomainResource) value, VALUE_TYPE); - } - } - - public static final PrimitiveValueType VALUE_TYPE = new DomainResourceTypeImpl(); - - private DomainResourceValues() - { - } - - public static DomainResourceValue create(DomainResource value) - { - return new DomainResourceValueImpl(value, VALUE_TYPE); - } -} diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResultSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResultSerializer.java index 4481d2dc3..1d139ce93 100644 --- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResultSerializer.java +++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResultSerializer.java @@ -6,13 +6,13 @@ import org.camunda.bpm.engine.impl.variable.serializer.PrimitiveValueSerializer; import org.camunda.bpm.engine.impl.variable.serializer.ValueFields; import org.camunda.bpm.engine.variable.impl.value.UntypedValueImpl; +import org.highmed.dsf.fhir.variables.FeasibilityQueryResultValues.FeasibilityQueryResultValue; import org.springframework.beans.factory.InitializingBean; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -public class FeasibilityQueryResultSerializer - extends PrimitiveValueSerializer<FeasibilityQueryResultValues.FeasibilityQueryResultValue> +public class FeasibilityQueryResultSerializer extends PrimitiveValueSerializer<FeasibilityQueryResultValue> implements InitializingBean { private final ObjectMapper objectMapper; @@ -31,7 +31,7 @@ public void afterPropertiesSet() throws Exception } @Override - public void writeValue(FeasibilityQueryResultValues.FeasibilityQueryResultValue value, ValueFields valueFields) + public void writeValue(FeasibilityQueryResultValue value, ValueFields valueFields) { FeasibilityQueryResult target = value.getValue(); try @@ -46,21 +46,20 @@ public void writeValue(FeasibilityQueryResultValues.FeasibilityQueryResultValue } @Override - public FeasibilityQueryResultValues.FeasibilityQueryResultValue convertToTypedValue(UntypedValueImpl untypedValue) + public FeasibilityQueryResultValue convertToTypedValue(UntypedValueImpl untypedValue) { return FeasibilityQueryResultValues.create((FeasibilityQueryResult) untypedValue.getValue()); } @Override - public FeasibilityQueryResultValues.FeasibilityQueryResultValue readValue(ValueFields valueFields) + public FeasibilityQueryResultValue readValue(ValueFields valueFields) { byte[] bytes = valueFields.getByteArrayValue(); try { - FeasibilityQueryResult target = (bytes == null || bytes.length <= 0) ? - null : - objectMapper.readValue(bytes, FeasibilityQueryResult.class); + FeasibilityQueryResult target = (bytes == null || bytes.length <= 0) ? null + : objectMapper.readValue(bytes, FeasibilityQueryResult.class); return FeasibilityQueryResultValues.create(target); } catch (IOException e) diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResultsSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResultsSerializer.java index 529dcfe7e..347d814a0 100644 --- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResultsSerializer.java +++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FeasibilityQueryResultsSerializer.java @@ -6,13 +6,13 @@ import org.camunda.bpm.engine.impl.variable.serializer.PrimitiveValueSerializer; import org.camunda.bpm.engine.impl.variable.serializer.ValueFields; import org.camunda.bpm.engine.variable.impl.value.UntypedValueImpl; +import org.highmed.dsf.fhir.variables.FeasibilityQueryResultsValues.FeasibilityQueryResultsValue; import org.springframework.beans.factory.InitializingBean; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -public class FeasibilityQueryResultsSerializer - extends PrimitiveValueSerializer<FeasibilityQueryResultsValues.FeasibilityQueryResultsValue> +public class FeasibilityQueryResultsSerializer extends PrimitiveValueSerializer<FeasibilityQueryResultsValue> implements InitializingBean { private final ObjectMapper objectMapper; @@ -31,7 +31,7 @@ public void afterPropertiesSet() throws Exception } @Override - public void writeValue(FeasibilityQueryResultsValues.FeasibilityQueryResultsValue value, ValueFields valueFields) + public void writeValue(FeasibilityQueryResultsValue value, ValueFields valueFields) { FeasibilityQueryResults targets = value.getValue(); try @@ -46,21 +46,20 @@ public void writeValue(FeasibilityQueryResultsValues.FeasibilityQueryResultsValu } @Override - public FeasibilityQueryResultsValues.FeasibilityQueryResultsValue convertToTypedValue(UntypedValueImpl untypedValue) + public FeasibilityQueryResultsValue convertToTypedValue(UntypedValueImpl untypedValue) { return FeasibilityQueryResultsValues.create((FeasibilityQueryResults) untypedValue.getValue()); } @Override - public FeasibilityQueryResultsValues.FeasibilityQueryResultsValue readValue(ValueFields valueFields) + public FeasibilityQueryResultsValue readValue(ValueFields valueFields) { byte[] bytes = valueFields.getByteArrayValue(); try { - FeasibilityQueryResults targets = (bytes == null || bytes.length <= 0) ? - null : - objectMapper.readValue(bytes, FeasibilityQueryResults.class); + FeasibilityQueryResults targets = (bytes == null || bytes.length <= 0) ? null + : objectMapper.readValue(bytes, FeasibilityQueryResults.class); return FeasibilityQueryResultsValues.create(targets); } catch (IOException e) diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirPlugin.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirPlugin.java index 9876f1246..55950dda5 100755 --- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirPlugin.java +++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirPlugin.java @@ -13,17 +13,17 @@ public class FhirPlugin implements ProcessEnginePlugin @SuppressWarnings("rawtypes") private final List<TypedValueSerializer> serializer; - public FhirPlugin(DomainResourceSerializer domainResourceSerializer, + public FhirPlugin(FhirResourceSerializer fhirResourceSerializer, + FhirResourcesListSerializer fhirResourcesListSerializer, MultiInstanceTargetSerializer multiInstanceTargetSerializer, MultiInstanceTargetsSerializer multiInstanceTargetsSerializer, FeasibilityQueryResultSerializer feasibilityQueryResultSerializer, FeasibilityQueryResultsSerializer feasibilityQueryResultsSerializer, OutputSerializer outputSerializer, OutputsSerializer outputsSerializer) { - serializer = Arrays - .asList(domainResourceSerializer, multiInstanceTargetSerializer, multiInstanceTargetsSerializer, - feasibilityQueryResultSerializer, feasibilityQueryResultsSerializer, outputSerializer, - outputsSerializer); + serializer = Arrays.asList(fhirResourceSerializer, fhirResourcesListSerializer, multiInstanceTargetSerializer, + multiInstanceTargetsSerializer, feasibilityQueryResultSerializer, feasibilityQueryResultsSerializer, + outputSerializer, outputsSerializer); } @Override diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/OrganizationDeserializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceJacksonDeserializer.java old mode 100755 new mode 100644 similarity index 52% rename from dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/OrganizationDeserializer.java rename to dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceJacksonDeserializer.java index aaa950303..cc2597b9d --- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/OrganizationDeserializer.java +++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceJacksonDeserializer.java @@ -3,7 +3,7 @@ import java.io.IOException; import java.util.Objects; -import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.Resource; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; @@ -11,21 +11,30 @@ import com.fasterxml.jackson.databind.JsonDeserializer; import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.parser.IParser; -public class OrganizationDeserializer extends JsonDeserializer<Organization> +public class FhirResourceJacksonDeserializer extends JsonDeserializer<Resource> { private final FhirContext fhirContext; - public OrganizationDeserializer(FhirContext fhirContext) + public FhirResourceJacksonDeserializer(FhirContext fhirContext) { this.fhirContext = Objects.requireNonNull(fhirContext, "fhirContext"); } @Override - public Organization deserialize(JsonParser p, DeserializationContext ctxt) + public Resource deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { String string = p.readValueAsTree().toString(); - return fhirContext.newJsonParser().parseResource(Organization.class, string); + return (Resource) newJsonParser().parseResource(string); + } + + private IParser newJsonParser() + { + IParser p = fhirContext.newJsonParser(); + p.setStripVersionsFromReferences(false); + p.setOverrideResourceIdWithBundleEntryFullUrl(false); + return p; } } diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/OrganizationSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceJacksonSerializer.java old mode 100755 new mode 100644 similarity index 50% rename from dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/OrganizationSerializer.java rename to dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceJacksonSerializer.java index 94291bf81..80269db13 --- a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/OrganizationSerializer.java +++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceJacksonSerializer.java @@ -3,7 +3,7 @@ import java.io.IOException; import java.util.Objects; -import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.Resource; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.JsonGenerator; @@ -11,21 +11,30 @@ import com.fasterxml.jackson.databind.SerializerProvider; import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.parser.IParser; -public class OrganizationSerializer extends JsonSerializer<Organization> +public class FhirResourceJacksonSerializer extends JsonSerializer<Resource> { private final FhirContext fhirContext; - public OrganizationSerializer(FhirContext fhirContext) + public FhirResourceJacksonSerializer(FhirContext fhirContext) { this.fhirContext = Objects.requireNonNull(fhirContext, "fhirContext"); } @Override - public void serialize(Organization value, JsonGenerator jgen, SerializerProvider provider) + public void serialize(Resource value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { - String text = fhirContext.newJsonParser().encodeResourceToString(value); + String text = newJsonParser().encodeResourceToString(value); jgen.writeRawValue(text); } + + private IParser newJsonParser() + { + IParser p = fhirContext.newJsonParser(); + p.setStripVersionsFromReferences(false); + p.setOverrideResourceIdWithBundleEntryFullUrl(false); + return p; + } } diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceSerializer.java new file mode 100644 index 000000000..04e187b85 --- /dev/null +++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceSerializer.java @@ -0,0 +1,87 @@ +package org.highmed.dsf.fhir.variables; + +import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +import org.camunda.bpm.engine.impl.variable.serializer.PrimitiveValueSerializer; +import org.camunda.bpm.engine.impl.variable.serializer.ValueFields; +import org.camunda.bpm.engine.variable.impl.value.UntypedValueImpl; +import org.highmed.dsf.fhir.variables.FhirResourceValues.FhirResourceValue; +import org.hl7.fhir.r4.model.Resource; +import org.springframework.beans.factory.InitializingBean; + +import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.parser.DataFormatException; +import ca.uhn.fhir.parser.IParser; + +public class FhirResourceSerializer extends PrimitiveValueSerializer<FhirResourceValue> implements InitializingBean +{ + private final FhirContext fhirContext; + + public FhirResourceSerializer(FhirContext fhirContext) + { + super(FhirResourceValues.VALUE_TYPE); + + this.fhirContext = fhirContext; + } + + @Override + public void afterPropertiesSet() throws Exception + { + Objects.requireNonNull(fhirContext, "fhirContext"); + } + + @Override + public void writeValue(FhirResourceValue value, ValueFields valueFields) + { + Resource resource = value.getValue(); + try + { + if (resource != null) + { + String s = newJsonParser().encodeResourceToString(resource); + valueFields.setTextValue(resource.getClass().getName()); + valueFields.setByteArrayValue(s.getBytes(StandardCharsets.UTF_8)); + } + } + catch (DataFormatException e) + { + throw new RuntimeException(e); + } + } + + private IParser newJsonParser() + { + IParser p = fhirContext.newJsonParser(); + p.setStripVersionsFromReferences(false); + p.setOverrideResourceIdWithBundleEntryFullUrl(false); + return p; + } + + @Override + public FhirResourceValue convertToTypedValue(UntypedValueImpl untypedValue) + { + return FhirResourceValues.create((Resource) untypedValue.getValue()); + } + + @Override + public FhirResourceValue readValue(ValueFields valueFields) + { + String className = valueFields.getTextValue(); + byte[] bytes = valueFields.getByteArrayValue(); + + try + { + @SuppressWarnings("unchecked") + Class<Resource> clazz = (Class<Resource>) Class.forName(className); + Resource resource = newJsonParser().parseResource(clazz, new ByteArrayInputStream(bytes)); + + return FhirResourceValues.create(resource); + } + catch (ClassNotFoundException e) + { + throw new RuntimeException(e); + } + } +} diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceValues.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceValues.java new file mode 100644 index 000000000..9a44504fc --- /dev/null +++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourceValues.java @@ -0,0 +1,54 @@ +package org.highmed.dsf.fhir.variables; + +import java.util.Map; + +import org.camunda.bpm.engine.variable.impl.type.PrimitiveValueTypeImpl; +import org.camunda.bpm.engine.variable.impl.value.PrimitiveTypeValueImpl; +import org.camunda.bpm.engine.variable.type.PrimitiveValueType; +import org.camunda.bpm.engine.variable.value.PrimitiveValue; +import org.camunda.bpm.engine.variable.value.TypedValue; +import org.hl7.fhir.r4.model.Resource; + +public final class FhirResourceValues +{ + public static interface FhirResourceValue extends PrimitiveValue<Resource> + { + } + + private static class FhirResourceValueImpl extends PrimitiveTypeValueImpl<Resource> implements FhirResourceValue + { + private static final long serialVersionUID = 1L; + + public FhirResourceValueImpl(Resource value, PrimitiveValueType type) + { + super(value, type); + } + } + + public static class FhirResourceTypeImpl extends PrimitiveValueTypeImpl + { + private static final long serialVersionUID = 1L; + + private FhirResourceTypeImpl() + { + super(Resource.class); + } + + @Override + public TypedValue createValue(Object value, Map<String, Object> valueInfo) + { + return new FhirResourceValueImpl((Resource) value, VALUE_TYPE); + } + } + + public static final PrimitiveValueType VALUE_TYPE = new FhirResourceTypeImpl(); + + private FhirResourceValues() + { + } + + public static FhirResourceValue create(Resource resource) + { + return new FhirResourceValueImpl(resource, VALUE_TYPE); + } +} diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourcesList.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourcesList.java new file mode 100644 index 000000000..188f209c1 --- /dev/null +++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourcesList.java @@ -0,0 +1,40 @@ +package org.highmed.dsf.fhir.variables; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.hl7.fhir.r4.model.Resource; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class FhirResourcesList +{ + private final List<Resource> resources = new ArrayList<>(); + + @JsonCreator + public FhirResourcesList(@JsonProperty("resources") Collection<? extends Resource> resources) + { + if (resources != null) + this.resources.addAll(resources); + } + + public FhirResourcesList(Resource... resources) + { + this(Arrays.asList(resources)); + } + + public List<Resource> getResources() + { + return Collections.unmodifiableList(resources); + } + + @SuppressWarnings("unchecked") + public <R extends Resource> List<R> getResourcesAndCast() + { + return (List<R>) getResources(); + } +} diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourcesListSerializer.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourcesListSerializer.java new file mode 100644 index 000000000..bf430e970 --- /dev/null +++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourcesListSerializer.java @@ -0,0 +1,79 @@ +package org.highmed.dsf.fhir.variables; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Objects; + +import org.camunda.bpm.engine.impl.variable.serializer.PrimitiveValueSerializer; +import org.camunda.bpm.engine.impl.variable.serializer.ValueFields; +import org.camunda.bpm.engine.variable.impl.value.UntypedValueImpl; +import org.highmed.dsf.fhir.variables.FhirResourcesListValues.FhirResourcesListValue; +import org.springframework.beans.factory.InitializingBean; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class FhirResourcesListSerializer extends PrimitiveValueSerializer<FhirResourcesListValue> + implements InitializingBean +{ + private final ObjectMapper objectMapper; + + public FhirResourcesListSerializer(ObjectMapper objectMapper) + { + super(FhirResourcesListValues.VALUE_TYPE); + + this.objectMapper = objectMapper; + } + + @Override + public void afterPropertiesSet() throws Exception + { + Objects.requireNonNull(objectMapper, "objectMapper"); + } + + @Override + public void writeValue(FhirResourcesListValue value, ValueFields valueFields) + { + FhirResourcesList resource = value.getValue(); + try + { + if (resource != null) + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + objectMapper.writeValue(out, resource); + + valueFields.setTextValue(resource.getClass().getName()); + valueFields.setByteArrayValue(out.toByteArray()); + } + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + @Override + public FhirResourcesListValue convertToTypedValue(UntypedValueImpl untypedValue) + { + return FhirResourcesListValues.create((FhirResourcesList) untypedValue.getValue()); + } + + @Override + public FhirResourcesListValue readValue(ValueFields valueFields) + { + String className = valueFields.getTextValue(); + byte[] bytes = valueFields.getByteArrayValue(); + + try + { + @SuppressWarnings("unchecked") + Class<FhirResourcesList> clazz = (Class<FhirResourcesList>) Class.forName(className); + FhirResourcesList resource = objectMapper.readValue(bytes, clazz); + + return FhirResourcesListValues.create(resource); + } + catch (ClassNotFoundException | IOException e) + { + throw new RuntimeException(e); + } + } +} diff --git a/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourcesListValues.java b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourcesListValues.java new file mode 100644 index 000000000..14c28c150 --- /dev/null +++ b/dsf-bpe/dsf-bpe-process-base/src/main/java/org/highmed/dsf/fhir/variables/FhirResourcesListValues.java @@ -0,0 +1,72 @@ +package org.highmed.dsf.fhir.variables; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.camunda.bpm.engine.variable.impl.type.PrimitiveValueTypeImpl; +import org.camunda.bpm.engine.variable.impl.value.PrimitiveTypeValueImpl; +import org.camunda.bpm.engine.variable.type.PrimitiveValueType; +import org.camunda.bpm.engine.variable.value.PrimitiveValue; +import org.camunda.bpm.engine.variable.value.TypedValue; +import org.hl7.fhir.r4.model.Resource; + +public final class FhirResourcesListValues +{ + public static interface FhirResourcesListValue extends PrimitiveValue<FhirResourcesList> + { + @SuppressWarnings("unchecked") + default <R extends Resource> List<R> getFhirResources() + { + return (List<R>) getValue().getResources(); + } + } + + private static class FhirResourcesListValueImpl extends PrimitiveTypeValueImpl<FhirResourcesList> + implements FhirResourcesListValue + { + private static final long serialVersionUID = 1L; + + public FhirResourcesListValueImpl(FhirResourcesList value, PrimitiveValueType type) + { + super(value, type); + } + } + + public static class FhirResourcesListTypeImpl extends PrimitiveValueTypeImpl + { + private static final long serialVersionUID = 1L; + + private FhirResourcesListTypeImpl() + { + super(FhirResourcesList.class); + } + + @Override + public TypedValue createValue(Object value, Map<String, Object> valueInfo) + { + return new FhirResourcesListValueImpl((FhirResourcesList) value, VALUE_TYPE); + } + } + + public static final PrimitiveValueType VALUE_TYPE = new FhirResourcesListTypeImpl(); + + private FhirResourcesListValues() + { + } + + public static FhirResourcesListValue create(Resource... resources) + { + return new FhirResourcesListValueImpl(new FhirResourcesList(resources), VALUE_TYPE); + } + + public static FhirResourcesListValue create(Collection<? extends Resource> resources) + { + return new FhirResourcesListValueImpl(new FhirResourcesList(resources), VALUE_TYPE); + } + + public static FhirResourcesListValue create(FhirResourcesList value) + { + return new FhirResourcesListValueImpl(value, VALUE_TYPE); + } +} diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckFeasibilityResources.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckFeasibilityResources.java index c747167ba..2bd78ebad 100755 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckFeasibilityResources.java +++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckFeasibilityResources.java @@ -10,6 +10,7 @@ import org.highmed.dsf.bpe.delegate.AbstractServiceDelegate; import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.FhirResourcesList; import org.hl7.fhir.r4.model.Group; import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.ResearchStudy; @@ -26,8 +27,8 @@ public void doExecute(DelegateExecution execution) throws Exception { ResearchStudy researchStudy = (ResearchStudy) execution.getVariable(Constants.VARIABLE_RESEARCH_STUDY); - @SuppressWarnings("unchecked") - List<Group> cohorts = (List<Group>) execution.getVariable(Constants.VARIABLE_COHORTS); + List<Group> cohorts = ((FhirResourcesList) execution.getVariable(Constants.VARIABLE_COHORTS)) + .getResourcesAndCast(); checkNumberOfParticipatingMedics(researchStudy); checkNumberOfCohortDefinitions(cohorts); diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckQueries.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckQueries.java index 111060597..6b8fd1fda 100644 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckQueries.java +++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/CheckQueries.java @@ -14,6 +14,7 @@ import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.group.GroupHelper; import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.FhirResourcesList; import org.highmed.dsf.fhir.variables.Outputs; import org.highmed.dsf.fhir.variables.OutputsValues; import org.hl7.fhir.r4.model.Group; @@ -41,25 +42,25 @@ public void afterPropertiesSet() throws Exception } @Override - @SuppressWarnings("unchecked") public void doExecute(DelegateExecution execution) throws Exception { Outputs outputs = (Outputs) execution.getVariable(Constants.VARIABLE_PROCESS_OUTPUTS); - List<Group> cohorts = (List<Group>) execution.getVariable(Constants.VARIABLE_COHORTS); + List<Group> cohorts = ((FhirResourcesList) execution.getVariable(Constants.VARIABLE_COHORTS)) + .getResourcesAndCast(); Map<String, String> queries = new HashMap<>(); - cohorts.forEach(group -> { + cohorts.forEach(group -> + { String aqlQuery = groupHelper.extractAqlQuery(group).toLowerCase(); String groupId = group.getId(); if (!aqlQuery.startsWith(SIMPLE_FEASIBILITY_QUERY_PREFIX)) { - String errorMessage = - "Initial single medic feasibility query check failed, wrong format for query of group with id '" - + groupId + "', expected query to start with '" + SIMPLE_FEASIBILITY_QUERY_PREFIX - + "' but got '" + aqlQuery + "'"; + String errorMessage = "Initial single medic feasibility query check failed, wrong format for query of group with id '" + + groupId + "', expected query to start with '" + SIMPLE_FEASIBILITY_QUERY_PREFIX + + "' but got '" + aqlQuery + "'"; logger.info(errorMessage); outputs.addErrorOutput(errorMessage); diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadFeasibilityResources.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadFeasibilityResources.java index 47e02ef2d..e8044c1ce 100644 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadFeasibilityResources.java +++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadFeasibilityResources.java @@ -13,6 +13,7 @@ import org.highmed.dsf.fhir.client.FhirWebserviceClientProvider; import org.highmed.dsf.fhir.organization.OrganizationProvider; import org.highmed.dsf.fhir.task.TaskHelper; +import org.highmed.dsf.fhir.variables.FhirResourcesListValues; import org.highmed.dsf.fhir.variables.Outputs; import org.highmed.dsf.fhir.variables.OutputsValues; import org.highmed.fhir.client.FhirWebserviceClient; @@ -60,7 +61,7 @@ public void doExecute(DelegateExecution execution) throws Exception Outputs outputs = (Outputs) execution.getVariable(Constants.VARIABLE_PROCESS_OUTPUTS); List<Group> cohortDefinitions = getCohortDefinitions(researchStudy, outputs, client); - execution.setVariable(Constants.VARIABLE_COHORTS, cohortDefinitions); + execution.setVariable(Constants.VARIABLE_COHORTS, FhirResourcesListValues.create(cohortDefinitions)); execution.setVariable(Constants.VARIABLE_PROCESS_OUTPUTS, OutputsValues.create(outputs)); boolean needsConsentCheck = getNeedsConsentCheck(task); @@ -82,8 +83,8 @@ private IdType getResearchStudyId(Task task) private FhirWebserviceClient getWebserviceClient(IdType researchStudyId) { - if (researchStudyId.getBaseUrl() == null || researchStudyId.getBaseUrl() - .equals(getFhirWebserviceClientProvider().getLocalBaseUrl())) + if (researchStudyId.getBaseUrl() == null + || researchStudyId.getBaseUrl().equals(getFhirWebserviceClientProvider().getLocalBaseUrl())) { return getFhirWebserviceClientProvider().getLocalWebserviceClient(); } @@ -101,9 +102,8 @@ private ResearchStudy getResearchStudy(IdType researchStudyid, FhirWebserviceCli } catch (WebApplicationException e) { - throw new ResourceNotFoundException( - "Error while reading ResearchStudy with id " + researchStudyid.getIdPart() + " from " + client - .getBaseUrl()); + throw new ResourceNotFoundException("Error while reading ResearchStudy with id " + + researchStudyid.getIdPart() + " from " + client.getBaseUrl()); } } @@ -112,7 +112,8 @@ private List<Group> getCohortDefinitions(ResearchStudy researchStudy, Outputs ou List<Group> cohortDefinitions = new ArrayList<>(); List<Reference> cohortDefinitionReferences = researchStudy.getEnrollment(); - cohortDefinitionReferences.forEach(reference -> { + cohortDefinitionReferences.forEach(reference -> + { try { IdType type = new IdType(reference.getReference()); @@ -125,9 +126,8 @@ private List<Group> getCohortDefinitions(ResearchStudy researchStudy, Outputs ou } catch (WebApplicationException e) { - String errorMessage = - "Error while reading cohort definition with id " + reference.getReference() + " from " + client - .getBaseUrl(); + String errorMessage = "Error while reading cohort definition with id " + reference.getReference() + + " from " + client.getBaseUrl(); logger.info(errorMessage); outputs.addErrorOutput(errorMessage); @@ -139,19 +139,20 @@ private List<Group> getCohortDefinitions(ResearchStudy researchStudy, Outputs ou private boolean getNeedsConsentCheck(Task task) { - return getTaskHelper().getFirstInputParameterBooleanValue(task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY, - Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK).orElseThrow( - () -> new IllegalArgumentException( - "NeedsConsentCheck boolean is not set in task with id='" + task.getId() - + "', this error should " + "have been caught by resource validation")); + return getTaskHelper() + .getFirstInputParameterBooleanValue(task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY, + Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK) + .orElseThrow(() -> new IllegalArgumentException("NeedsConsentCheck boolean is not set in task with id='" + + task.getId() + "', this error should " + "have been caught by resource validation")); } private boolean getNeedsRecordLinkageCheck(Task task) { - return getTaskHelper().getFirstInputParameterBooleanValue(task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY, - Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE).orElseThrow( - () -> new IllegalArgumentException( - "NeedsRecordLinkage boolean is not set in task with id='" + task.getId() - + "', this error should " + "have been caught by resource validation")); + return getTaskHelper() + .getFirstInputParameterBooleanValue(task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY, + Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE) + .orElseThrow( + () -> new IllegalArgumentException("NeedsRecordLinkage boolean is not set in task with id='" + + task.getId() + "', this error should " + "have been caught by resource validation")); } } diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java index 63c94d0ad..7217585e6 100644 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java +++ b/dsf-bpe/dsf-bpe-process-feasibility/src/main/java/org/highmed/dsf/bpe/service/DownloadResearchStudyResource.java @@ -47,7 +47,7 @@ public void doExecute(DelegateExecution execution) throws Exception execution.setVariable(Constants.VARIABLE_NEEDS_RECORD_LINKAGE, needsRecordLinkage); // TODO: remove when implemented - if(needsConsentCheck || needsRecordLinkage) + if (needsConsentCheck || needsRecordLinkage) { throw new UnsupportedOperationException("Consent Check and Record Linkage not yet supported."); } @@ -57,10 +57,10 @@ private IdType getResearchStudyId(Task task) { Reference researchStudyReference = getTaskHelper() .getInputParameterReferenceValues(task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY, - Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE).findFirst() - .orElseThrow(() -> new IllegalArgumentException( - "ResearchStudy reference is not set in task with id='" + task.getId() + "', this error should " - + "have been caught by resource validation")); + Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_RESEARCH_STUDY_REFERENCE) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("ResearchStudy reference is not set in task with id='" + + task.getId() + "', this error should " + "have been caught by resource validation")); return new IdType(researchStudyReference.getReference()); } @@ -73,25 +73,27 @@ private ResearchStudy getResearchStudy(IdType researchStudyid, FhirWebserviceCli } catch (WebApplicationException e) { - throw new ResourceNotFoundException( - "Error while reading ResearchStudy with id " + researchStudyid.getIdPart() + " from " + client - .getBaseUrl()); + throw new ResourceNotFoundException("Error while reading ResearchStudy with id " + + researchStudyid.getIdPart() + " from " + client.getBaseUrl()); } } private boolean getNeedsConsentCheck(Task task) { - return getTaskHelper().getFirstInputParameterBooleanValue(task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY, - Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK).orElseThrow(() -> new IllegalArgumentException( - "NeedsConsentCheck boolean is not set in task with id='" + task.getId() + "', this error should " - + "have been caught by resource validation")); + return getTaskHelper() + .getFirstInputParameterBooleanValue(task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY, + Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_CONSENT_CHECK) + .orElseThrow(() -> new IllegalArgumentException("NeedsConsentCheck boolean is not set in task with id='" + + task.getId() + "', this error should " + "have been caught by resource validation")); } private boolean getNeedsRecordLinkageCheck(Task task) { - return getTaskHelper().getFirstInputParameterBooleanValue(task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY, - Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE).orElseThrow(() -> new IllegalArgumentException( - "NeedsRecordLinkage boolean is not set in task with id='" + task.getId() + "', this error should " - + "have been caught by resource validation")); + return getTaskHelper() + .getFirstInputParameterBooleanValue(task, Constants.CODESYSTEM_HIGHMED_FEASIBILITY, + Constants.CODESYSTEM_HIGHMED_FEASIBILITY_VALUE_NEEDS_RECORD_LINKAGE) + .orElseThrow( + () -> new IllegalArgumentException("NeedsRecordLinkage boolean is not set in task with id='" + + task.getId() + "', this error should " + "have been caught by resource validation")); } } diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/FhirConfig.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/FhirConfig.java index b65238bf9..d2e8cdab8 100755 --- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/FhirConfig.java +++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/bpe/spring/config/FhirConfig.java @@ -22,19 +22,20 @@ import org.highmed.dsf.fhir.task.TaskHandler; import org.highmed.dsf.fhir.task.TaskHelper; import org.highmed.dsf.fhir.task.TaskHelperImpl; -import org.highmed.dsf.fhir.variables.DomainResourceSerializer; import org.highmed.dsf.fhir.variables.FeasibilityQueryResultSerializer; import org.highmed.dsf.fhir.variables.FeasibilityQueryResultsSerializer; import org.highmed.dsf.fhir.variables.FhirPlugin; +import org.highmed.dsf.fhir.variables.FhirResourceJacksonDeserializer; +import org.highmed.dsf.fhir.variables.FhirResourceJacksonSerializer; +import org.highmed.dsf.fhir.variables.FhirResourceSerializer; +import org.highmed.dsf.fhir.variables.FhirResourcesListSerializer; import org.highmed.dsf.fhir.variables.MultiInstanceTargetSerializer; import org.highmed.dsf.fhir.variables.MultiInstanceTargetsSerializer; -import org.highmed.dsf.fhir.variables.OrganizationDeserializer; -import org.highmed.dsf.fhir.variables.OrganizationSerializer; import org.highmed.dsf.fhir.variables.OutputSerializer; import org.highmed.dsf.fhir.variables.OutputsSerializer; import org.highmed.dsf.fhir.websocket.FhirConnector; import org.highmed.dsf.fhir.websocket.LastEventTimeIo; -import org.hl7.fhir.r4.model.Organization; +import org.hl7.fhir.r4.model.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -119,26 +120,14 @@ public ObjectMapper fhirObjectMapper() // mapper.enable(SerializationFeature.INDENT_OUTPUT); SimpleModule module = new SimpleModule(); - module.addSerializer(Organization.class, organizationSerializer()); - module.addDeserializer(Organization.class, organizationDeserializer()); + module.addSerializer(Resource.class, new FhirResourceJacksonSerializer(fhirContext())); + module.addDeserializer(Resource.class, new FhirResourceJacksonDeserializer(fhirContext())); mapper.registerModule(module); return mapper; } - @Bean - public OrganizationSerializer organizationSerializer() - { - return new OrganizationSerializer(fhirContext()); - } - - @Bean - public OrganizationDeserializer organizationDeserializer() - { - return new OrganizationDeserializer(fhirContext()); - } - @Bean public FhirContext fhirContext() { @@ -154,15 +143,21 @@ public ReferenceExtractor referenceExtractor() @Bean public ProcessEnginePlugin fhirPlugin() { - return new FhirPlugin(domainResourceSerializer(), multiInstanceTargetSerializer(), + return new FhirPlugin(fhirResourceSerializer(), fhirResourcesListSerializer(), multiInstanceTargetSerializer(), multiInstanceTargetsSerializer(), feasibilityQueryResultSerializer(), feasibilityQueryResultsSerializer(), outputSerializer(), outputsSerializer()); } @Bean - public DomainResourceSerializer domainResourceSerializer() + public FhirResourceSerializer fhirResourceSerializer() + { + return new FhirResourceSerializer(fhirContext()); + } + + @Bean + public FhirResourcesListSerializer fhirResourcesListSerializer() { - return new DomainResourceSerializer(fhirContext()); + return new FhirResourcesListSerializer(fhirObjectMapper()); } @Bean diff --git a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/task/TaskHandler.java b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/task/TaskHandler.java index ee0ede68b..cfcc32a4e 100755 --- a/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/task/TaskHandler.java +++ b/dsf-bpe/dsf-bpe-server/src/main/java/org/highmed/dsf/fhir/task/TaskHandler.java @@ -15,7 +15,7 @@ import org.camunda.bpm.engine.runtime.ProcessInstanceQuery; import org.camunda.bpm.engine.variable.Variables; import org.highmed.dsf.bpe.Constants; -import org.highmed.dsf.fhir.variables.DomainResourceValues; +import org.highmed.dsf.fhir.variables.FhirResourceValues; import org.highmed.fhir.client.FhirWebserviceClient; import org.hl7.fhir.r4.model.Task; import org.slf4j.Logger; @@ -66,7 +66,7 @@ public void onTask(Task task) String correlationKey = taskHelper.getFirstInputParameterStringValue(task, Constants.CODESYSTEM_HIGHMED_BPMN, Constants.CODESYSTEM_HIGHMED_BPMN_VALUE_CORRELATION_KEY).orElse(null); - Map<String, Object> variables = Map.of(Constants.VARIABLE_TASK, DomainResourceValues.create(task)); + Map<String, Object> variables = Map.of(Constants.VARIABLE_TASK, FhirResourceValues.create(task)); try { From a0c378c020b98cbaae8b65d063931a1d733d600a Mon Sep 17 00:00:00 2001 From: Reto Wettstein <Reto.Wettstein@med.uni-heidelberg.de> Date: Fri, 13 Mar 2020 10:26:23 +0100 Subject: [PATCH 50/55] removes unneeded starter json files --- .../simple-feasibility-bundle.example.json | 268 ------------------ .../resources/start-process-task.example.json | 41 --- .../test/resources/parent-task.example.json | 41 --- ...request-update-resources-task.example.json | 64 ----- .../update-whitelist-task.example.json | 41 --- 5 files changed, 455 deletions(-) delete mode 100755 dsf-bpe/dsf-bpe-process-feasibility/src/test/resources/simple-feasibility-bundle.example.json delete mode 100755 dsf-bpe/dsf-bpe-process-ping/src/test/resources/start-process-task.example.json delete mode 100644 dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-parent/src/test/resources/parent-task.example.json delete mode 100755 dsf-bpe/dsf-bpe-process-update-resources/src/test/resources/request-update-resources-task.example.json delete mode 100755 dsf-bpe/dsf-bpe-process-update-whitelist/src/test/resources/update-whitelist-task.example.json diff --git a/dsf-bpe/dsf-bpe-process-feasibility/src/test/resources/simple-feasibility-bundle.example.json b/dsf-bpe/dsf-bpe-process-feasibility/src/test/resources/simple-feasibility-bundle.example.json deleted file mode 100755 index 23f982674..000000000 --- a/dsf-bpe/dsf-bpe-process-feasibility/src/test/resources/simple-feasibility-bundle.example.json +++ /dev/null @@ -1,268 +0,0 @@ -{ - "resourceType":"Bundle", - "type":"transaction", - "entry":[ - { - "fullUrl":"urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8aa", - "resource":{ - "resourceType":"Group", - "meta":{ - "profile":"http://highmed.org/fhir/StructureDefinition/highmed-group" - }, - "text": { - "div":"This is the description", - "status":"additional" - }, - "type":"person", - "actual":true, - "extension":[ - { - "url":"http://highmed.org/fhir/StructureDefinition/query", - "valueExpression":[ - { - "language":"application/x-aql-query", - "expression":"SELECT COUNT(e) FROM EHR e" - } - ] - } - ] - }, - "request":{ - "method":"POST", - "url":"Group" - } - }, - { - "fullUrl":"urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8bb", - "resource":{ - "resourceType":"Group", - "meta":{ - "profile":"http://highmed.org/fhir/StructureDefinition/highmed-group" - }, - "text": { - "div":"This is the description", - "status":"additional" - }, - "type":"person", - "actual":true, - "extension":[ - { - "url":"http://highmed.org/fhir/StructureDefinition/query", - "valueExpression":[ - { - "language":"application/x-aql-query", - "expression":"SELECT COUNT(e) FROM EHR e" - } - ] - } - ] - }, - "request":{ - "method":"POST", - "url":"Group" - } - }, - { - "fullUrl":"urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8xx", - "resource":{ - "resourceType":"Practitioner", - "meta":{ - "profile":"http://highmed.org/fhir/StructureDefinition/highmed-practitioner" - }, - "name":[ - { - "family":"HiGHmed", - "given":[ - "Test" - ] - } - ], - "telecom":[ - { - "system":"phone", - "value":"+491710001122" - }, - { - "system":"email", - "value":"test-practitioner@highmed.org" - } - ], - "address":[ - { - "line":[ - "Highmedstraße 12" - ], - "city":"Berlin", - "postalCode":"10115", - "country":"DE" - } - ] - }, - "request":{ - "method":"POST", - "url":"Practitioner" - } - }, - { - "fullUrl":"urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8yy", - "resource":{ - "resourceType":"PractitionerRole", - "meta":{ - "profile":"http://highmed.org/fhir/StructureDefinition/highmed-practitioner-role" - }, - "practitioner":{ - "reference":"urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8xx" - }, - "organization":{ - "identifier":{ - "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", - "value":"Test_Organization" - }, - "type":"Organization" - } - }, - "request":{ - "method":"POST", - "url":"PractitionerRole" - } - }, - { - "fullUrl":"urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8cc", - "resource":{ - "resourceType":"ResearchStudy", - "meta":{ - "profile":"http://highmed.org/fhir/StructureDefinition/highmed-research-study" - }, - "title": "Research Study Test", - "status":"active", - "description":"This is a test research study based on the highmed profile. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.", - "enrollment":[ - { - "reference":"urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8aa" - }, - { - "reference":"urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8bb" - } - ], - "principalInvestigator":{ - "reference":"urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8xx" - }, - "extension":[ - { - "url":"http://highmed.org/fhir/StructureDefinition/participating-medic", - "valueReference":{ - "identifier":{ - "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", - "value":"Test_Organization" - }, - "type":"Organization" - } - }, - { - "url":"http://highmed.org/fhir/StructureDefinition/participating-medic", - "valueReference":{ - "identifier":{ - "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", - "value":"Test_Organization_2" - }, - "type":"Organization" - } - }, - { - "url":"http://highmed.org/fhir/StructureDefinition/participating-medic", - "valueReference":{ - "identifier":{ - "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", - "value":"Test_Organization_3" - }, - "type":"Organization" - } - } - ] - }, - "request":{ - "method":"POST", - "url":"ResearchStudy" - } - }, - { - "fullUrl":"urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8dd", - "resource":{ - "resourceType":"Task", - "meta":{ - "profile":"http://highmed.org/fhir/StructureDefinition/highmed-task-request-simple-feasibility" - }, - "instantiatesUri":"http://highmed.org/bpe/Process/requestSimpleFeasibility/1.0.0", - "status":"requested", - "intent":"order", - "authoredOn":"2019-10-21", - "requester":{ - "reference":"urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8xx" - }, - "restriction":{ - "recipient":[ - { - "identifier":{ - "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", - "value":"Test_Organization" - }, - "type":"Organization" - } - ] - }, - "input":[ - { - "type":{ - "coding":[ - { - "system":"http://highmed.org/fhir/CodeSystem/bpmn-message", - "code":"message-name" - } - ] - }, - "valueString":"requestSimpleFeasibilityMessage" - }, - { - "type":{ - "coding":[ - { - "system":"http://highmed.org/fhir/CodeSystem/feasibility", - "code":"research-study-reference" - } - ] - }, - "valueReference":{ - "reference":"urn:uuid:ae194285-d08e-46c7-a9a7-9a47624dd8cc" - } - }, - { - "type":{ - "coding":[ - { - "system":"http://highmed.org/fhir/CodeSystem/feasibility", - "code":"needs-record-linkage" - } - ] - }, - "valueBoolean": false - }, - { - "type":{ - "coding":[ - { - "system":"http://highmed.org/fhir/CodeSystem/feasibility", - "code":"needs-consent-check" - } - ] - }, - "valueBoolean": false - } - ] - }, - "request":{ - "method":"POST", - "url":"Task" - } - } - ] -} \ No newline at end of file diff --git a/dsf-bpe/dsf-bpe-process-ping/src/test/resources/start-process-task.example.json b/dsf-bpe/dsf-bpe-process-ping/src/test/resources/start-process-task.example.json deleted file mode 100755 index 9e7a896e7..000000000 --- a/dsf-bpe/dsf-bpe-process-ping/src/test/resources/start-process-task.example.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "resourceType":"Task", - "meta":{ - "profile":"http://highmed.org/fhir/StructureDefinition/highmed-task-start-process" - }, - "instantiatesUri":"http://highmed.org/bpe/Process/ping/1.0.0", - "status":"requested", - "intent":"order", - "authoredOn":"2019-10-21", - "requester":{ - "identifier":{ - "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", - "value":"Test_Organization" - }, - "type":"Organization" - }, - "restriction":{ - "recipient":[ - { - "identifier":{ - "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", - "value":"Test_Organization_2" - }, - "type":"Organization" - } - ] - }, - "input":[ - { - "type": { - "coding": [ - { - "system": "http://highmed.org/fhir/CodeSystem/bpmn-message", - "code": "message-name" - } - ] - }, - "valueString": "startProcessMessage" - } - ] -} \ No newline at end of file diff --git a/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-parent/src/test/resources/parent-task.example.json b/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-parent/src/test/resources/parent-task.example.json deleted file mode 100644 index 3cdb96f68..000000000 --- a/dsf-bpe/dsf-bpe-process-plugin-example/dsf-bpe-process-parent/src/test/resources/parent-task.example.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "resourceType":"Task", - "meta":{ - "profile":"http://highmed.org/fhir/StructureDefinition/highmed-task-plugin-base" - }, - "instantiatesUri":"http://highmed.org/bpe/Process/parentPlugin/1.0.0", - "status":"requested", - "intent":"order", - "authoredOn":"2019-10-21", - "requester":{ - "identifier":{ - "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", - "value":"Test_Organization" - }, - "type":"Organization" - }, - "restriction":{ - "recipient":[ - { - "identifier":{ - "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", - "value":"Test_Organization" - }, - "type":"Organization" - } - ] - }, - "input":[ - { - "type": { - "coding": [ - { - "system": "http://highmed.org/fhir/CodeSystem/bpmn-message", - "code": "message-name" - } - ] - }, - "valueString": "parentPluginMessage" - } - ] -} \ No newline at end of file diff --git a/dsf-bpe/dsf-bpe-process-update-resources/src/test/resources/request-update-resources-task.example.json b/dsf-bpe/dsf-bpe-process-update-resources/src/test/resources/request-update-resources-task.example.json deleted file mode 100755 index d86cc4ef1..000000000 --- a/dsf-bpe/dsf-bpe-process-update-resources/src/test/resources/request-update-resources-task.example.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "resourceType":"Task", - "meta":{ - "profile":"http://highmed.org/fhir/StructureDefinition/highmed-task-request-update-resources" - }, - "instantiatesUri":"http://highmed.org/bpe/Process/requestUpdateResources/1.0.0", - "status":"requested", - "intent":"order", - "requester":{ - "identifier":{ - "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", - "value":"Test_Organization" - }, - "type":"Organization" - }, - "restriction":{ - "recipient":[ - { - "identifier":{ - "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", - "value":"Test_Organization" - }, - "type":"Organization" - } - ] - }, - "input":[ - { - "type":{ - "coding":[ - { - "system":"http://highmed.org/fhir/CodeSystem/bpmn-message", - "code":"message-name" - } - ] - }, - "valueString":"requestUpdateResourcesMessage" - }, - { - "type":{ - "coding":[ - { - "system":"http://highmed.org/fhir/CodeSystem/update-resources", - "code":"bundle-reference" - } - ] - }, - "valueReference": { - "reference": "Bundle/31fcdb44-2950-4195-8f5f-89d5dcba812b" - } - }, - { - "type":{ - "coding":[ - { - "system":"http://highmed.org/fhir/CodeSystem/update-resources", - "code":"organization-identifier-search-parameter" - } - ] - }, - "valueString":"http://highmed.org/fhir/NamingSystem/organization-identifier|" - } - ] -} \ No newline at end of file diff --git a/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/resources/update-whitelist-task.example.json b/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/resources/update-whitelist-task.example.json deleted file mode 100755 index 7504fa3c7..000000000 --- a/dsf-bpe/dsf-bpe-process-update-whitelist/src/test/resources/update-whitelist-task.example.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "resourceType":"Task", - "meta":{ - "profile":"http://highmed.org/fhir/StructureDefinition/highmed-task-update-whitelist" - }, - "instantiatesUri":"http://highmed.org/bpe/Process/updateWhiteList/0.1.0", - "status":"requested", - "intent":"order", - "authoredOn":"2019-10-21", - "requester":{ - "identifier":{ - "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", - "value":"Test_Organization" - }, - "type":"Organization" - }, - "restriction":{ - "recipient":[ - { - "identifier":{ - "system":"http://highmed.org/fhir/NamingSystem/organization-identifier", - "value":"Test_Organization" - }, - "type":"Organization" - } - ] - }, - "input":[ - { - "type":{ - "coding":[ - { - "system":"http://highmed.org/fhir/CodeSystem/bpmn-message", - "code":"message-name" - } - ] - }, - "valueString":"updateWhitelistMessage" - } - ] -} \ No newline at end of file From f3186402a8682eee205f944cb6b424f77b1c3d78 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 17 Mar 2020 15:15:17 +0100 Subject: [PATCH 51/55] removed redundant check, better error message --- .../dsf/fhir/authorization/TaskAuthorizationRule.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java index 3a66050de..1bd3ce9c6 100644 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/authorization/TaskAuthorizationRule.java @@ -111,7 +111,7 @@ private Optional<String> newResourceOk(Connection connection, User user, Task ne if (newResource.hasRestriction()) { - if (newResource.getRestriction().hasRecipient() && newResource.getRestriction().getRecipient().size() == 1) + if (newResource.getRestriction().getRecipient().size() == 1) { ResourceReference reference = new ResourceReference("task.restriction.recipient", newResource.getRestriction().getRecipientFirstRep(), Organization.class); @@ -160,7 +160,8 @@ private Optional<String> newResourceOk(Connection connection, User user, Task ne if (getBpmnMessageName(newResource).count() != 1) { errors.add("task.input with system " + CODE_SYSTEM_BPMN_MESSAGE + " and code " - + CODE_SYSTEM_BPMN_MESSAGE_MESSAGE_NAME + " with string value not empty missing"); + + CODE_SYSTEM_BPMN_MESSAGE_MESSAGE_NAME + + " with string value not empty missing or more than one"); } } else From 3bb535b87aa919584aa4d4d4f2f6c92a0cd3d318 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 17 Mar 2020 15:15:49 +0100 Subject: [PATCH 52/55] added null check --- .../org/highmed/fhir/client/FhirWebserviceClientJersey.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java b/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java index 10c6f715c..d4ba1bc89 100755 --- a/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java +++ b/dsf-fhir/dsf-fhir-webservice-client/src/main/java/org/highmed/fhir/client/FhirWebserviceClientJersey.java @@ -556,7 +556,8 @@ public Bundle postBundle(Bundle bundle) private String toString(OperationOutcome outcome) { - return outcome.getIssue().stream().map(i -> toString(i)).collect(Collectors.joining("\n")); + return outcome == null ? "" + : outcome.getIssue().stream().map(i -> toString(i)).collect(Collectors.joining("\n")); } private String toString(OperationOutcomeIssueComponent issue) From 305f17abe0f672ae7e1cc733797f9a8977eeee53 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 17 Mar 2020 15:17:18 +0100 Subject: [PATCH 53/55] added DataFormatExceptionHandler to handle HAPI parsing errors -> 403 Parsing errors now result in a HTTP Status 403 FORBIDDEN. --- .../exception/DataFormatExceptionHandler.java | 48 +++++++++++++++++++ .../fhir/spring/config/WebserviceConfig.java | 7 +++ 2 files changed, 55 insertions(+) create mode 100644 dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/exception/DataFormatExceptionHandler.java diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/exception/DataFormatExceptionHandler.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/exception/DataFormatExceptionHandler.java new file mode 100644 index 000000000..7264eddad --- /dev/null +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/exception/DataFormatExceptionHandler.java @@ -0,0 +1,48 @@ +package org.highmed.dsf.fhir.exception; + +import java.util.Objects; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +import org.highmed.dsf.fhir.help.ResponseGenerator; +import org.hl7.fhir.r4.model.OperationOutcome; +import org.hl7.fhir.r4.model.OperationOutcome.IssueSeverity; +import org.hl7.fhir.r4.model.OperationOutcome.IssueType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; + +import ca.uhn.fhir.parser.DataFormatException; + +@Provider +public class DataFormatExceptionHandler implements ExceptionMapper<DataFormatException>, InitializingBean +{ + private static final Logger logger = LoggerFactory.getLogger(DataFormatExceptionHandler.class); + + private final ResponseGenerator responseGenerator; + + public DataFormatExceptionHandler(ResponseGenerator responseGenerator) + { + this.responseGenerator = responseGenerator; + } + + @Override + public void afterPropertiesSet() throws Exception + { + Objects.requireNonNull(responseGenerator, "responseGenerator"); + } + + @Override + public Response toResponse(DataFormatException exception) + { + logger.warn("Error while parsing resource: {}, returning OperationOutcome with status 403 Forbidden", + exception.getMessage()); + + OperationOutcome outcome = responseGenerator.createOutcome(IssueSeverity.ERROR, IssueType.STRUCTURE, + "Unable to parse resource"); + return Response.status(Status.FORBIDDEN).entity(outcome).build(); + } +} diff --git a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java index 0704ee5e7..b05a34df5 100755 --- a/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java +++ b/dsf-fhir/dsf-fhir-server/src/main/java/org/highmed/dsf/fhir/spring/config/WebserviceConfig.java @@ -1,6 +1,7 @@ package org.highmed.dsf.fhir.spring.config; import org.highmed.dsf.fhir.adapter.HtmlFhirAdapter.ServerBaseProvider; +import org.highmed.dsf.fhir.exception.DataFormatExceptionHandler; import org.highmed.dsf.fhir.webservice.impl.ActivityDefinitionServiceImpl; import org.highmed.dsf.fhir.webservice.impl.BinaryServiceImpl; import org.highmed.dsf.fhir.webservice.impl.BundleServiceImpl; @@ -136,6 +137,12 @@ public ServerBaseProvider serverBaseProvider() return () -> serverBase; } + @Bean + public DataFormatExceptionHandler dataFormatExceptionHandler() + { + return new DataFormatExceptionHandler(helperConfig.responseGenerator()); + } + @Bean public ActivityDefinitionService activityDefinitionService() { From 153ed93668515b8946c42ede17380b02011cd955 Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 17 Mar 2020 15:17:36 +0100 Subject: [PATCH 54/55] additional integration tests --- .../fhir/integration/TaskIntegrationTest.java | 507 ++++++++++++++++++ 1 file changed, 507 insertions(+) diff --git a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java index 5c482061a..f121dd7fb 100755 --- a/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java +++ b/dsf-fhir/dsf-fhir-server/src/test/java/org/highmed/dsf/fhir/integration/TaskIntegrationTest.java @@ -3,10 +3,13 @@ import static junit.framework.TestCase.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.nio.file.Paths; import java.util.Date; +import java.util.EnumSet; import java.util.List; +import java.util.UUID; import java.util.concurrent.BlockingDeque; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.TimeUnit; @@ -16,14 +19,18 @@ import org.highmed.dsf.fhir.authentication.OrganizationProvider; import org.highmed.dsf.fhir.dao.TaskDao; +import org.highmed.fhir.client.FhirWebserviceClient; import org.highmed.fhir.client.WebsocketClient; import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.DomainResource; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.Reference; import org.hl7.fhir.r4.model.StringType; import org.hl7.fhir.r4.model.Task; +import org.hl7.fhir.r4.model.Task.ParameterComponent; import org.hl7.fhir.r4.model.Task.TaskIntent; +import org.hl7.fhir.r4.model.Task.TaskRestrictionComponent; import org.hl7.fhir.r4.model.Task.TaskStatus; import org.junit.Test; @@ -255,4 +262,504 @@ public void testUpdateTaskStartPingProcessStatusInProgressToCompleted() throws E getWebserviceClient().update(created); } + + @Test + public void testCreateForbiddenLocalUserIllegalStatus() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + EnumSet<TaskStatus> illegalCreateStates = EnumSet.of(TaskStatus.RECEIVED, TaskStatus.ACCEPTED, + TaskStatus.REJECTED, TaskStatus.READY, TaskStatus.CANCELLED, TaskStatus.INPROGRESS, TaskStatus.ONHOLD, + TaskStatus.FAILED, TaskStatus.COMPLETED, TaskStatus.ENTEREDINERROR, TaskStatus.NULL); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/0.1.0"); + t.setIntent(TaskIntent.ORDER); + t.setAuthoredOn(new Date()); + Reference localOrg = new Reference(organizationProvider.getLocalOrganization().get()); + t.setRequester(localOrg); + t.getRestriction().addRecipient(localOrg); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("startProcessMessage")); + + t.setStatus(null); + testCreateExpectForbidden(getWebserviceClient(), t); + + for (TaskStatus illegal : illegalCreateStates) + { + t.setStatus(illegal); + testCreateExpectForbidden(getWebserviceClient(), t); + } + } + + @Test + public void testCreateForbiddenExternalUserIllegalStatus() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + EnumSet<TaskStatus> illegalCreateStates = EnumSet.of(TaskStatus.RECEIVED, TaskStatus.ACCEPTED, + TaskStatus.REJECTED, TaskStatus.READY, TaskStatus.CANCELLED, TaskStatus.INPROGRESS, TaskStatus.ONHOLD, + TaskStatus.FAILED, TaskStatus.COMPLETED, TaskStatus.ENTEREDINERROR, TaskStatus.NULL); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-ping"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/pong/0.1.0"); + t.setIntent(TaskIntent.ORDER); + t.setAuthoredOn(new Date()); + Reference requester = new Reference().setType("Organization"); + requester.getIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier") + .setValue("External_Test_Organization"); + t.setRequester(requester); + t.getRestriction().addRecipient(new Reference(organizationProvider.getLocalOrganization().get())); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("pingMessage")); + + t.setStatus(null); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + for (TaskStatus illegal : illegalCreateStates) + { + t.setStatus(illegal); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + } + } + + private void testCreateExpectForbidden(FhirWebserviceClient client, Task task) throws Exception + { + try + { + client.create(task); + fail("WebApplicationException expected"); + } + catch (WebApplicationException e) + { + assertEquals(403, e.getResponse().getStatus()); + } + } + + @Test + public void testCreateForbiddenLocalUserNotPartOfRequesterOrganization() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/0.1.0"); + t.setIntent(TaskIntent.ORDER); + t.setStatus(TaskStatus.DRAFT); + t.setAuthoredOn(new Date()); + Reference localOrg = new Reference(organizationProvider.getLocalOrganization().get()); + t.getRestriction().addRecipient(localOrg); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("startProcessMessage")); + + t.setRequester(null); + testCreateExpectForbidden(getWebserviceClient(), t); + + t.setRequester(new Reference()); + testCreateExpectForbidden(getWebserviceClient(), t); + + Reference requester1 = new Reference().setType("Organization"); + requester1.getIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier") + .setValue("External_Test_Organization"); + t.setRequester(requester1); + testCreateExpectForbidden(getWebserviceClient(), t); + + Reference requester2 = new Reference() + .setReference("http://foo.test/fhir/Organization/" + UUID.randomUUID().toString()); + t.setRequester(requester2); + testCreateExpectForbidden(getWebserviceClient(), t); + } + + @Test + public void testCreateForbiddenExternalUserNotPartOfRequesterOrganization() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-ping"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/pong/0.1.0"); + t.setIntent(TaskIntent.ORDER); + t.setStatus(TaskStatus.DRAFT); + t.setAuthoredOn(new Date()); + t.getRestriction().addRecipient(new Reference(organizationProvider.getLocalOrganization().get())); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("pingMessage")); + + t.setRequester(null); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + t.setRequester(new Reference()); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + Reference requester1 = new Reference() + .setReferenceElement(organizationProvider.getLocalOrganization().get().getIdElement().toVersionless()); + t.setRequester(requester1); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + Reference requester2 = new Reference() + .setReference("http://foo.test/fhir/Organization/" + UUID.randomUUID().toString()); + t.setRequester(requester2); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + } + + @Test + public void testCreateForbiddenLocalUserRestrictionRecipientNotValidByLocalUser() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/0.1.0"); + t.setIntent(TaskIntent.ORDER); + t.setStatus(TaskStatus.DRAFT); + t.setAuthoredOn(new Date()); + Reference localOrg = new Reference(organizationProvider.getLocalOrganization().get()); + t.setRequester(localOrg); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("startProcessMessage")); + + t.setRestriction(null); + testCreateExpectForbidden(getWebserviceClient(), t); + + t.getRestriction().addExtension().setUrl("test"); + testCreateExpectForbidden(getWebserviceClient(), t); + + Reference requester0 = new Reference().setReference("Organization/" + UUID.randomUUID().toString()); + t.setRestriction(new TaskRestrictionComponent()); + t.getRestriction().addRecipient(requester0); + testCreateExpectForbidden(getWebserviceClient(), t); + + Reference requester1 = new Reference().setType("Organization"); + requester1.getIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier") + .setValue("External_Test_Organization"); + t.setRestriction(new TaskRestrictionComponent()); + t.getRestriction().addRecipient(requester1); + testCreateExpectForbidden(getWebserviceClient(), t); + + Reference requester2 = new Reference() + .setReference("http://foo.test/fhir/Organization/" + UUID.randomUUID().toString()); + t.setRestriction(new TaskRestrictionComponent()); + t.getRestriction().addRecipient(requester2); + testCreateExpectForbidden(getWebserviceClient(), t); + + t.setRestriction(new TaskRestrictionComponent()); + t.getRestriction().addRecipient(requester1).addRecipient(requester2); + testCreateExpectForbidden(getWebserviceClient(), t); + + t.setRestriction(new TaskRestrictionComponent()); + t.getRestriction().addRecipient(new Reference(organizationProvider.getLocalOrganization().get())) + .addRecipient(requester0); + testCreateExpectForbidden(getWebserviceClient(), t); + } + + @Test + public void testCreateForbiddenLocalUserRestrictionRecipientNotValidByExternalUser() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-ping"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/pong/0.1.0"); + t.setIntent(TaskIntent.ORDER); + t.setStatus(TaskStatus.DRAFT); + t.setAuthoredOn(new Date()); + Reference requester = new Reference().setType("Organization"); + requester.getIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier") + .setValue("External_Test_Organization"); + t.setRequester(requester); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("pingMessage")); + + t.setRestriction(null); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + t.getRestriction().addExtension().setUrl("test"); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + Reference requester0 = new Reference().setReference("Organization/" + UUID.randomUUID().toString()); + t.setRestriction(new TaskRestrictionComponent()); + t.getRestriction().addRecipient(requester0); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + Reference requester1 = new Reference().setType("Organization"); + requester1.getIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier") + .setValue("External_Test_Organization"); + t.setRestriction(new TaskRestrictionComponent()); + t.getRestriction().addRecipient(requester1); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + Reference requester2 = new Reference() + .setReference("http://foo.test/fhir/Organization/" + UUID.randomUUID().toString()); + t.setRestriction(new TaskRestrictionComponent()); + t.getRestriction().addRecipient(requester2); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + t.setRestriction(new TaskRestrictionComponent()); + t.getRestriction().addRecipient(requester1).addRecipient(requester2); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + t.setRestriction(new TaskRestrictionComponent()); + t.getRestriction().addRecipient(new Reference(organizationProvider.getLocalOrganization().get())) + .addRecipient(requester0); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + } + + @Test + public void testCreateForbiddenInstantiatesUriNotValidByLocalUser() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"); + // t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/0.1.0"); + t.setIntent(TaskIntent.ORDER); + t.setStatus(TaskStatus.DRAFT); + t.setAuthoredOn(new Date()); + Reference localOrg = new Reference(organizationProvider.getLocalOrganization().get()); + t.setRequester(localOrg); + t.getRestriction().addRecipient(localOrg); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("startProcessMessage")); + + t.setInstantiatesUri(null); + testCreateExpectForbidden(getWebserviceClient(), t); + + t.setInstantiatesUri("not-a-valid-pattern"); + testCreateExpectForbidden(getWebserviceClient(), t); + } + + @Test + public void testCreateForbiddenInstantiatesUriNotValidByExternalUser() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-ping"); + // t.setInstantiatesUri("http://highmed.org/bpe/Process/pong/0.1.0"); + t.setIntent(TaskIntent.ORDER); + t.setStatus(TaskStatus.DRAFT); + t.setAuthoredOn(new Date()); + Reference requester = new Reference().setType("Organization"); + requester.getIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier") + .setValue("External_Test_Organization"); + t.setRequester(requester); + Reference localOrg = new Reference(organizationProvider.getLocalOrganization().get()); + t.getRestriction().addRecipient(localOrg); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("pingMessage")); + + t.setInstantiatesUri(null); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + t.setInstantiatesUri("not-a-valid-pattern"); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + } + + @Test + public void testCreateForbiddenInputNotValidByLocalUser() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/0.1.0"); + t.setIntent(TaskIntent.ORDER); + t.setStatus(TaskStatus.DRAFT); + t.setAuthoredOn(new Date()); + Reference localOrg = new Reference(organizationProvider.getLocalOrganization().get()); + t.setRequester(localOrg); + t.getRestriction().addRecipient(localOrg); + // t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + // .setCode("message-name"); + // t.getInputFirstRep().setValue(new StringType("startProcessMessage")); + + t.setInput(null); + testCreateExpectForbidden(getWebserviceClient(), t); + + t.setInput(null); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("system").setCode("code"); + t.getInputFirstRep().setValue(new StringType("value")); + testCreateExpectForbidden(getWebserviceClient(), t); + + t.setInput(null); + ParameterComponent in1 = t.addInput(); + in1.getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + in1.setValue(new StringType("startProcessMessage")); + ParameterComponent in2 = t.addInput(); + in2.getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + in2.setValue(new StringType("startProcessMessage")); + testCreateExpectForbidden(getWebserviceClient(), t); + + t.setInput(null); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + testCreateExpectForbidden(getWebserviceClient(), t); + + t.setInput(null); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode(""); + t.getInputFirstRep().setValue(new StringType("startProcessMessage")); + testCreateExpectForbidden(getWebserviceClient(), t); + + t.setInput(null); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("")); + testCreateExpectForbidden(getWebserviceClient(), t); + + t.setInput(null); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new Coding().setSystem("system").setCode("code")); + testCreateExpectForbidden(getWebserviceClient(), t); + } + + @Test + public void testCreateForbiddenInputNotValidByExternalUser() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-ping"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/pong/0.1.0"); + t.setIntent(TaskIntent.ORDER); + t.setStatus(TaskStatus.DRAFT); + t.setAuthoredOn(new Date()); + Reference requester = new Reference().setType("Organization"); + requester.getIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier") + .setValue("External_Test_Organization"); + t.setRequester(requester); + Reference localOrg = new Reference(organizationProvider.getLocalOrganization().get()); + t.getRestriction().addRecipient(localOrg); + // t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + // .setCode("message-name"); + // t.getInputFirstRep().setValue(new StringType("pingMessage")); + + t.setInput(null); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + t.setInput(null); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("system").setCode("code"); + t.getInputFirstRep().setValue(new StringType("value")); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + t.setInput(null); + ParameterComponent in1 = t.addInput(); + in1.getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + in1.setValue(new StringType("startProcessMessage")); + ParameterComponent in2 = t.addInput(); + in2.getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + in2.setValue(new StringType("startProcessMessage")); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + t.setInput(null); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + t.setInput(null); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode(""); + t.getInputFirstRep().setValue(new StringType("pingMessage")); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + t.setInput(null); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("")); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + + t.setInput(null); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new Coding().setSystem("system").setCode("code")); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + } + + @Test + public void testCreateForbiddenOutputNotValidByLocalUser() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-start-process"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/ping/0.1.0"); + t.setIntent(TaskIntent.ORDER); + t.setStatus(TaskStatus.DRAFT); + t.setAuthoredOn(new Date()); + Reference localOrg = new Reference(organizationProvider.getLocalOrganization().get()); + t.setRequester(localOrg); + t.getRestriction().addRecipient(localOrg); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("startProcessMessage")); + + t.getOutputFirstRep().getType().getCodingFirstRep().setSystem("system").setCode("code"); + t.getOutputFirstRep().setValue(new StringType("value")); + testCreateExpectForbidden(getWebserviceClient(), t); + } + + @Test + public void testCreateForbiddenOutputNotValidByExternalUser() throws Exception + { + OrganizationProvider organizationProvider = getSpringWebApplicationContext() + .getBean(OrganizationProvider.class); + assertNotNull(organizationProvider); + + Task t = new Task(); + t.getMeta().addProfile("http://highmed.org/fhir/StructureDefinition/highmed-task-ping"); + t.setInstantiatesUri("http://highmed.org/bpe/Process/pong/0.1.0"); + t.setIntent(TaskIntent.ORDER); + t.setStatus(TaskStatus.DRAFT); + t.setAuthoredOn(new Date()); + Reference requester = new Reference().setType("Organization"); + requester.getIdentifier().setSystem("http://highmed.org/fhir/NamingSystem/organization-identifier") + .setValue("External_Test_Organization"); + t.setRequester(requester); + Reference localOrg = new Reference(organizationProvider.getLocalOrganization().get()); + t.getRestriction().addRecipient(localOrg); + t.getInputFirstRep().getType().getCodingFirstRep().setSystem("http://highmed.org/fhir/CodeSystem/bpmn-message") + .setCode("message-name"); + t.getInputFirstRep().setValue(new StringType("pingMessage")); + + t.getOutputFirstRep().getType().getCodingFirstRep().setSystem("system").setCode("code"); + t.getOutputFirstRep().setValue(new StringType("value")); + testCreateExpectForbidden(getExternalWebserviceClient(), t); + } } From d7054f4a128ddda04947daeab63edfb756eea15f Mon Sep 17 00:00:00 2001 From: Hauke Hund <hauke.hund@hs-heilbronn.de> Date: Tue, 17 Mar 2020 18:15:28 +0100 Subject: [PATCH 55/55] camunda upgrade 7.11 to 7.12 --- ...stgres_engine_7.11.0.sql => postgres_engine_7.12.0.sql} | 7 ++++++- ...es_identity_7.11.0.sql => postgres_identity_7.12.0.sql} | 0 .../resources/db/db.camunda_engine.changelog-0.1.0.xml | 2 +- .../resources/db/db.camunda_identity.changelog-0.1.0.xml | 2 +- dsf-bpe/pom.xml | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) rename dsf-bpe/dsf-bpe-server/src/main/resources/db/camunda/{postgres_engine_7.11.0.sql => postgres_engine_7.12.0.sql} (99%) rename dsf-bpe/dsf-bpe-server/src/main/resources/db/camunda/{postgres_identity_7.11.0.sql => postgres_identity_7.12.0.sql} (100%) diff --git a/dsf-bpe/dsf-bpe-server/src/main/resources/db/camunda/postgres_engine_7.11.0.sql b/dsf-bpe/dsf-bpe-server/src/main/resources/db/camunda/postgres_engine_7.12.0.sql similarity index 99% rename from dsf-bpe/dsf-bpe-server/src/main/resources/db/camunda/postgres_engine_7.11.0.sql rename to dsf-bpe/dsf-bpe-server/src/main/resources/db/camunda/postgres_engine_7.12.0.sql index 511de9289..f9c8e2f41 100644 --- a/dsf-bpe/dsf-bpe-server/src/main/resources/db/camunda/postgres_engine_7.11.0.sql +++ b/dsf-bpe/dsf-bpe-server/src/main/resources/db/camunda/postgres_engine_7.12.0.sql @@ -63,7 +63,7 @@ create table ACT_GE_SCHEMA_LOG ( ); insert into ACT_GE_SCHEMA_LOG -values ('0', CURRENT_TIMESTAMP, '7.11.0'); +values ('0', CURRENT_TIMESTAMP, '7.12.0'); create table ACT_RE_DEPLOYMENT ( ID_ varchar(64), @@ -114,6 +114,7 @@ create table ACT_RU_JOB ( EXCEPTION_MSG_ varchar(4000), DUEDATE_ timestamp, REPEAT_ varchar(255), + REPEAT_OFFSET_ bigint DEFAULT 0, HANDLER_TYPE_ varchar(255), HANDLER_CFG_ varchar(4000), DEPLOYMENT_ID_ varchar(64), @@ -971,6 +972,7 @@ create table ACT_HI_OP_LOG ( REMOVAL_TIME_ timestamp, CATEGORY_ varchar(64), EXTERNAL_TASK_ID_ varchar(64), + ANNOTATION_ varchar(4000), primary key (ID_) ); @@ -989,6 +991,7 @@ create table ACT_HI_INCIDENT ( CAUSE_INCIDENT_ID_ varchar(64), ROOT_CAUSE_INCIDENT_ID_ varchar(64), CONFIGURATION_ varchar(255), + HISTORY_CONFIGURATION_ varchar(255), INCIDENT_STATE_ integer, TENANT_ID_ varchar(64), JOB_DEF_ID_ varchar(64), @@ -1104,6 +1107,7 @@ create index ACT_IDX_HI_DETAIL_PROC_DEF_KEY on ACT_HI_DETAIL(PROC_DEF_KEY_); create index ACT_IDX_HI_DETAIL_BYTEAR on ACT_HI_DETAIL(BYTEARRAY_ID_); create index ACT_IDX_HI_DETAIL_RM_TIME on ACT_HI_DETAIL(REMOVAL_TIME_); create index ACT_IDX_HI_DETAIL_TASK_BYTEAR on ACT_HI_DETAIL(BYTEARRAY_ID_, TASK_ID_); +create index ACT_IDX_HI_DETAIL_VAR_INST_ID on ACT_HI_DETAIL(VAR_INST_ID_); create index ACT_IDX_HI_IDENT_LNK_ROOT_PI on ACT_HI_IDENTITYLINK(ROOT_PROC_INST_ID_); create index ACT_IDX_HI_IDENT_LNK_USER on ACT_HI_IDENTITYLINK(USER_ID_); @@ -1137,6 +1141,7 @@ create index ACT_IDX_HI_JOB_LOG_JOB_DEF_ID on ACT_HI_JOB_LOG(JOB_DEF_ID_); create index ACT_IDX_HI_JOB_LOG_PROC_DEF_KEY on ACT_HI_JOB_LOG(PROCESS_DEF_KEY_); create index ACT_IDX_HI_JOB_LOG_EX_STACK on ACT_HI_JOB_LOG(JOB_EXCEPTION_STACK_ID_); create index ACT_IDX_HI_JOB_LOG_RM_TIME on ACT_HI_JOB_LOG(REMOVAL_TIME_); +create index ACT_IDX_HI_JOB_LOG_JOB_CONF on ACT_HI_JOB_LOG(JOB_DEF_CONFIGURATION_); create index ACT_HI_BAT_RM_TIME on ACT_HI_BATCH(REMOVAL_TIME_); diff --git a/dsf-bpe/dsf-bpe-server/src/main/resources/db/camunda/postgres_identity_7.11.0.sql b/dsf-bpe/dsf-bpe-server/src/main/resources/db/camunda/postgres_identity_7.12.0.sql similarity index 100% rename from dsf-bpe/dsf-bpe-server/src/main/resources/db/camunda/postgres_identity_7.11.0.sql rename to dsf-bpe/dsf-bpe-server/src/main/resources/db/camunda/postgres_identity_7.12.0.sql diff --git a/dsf-bpe/dsf-bpe-server/src/main/resources/db/db.camunda_engine.changelog-0.1.0.xml b/dsf-bpe/dsf-bpe-server/src/main/resources/db/db.camunda_engine.changelog-0.1.0.xml index 16cd681c2..a8a78757b 100644 --- a/dsf-bpe/dsf-bpe-server/src/main/resources/db/db.camunda_engine.changelog-0.1.0.xml +++ b/dsf-bpe/dsf-bpe-server/src/main/resources/db/db.camunda_engine.changelog-0.1.0.xml @@ -6,7 +6,7 @@ http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> <changeSet author="camunda.org" id="db.camunda_engine.changelog-0.1.0"> - <sqlFile dbms="postgresql" encoding="utf8" path="db/camunda/postgres_engine_7.11.0.sql" /> + <sqlFile dbms="postgresql" encoding="utf8" path="db/camunda/postgres_engine_7.12.0.sql" /> <sql dbms="postgresql"> GRANT ALL ON TABLE ACT_GE_SCHEMA_LOG TO ${db.liquibase_user}; diff --git a/dsf-bpe/dsf-bpe-server/src/main/resources/db/db.camunda_identity.changelog-0.1.0.xml b/dsf-bpe/dsf-bpe-server/src/main/resources/db/db.camunda_identity.changelog-0.1.0.xml index 6605dd7df..047744615 100644 --- a/dsf-bpe/dsf-bpe-server/src/main/resources/db/db.camunda_identity.changelog-0.1.0.xml +++ b/dsf-bpe/dsf-bpe-server/src/main/resources/db/db.camunda_identity.changelog-0.1.0.xml @@ -6,7 +6,7 @@ http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> <changeSet author="camunda.org" id="db.camunda_identity.changelog-0.1.0"> - <sqlFile dbms="postgresql" encoding="utf8" path="db/camunda/postgres_identity_7.11.0.sql" /> + <sqlFile dbms="postgresql" encoding="utf8" path="db/camunda/postgres_identity_7.12.0.sql" /> <sql dbms="postgresql"> GRANT ALL ON TABLE ACT_ID_GROUP TO ${db.liquibase_user}; diff --git a/dsf-bpe/pom.xml b/dsf-bpe/pom.xml index 828f57891..862c1c6c9 100755 --- a/dsf-bpe/pom.xml +++ b/dsf-bpe/pom.xml @@ -25,7 +25,7 @@ <properties> <!-- if upgrading, copy version specific camunda sql scripts to dsf-bpe-server/src/main/resource/db/camunda and create a corresponding liquibase migration script --> - <camunda.version>7.11.0</camunda.version> + <camunda.version>7.12.0</camunda.version> </properties> <repositories>