getFlags() {
+ return Collections.unmodifiableSet(myFlags);
+ }
+
+ /**
+ * This property configures any flags affecting how authorization is
+ * applied. By default no flags are applied.
+ *
+ * @param theFlags The flags (must not be null)
+ * @see #setFlags(Collection)
+ */
+ public AuthorizationInterceptor setFlags(AuthorizationFlagsEnum... theFlags) {
+ Validate.notNull(theFlags, "theFlags must not be null");
+ return setFlags(Lists.newArrayList(theFlags));
+ }
+
/**
* Handle an access control verdict of {@link PolicyEnum#DENY}.
*
@@ -325,6 +350,19 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
handleUserOperation(theRequest, theNewResource, RestOperationTypeEnum.UPDATE);
}
+ /**
+ * This property configures any flags affecting how authorization is
+ * applied. By default no flags are applied.
+ *
+ * @param theFlags The flags (must not be null)
+ * @see #setFlags(AuthorizationFlagsEnum...)
+ */
+ public AuthorizationInterceptor setFlags(Collection theFlags) {
+ Validate.notNull(theFlags, "theFlags must not be null");
+ myFlags = new HashSet<>(theFlags);
+ return this;
+ }
+
private static UnsupportedOperationException failForDstu1() {
return new UnsupportedOperationException("Use of this interceptor on DSTU1 servers is not supportd");
}
@@ -333,7 +371,7 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
if (theResponseObject == null) {
return Collections.emptyList();
}
-
+
List retVal;
boolean isContainer = false;
@@ -342,11 +380,11 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
} else if (theResponseObject instanceof IBaseParameters) {
isContainer = true;
}
-
+
if (!isContainer) {
return Collections.singletonList(theResponseObject);
}
-
+
retVal = fhirContext.newTerser().getAllPopulatedChildElementsOfType(theResponseObject, IBaseResource.class);
// Exclude the container
diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/IAuthRule.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/IAuthRule.java
index 9c6cf5db261..8f19e384c5a 100644
--- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/IAuthRule.java
+++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/IAuthRule.java
@@ -27,6 +27,15 @@ import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor.Verdict;
+import java.util.Set;
+
+/**
+ * Note: At this time, this interface is considered internal API to HAPI FHIR,
+ * and is subject to change without warning. Create your own implementations at
+ * your own risk. If you have use cases that are not met by the current
+ * implementation, please consider raising them on the HAPI FHIR
+ * Google Group.
+ */
public interface IAuthRule {
/**
@@ -44,9 +53,10 @@ public interface IAuthRule {
* @param theRuleApplier
* The rule applying module (this can be used by rules to apply the rule set to
* nested objects in the request, such as nested requests in a transaction)
+ * @param theFlags
* @return Returns a policy decision, or null
if the rule does not apply
*/
- Verdict applyRule(RestOperationTypeEnum theOperation, RequestDetails theRequestDetails, IBaseResource theInputResource, IIdType theInputResourceId, IBaseResource theOutputResource, IRuleApplier theRuleApplier);
+ Verdict applyRule(RestOperationTypeEnum theOperation, RequestDetails theRequestDetails, IBaseResource theInputResource, IIdType theInputResourceId, IBaseResource theOutputResource, IRuleApplier theRuleApplier, Set theFlags);
/**
* Returns a name for this rule, to be used in logs and error messages
diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/OperationRule.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/OperationRule.java
index bd80964f966..e9571bb555d 100644
--- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/OperationRule.java
+++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/OperationRule.java
@@ -29,10 +29,11 @@ import org.hl7.fhir.instance.model.api.IIdType;
import java.util.HashSet;
import java.util.List;
+import java.util.Set;
class OperationRule extends BaseRule implements IAuthRule {
- private RuleBuilder.ITenantApplicabilityChecker myTenentApplicabilityChecker;
+ private RuleBuilder.ITenantApplicabilityChecker myTenantApplicabilityChecker;
private String myOperationName;
private boolean myAppliesToServer;
private HashSet> myAppliesToTypes;
@@ -75,17 +76,25 @@ class OperationRule extends BaseRule implements IAuthRule {
}
@Override
- public Verdict applyRule(RestOperationTypeEnum theOperation, RequestDetails theRequestDetails, IBaseResource theInputResource, IIdType theInputResourceId, IBaseResource theOutputResource, IRuleApplier theRuleApplier) {
+ public Verdict applyRule(RestOperationTypeEnum theOperation, RequestDetails theRequestDetails, IBaseResource theInputResource, IIdType theInputResourceId, IBaseResource theOutputResource, IRuleApplier theRuleApplier, Set theFlags) {
FhirContext ctx = theRequestDetails.getServer().getFhirContext();
- if (myTenentApplicabilityChecker != null) {
- if (!myTenentApplicabilityChecker.applies(theRequestDetails)) {
+ if (myTenantApplicabilityChecker != null) {
+ if (!myTenantApplicabilityChecker.applies(theRequestDetails)) {
return null;
}
}
boolean applies = false;
switch (theOperation) {
+ case ADD_TAGS:
+ case DELETE_TAGS:
+ case GET_TAGS:
+ case GET_PAGE:
+ case GRAPHQL_REQUEST:
+ // These things can't be tracked by the AuthorizationInterceptor
+ // at this time
+ return null;
case EXTENDED_OPERATION_SERVER:
if (myAppliesToServer || myAppliesAtAnyLevel) {
applies = true;
@@ -130,6 +139,40 @@ class OperationRule extends BaseRule implements IAuthRule {
}
}
break;
+ case CREATE:
+ break;
+ case DELETE:
+ break;
+ case HISTORY_INSTANCE:
+ break;
+ case HISTORY_SYSTEM:
+ break;
+ case HISTORY_TYPE:
+ break;
+ case READ:
+ break;
+ case SEARCH_SYSTEM:
+ break;
+ case SEARCH_TYPE:
+ break;
+ case TRANSACTION:
+ break;
+ case UPDATE:
+ break;
+ case VALIDATE:
+ break;
+ case VREAD:
+ break;
+ case METADATA:
+ break;
+ case META_ADD:
+ break;
+ case META:
+ break;
+ case META_DELETE:
+ break;
+ case PATCH:
+ break;
default:
return null;
}
@@ -160,8 +203,8 @@ class OperationRule extends BaseRule implements IAuthRule {
myOperationName = theOperationName;
}
- public void setTenentApplicabilityChecker(RuleBuilder.ITenantApplicabilityChecker theTenentApplicabilityChecker) {
- myTenentApplicabilityChecker = theTenentApplicabilityChecker;
+ public void setTenantApplicabilityChecker(RuleBuilder.ITenantApplicabilityChecker theTenantApplicabilityChecker) {
+ myTenantApplicabilityChecker = theTenantApplicabilityChecker;
}
}
diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleBuilder.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleBuilder.java
index 052784c9a91..81d523e1e0c 100644
--- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleBuilder.java
+++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleBuilder.java
@@ -174,7 +174,7 @@ public class RuleBuilder implements IAuthRuleBuilder {
myOpRule.setTenantApplicabilityChecker(myTenantApplicabilityChecker);
}
if (myOperationRule != null) {
- myOperationRule.setTenentApplicabilityChecker(myTenantApplicabilityChecker);
+ myOperationRule.setTenantApplicabilityChecker(myTenantApplicabilityChecker);
}
}
diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleImplConditional.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleImplConditional.java
index 60695803f6f..7b9ac8140d6 100644
--- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleImplConditional.java
+++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleImplConditional.java
@@ -41,7 +41,7 @@ public class RuleImplConditional extends BaseRule implements IAuthRule {
@Override
public Verdict applyRule(RestOperationTypeEnum theOperation, RequestDetails theRequestDetails, IBaseResource theInputResource, IIdType theInputResourceId, IBaseResource theOutputResource,
- IRuleApplier theRuleApplier) {
+ IRuleApplier theRuleApplier, Set theFlags) {
if (theInputResourceId != null) {
return null;
diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleImplOp.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleImplOp.java
index 6605793bbaa..327f5d10584 100644
--- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleImplOp.java
+++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleImplOp.java
@@ -1,5 +1,28 @@
package ca.uhn.fhir.rest.server.interceptor.auth;
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.context.RuntimeResourceDefinition;
+import ca.uhn.fhir.context.RuntimeSearchParam;
+import ca.uhn.fhir.rest.api.RequestTypeEnum;
+import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
+import ca.uhn.fhir.rest.api.server.RequestDetails;
+import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
+import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor.Verdict;
+import ca.uhn.fhir.util.BundleUtil;
+import ca.uhn.fhir.util.BundleUtil.BundleEntryParts;
+import ca.uhn.fhir.util.FhirTerser;
+import org.apache.commons.codec.binary.StringUtils;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.hl7.fhir.instance.model.api.IBaseBundle;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.instance.model.api.IIdType;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
import static org.apache.commons.lang3.StringUtils.isNotBlank;
/*
@@ -11,9 +34,9 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -22,26 +45,6 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
* #L%
*/
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-import org.hl7.fhir.instance.model.api.IBaseBundle;
-import org.hl7.fhir.instance.model.api.IBaseResource;
-import org.hl7.fhir.instance.model.api.IIdType;
-
-import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.context.RuntimeResourceDefinition;
-import ca.uhn.fhir.rest.api.*;
-import ca.uhn.fhir.rest.api.server.RequestDetails;
-import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
-import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor.Verdict;
-import ca.uhn.fhir.util.BundleUtil;
-import ca.uhn.fhir.util.BundleUtil.BundleEntryParts;
-import ca.uhn.fhir.util.FhirTerser;
-
class RuleImplOp extends BaseRule /* implements IAuthRule */ {
private AppliesTypeEnum myAppliesTo;
@@ -54,13 +57,16 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ {
private List myAppliesToInstances;
private RuleBuilder.ITenantApplicabilityChecker myTenantApplicabilityChecker;
+ /**
+ * Constructor
+ */
public RuleImplOp(String theRuleName) {
super(theRuleName);
}
@Override
public Verdict applyRule(RestOperationTypeEnum theOperation, RequestDetails theRequestDetails, IBaseResource theInputResource, IIdType theInputResourceId, IBaseResource theOutputResource,
- IRuleApplier theRuleApplier) {
+ IRuleApplier theRuleApplier, Set theFlags) {
if (myTenantApplicabilityChecker != null) {
if (!myTenantApplicabilityChecker.applies(theRequestDetails)) {
@@ -73,232 +79,327 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ {
IBaseResource appliesToResource;
IIdType appliesToResourceId = null;
String appliesToResourceType = null;
+ Map appliesToSearchParams = null;
switch (myOp) {
- case READ:
- if (theOutputResource == null) {
- switch (theOperation) {
- case READ:
- case VREAD:
- appliesToResourceId = theInputResourceId;
- appliesToResourceType = theInputResourceId.getResourceType();
- break;
- case SEARCH_SYSTEM:
- case SEARCH_TYPE:
- case HISTORY_INSTANCE:
- case HISTORY_SYSTEM:
- case HISTORY_TYPE:
+ case READ:
+ if (theOutputResource == null) {
if (!applyTesters(theOperation, theRequestDetails, theInputResourceId, theInputResource, theOutputResource)) {
return null;
}
- return new Verdict(PolicyEnum.ALLOW, this);
- default:
- return null;
+
+ switch (theOperation) {
+ case READ:
+ case VREAD:
+ appliesToResourceId = theInputResourceId;
+ appliesToResourceType = theInputResourceId.getResourceType();
+ break;
+ case SEARCH_SYSTEM:
+ case HISTORY_SYSTEM:
+ if (theFlags.contains(AuthorizationFlagsEnum.NO_NOT_PROACTIVELY_BLOCK_COMPARTMENT_READ_ACCESS)) {
+ return new Verdict(PolicyEnum.ALLOW, this);
+ }
+ break;
+ case SEARCH_TYPE:
+ if (theFlags.contains(AuthorizationFlagsEnum.NO_NOT_PROACTIVELY_BLOCK_COMPARTMENT_READ_ACCESS)) {
+ return new Verdict(PolicyEnum.ALLOW, this);
+ }
+ appliesToResourceType = theRequestDetails.getResourceName();
+ appliesToSearchParams = theRequestDetails.getParameters();
+ break;
+ case HISTORY_TYPE:
+ if (theFlags.contains(AuthorizationFlagsEnum.NO_NOT_PROACTIVELY_BLOCK_COMPARTMENT_READ_ACCESS)) {
+ return new Verdict(PolicyEnum.ALLOW, this);
+ }
+ appliesToResourceType = theRequestDetails.getResourceName();
+ break;
+ case HISTORY_INSTANCE:
+ if (theFlags.contains(AuthorizationFlagsEnum.NO_NOT_PROACTIVELY_BLOCK_COMPARTMENT_READ_ACCESS)) {
+ return new Verdict(PolicyEnum.ALLOW, this);
+ }
+ appliesToResourceId = theInputResourceId;
+ break;
+ case GET_PAGE:
+ return new Verdict(PolicyEnum.ALLOW, this);
+
+ // None of the following are checked on the way in
+ case ADD_TAGS:
+ case DELETE_TAGS:
+ case GET_TAGS:
+ case GRAPHQL_REQUEST:
+ case EXTENDED_OPERATION_SERVER:
+ case EXTENDED_OPERATION_TYPE:
+ case EXTENDED_OPERATION_INSTANCE:
+ case CREATE:
+ case DELETE:
+ case TRANSACTION:
+ case UPDATE:
+ case VALIDATE:
+ case METADATA:
+ case META_ADD:
+ case META:
+ case META_DELETE:
+ case PATCH:
+ default:
+ return null;
+ }
+ }
+ appliesToResource = theOutputResource;
+ if (theOutputResource != null) {
+ appliesToResourceId = theOutputResource.getIdElement();
}
- }
- appliesToResource = theOutputResource;
- if (theOutputResource != null) {
- appliesToResourceId = theOutputResource.getIdElement();
- }
- break;
- case WRITE:
- if (theInputResource == null && theInputResourceId == null) {
- return null;
- }
- switch (theOperation) {
- case CREATE:
- case UPDATE:
- case ADD_TAGS:
- case DELETE_TAGS:
- case META_ADD:
- case META_DELETE:
- case PATCH:
- appliesToResource = theInputResource;
- appliesToResourceId = theInputResourceId;
break;
- default:
- return null;
- }
- break;
- case DELETE:
- if (theOperation == RestOperationTypeEnum.DELETE) {
- if (theInputResource == null) {
- return newVerdict();
- }
- appliesToResource = theInputResource;
- } else {
- return null;
- }
- break;
- case BATCH:
- case TRANSACTION:
- if (!(theOperation == RestOperationTypeEnum.TRANSACTION)) {
- return null;
- }
- if (theInputResource != null && requestAppliesToTransaction(ctx, myOp, theInputResource)) {
- if (getMode() == PolicyEnum.DENY) {
- return new Verdict(PolicyEnum.DENY, this);
- }
- List inputResources = BundleUtil.toListOfEntries(ctx, (IBaseBundle) theInputResource);
- Verdict verdict = null;
- for (BundleEntryParts nextPart : inputResources) {
-
- IBaseResource inputResource = nextPart.getResource();
- RestOperationTypeEnum operation = null;
- if (nextPart.getRequestType() == RequestTypeEnum.GET) {
- continue;
- }
- if (nextPart.getRequestType() == RequestTypeEnum.POST) {
- operation = RestOperationTypeEnum.CREATE;
- } else if (nextPart.getRequestType() == RequestTypeEnum.PUT) {
- operation = RestOperationTypeEnum.UPDATE;
- } else {
- throw new InvalidRequestException("Can not handle transaction with operation of type " + nextPart.getRequestType());
- }
-
- /*
- * This is basically just being conservative - Be careful of transactions containing
- * nested operations and nested transactions. We block the by default. At some point
- * it would be nice to be more nuanced here.
- */
- RuntimeResourceDefinition resourceDef = ctx.getResourceDefinition(nextPart.getResource());
- if ("Parameters".equals(resourceDef.getName()) || "Bundle".equals(resourceDef.getName())) {
- throw new InvalidRequestException("Can not handle transaction with nested resource of type " + resourceDef.getName());
- }
-
- Verdict newVerdict = theRuleApplier.applyRulesAndReturnDecision(operation, theRequestDetails, inputResource, null, null);
- if (newVerdict == null) {
- continue;
- } else if (verdict == null) {
- verdict = newVerdict;
- } else if (verdict.getDecision() == PolicyEnum.ALLOW && newVerdict.getDecision() == PolicyEnum.DENY) {
- verdict = newVerdict;
- }
- }
- return verdict;
- } else if (theOutputResource != null) {
-
- List outputResources = AuthorizationInterceptor.toListOfResourcesAndExcludeContainer(theOutputResource, theRequestDetails.getFhirContext());
-
- Verdict verdict = null;
- for (IBaseResource nextResource : outputResources) {
- if (nextResource == null) {
- continue;
- }
- Verdict newVerdict = theRuleApplier.applyRulesAndReturnDecision(RestOperationTypeEnum.READ, theRequestDetails, null, null, nextResource);
- if (newVerdict == null) {
- continue;
- } else if (verdict == null) {
- verdict = newVerdict;
- } else if (verdict.getDecision() == PolicyEnum.ALLOW && newVerdict.getDecision() == PolicyEnum.DENY) {
- verdict = newVerdict;
- }
- }
- return verdict;
- } else {
- return null;
- }
- case ALLOW_ALL:
- if (!applyTesters(theOperation, theRequestDetails, theInputResourceId, theInputResource, theOutputResource)) {
- return null;
- }
- return new Verdict(PolicyEnum.ALLOW, this);
- case DENY_ALL:
- if (!applyTesters(theOperation, theRequestDetails, theInputResourceId, theInputResource, theOutputResource)) {
- return null;
- }
- return new Verdict(PolicyEnum.DENY, this);
- case METADATA:
- if (theOperation == RestOperationTypeEnum.METADATA) {
- if (!applyTesters(theOperation, theRequestDetails, theInputResourceId, theInputResource, theOutputResource)) {
+ case WRITE:
+ if (theInputResource == null && theInputResourceId == null) {
return null;
}
- return newVerdict();
- }
- return null;
- default:
- // Should not happen
- throw new IllegalStateException("Unable to apply security to event of type " + theOperation);
- }
+ switch (theOperation) {
+ case CREATE:
+ case UPDATE:
+ case ADD_TAGS:
+ case DELETE_TAGS:
+ case META_ADD:
+ case META_DELETE:
+ case PATCH:
+ appliesToResource = theInputResource;
+ appliesToResourceId = theInputResourceId;
+ break;
+ default:
+ return null;
+ }
+ break;
+ case DELETE:
+ if (theOperation == RestOperationTypeEnum.DELETE) {
+ if (theInputResource == null) {
+ return newVerdict();
+ }
+ appliesToResource = theInputResource;
+ } else {
+ return null;
+ }
+ break;
+ case BATCH:
+ case TRANSACTION:
+ if (!(theOperation == RestOperationTypeEnum.TRANSACTION)) {
+ return null;
+ }
+ if (theInputResource != null && requestAppliesToTransaction(ctx, myOp, theInputResource)) {
+ if (getMode() == PolicyEnum.DENY) {
+ return new Verdict(PolicyEnum.DENY, this);
+ }
+ List inputResources = BundleUtil.toListOfEntries(ctx, (IBaseBundle) theInputResource);
+ Verdict verdict = null;
+ for (BundleEntryParts nextPart : inputResources) {
- switch (myAppliesTo) {
- case INSTANCES:
- if (appliesToResourceId != null) {
- for (IIdType next : myAppliesToInstances) {
- if (isNotBlank(next.getResourceType())) {
- if (!next.getResourceType().equals(appliesToResourceId.getResourceType())) {
+ IBaseResource inputResource = nextPart.getResource();
+ RestOperationTypeEnum operation = null;
+ if (nextPart.getRequestType() == RequestTypeEnum.GET) {
continue;
}
+ if (nextPart.getRequestType() == RequestTypeEnum.POST) {
+ operation = RestOperationTypeEnum.CREATE;
+ } else if (nextPart.getRequestType() == RequestTypeEnum.PUT) {
+ operation = RestOperationTypeEnum.UPDATE;
+ } else {
+ throw new InvalidRequestException("Can not handle transaction with operation of type " + nextPart.getRequestType());
+ }
+
+ /*
+ * This is basically just being conservative - Be careful of transactions containing
+ * nested operations and nested transactions. We block the by default. At some point
+ * it would be nice to be more nuanced here.
+ */
+ RuntimeResourceDefinition resourceDef = ctx.getResourceDefinition(nextPart.getResource());
+ if ("Parameters".equals(resourceDef.getName()) || "Bundle".equals(resourceDef.getName())) {
+ throw new InvalidRequestException("Can not handle transaction with nested resource of type " + resourceDef.getName());
+ }
+
+ Verdict newVerdict = theRuleApplier.applyRulesAndReturnDecision(operation, theRequestDetails, inputResource, null, null);
+ if (newVerdict == null) {
+ continue;
+ } else if (verdict == null) {
+ verdict = newVerdict;
+ } else if (verdict.getDecision() == PolicyEnum.ALLOW && newVerdict.getDecision() == PolicyEnum.DENY) {
+ verdict = newVerdict;
+ }
}
- if (!next.getIdPart().equals(appliesToResourceId.getIdPart())) {
- continue;
+ return verdict;
+ } else if (theOutputResource != null) {
+
+ List outputResources = AuthorizationInterceptor.toListOfResourcesAndExcludeContainer(theOutputResource, theRequestDetails.getFhirContext());
+
+ Verdict verdict = null;
+ for (IBaseResource nextResource : outputResources) {
+ if (nextResource == null) {
+ continue;
+ }
+ Verdict newVerdict = theRuleApplier.applyRulesAndReturnDecision(RestOperationTypeEnum.READ, theRequestDetails, null, null, nextResource);
+ if (newVerdict == null) {
+ continue;
+ } else if (verdict == null) {
+ verdict = newVerdict;
+ } else if (verdict.getDecision() == PolicyEnum.ALLOW && newVerdict.getDecision() == PolicyEnum.DENY) {
+ verdict = newVerdict;
+ }
}
- if (!applyTesters(theOperation, theRequestDetails, theInputResourceId, theInputResource, theOutputResource)) {
- return null;
- }
- return newVerdict();
+ return verdict;
+ } else {
+ return null;
}
- }
- return null;
- case ALL_RESOURCES:
- if (appliesToResourceType != null) {
+ case ALLOW_ALL:
if (!applyTesters(theOperation, theRequestDetails, theInputResourceId, theInputResource, theOutputResource)) {
return null;
}
return new Verdict(PolicyEnum.ALLOW, this);
- }
- break;
- case TYPES:
- if (appliesToResource != null) {
- if (myAppliesToTypes.contains(appliesToResource.getClass()) == false) {
+ case DENY_ALL:
+ if (!applyTesters(theOperation, theRequestDetails, theInputResourceId, theInputResource, theOutputResource)) {
return null;
}
- }
- if (appliesToResourceId != null && appliesToResourceId.hasResourceType()) {
- Class extends IBaseResource> type = theRequestDetails.getServer().getFhirContext().getResourceDefinition(appliesToResourceId.getResourceType()).getImplementingClass();
- if (myAppliesToTypes.contains(type) == false) {
- return null;
- }
- }
- if (appliesToResourceType != null) {
- Class extends IBaseResource> type = theRequestDetails.getServer().getFhirContext().getResourceDefinition(appliesToResourceType).getImplementingClass();
- if (myAppliesToTypes.contains(type)) {
+ return new Verdict(PolicyEnum.DENY, this);
+ case METADATA:
+ if (theOperation == RestOperationTypeEnum.METADATA) {
if (!applyTesters(theOperation, theRequestDetails, theInputResourceId, theInputResource, theOutputResource)) {
return null;
}
- return new Verdict(PolicyEnum.ALLOW, this);
+ return newVerdict();
}
- }
- break;
- default:
- throw new IllegalStateException("Unable to apply security to event of applies to type " + myAppliesTo);
+ return null;
+ default:
+ // Should not happen
+ throw new IllegalStateException("Unable to apply security to event of type " + theOperation);
+ }
+
+ switch (myAppliesTo) {
+ case INSTANCES:
+ if (appliesToResourceId != null) {
+ for (IIdType next : myAppliesToInstances) {
+ if (isNotBlank(next.getResourceType())) {
+ if (!next.getResourceType().equals(appliesToResourceId.getResourceType())) {
+ continue;
+ }
+ }
+ if (!next.getIdPart().equals(appliesToResourceId.getIdPart())) {
+ continue;
+ }
+ if (!applyTesters(theOperation, theRequestDetails, theInputResourceId, theInputResource, theOutputResource)) {
+ return null;
+ }
+ return newVerdict();
+ }
+ }
+ return null;
+ case ALL_RESOURCES:
+ if (appliesToResourceType != null) {
+ if (!applyTesters(theOperation, theRequestDetails, theInputResourceId, theInputResource, theOutputResource)) {
+ return null;
+ }
+ if (myClassifierType == ClassifierTypeEnum.ANY_ID) {
+ return new Verdict(PolicyEnum.ALLOW, this);
+ }
+ }
+ break;
+ case TYPES:
+ if (appliesToResource != null) {
+ if (myClassifierType == ClassifierTypeEnum.ANY_ID) {
+ if (myAppliesToTypes.contains(appliesToResource.getClass()) == false) {
+ return null;
+ }
+ }
+ }
+// if (myClassifierType == ClassifierTypeEnum.ANY_ID) {
+ if (appliesToResourceId != null && appliesToResourceId.hasResourceType()) {
+ Class extends IBaseResource> type = theRequestDetails.getServer().getFhirContext().getResourceDefinition(appliesToResourceId.getResourceType()).getImplementingClass();
+ if (myAppliesToTypes.contains(type) == false) {
+ return null;
+ }
+ }
+// }
+ if (appliesToResourceType != null) {
+ Class extends IBaseResource> type = theRequestDetails.getServer().getFhirContext().getResourceDefinition(appliesToResourceType).getImplementingClass();
+ if (myAppliesToTypes.contains(type)) {
+ if (!applyTesters(theOperation, theRequestDetails, theInputResourceId, theInputResource, theOutputResource)) {
+ return null;
+ }
+ if (myClassifierType == ClassifierTypeEnum.ANY_ID) {
+ return new Verdict(PolicyEnum.ALLOW, this);
+ } else if (myClassifierType == ClassifierTypeEnum.IN_COMPARTMENT) {
+ // ok we'll check below
+ }
+ }
+ }
+ break;
+ default:
+ throw new IllegalStateException("Unable to apply security to event of applies to type " + myAppliesTo);
}
switch (myClassifierType) {
- case ANY_ID:
- break;
- case IN_COMPARTMENT:
- FhirTerser t = ctx.newTerser();
- boolean foundMatch = false;
- for (IIdType next : myClassifierCompartmentOwners) {
- if (appliesToResource != null) {
- if (t.isSourceInCompartmentForTarget(myClassifierCompartmentName, appliesToResource, next)) {
- foundMatch = true;
- break;
+ case ANY_ID:
+ break;
+ case IN_COMPARTMENT:
+ FhirTerser t = ctx.newTerser();
+ boolean foundMatch = false;
+ for (IIdType next : myClassifierCompartmentOwners) {
+ if (appliesToResource != null) {
+ if (t.isSourceInCompartmentForTarget(myClassifierCompartmentName, appliesToResource, next)) {
+ foundMatch = true;
+ break;
+ }
+ }
+ if (appliesToResourceId != null && appliesToResourceId.hasResourceType() && appliesToResourceId.hasIdPart()) {
+ if (appliesToResourceId.toUnqualifiedVersionless().getValue().equals(next.toUnqualifiedVersionless().getValue())) {
+ foundMatch = true;
+ break;
+ }
+ }
+
+ /*
+ * If we're trying to read a resource that could potentially be
+ * in the given compartment, we'll let the request through and
+ * catch any issues on the response.
+ *
+ * This is less than perfect, but it's the best we can do-
+ * If the user is allowed to see compartment "Patient/123" and
+ * the client is requesting to read a CarePlan, there is nothing
+ * in the request URL that indicates whether or not the CarePlan
+ * might be in the given compartment.
+ */
+ if (isNotBlank(appliesToResourceType)) {
+ RuntimeResourceDefinition sourceDef = theRequestDetails.getFhirContext().getResourceDefinition(appliesToResourceType);
+ String compartmentOwnerResourceType = next.getResourceType();
+ if (!StringUtils.equals(appliesToResourceType, compartmentOwnerResourceType)) {
+ List params = sourceDef.getSearchParamsForCompartmentName(compartmentOwnerResourceType);
+ if (params.isEmpty() == false) {
+
+ /*
+ * If this is a search, we can at least check whether
+ * the client has requested a search parameter that
+ * would match the given compartment. In this case, this
+ * is a very effective mechanism.
+ */
+ if (appliesToSearchParams != null && !theFlags.contains(AuthorizationFlagsEnum.NO_NOT_PROACTIVELY_BLOCK_COMPARTMENT_READ_ACCESS)) {
+ for (RuntimeSearchParam nextRuntimeSearchParam : params) {
+ String[] values = appliesToSearchParams.get(nextRuntimeSearchParam.getName());
+ if (values != null) {
+ for (String nextParameterValue : values) {
+ if (nextParameterValue.equals(next.getValue())) {
+ return new Verdict(PolicyEnum.ALLOW, this);
+ }
+ }
+ }
+ }
+ } else {
+ return new Verdict(PolicyEnum.ALLOW, this);
+ }
+ break;
+ }
+ }
}
}
- if (appliesToResourceId != null && appliesToResourceId.hasResourceType() && appliesToResourceId.hasIdPart()) {
- if (appliesToResourceId.toUnqualifiedVersionless().getValue().equals(next.toUnqualifiedVersionless().getValue())) {
- foundMatch = true;
- break;
- }
+ if (!foundMatch) {
+ return null;
}
- }
- if (!foundMatch) {
- return null;
- }
- break;
- default:
- throw new IllegalStateException("Unable to apply security to event of applies to type " + myAppliesTo);
+ break;
+ default:
+ throw new IllegalStateException("Unable to apply security to event of applies to type " + myAppliesTo);
}
if (!applyTesters(theOperation, theRequestDetails, theInputResourceId, theInputResource, theOutputResource)) {
@@ -308,22 +409,12 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ {
return newVerdict();
}
- public void setTenantApplicabilityChecker(RuleBuilder.ITenantApplicabilityChecker theTenantApplicabilityChecker) {
- myTenantApplicabilityChecker = theTenantApplicabilityChecker;
+ public TransactionAppliesToEnum getTransactionAppliesToOp() {
+ return myTransactionAppliesToOp;
}
- @Override
- public String toString() {
- ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
- builder.append("op", myOp);
- builder.append("transactionAppliesToOp", myTransactionAppliesToOp);
- builder.append("appliesTo", myAppliesTo);
- builder.append("appliesToTypes", myAppliesToTypes);
- builder.append("appliesToTenant", myTenantApplicabilityChecker);
- builder.append("classifierCompartmentName", myClassifierCompartmentName);
- builder.append("classifierCompartmentOwners", myClassifierCompartmentOwners);
- builder.append("classifierType", myClassifierType);
- return builder.toString();
+ public void setTransactionAppliesToOp(TransactionAppliesToEnum theOp) {
+ myTransactionAppliesToOp = theOp;
}
private boolean requestAppliesToTransaction(FhirContext theContext, RuleOpEnum theOp, IBaseResource theInputResource) {
@@ -334,23 +425,23 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ {
IBaseBundle request = (IBaseBundle) theInputResource;
String bundleType = BundleUtil.getBundleType(theContext, request);
switch (theOp) {
- case TRANSACTION:
- return "transaction".equals(bundleType);
- case BATCH:
- return "batch".equals(bundleType);
- default:
- return false;
+ case TRANSACTION:
+ return "transaction".equals(bundleType);
+ case BATCH:
+ return "batch".equals(bundleType);
+ default:
+ return false;
}
}
- public TransactionAppliesToEnum getTransactionAppliesToOp() {
- return myTransactionAppliesToOp;
- }
-
public void setAppliesTo(AppliesTypeEnum theAppliesTo) {
myAppliesTo = theAppliesTo;
}
+ public void setAppliesToInstances(List theAppliesToInstances) {
+ myAppliesToInstances = theAppliesToInstances;
+ }
+
public void setAppliesToTypes(Set> theAppliesToTypes) {
myAppliesToTypes = theAppliesToTypes;
}
@@ -372,12 +463,22 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ {
return this;
}
- public void setTransactionAppliesToOp(TransactionAppliesToEnum theOp) {
- myTransactionAppliesToOp = theOp;
+ public void setTenantApplicabilityChecker(RuleBuilder.ITenantApplicabilityChecker theTenantApplicabilityChecker) {
+ myTenantApplicabilityChecker = theTenantApplicabilityChecker;
}
- public void setAppliesToInstances(List theAppliesToInstances) {
- myAppliesToInstances = theAppliesToInstances;
+ @Override
+ public String toString() {
+ ToStringBuilder builder = new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE);
+ builder.append("op", myOp);
+ builder.append("transactionAppliesToOp", myTransactionAppliesToOp);
+ builder.append("appliesTo", myAppliesTo);
+ builder.append("appliesToTypes", myAppliesToTypes);
+ builder.append("appliesToTenant", myTenantApplicabilityChecker);
+ builder.append("classifierCompartmentName", myClassifierCompartmentName);
+ builder.append("classifierCompartmentOwners", myClassifierCompartmentOwners);
+ builder.append("classifierType", myClassifierType);
+ return builder.toString();
}
}
diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorDstu2Test.java
index e9e911311ca..295fc423344 100644
--- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorDstu2Test.java
+++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorDstu2Test.java
@@ -15,6 +15,7 @@ import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;
+import ca.uhn.fhir.rest.param.ReferenceParam;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
@@ -65,7 +66,7 @@ public class AuthorizationInterceptorDstu2Test {
@Before
public void before() {
ourCtx.setAddProfileTagWhenEncoding(AddProfileTagEnum.NEVER);
- for (IServerInterceptor next : new ArrayList(ourServlet.getInterceptors())) {
+ for (IServerInterceptor next : new ArrayList<>(ourServlet.getInterceptors())) {
ourServlet.unregisterInterceptor(next);
}
ourReturn = null;
@@ -1166,8 +1167,8 @@ public class AuthorizationInterceptorDstu2Test {
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
status = ourClient.execute(httpGet);
extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
+ assertEquals(403, status.getStatusLine().getStatusCode());
+ assertFalse(ourHitMethod);
}
@@ -1177,8 +1178,8 @@ public class AuthorizationInterceptorDstu2Test {
@Override
public List buildRuleList(RequestDetails theRequestDetails) {
return new RuleBuilder()
- .allow("Rule 1").read().resourcesOfType(Patient.class).inCompartment("Patient", new IdDt("Patient/1"))
- .build();
+ .allow("Rule 1").read().resourcesOfType(Observation.class).inCompartment("Patient", new IdDt("Patient/1"))
+ .build();
}
});
@@ -1187,13 +1188,13 @@ public class AuthorizationInterceptorDstu2Test {
String respString;
Bundle respBundle;
- ourReturn = new ArrayList();
+ ourReturn = new ArrayList<>();
for (int i = 0; i < 10; i++) {
- ourReturn.add(createPatient(1));
+ ourReturn.add(createObservation(i, "Patient/1"));
}
ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_count=5&_format=json");
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation?_count=5&_format=json&subject=Patient/1");
status = ourClient.execute(httpGet);
respString = extractResponseAndClose(status);
assertEquals(200, status.getStatusLine().getStatusCode());
@@ -1201,7 +1202,7 @@ public class AuthorizationInterceptorDstu2Test {
respBundle = ourCtx.newJsonParser().parseResource(Bundle.class, respString);
assertEquals(5, respBundle.getEntry().size());
assertEquals(10, respBundle.getTotal().intValue());
- assertEquals("Patient/1", respBundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
+ assertEquals("Observation/0", respBundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
assertNotNull(respBundle.getLink("next"));
// Load next page
@@ -1215,7 +1216,7 @@ public class AuthorizationInterceptorDstu2Test {
respBundle = ourCtx.newJsonParser().parseResource(Bundle.class, respString);
assertEquals(5, respBundle.getEntry().size());
assertEquals(10, respBundle.getTotal().intValue());
- assertEquals("Patient/1", respBundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
+ assertEquals("Observation/5", respBundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
assertNull(respBundle.getLink("next"));
}
@@ -1226,8 +1227,8 @@ public class AuthorizationInterceptorDstu2Test {
@Override
public List buildRuleList(RequestDetails theRequestDetails) {
return new RuleBuilder()
- .allow("Rule 1").read().resourcesOfType(Patient.class).inCompartment("Patient", new IdDt("Patient/1"))
- .build();
+ .allow("Rule 1").read().resourcesOfType(Observation.class).inCompartment("Patient", new IdDt("Patient/1"))
+ .build();
}
});
@@ -1236,16 +1237,16 @@ public class AuthorizationInterceptorDstu2Test {
String respString;
Bundle respBundle;
- ourReturn = new ArrayList();
+ ourReturn = new ArrayList<>();
for (int i = 0; i < 5; i++) {
- ourReturn.add(createPatient(1));
+ ourReturn.add(createObservation(i, "Patient/1"));
}
- for (int i = 0; i < 5; i++) {
- ourReturn.add(createPatient(2));
+ for (int i = 5; i < 10; i++) {
+ ourReturn.add(createObservation(i, "Patient/2"));
}
ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_count=5&_format=json");
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation?_count=5&_format=json&subject=Patient/1");
status = ourClient.execute(httpGet);
respString = extractResponseAndClose(status);
assertEquals(200, status.getStatusLine().getStatusCode());
@@ -1253,7 +1254,7 @@ public class AuthorizationInterceptorDstu2Test {
respBundle = ourCtx.newJsonParser().parseResource(Bundle.class, respString);
assertEquals(5, respBundle.getEntry().size());
assertEquals(10, respBundle.getTotal().intValue());
- assertEquals("Patient/1", respBundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
+ assertEquals("Observation/0", respBundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
assertNotNull(respBundle.getLink("next"));
// Load next page
@@ -1261,7 +1262,7 @@ public class AuthorizationInterceptorDstu2Test {
ourHitMethod = false;
httpGet = new HttpGet(respBundle.getLink("next").getUrl());
status = ourClient.execute(httpGet);
- respString = extractResponseAndClose(status);
+ extractResponseAndClose(status);
assertEquals(403, status.getStatusLine().getStatusCode());
assertFalse(ourHitMethod);
@@ -1283,7 +1284,7 @@ public class AuthorizationInterceptorDstu2Test {
HttpResponse status;
String response;
- ourReturn = Arrays.asList(createPatient(2));
+ ourReturn = Collections.singletonList(createPatient(2));
ourHitMethod = false;
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/2");
status = ourClient.execute(httpGet);
@@ -1291,9 +1292,9 @@ public class AuthorizationInterceptorDstu2Test {
ourLog.info(response);
assertThat(response, containsString("Access denied by default policy (no applicable rules)"));
assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
+ assertFalse(ourHitMethod);
- ourReturn = Arrays.asList(createObservation(10, "Patient/2"));
+ ourReturn = Collections.singletonList(createObservation(10, "Patient/2"));
ourHitMethod = false;
httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/10");
status = ourClient.execute(httpGet);
@@ -1303,7 +1304,7 @@ public class AuthorizationInterceptorDstu2Test {
assertEquals(403, status.getStatusLine().getStatusCode());
assertTrue(ourHitMethod);
- ourReturn = Arrays.asList(createCarePlan(10, "Patient/2"));
+ ourReturn = Collections.singletonList(createCarePlan(10, "Patient/2"));
ourHitMethod = false;
httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/10");
status = ourClient.execute(httpGet);
@@ -1321,7 +1322,7 @@ public class AuthorizationInterceptorDstu2Test {
ourLog.info(response);
assertThat(response, containsString("Access denied by default policy (no applicable rules)"));
assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
+ assertFalse(ourHitMethod);
ourReturn = Arrays.asList(createPatient(2), createObservation(10, "Patient/1"));
ourHitMethod = false;
@@ -1331,7 +1332,7 @@ public class AuthorizationInterceptorDstu2Test {
ourLog.info(response);
assertThat(response, containsString("Access denied by default policy (no applicable rules)"));
assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
+ assertFalse(ourHitMethod);
}
@@ -1359,7 +1360,7 @@ public class AuthorizationInterceptorDstu2Test {
HttpPost httpPost;
HttpResponse status;
- ourReturn = Arrays.asList((IResource) output);
+ ourReturn = Collections.singletonList(output);
ourHitMethod = false;
httpPost = new HttpPost("http://localhost:" + ourPort + "/");
httpPost.setEntity(createFhirResourceEntity(input));
@@ -1419,6 +1420,7 @@ public class AuthorizationInterceptorDstu2Test {
httpPost.setEntity(createFhirResourceEntity(createObservation(null, "Patient/1")));
status = ourClient.execute(httpPost);
response = extractResponseAndClose(status);
+ ourLog.debug(response);
assertEquals(201, status.getStatusLine().getStatusCode());
assertTrue(ourHitMethod);
}
@@ -1469,7 +1471,7 @@ public class AuthorizationInterceptorDstu2Test {
HttpDelete httpDelete;
HttpResponse status;
- ourReturn = Arrays.asList(createPatient(1));
+ ourReturn = Collections.singletonList(createPatient(1));
ourHitMethod = false;
httpDelete = new HttpDelete("http://localhost:" + ourPort + "/Patient?foo=bar");
@@ -1497,7 +1499,7 @@ public class AuthorizationInterceptorDstu2Test {
HttpDelete httpDelete;
HttpResponse status;
- ourReturn = Arrays.asList(createPatient(1));
+ ourReturn = Collections.singletonList(createPatient(1));
ourHitMethod = false;
httpDelete = new HttpDelete("http://localhost:" + ourPort + "/Patient?foo=bar");
@@ -1525,7 +1527,7 @@ public class AuthorizationInterceptorDstu2Test {
HttpResponse status;
ourHitMethod = false;
- ourReturn = Arrays.asList(createPatient(2));
+ ourReturn = Collections.singletonList(createPatient(2));
httpDelete = new HttpDelete("http://localhost:" + ourPort + "/Patient/2");
status = ourClient.execute(httpDelete);
extractResponseAndClose(status);
@@ -1533,7 +1535,7 @@ public class AuthorizationInterceptorDstu2Test {
assertTrue(ourHitMethod);
ourHitMethod = false;
- ourReturn = Arrays.asList(createPatient(1));
+ ourReturn = Collections.singletonList(createPatient(1));
httpDelete = new HttpDelete("http://localhost:" + ourPort + "/Patient/1");
status = ourClient.execute(httpDelete);
extractResponseAndClose(status);
@@ -1665,6 +1667,7 @@ public class AuthorizationInterceptorDstu2Test {
httpPost.setEntity(createFhirResourceEntity(createPatient(null)));
status = ourClient.execute(httpPost);
response = extractResponseAndClose(status);
+ ourLog.debug(response);
assertEquals(200, status.getStatusLine().getStatusCode());
assertTrue(ourHitMethod);
@@ -1703,6 +1706,7 @@ public class AuthorizationInterceptorDstu2Test {
httpPost.setEntity(createFhirResourceEntity(createPatient(null)));
status = ourClient.execute(httpPost);
response = extractResponseAndClose(status);
+ ourLog.debug(response);
assertEquals(200, status.getStatusLine().getStatusCode());
assertTrue(ourHitMethod);
@@ -1718,7 +1722,7 @@ public class AuthorizationInterceptorDstu2Test {
}
@Test
- public void testInvalidInstanceIds() throws Exception {
+ public void testInvalidInstanceIds() {
try {
new RuleBuilder().allow("Rule 1").write().instance((String) null);
fail();
@@ -2009,7 +2013,7 @@ public class AuthorizationInterceptorDstu2Test {
}
@Search()
- public List search() {
+ public List search(@OptionalParam(name="subject")ReferenceParam theSubject) {
ourHitMethod = true;
return ourReturn;
}
diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/AdditionalRequestHeadersInterceptorR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/AdditionalRequestHeadersInterceptorR4Test.java
deleted file mode 100644
index 5989618acb0..00000000000
--- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/AdditionalRequestHeadersInterceptorR4Test.java
+++ /dev/null
@@ -1,2202 +0,0 @@
-package ca.uhn.fhir.rest.server.interceptor;
-
-import ca.uhn.fhir.context.FhirContext;
-import ca.uhn.fhir.context.api.AddProfileTagEnum;
-import ca.uhn.fhir.rest.annotation.*;
-import ca.uhn.fhir.rest.api.Constants;
-import ca.uhn.fhir.rest.api.*;
-import ca.uhn.fhir.rest.api.server.IRequestOperationCallback;
-import ca.uhn.fhir.rest.api.server.RequestDetails;
-import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
-import ca.uhn.fhir.rest.server.IResourceProvider;
-import ca.uhn.fhir.rest.server.RestfulServer;
-import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
-import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor;
-import ca.uhn.fhir.rest.server.interceptor.auth.IAuthRule;
-import ca.uhn.fhir.rest.server.interceptor.auth.PolicyEnum;
-import ca.uhn.fhir.rest.server.interceptor.auth.RuleBuilder;
-import ca.uhn.fhir.util.PortUtil;
-import ca.uhn.fhir.util.TestUtil;
-import org.apache.commons.io.IOUtils;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.methods.*;
-import org.apache.http.entity.ContentType;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClientBuilder;
-import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.servlet.ServletHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.hl7.fhir.instance.model.api.IBaseResource;
-import org.hl7.fhir.r4.model.*;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import static org.apache.commons.lang3.StringUtils.isNotBlank;
-import static org.hamcrest.Matchers.containsString;
-import static org.junit.Assert.*;
-
-public class AdditionalRequestHeadersInterceptorR4Test {
-
- private static final String ERR403 = "{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"severity\":\"error\",\"code\":\"processing\",\"diagnostics\":\"Access denied by default policy (no applicable rules)\"}]}";
- private static CloseableHttpClient ourClient;
- private static String ourConditionalCreateId;
- private static FhirContext ourCtx = FhirContext.forR4();
- private static boolean ourHitMethod;
- private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(AdditionalRequestHeadersInterceptorR4Test.class);
- private static int ourPort;
- private static List ourReturn;
- private static Server ourServer;
- private static RestfulServer ourServlet;
-
- @Before
- public void before() {
- ourCtx.setAddProfileTagWhenEncoding(AddProfileTagEnum.NEVER);
- for (IServerInterceptor next : new ArrayList<>(ourServlet.getInterceptors())) {
- ourServlet.unregisterInterceptor(next);
- }
- ourReturn = null;
- ourHitMethod = false;
- ourConditionalCreateId = "1123";
- }
-
- private Resource createCarePlan(Integer theId, String theSubjectId) {
- CarePlan retVal = new CarePlan();
- if (theId != null) {
- retVal.setId(new IdType("CarePlan", (long) theId));
- }
- retVal.setSubject(new Reference("Patient/" + theSubjectId));
- return retVal;
- }
-
- private HttpEntity createFhirResourceEntity(IBaseResource theResource) {
- String out = ourCtx.newJsonParser().encodeResourceToString(theResource);
- return new StringEntity(out, ContentType.create(Constants.CT_FHIR_JSON, "UTF-8"));
- }
-
- private Resource createObservation(Integer theId, String theSubjectId) {
- Observation retVal = new Observation();
- if (theId != null) {
- retVal.setId(new IdType("Observation", (long) theId));
- }
- retVal.getCode().setText("OBS");
- retVal.setSubject(new Reference(theSubjectId));
- return retVal;
- }
-
- private Resource createPatient(Integer theId) {
- Patient retVal = new Patient();
- if (theId != null) {
- retVal.setId(new IdType("Patient", (long) theId));
- }
- retVal.addName().setFamily("FAM");
- return retVal;
- }
-
- private Resource createPatient(Integer theId, int theVersion) {
- Resource retVal = createPatient(theId);
- retVal.setId(retVal.getIdElement().withVersion(Integer.toString(theVersion)));
- return retVal;
- }
-
- private String extractResponseAndClose(HttpResponse status) throws IOException {
- if (status.getEntity() == null) {
- return null;
- }
- String responseContent;
- responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
- IOUtils.closeQuietly(status.getEntity().getContent());
- return responseContent;
- }
-
- @Test
- public void testAllowAll() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .deny("Rule 1").read().resourcesOfType(Patient.class).withAnyId().andThen()
- .allowAll("Default Rule")
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
- String response;
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createObservation(10, "Patient/2"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/10");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by rule: Rule 1"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$validate");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- }
-
- /**
- * #528
- */
- @Test
- public void testAllowByCompartmentWithAnyType() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder().allow("Rule 1").read().allResources().inCompartment("Patient", new IdType("Patient/845bd9f1-3635-4866-a6c8-1ca085df5c1a")).andThen().denyAll().build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createCarePlan(10, "845bd9f1-3635-4866-a6c8-1ca085df5c1a"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/135154");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createCarePlan(10, "FOO"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/135154");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- }
-
- /**
- * #528
- */
- @Test
- public void testAllowByCompartmentWithType() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder().allow("Rule 1").read().resourcesOfType(CarePlan.class).inCompartment("Patient", new IdType("Patient/845bd9f1-3635-4866-a6c8-1ca085df5c1a")).andThen().denyAll()
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createCarePlan(10, "845bd9f1-3635-4866-a6c8-1ca085df5c1a"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/135154");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createCarePlan(10, "FOO"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/135154");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
- }
-
- @Test
- public void testBatchWhenOnlyTransactionAllowed() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").transaction().withAnyOperation().andApplyNormalRules().andThen()
- .allow("Rule 2").write().allResources().inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 2").read().allResources().inCompartment("Patient", new IdType("Patient/1")).andThen()
- .build();
- }
- });
-
- Bundle input = new Bundle();
- input.setType(Bundle.BundleType.BATCH);
- input.addEntry().setResource(createPatient(1)).getRequest().setUrl("/Patient").setMethod(Bundle.HTTPVerb.POST);
-
- Bundle output = new Bundle();
- output.setType(Bundle.BundleType.TRANSACTIONRESPONSE);
- output.addEntry().getResponse().setLocation("/Patient/1");
-
- HttpPost httpPost;
- HttpResponse status;
-
- ourReturn = Collections.singletonList((Resource) output);
- ourHitMethod = false;
- httpPost = new HttpPost("http://localhost:" + ourPort + "/");
- httpPost.setEntity(createFhirResourceEntity(input));
- status = ourClient.execute(httpPost);
- extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- }
-
- @Test
- public void testBatchWhenTransactionReadDenied() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").transaction().withAnyOperation().andApplyNormalRules().andThen()
- .allow("Rule 2").write().allResources().inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 2").read().allResources().inCompartment("Patient", new IdType("Patient/1")).andThen()
- .build();
- }
- });
-
- Bundle input = new Bundle();
- input.setType(Bundle.BundleType.BATCH);
- input.addEntry().setResource(createPatient(1)).getRequest().setUrl("/Patient").setMethod(Bundle.HTTPVerb.POST);
-
- Bundle output = new Bundle();
- output.setType(Bundle.BundleType.TRANSACTIONRESPONSE);
- output.addEntry().setResource(createPatient(2));
-
- HttpPost httpPost;
- HttpResponse status;
-
- ourReturn = Collections.singletonList((Resource) output);
- ourHitMethod = false;
- httpPost = new HttpPost("http://localhost:" + ourPort + "/");
- httpPost.setEntity(createFhirResourceEntity(input));
- status = ourClient.execute(httpPost);
- extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- }
-
- @Test
- public void testBatchWhenTransactionWrongBundleType() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").transaction().withAnyOperation().andApplyNormalRules().andThen()
- .allow("Rule 2").write().allResources().inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 2").read().allResources().inCompartment("Patient", new IdType("Patient/1")).andThen()
- .build();
- }
- });
-
- Bundle input = new Bundle();
- input.setType(Bundle.BundleType.COLLECTION);
- input.addEntry().setResource(createPatient(1)).getRequest().setUrl("/Patient").setMethod(Bundle.HTTPVerb.POST);
-
- Bundle output = new Bundle();
- output.setType(Bundle.BundleType.TRANSACTIONRESPONSE);
- output.addEntry().setResource(createPatient(1));
-
- HttpPost httpPost;
- HttpResponse status;
- String response;
-
- ourReturn = Collections.singletonList((Resource) output);
- ourHitMethod = false;
- httpPost = new HttpPost("http://localhost:" + ourPort + "/");
- httpPost.setEntity(createFhirResourceEntity(input));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertEquals(ERR403, response);
- }
-
- @Test
- public void testDeleteByCompartment() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").delete().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 2").delete().resourcesOfType(Observation.class).inCompartment("Patient", new IdType("Patient/1"))
- .build();
- }
- });
-
- HttpDelete httpDelete;
- HttpResponse status;
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpDelete = new HttpDelete("http://localhost:" + ourPort + "/Patient/2");
- status = ourClient.execute(httpDelete);
- extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(1));
- httpDelete = new HttpDelete("http://localhost:" + ourPort + "/Patient/1");
- status = ourClient.execute(httpDelete);
- extractResponseAndClose(status);
- assertEquals(204, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
- }
-
- @Test
- public void testDenyAll() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow().read().resourcesOfType(Patient.class).withAnyId().andThen()
- .denyAll("Default Rule")
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
- String response;
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createObservation(10, "Patient/2"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/10");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by rule: Default Rule"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$validate");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by rule: Default Rule"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by rule: Default Rule"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
- }
-
- /**
- * #528
- */
- @Test
- public void testDenyByCompartmentWithAnyType() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder().deny("Rule 1").read().allResources().inCompartment("Patient", new IdType("Patient/845bd9f1-3635-4866-a6c8-1ca085df5c1a")).andThen().allowAll().build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createCarePlan(10, "845bd9f1-3635-4866-a6c8-1ca085df5c1a"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/135154");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createCarePlan(10, "FOO"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/135154");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- }
-
- /**
- * #528
- */
- @Test
- public void testDenyByCompartmentWithType() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder().deny("Rule 1").read().resourcesOfType(CarePlan.class).inCompartment("Patient", new IdType("Patient/845bd9f1-3635-4866-a6c8-1ca085df5c1a")).andThen().allowAll()
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createCarePlan(10, "845bd9f1-3635-4866-a6c8-1ca085df5c1a"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/135154");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createCarePlan(10, "FOO"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/135154");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
- }
-
- @Test
- public void testHistoryWithReadAll() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").read().allResources().withAnyId()
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
-
- ourReturn = Collections.singletonList(createPatient(2, 1));
-
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/_history");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/_history");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/_history");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
- }
-
- @Test
- public void testMetadataAllow() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").metadata()
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
-
- ourReturn = Collections.singletonList(createPatient(2));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/metadata");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- }
-
- @Test
- public void testMetadataDeny() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.ALLOW) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .deny("Rule 1").metadata()
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
-
- ourReturn = Collections.singletonList(createPatient(2));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/metadata");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- }
-
- @Test
- public void testOperationAnyName() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("RULE 1").operation().withAnyName().onServer().andThen()
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
-
- // Server
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createObservation(10, "Patient/2"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/$opName");
- status = ourClient.execute(httpGet);
- String response = extractResponseAndClose(status);
- ourLog.info(response);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- }
-
- @Test
- public void testOperationByInstanceOfTypeAllowed() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").operation().named("everything").onInstancesOfType(Patient.class)
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
- String response;
-
- ourReturn = new ArrayList<>();
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$everything");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- assertThat(response, containsString("Bundle"));
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertEquals(true, ourHitMethod);
-
- ourReturn = new ArrayList<>();
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Encounter/1/$everything");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- assertThat(response, containsString("OperationOutcome"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertEquals(false, ourHitMethod);
-
- }
-
- @Test
- public void testOperationByInstanceOfTypeWithInvalidReturnValue() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").operation().named("everything").onInstancesOfType(Patient.class).andThen()
- .allow("Rule 2").read().allResources().inCompartment("Patient", new IdType("Patient/1")).andThen()
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
- String response;
-
- // With a return value we don't allow
- ourReturn = Collections.singletonList(createPatient(222));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$everything");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- assertThat(response, containsString("OperationOutcome"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertEquals(true, ourHitMethod);
-
- // With a return value we do
- ourReturn = Collections.singletonList(createPatient(1));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$everything");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- assertThat(response, containsString("Bundle"));
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertEquals(true, ourHitMethod);
-
- }
-
- @Test
- public void testOperationByInstanceOfTypeWithReturnValue() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").operation().named("everything").onInstancesOfType(Patient.class)
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
- String response;
-
- ourReturn = new ArrayList<>();
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$everything");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- assertThat(response, containsString("Bundle"));
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertEquals(true, ourHitMethod);
-
- ourReturn = new ArrayList<>();
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Encounter/1/$everything");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- assertThat(response, containsString("OperationOutcome"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertEquals(false, ourHitMethod);
- }
-
- @Test
- public void testOperationInstanceLevel() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("RULE 1").operation().named("opName").onInstance(new IdType("http://example.com/Patient/1/_history/2")).andThen()
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
- String response;
-
- // Server
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createObservation(10, "Patient/2"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- assertThat(response, containsString("Access denied by default policy"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- // Type
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- // Instance
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- // Wrong instance
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/2/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- }
-
- @Test
- public void testOperationInstanceLevelAnyInstance() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("RULE 1").operation().named("opName").onAnyInstance().andThen()
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
- String response;
-
- // Server
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createObservation(10, "Patient/2"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- assertThat(response, containsString("Access denied by default policy"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- // Type
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- // Instance
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- // Another Instance
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/2/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- // Wrong name
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/2/$opName2");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- }
-
- @Test
- public void testOperationNotAllowedWithWritePermissiom() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("RULE 1").write().allResources().withAnyId().andThen()
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
- String response;
-
- // Server
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createObservation(10, "Patient/2"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- assertThat(response, containsString("Access denied by default policy"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- // System
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- // Type
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- // Instance
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
- }
-
- @Test
- public void testOperationServerLevel() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("RULE 1").operation().named("opName").onServer().andThen()
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
- String response;
-
- // Server
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createObservation(10, "Patient/2"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/$opName");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- // Type
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- // Instance
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
- }
-
- @Test
- public void testOperationTypeLevel() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("RULE 1").operation().named("opName").onType(Patient.class).andThen()
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
- String response;
-
- // Server
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createObservation(10, "Patient/2"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- assertThat(response, containsString("Access denied by default policy"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- // Type
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- // Wrong type
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/1/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- // Wrong name
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$opName2");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- // Instance
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
- }
-
- @Test
- public void testOperationTypeLevelWildcard() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("RULE 1").operation().named("opName").onAnyType().andThen()
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
- String response;
-
- // Server
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createObservation(10, "Patient/2"));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- assertThat(response, containsString("Access denied by default policy"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- // Type
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- // Another type
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- // Wrong name
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$opName2");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- // Instance
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$opName");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
- }
-
- @Test
- public void testReadByAnyId() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").read().resourcesOfType(Patient.class).withAnyId()
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
- String response;
-
- ourReturn = Collections.singletonList(createPatient(2));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourReturn = Collections.singletonList(createPatient(2));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/_history/222");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourReturn = Collections.singletonList(createObservation(10, "Patient/2"));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/10");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy (no applicable rules)"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- ourReturn = Arrays.asList(createPatient(1), createObservation(10, "Patient/2"));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy (no applicable rules)"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourReturn = Arrays.asList(createPatient(2), createObservation(10, "Patient/1"));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy (no applicable rules)"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- }
-
- @Test
- public void testReadByCompartmentRight() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").read().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 2").read().resourcesOfType(Observation.class).inCompartment("Patient", new IdType("Patient/1"))
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
-
- ourReturn = Collections.singletonList(createPatient(1));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourReturn = Collections.singletonList(createObservation(10, "Patient/1"));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/10");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourReturn = Arrays.asList(createPatient(1), createObservation(10, "Patient/1"));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- }
-
- @Test
- public void testReadPageRight() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").read().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1"))
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
- String respString;
- Bundle respBundle;
-
- ourReturn = new ArrayList<>();
- for (int i = 0; i < 10; i++) {
- ourReturn.add(createPatient(1));
- }
-
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_count=5&_format=json");
- status = ourClient.execute(httpGet);
- respString = extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
- respBundle = ourCtx.newJsonParser().parseResource(Bundle.class, respString);
- assertEquals(5, respBundle.getEntry().size());
- assertEquals(10, respBundle.getTotal());
- assertEquals("Patient/1", respBundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
- assertNotNull(respBundle.getLink("next"));
-
- // Load next page
-
- ourHitMethod = false;
- httpGet = new HttpGet(respBundle.getLink("next").getUrl());
- status = ourClient.execute(httpGet);
- respString = extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
- respBundle = ourCtx.newJsonParser().parseResource(Bundle.class, respString);
- assertEquals(5, respBundle.getEntry().size());
- assertEquals(10, respBundle.getTotal());
- assertEquals("Patient/1", respBundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
- assertNull(respBundle.getLink("next"));
-
- }
-
- @Test
- public void testReadPageWrong() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").read().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1"))
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
- String respString;
- Bundle respBundle;
-
- ourReturn = new ArrayList<>();
- for (int i = 0; i < 5; i++) {
- ourReturn.add(createPatient(1));
- }
- for (int i = 0; i < 5; i++) {
- ourReturn.add(createPatient(2));
- }
-
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_count=5&_format=json");
- status = ourClient.execute(httpGet);
- respString = extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
- respBundle = ourCtx.newJsonParser().parseResource(Bundle.class, respString);
- assertEquals(5, respBundle.getEntry().size());
- assertEquals(10, respBundle.getTotal());
- assertEquals("Patient/1", respBundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
- assertNotNull(respBundle.getLink("next"));
-
- // Load next page
-
- ourHitMethod = false;
- httpGet = new HttpGet(respBundle.getLink("next").getUrl());
- status = ourClient.execute(httpGet);
- respString = extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- }
-
- @Test
- public void testReadByCompartmentWrong() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").read().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 2").read().resourcesOfType(Observation.class).inCompartment("Patient", new IdType("Patient/1"))
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
- String response;
-
- ourReturn = Collections.singletonList(createPatient(2));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/2");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy (no applicable rules)"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourReturn = Collections.singletonList(createObservation(10, "Patient/2"));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/10");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy (no applicable rules)"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourReturn = Collections.singletonList(createCarePlan(10, "Patient/2"));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/10");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy (no applicable rules)"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- ourReturn = Arrays.asList(createPatient(1), createObservation(10, "Patient/2"));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy (no applicable rules)"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourReturn = Arrays.asList(createPatient(2), createObservation(10, "Patient/1"));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- ourLog.info(response);
- assertThat(response, containsString("Access denied by default policy (no applicable rules)"));
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- }
-
- @Test
- public void testTransactionWriteGood() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").transaction().withAnyOperation().andApplyNormalRules().andThen()
- .allow("Rule 2").write().allResources().inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 2").read().allResources().inCompartment("Patient", new IdType("Patient/1")).andThen()
- .build();
- }
- });
-
- Bundle input = new Bundle();
- input.setType(Bundle.BundleType.TRANSACTION);
- input.addEntry().setResource(createPatient(1)).getRequest().setUrl("/Patient").setMethod(Bundle.HTTPVerb.PUT);
-
- Bundle output = new Bundle();
- output.setType(Bundle.BundleType.TRANSACTIONRESPONSE);
- output.addEntry().getResponse().setLocation("/Patient/1");
-
- HttpPost httpPost;
- HttpResponse status;
-
- ourReturn = Collections.singletonList((Resource) output);
- ourHitMethod = false;
- httpPost = new HttpPost("http://localhost:" + ourPort + "/");
- httpPost.setEntity(createFhirResourceEntity(input));
- status = ourClient.execute(httpPost);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- }
-
- @Test
- public void testWriteByCompartmentCreate() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").write().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 1b").write().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1123")).andThen()
- .allow("Rule 2").write().resourcesOfType(Observation.class).inCompartment("Patient", new IdType("Patient/1"))
- .build();
- }
- });
-
- HttpEntityEnclosingRequestBase httpPost;
- HttpResponse status;
- String response;
-
- ourHitMethod = false;
- httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
- httpPost.setEntity(createFhirResourceEntity(createPatient(null)));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertEquals(ERR403, response);
- assertFalse(ourHitMethod);
-
- // Conditional
- ourHitMethod = false;
- httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
- httpPost.addHeader("If-None-Exist", "Patient?foo=bar");
- httpPost.setEntity(createFhirResourceEntity(createPatient(null)));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertEquals(ERR403, response);
- assertFalse(ourHitMethod);
-
- ourHitMethod = false;
- httpPost = new HttpPost("http://localhost:" + ourPort + "/Observation");
- httpPost.setEntity(createFhirResourceEntity(createObservation(null, "Patient/2")));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertEquals(ERR403, response);
- assertFalse(ourHitMethod);
-
- ourHitMethod = false;
- httpPost = new HttpPost("http://localhost:" + ourPort + "/Observation");
- httpPost.setEntity(createFhirResourceEntity(createObservation(null, "Patient/1")));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(201, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
- }
-
- @Test
- public void testWriteByCompartmentCreateConditionalResolvesToValid() throws Exception {
- ourConditionalCreateId = "1";
-
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").write().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 2").createConditional().resourcesOfType(Patient.class)
- .build();
- }
- });
-
- HttpEntityEnclosingRequestBase httpPost;
- HttpResponse status;
-
- ourHitMethod = false;
- httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
- httpPost.addHeader(Constants.HEADER_IF_NONE_EXIST, "foo=bar");
- httpPost.setEntity(createFhirResourceEntity(createPatient(null)));
- status = ourClient.execute(httpPost);
- String response = extractResponseAndClose(status);
- ourLog.info(response);
- assertEquals(201, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- }
-
- @Test
- public void testWriteByCompartmentDeleteConditionalResolvesToValid() throws Exception {
- ourConditionalCreateId = "1";
-
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").delete().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 2").deleteConditional().resourcesOfType(Patient.class)
- .build();
- }
- });
-
- HttpDelete httpDelete;
- HttpResponse status;
-
- ourReturn = Collections.singletonList(createPatient(1));
-
- ourHitMethod = false;
- httpDelete = new HttpDelete("http://localhost:" + ourPort + "/Patient?foo=bar");
- status = ourClient.execute(httpDelete);
- String response = extractResponseAndClose(status);
- ourLog.info(response);
- assertEquals(204, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- }
-
- @Test
- public void testWriteByCompartmentDeleteConditionalWithoutDirectMatch() throws Exception {
- ourConditionalCreateId = "1";
-
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 2").deleteConditional().resourcesOfType(Patient.class)
- .build();
- }
- });
-
- HttpDelete httpDelete;
- HttpResponse status;
-
- ourReturn = Collections.singletonList(createPatient(1));
-
- ourHitMethod = false;
- httpDelete = new HttpDelete("http://localhost:" + ourPort + "/Patient?foo=bar");
- status = ourClient.execute(httpDelete);
- String response = extractResponseAndClose(status);
- ourLog.info(response);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- }
-
- @Test
- public void testWriteByCompartmentDoesntAllowDelete() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").write().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 2").write().resourcesOfType(Observation.class).inCompartment("Patient", new IdType("Patient/1"))
- .build();
- }
- });
-
- HttpDelete httpDelete;
- HttpResponse status;
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(2));
- httpDelete = new HttpDelete("http://localhost:" + ourPort + "/Patient/2");
- status = ourClient.execute(httpDelete);
- extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(createPatient(1));
- httpDelete = new HttpDelete("http://localhost:" + ourPort + "/Patient/1");
- status = ourClient.execute(httpDelete);
- extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
- }
-
- @Test
- public void testWriteByCompartmentUpdate() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").write().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 2").write().resourcesOfType(Observation.class).inCompartment("Patient", new IdType("Patient/1"))
- .build();
- }
- });
-
- HttpEntityEnclosingRequestBase httpPost;
- String response;
- HttpResponse status;
-
- ourHitMethod = false;
- httpPost = new HttpPut("http://localhost:" + ourPort + "/Patient/2");
- httpPost.setEntity(createFhirResourceEntity(createPatient(2)));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(ERR403, response);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- ourHitMethod = false;
- httpPost = new HttpPut("http://localhost:" + ourPort + "/Patient/1");
- httpPost.setEntity(createFhirResourceEntity(createPatient(1)));
- status = ourClient.execute(httpPost);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- // Conditional
- ourHitMethod = false;
- httpPost = new HttpPut("http://localhost:" + ourPort + "/Patient?foo=bar");
- httpPost.setEntity(createFhirResourceEntity(createPatient(1)));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(ERR403, response);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- ourHitMethod = false;
- httpPost = new HttpPut("http://localhost:" + ourPort + "/Patient?foo=bar");
- httpPost.setEntity(createFhirResourceEntity(createPatient(99)));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(ERR403, response);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
-
- ourHitMethod = false;
- httpPost = new HttpPut("http://localhost:" + ourPort + "/Observation/10");
- httpPost.setEntity(createFhirResourceEntity(createObservation(10, "Patient/1")));
- status = ourClient.execute(httpPost);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- httpPost = new HttpPut("http://localhost:" + ourPort + "/Observation/10");
- httpPost.setEntity(createFhirResourceEntity(createObservation(10, "Patient/2")));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(ERR403, response);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
- }
-
- @Test
- public void testWriteByCompartmentUpdateConditionalResolvesToInvalid() throws Exception {
- ourConditionalCreateId = "1123";
-
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").write().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 2").write().resourcesOfType(Observation.class).inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 3").updateConditional().resourcesOfType(Patient.class)
- .build();
- }
- });
-
- HttpEntityEnclosingRequestBase httpPost;
- HttpResponse status;
- String response;
-
- ourHitMethod = false;
- httpPost = new HttpPut("http://localhost:" + ourPort + "/Patient?foo=bar");
- httpPost.setEntity(createFhirResourceEntity(createPatient(null)));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertEquals(ERR403, response);
- assertTrue(ourHitMethod);
-
- }
-
- @Test
- public void testWriteByCompartmentUpdateConditionalResolvesToValid() throws Exception {
- ourConditionalCreateId = "1";
-
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").write().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 2").write().resourcesOfType(Observation.class).inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 3").updateConditional().resourcesOfType(Patient.class)
- .build();
- }
- });
-
- HttpEntityEnclosingRequestBase httpPost;
- HttpResponse status;
- String response;
-
- ourHitMethod = false;
- httpPost = new HttpPut("http://localhost:" + ourPort + "/Patient?foo=bar");
- httpPost.setEntity(createFhirResourceEntity(createPatient(null)));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- httpPost = new HttpPut("http://localhost:" + ourPort + "/Observation?foo=bar");
- httpPost.setEntity(createFhirResourceEntity(createObservation(null, "Patient/12")));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertEquals(ERR403, response);
- assertFalse(ourHitMethod);
-
- }
-
- @Test
- public void testWriteByCompartmentUpdateConditionalResolvesToValidAllTypes() throws Exception {
- ourConditionalCreateId = "1";
-
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").write().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 2").write().resourcesOfType(Observation.class).inCompartment("Patient", new IdType("Patient/1")).andThen()
- .allow("Rule 3").updateConditional().allResources()
- .build();
- }
- });
-
- HttpEntityEnclosingRequestBase httpPost;
- HttpResponse status;
- String response;
-
- ourHitMethod = false;
- httpPost = new HttpPut("http://localhost:" + ourPort + "/Patient?foo=bar");
- httpPost.setEntity(createFhirResourceEntity(createPatient(null)));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- httpPost = new HttpPut("http://localhost:" + ourPort + "/Observation?foo=bar");
- httpPost.setEntity(createFhirResourceEntity(createObservation(null, "Patient/12")));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertEquals(ERR403, response);
- assertTrue(ourHitMethod);
-
- }
-
- @Test
- public void testInvalidInstanceIds() throws Exception {
- try {
- new RuleBuilder().allow("Rule 1").write().instance((String) null);
- fail();
- } catch (NullPointerException e) {
- assertEquals("theId must not be null or empty", e.getMessage());
- }
- try {
- new RuleBuilder().allow("Rule 1").write().instance("");
- fail();
- } catch (IllegalArgumentException e) {
- assertEquals("theId must not be null or empty", e.getMessage());
- }
- try {
- new RuleBuilder().allow("Rule 1").write().instance("Observation/");
- fail();
- } catch (IllegalArgumentException e) {
- assertEquals("theId must contain an ID part", e.getMessage());
- }
- try {
- new RuleBuilder().allow("Rule 1").write().instance(new IdType());
- fail();
- } catch (NullPointerException e) {
- assertEquals("theId.getValue() must not be null or empty", e.getMessage());
- }
- try {
- new RuleBuilder().allow("Rule 1").write().instance(new IdType(""));
- fail();
- } catch (NullPointerException e) {
- assertEquals("theId.getValue() must not be null or empty", e.getMessage());
- }
- try {
- new RuleBuilder().allow("Rule 1").write().instance(new IdType("Observation", (String) null));
- fail();
- } catch (NullPointerException e) {
- assertEquals("theId must contain an ID part", e.getMessage());
- }
- }
-
- @Test
- public void testWritePatchByInstance() throws Exception {
- ourConditionalCreateId = "1";
-
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").write().instance("Patient/900").andThen()
- .build();
- }
- });
-
- HttpEntityEnclosingRequestBase httpPost;
- HttpResponse status;
- String response;
-
- String input = "[ { \"op\": \"replace\", \"path\": \"/gender\", \"value\": \"male\" } ]";
-
- ourHitMethod = false;
- httpPost = new HttpPatch("http://localhost:" + ourPort + "/Patient/900");
- httpPost.setEntity(new StringEntity(input, ContentType.parse("application/json-patch+json")));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(204, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- httpPost = new HttpPatch("http://localhost:" + ourPort + "/Patient/999");
- httpPost.setEntity(new StringEntity(input, ContentType.parse("application/json-patch+json")));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertFalse(ourHitMethod);
- }
-
- @Test
- public void testWriteByInstance() throws Exception {
- ourConditionalCreateId = "1";
-
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").write().instance("Observation/900").andThen()
- .allow("Rule 1").write().instance("901").andThen()
- .build();
- }
- });
-
- HttpEntityEnclosingRequestBase httpPost;
- HttpResponse status;
- String response;
-
- ourHitMethod = false;
- httpPost = new HttpPut("http://localhost:" + ourPort + "/Observation/900");
- httpPost.setEntity(createFhirResourceEntity(createObservation(900, "Patient/12")));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- httpPost = new HttpPut("http://localhost:" + ourPort + "/Observation/901");
- httpPost.setEntity(createFhirResourceEntity(createObservation(901, "Patient/12")));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourHitMethod = false;
- httpPost = new HttpPost("http://localhost:" + ourPort + "/Observation");
- httpPost.setEntity(createFhirResourceEntity(createObservation(null, "Patient/900")));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertEquals(ERR403, response);
- assertFalse(ourHitMethod);
-
- ourHitMethod = false;
- httpPost = new HttpPost("http://localhost:" + ourPort + "/Patient");
- httpPost.setEntity(createFhirResourceEntity(createPatient(null)));
- status = ourClient.execute(httpPost);
- response = extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertEquals(ERR403, response);
- assertFalse(ourHitMethod);
-
- }
-
- @Test
- public void testReadByInstance() throws Exception {
- ourConditionalCreateId = "1";
-
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder()
- .allow("Rule 1").read().instance("Observation/900").andThen()
- .allow("Rule 1").read().instance("901").andThen()
- .build();
- }
- });
-
- HttpResponse status;
- String response;
- HttpGet httpGet;
-
- ourReturn = Collections.singletonList(createObservation(900, "Patient/1"));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/900");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourReturn = Collections.singletonList(createPatient(901));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/901");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- ourReturn = Collections.singletonList(createPatient(1));
- ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=json");
- status = ourClient.execute(httpGet);
- response = extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertEquals(ERR403, response);
- assertFalse(ourHitMethod);
-
- }
-
- @AfterClass
- public static void afterClassClearContext() throws Exception {
- ourServer.stop();
- TestUtil.clearAllStaticFieldsForUnitTest();
- }
-
- @BeforeClass
- public static void beforeClass() throws Exception {
-
- ourPort = PortUtil.findFreePort();
- ourServer = new Server(ourPort);
-
- DummyPatientResourceProvider patProvider = new DummyPatientResourceProvider();
- DummyObservationResourceProvider obsProv = new DummyObservationResourceProvider();
- DummyEncounterResourceProvider encProv = new DummyEncounterResourceProvider();
- DummyCarePlanResourceProvider cpProv = new DummyCarePlanResourceProvider();
- PlainProvider plainProvider = new PlainProvider();
-
- ServletHandler proxyHandler = new ServletHandler();
- ourServlet = new RestfulServer(ourCtx);
- ourServlet.setFhirContext(ourCtx);
- ourServlet.setResourceProviders(patProvider, obsProv, encProv, cpProv);
- ourServlet.setPlainProviders(plainProvider);
- ourServlet.setPagingProvider(new FifoMemoryPagingProvider(100));
- ServletHolder servletHolder = new ServletHolder(ourServlet);
- proxyHandler.addServletWithMapping(servletHolder, "/*");
- ourServer.setHandler(proxyHandler);
- ourServer.start();
-
- PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(5000, TimeUnit.MILLISECONDS);
- HttpClientBuilder builder = HttpClientBuilder.create();
- builder.setConnectionManager(connectionManager);
- ourClient = builder.build();
-
- }
-
- public static class DummyCarePlanResourceProvider implements IResourceProvider {
-
- @Override
- public Class extends IBaseResource> getResourceType() {
- return CarePlan.class;
- }
-
- @Read(version = true)
- public CarePlan read(@IdParam IdType theId) {
- ourHitMethod = true;
- return (CarePlan) ourReturn.get(0);
- }
-
- @Search()
- public List search() {
- ourHitMethod = true;
- return ourReturn;
- }
- }
-
- public static class DummyEncounterResourceProvider implements IResourceProvider {
-
- @Operation(name = "everything", idempotent = true)
- public Bundle everything(@IdParam IdType theId) {
- ourHitMethod = true;
- Bundle retVal = new Bundle();
- for (Resource next : ourReturn) {
- retVal.addEntry().setResource(next);
- }
- return retVal;
- }
-
- @Override
- public Class extends IBaseResource> getResourceType() {
- return Encounter.class;
- }
- }
-
- public static class DummyObservationResourceProvider implements IResourceProvider {
-
- @Create()
- public MethodOutcome create(@ResourceParam Observation theResource, @ConditionalUrlParam String theConditionalUrl) {
- ourHitMethod = true;
- theResource.setId("Observation/1/_history/1");
- MethodOutcome retVal = new MethodOutcome();
- retVal.setCreated(true);
- retVal.setResource(theResource);
- return retVal;
- }
-
- @Delete()
- public MethodOutcome delete(@IdParam IdType theId) {
- ourHitMethod = true;
- MethodOutcome retVal = new MethodOutcome();
- return retVal;
- }
-
- @Override
- public Class extends IBaseResource> getResourceType() {
- return Observation.class;
- }
-
- @Operation(name = "opName", idempotent = true)
- public Parameters operation() {
- ourHitMethod = true;
- return (Parameters) new Parameters().setId("1");
- }
-
- @Operation(name = "opName", idempotent = true)
- public Parameters operation(@IdParam IdType theId) {
- ourHitMethod = true;
- return (Parameters) new Parameters().setId("1");
- }
-
- @Read(version = true)
- public Observation read(@IdParam IdType theId) {
- ourHitMethod = true;
- return (Observation) ourReturn.get(0);
- }
-
- @Search()
- public List search() {
- ourHitMethod = true;
- return ourReturn;
- }
-
- @Update()
- public MethodOutcome update(@IdParam IdType theId, @ResourceParam Observation theResource, @ConditionalUrlParam String theConditionalUrl, RequestDetails theRequestDetails) {
- ourHitMethod = true;
-
- if (isNotBlank(theConditionalUrl)) {
- IdType actual = new IdType("Observation", ourConditionalCreateId);
- ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails, actual);
- subRequest.notifyIncomingRequestPreHandled(RestOperationTypeEnum.UPDATE);
- theResource.setId(actual);
- } else {
- ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails, theResource);
- subRequest.notifyIncomingRequestPreHandled(RestOperationTypeEnum.UPDATE);
- theResource.setId(theId.withVersion("2"));
- }
-
- MethodOutcome retVal = new MethodOutcome();
- retVal.setResource(theResource);
- return retVal;
- }
-
- }
-
- public static class DummyPatientResourceProvider implements IResourceProvider {
-
- @Create()
- public MethodOutcome create(@ResourceParam Patient theResource, @ConditionalUrlParam String theConditionalUrl, RequestDetails theRequestDetails) {
-
- if (isNotBlank(theConditionalUrl)) {
- IdType actual = new IdType("Patient", ourConditionalCreateId);
- ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails, actual);
- subRequest.notifyIncomingRequestPreHandled(RestOperationTypeEnum.CREATE);
- } else {
- ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails, theResource);
- subRequest.notifyIncomingRequestPreHandled(RestOperationTypeEnum.CREATE);
- }
-
- ourHitMethod = true;
- theResource.setId("Patient/1/_history/1");
- MethodOutcome retVal = new MethodOutcome();
- retVal.setCreated(true);
- retVal.setResource(theResource);
- return retVal;
- }
-
- @Delete()
- public MethodOutcome delete(IRequestOperationCallback theRequestOperationCallback, @IdParam IdType theId, @ConditionalUrlParam String theConditionalUrl, RequestDetails theRequestDetails) {
- ourHitMethod = true;
- for (IBaseResource next : ourReturn) {
- theRequestOperationCallback.resourceDeleted(next);
- }
- MethodOutcome retVal = new MethodOutcome();
- return retVal;
- }
-
- @Operation(name = "everything", idempotent = true)
- public Bundle everything(@IdParam IdType theId) {
- ourHitMethod = true;
- Bundle retVal = new Bundle();
- for (Resource next : ourReturn) {
- retVal.addEntry().setResource(next);
- }
- return retVal;
- }
-
- @Override
- public Class extends IBaseResource> getResourceType() {
- return Patient.class;
- }
-
- @History()
- public List history() {
- ourHitMethod = true;
- return (ourReturn);
- }
-
- @History()
- public List history(@IdParam IdType theId) {
- ourHitMethod = true;
- return (ourReturn);
- }
-
- @Operation(name = "opName", idempotent = true)
- public Parameters operation() {
- ourHitMethod = true;
- return (Parameters) new Parameters().setId("1");
- }
-
- @Operation(name = "opName", idempotent = true)
- public Parameters operation(@IdParam IdType theId) {
- ourHitMethod = true;
- return (Parameters) new Parameters().setId("1");
- }
-
- @Operation(name = "opName2", idempotent = true)
- public Parameters operation2(@IdParam IdType theId) {
- ourHitMethod = true;
- return (Parameters) new Parameters().setId("1");
- }
-
- @Operation(name = "opName2", idempotent = true)
- public Parameters operation2() {
- ourHitMethod = true;
- return (Parameters) new Parameters().setId("1");
- }
-
- @Read(version = true)
- public Patient read(@IdParam IdType theId) {
- ourHitMethod = true;
- return (Patient) ourReturn.get(0);
- }
-
- @Search()
- public List search() {
- ourHitMethod = true;
- return ourReturn;
- }
-
- @Update()
- public MethodOutcome update(@IdParam IdType theId, @ResourceParam Patient theResource, @ConditionalUrlParam String theConditionalUrl, RequestDetails theRequestDetails) {
- ourHitMethod = true;
-
- if (isNotBlank(theConditionalUrl)) {
- IdType actual = new IdType("Patient", ourConditionalCreateId);
- ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails, actual);
- subRequest.notifyIncomingRequestPreHandled(RestOperationTypeEnum.UPDATE);
- theResource.setId(actual);
- } else {
- ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails, theResource);
- subRequest.notifyIncomingRequestPreHandled(RestOperationTypeEnum.UPDATE);
- theResource.setId(theId.withVersion("2"));
- }
-
- MethodOutcome retVal = new MethodOutcome();
- retVal.setResource(theResource);
- return retVal;
- }
-
- @Patch()
- public MethodOutcome patch(@IdParam IdType theId, @ResourceParam String theResource, PatchTypeEnum thePatchType) {
- ourHitMethod = true;
-
- MethodOutcome retVal = new MethodOutcome();
- return retVal;
- }
-
- @Validate
- public MethodOutcome validate(@ResourceParam Patient theResource, @IdParam IdType theId, @ResourceParam String theRawResource, @ResourceParam EncodingEnum theEncoding,
- @Validate.Mode ValidationModeEnum theMode, @Validate.Profile String theProfile, RequestDetails theRequestDetails) {
- ourHitMethod = true;
- OperationOutcome oo = new OperationOutcome();
- oo.addIssue().setDiagnostics("OK");
- return new MethodOutcome(oo);
- }
-
- @Validate
- public MethodOutcome validate(@ResourceParam Patient theResource, @ResourceParam String theRawResource, @ResourceParam EncodingEnum theEncoding, @Validate.Mode ValidationModeEnum theMode,
- @Validate.Profile String theProfile, RequestDetails theRequestDetails) {
- ourHitMethod = true;
- OperationOutcome oo = new OperationOutcome();
- oo.addIssue().setDiagnostics("OK");
- return new MethodOutcome(oo);
- }
-
- }
-
- public static class PlainProvider {
-
- @History()
- public List history() {
- ourHitMethod = true;
- return (ourReturn);
- }
-
- @Operation(name = "opName", idempotent = true)
- public Parameters operation() {
- ourHitMethod = true;
- return (Parameters) new Parameters().setId("1");
- }
-
- @Transaction()
- public Bundle search(@TransactionParam Bundle theInput) {
- ourHitMethod = true;
- return (Bundle) ourReturn.get(0);
- }
-
- }
-
-}
diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/AuthorizationInterceptorR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/AuthorizationInterceptorR4Test.java
index 61da96bb604..17febb9ea89 100644
--- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/AuthorizationInterceptorR4Test.java
+++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/AuthorizationInterceptorR4Test.java
@@ -8,9 +8,11 @@ import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.api.server.IRequestOperationCallback;
import ca.uhn.fhir.rest.api.server.RequestDetails;
+import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.RestfulServer;
+import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
import ca.uhn.fhir.rest.server.interceptor.auth.*;
import ca.uhn.fhir.rest.server.tenant.UrlBaseTenantIdentificationStrategy;
@@ -287,6 +289,68 @@ public class AuthorizationInterceptorR4Test {
}
+ @Test
+ public void testAllowByCompartmentUsingUnqualifiedIds() throws Exception {
+ ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
+ @Override
+ public List buildRuleList(RequestDetails theRequestDetails) {
+ return new RuleBuilder().allow().read().resourcesOfType(CarePlan.class).inCompartment("Patient", new IdType("Patient/123")).andThen().denyAll()
+ .build();
+ }
+ });
+
+ HttpGet httpGet;
+ HttpResponse status;
+
+ Patient patient;
+ CarePlan carePlan;
+
+ // Unqualified
+ patient = new Patient();
+ patient.setId("123");
+ carePlan = new CarePlan();
+ carePlan.setStatus(CarePlan.CarePlanStatus.ACTIVE);
+ carePlan.getSubject().setResource(patient);
+
+ ourHitMethod = false;
+ ourReturn = Collections.singletonList(carePlan);
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/135154");
+ status = ourClient.execute(httpGet);
+ extractResponseAndClose(status);
+ assertEquals(200, status.getStatusLine().getStatusCode());
+ assertTrue(ourHitMethod);
+
+ // Qualified
+ patient = new Patient();
+ patient.setId("Patient/123");
+ carePlan = new CarePlan();
+ carePlan.setStatus(CarePlan.CarePlanStatus.ACTIVE);
+ carePlan.getSubject().setResource(patient);
+
+ ourHitMethod = false;
+ ourReturn = Collections.singletonList(carePlan);
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/135154");
+ status = ourClient.execute(httpGet);
+ extractResponseAndClose(status);
+ assertEquals(200, status.getStatusLine().getStatusCode());
+ assertTrue(ourHitMethod);
+
+ // Wrong one
+ patient = new Patient();
+ patient.setId("456");
+ carePlan = new CarePlan();
+ carePlan.setStatus(CarePlan.CarePlanStatus.ACTIVE);
+ carePlan.getSubject().setResource(patient);
+
+ ourHitMethod = false;
+ ourReturn = Collections.singletonList(carePlan);
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/135154");
+ status = ourClient.execute(httpGet);
+ extractResponseAndClose(status);
+ assertEquals(403, status.getStatusLine().getStatusCode());
+ assertTrue(ourHitMethod);
+ }
+
/**
* #528
*/
@@ -390,69 +454,6 @@ public class AuthorizationInterceptorR4Test {
assertTrue(ourHitMethod);
}
- @Test
- public void testAllowByCompartmentUsingUnqualifiedIds() throws Exception {
- ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
- @Override
- public List buildRuleList(RequestDetails theRequestDetails) {
- return new RuleBuilder().allow().read().resourcesOfType(CarePlan.class).inCompartment("Patient", new IdType("Patient/123")).andThen().denyAll()
- .build();
- }
- });
-
- HttpGet httpGet;
- HttpResponse status;
-
- Patient patient;
- CarePlan carePlan;
-
- // Unqualified
- patient = new Patient();
- patient.setId("123");
- carePlan = new CarePlan();
- carePlan.setStatus(CarePlan.CarePlanStatus.ACTIVE);
- carePlan.getSubject().setResource(patient);
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(carePlan);
- httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/135154");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- // Qualified
- patient = new Patient();
- patient.setId("Patient/123");
- carePlan = new CarePlan();
- carePlan.setStatus(CarePlan.CarePlanStatus.ACTIVE);
- carePlan.getSubject().setResource(patient);
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(carePlan);
- httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/135154");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
-
- // Wrong one
- patient = new Patient();
- patient.setId("456");
- carePlan = new CarePlan();
- carePlan.setStatus(CarePlan.CarePlanStatus.ACTIVE);
- carePlan.getSubject().setResource(patient);
-
- ourHitMethod = false;
- ourReturn = Collections.singletonList(carePlan);
- httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/135154");
- status = ourClient.execute(httpGet);
- extractResponseAndClose(status);
- assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
- }
-
-
@Test
public void testBatchWhenOnlyTransactionAllowed() throws Exception {
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
@@ -477,7 +478,7 @@ public class AuthorizationInterceptorR4Test {
HttpPost httpPost;
HttpResponse status;
- ourReturn = Collections.singletonList((Resource) output);
+ ourReturn = Collections.singletonList(output);
ourHitMethod = false;
httpPost = new HttpPost("http://localhost:" + ourPort + "/");
httpPost.setEntity(createFhirResourceEntity(input));
@@ -510,7 +511,7 @@ public class AuthorizationInterceptorR4Test {
HttpPost httpPost;
HttpResponse status;
- ourReturn = Collections.singletonList((Resource) output);
+ ourReturn = Collections.singletonList(output);
ourHitMethod = false;
httpPost = new HttpPost("http://localhost:" + ourPort + "/");
httpPost.setEntity(createFhirResourceEntity(input));
@@ -544,7 +545,7 @@ public class AuthorizationInterceptorR4Test {
HttpResponse status;
String response;
- ourReturn = Collections.singletonList((Resource) output);
+ ourReturn = Collections.singletonList(output);
ourHitMethod = false;
httpPost = new HttpPost("http://localhost:" + ourPort + "/");
httpPost.setEntity(createFhirResourceEntity(input));
@@ -1841,13 +1842,86 @@ public class AuthorizationInterceptorR4Test {
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
status = ourClient.execute(httpGet);
extractResponseAndClose(status);
- assertEquals(200, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
+ assertEquals(403, status.getStatusLine().getStatusCode());
+ assertFalse(ourHitMethod);
}
@Test
- public void testReadByCompartmentWrong() throws Exception {
+ public void testReadByCompartmentWrongAllTypesProactiveBlockEnabledNoResponse() throws Exception {
+ ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
+ @Override
+ public List buildRuleList(RequestDetails theRequestDetails) {
+ return new RuleBuilder()
+ .allow("Rule 1").read().allResources().inCompartment("Patient", new IdType("Patient/1")).andThen()
+ .build();
+ }
+ }.setFlags());
+
+ HttpGet httpGet;
+ HttpResponse status;
+ String response;
+
+ ourReturn = Collections.emptyList();
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/2");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(403, status.getStatusLine().getStatusCode());
+ assertFalse(ourHitMethod);
+
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/10");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(404, status.getStatusLine().getStatusCode());
+ assertTrue(ourHitMethod);
+
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/10");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(404, status.getStatusLine().getStatusCode());
+ assertTrue(ourHitMethod);
+
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(403, status.getStatusLine().getStatusCode());
+ assertFalse(ourHitMethod);
+
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/_history");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(403, status.getStatusLine().getStatusCode());
+ assertFalse(ourHitMethod);
+
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/_history");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(403, status.getStatusLine().getStatusCode());
+ assertFalse(ourHitMethod);
+
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/999/_history");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(403, status.getStatusLine().getStatusCode());
+ assertFalse(ourHitMethod);
+ }
+
+ @Test
+ public void testReadByCompartmentWrongProactiveBlockDisabled() throws Exception {
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
@Override
public List buildRuleList(RequestDetails theRequestDetails) {
@@ -1856,7 +1930,7 @@ public class AuthorizationInterceptorR4Test {
.allow("Rule 2").read().resourcesOfType(Observation.class).inCompartment("Patient", new IdType("Patient/1"))
.build();
}
- });
+ }.setFlags(AuthorizationFlagsEnum.NO_NOT_PROACTIVELY_BLOCK_COMPARTMENT_READ_ACCESS));
HttpGet httpGet;
HttpResponse status;
@@ -1870,7 +1944,7 @@ public class AuthorizationInterceptorR4Test {
ourLog.info(response);
assertThat(response, containsString("Access denied by default policy (no applicable rules)"));
assertEquals(403, status.getStatusLine().getStatusCode());
- assertTrue(ourHitMethod);
+ assertFalse(ourHitMethod);
ourReturn = Collections.singletonList(createObservation(10, "Patient/2"));
ourHitMethod = false;
@@ -1914,6 +1988,133 @@ public class AuthorizationInterceptorR4Test {
}
+ @Test
+ public void testReadByCompartmentWrongProactiveBlockDisabledNoResponse() throws Exception {
+ ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
+ @Override
+ public List buildRuleList(RequestDetails theRequestDetails) {
+ return new RuleBuilder()
+ .allow("Rule 1").read().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1")).andThen()
+ .allow("Rule 2").read().resourcesOfType(Observation.class).inCompartment("Patient", new IdType("Patient/1"))
+ .build();
+ }
+ }.setFlags(AuthorizationFlagsEnum.NO_NOT_PROACTIVELY_BLOCK_COMPARTMENT_READ_ACCESS));
+
+ HttpGet httpGet;
+ HttpResponse status;
+ String response;
+
+ ourReturn = Collections.emptyList();
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/2");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(403, status.getStatusLine().getStatusCode());
+ assertFalse(ourHitMethod);
+
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/10");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(404, status.getStatusLine().getStatusCode());
+ assertTrue(ourHitMethod);
+
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/10");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(403, status.getStatusLine().getStatusCode());
+ assertFalse(ourHitMethod);
+
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(200, status.getStatusLine().getStatusCode());
+ assertTrue(ourHitMethod);
+
+ }
+
+ @Test
+ public void testReadByCompartmentWrongProactiveBlockEnabledNoResponse() throws Exception {
+ ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
+ @Override
+ public List buildRuleList(RequestDetails theRequestDetails) {
+ return new RuleBuilder()
+ .allow("Rule 1").read().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1")).andThen()
+ .allow("Rule 2").read().resourcesOfType(Observation.class).inCompartment("Patient", new IdType("Patient/1"))
+ .build();
+ }
+ }.setFlags());
+
+ HttpGet httpGet;
+ HttpResponse status;
+ String response;
+
+ ourReturn = Collections.emptyList();
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/2");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(403, status.getStatusLine().getStatusCode());
+ assertFalse(ourHitMethod);
+
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/10");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(404, status.getStatusLine().getStatusCode());
+ assertTrue(ourHitMethod);
+
+ // CarePlan could potentially be in the Patient/1 compartment but we don't
+ // have any rules explicitly allowing CarePlan so it's blocked
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/CarePlan/10");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(403, status.getStatusLine().getStatusCode());
+ assertFalse(ourHitMethod);
+
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(403, status.getStatusLine().getStatusCode());
+ assertFalse(ourHitMethod);
+
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/_history");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(403, status.getStatusLine().getStatusCode());
+ assertFalse(ourHitMethod);
+
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/_history");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(403, status.getStatusLine().getStatusCode());
+ assertFalse(ourHitMethod);
+
+ ourHitMethod = false;
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/999/_history");
+ status = ourClient.execute(httpGet);
+ response = extractResponseAndClose(status);
+ ourLog.info(response);
+ assertEquals(403, status.getStatusLine().getStatusCode());
+ assertFalse(ourHitMethod);
+ }
+
@Test
public void testReadByInstance() throws Exception {
ourConditionalCreateId = "1";
@@ -1965,7 +2166,7 @@ public class AuthorizationInterceptorR4Test {
@Override
public List buildRuleList(RequestDetails theRequestDetails) {
return new RuleBuilder()
- .allow("Rule 1").read().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1"))
+ .allow("Rule 1").read().resourcesOfType(Observation.class).inCompartment("Patient", new IdType("Patient/1"))
.build();
}
});
@@ -1977,11 +2178,11 @@ public class AuthorizationInterceptorR4Test {
ourReturn = new ArrayList<>();
for (int i = 0; i < 10; i++) {
- ourReturn.add(createPatient(1));
+ ourReturn.add(createObservation(i, "Patient/1"));
}
ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_count=5&_format=json");
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation?_count=5&_format=json&subject=Patient/1");
status = ourClient.execute(httpGet);
respString = extractResponseAndClose(status);
assertEquals(200, status.getStatusLine().getStatusCode());
@@ -1989,7 +2190,7 @@ public class AuthorizationInterceptorR4Test {
respBundle = ourCtx.newJsonParser().parseResource(Bundle.class, respString);
assertEquals(5, respBundle.getEntry().size());
assertEquals(10, respBundle.getTotal());
- assertEquals("Patient/1", respBundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
+ assertEquals("Observation/0", respBundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
assertNotNull(respBundle.getLink("next"));
// Load next page
@@ -2003,7 +2204,7 @@ public class AuthorizationInterceptorR4Test {
respBundle = ourCtx.newJsonParser().parseResource(Bundle.class, respString);
assertEquals(5, respBundle.getEntry().size());
assertEquals(10, respBundle.getTotal());
- assertEquals("Patient/1", respBundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
+ assertEquals("Observation/5", respBundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
assertNull(respBundle.getLink("next"));
}
@@ -2014,7 +2215,7 @@ public class AuthorizationInterceptorR4Test {
@Override
public List buildRuleList(RequestDetails theRequestDetails) {
return new RuleBuilder()
- .allow("Rule 1").read().resourcesOfType(Patient.class).inCompartment("Patient", new IdType("Patient/1"))
+ .allow("Rule 1").read().resourcesOfType(Observation.class).inCompartment("Patient", new IdType("Patient/1"))
.build();
}
});
@@ -2026,14 +2227,14 @@ public class AuthorizationInterceptorR4Test {
ourReturn = new ArrayList<>();
for (int i = 0; i < 5; i++) {
- ourReturn.add(createPatient(1));
+ ourReturn.add(createObservation(i, "Patient/1"));
}
- for (int i = 0; i < 5; i++) {
- ourReturn.add(createPatient(2));
+ for (int i = 5; i < 10; i++) {
+ ourReturn.add(createObservation(i, "Patient/2"));
}
ourHitMethod = false;
- httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?_count=5&_format=json");
+ httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation?_count=5&_format=json&subject=Patient/1");
status = ourClient.execute(httpGet);
respString = extractResponseAndClose(status);
assertEquals(200, status.getStatusLine().getStatusCode());
@@ -2041,7 +2242,7 @@ public class AuthorizationInterceptorR4Test {
respBundle = ourCtx.newJsonParser().parseResource(Bundle.class, respString);
assertEquals(5, respBundle.getEntry().size());
assertEquals(10, respBundle.getTotal());
- assertEquals("Patient/1", respBundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
+ assertEquals("Observation/0", respBundle.getEntry().get(0).getResource().getIdElement().toUnqualifiedVersionless().getValue());
assertNotNull(respBundle.getLink("next"));
// Load next page
@@ -2078,7 +2279,7 @@ public class AuthorizationInterceptorR4Test {
Bundle input = createTransactionWithPlaceholdersRequestBundle();
Bundle output = createTransactionWithPlaceholdersResponseBundle();
- ourReturn = Collections.singletonList((Resource) output);
+ ourReturn = Collections.singletonList(output);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/");
httpPost.setEntity(createFhirResourceEntity(input));
CloseableHttpResponse status = ourClient.execute(httpPost);
@@ -2111,7 +2312,7 @@ public class AuthorizationInterceptorR4Test {
Bundle input = createTransactionWithPlaceholdersRequestBundle();
Bundle output = createTransactionWithPlaceholdersResponseBundle();
- ourReturn = Collections.singletonList((Resource) output);
+ ourReturn = Collections.singletonList(output);
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/");
httpPost.setEntity(createFhirResourceEntity(input));
CloseableHttpResponse status = ourClient.execute(httpPost);
@@ -2146,7 +2347,7 @@ public class AuthorizationInterceptorR4Test {
HttpPost httpPost;
HttpResponse status;
- ourReturn = Collections.singletonList((Resource) output);
+ ourReturn = Collections.singletonList(output);
ourHitMethod = false;
httpPost = new HttpPost("http://localhost:" + ourPort + "/");
httpPost.setEntity(createFhirResourceEntity(input));
@@ -2640,6 +2841,9 @@ public class AuthorizationInterceptorR4Test {
@Read(version = true)
public CarePlan read(@IdParam IdType theId) {
ourHitMethod = true;
+ if (ourReturn.isEmpty()) {
+ throw new ResourceNotFoundException(theId);
+ }
return (CarePlan) ourReturn.get(0);
}
@@ -2733,11 +2937,14 @@ public class AuthorizationInterceptorR4Test {
@Read(version = true)
public Observation read(@IdParam IdType theId) {
ourHitMethod = true;
+ if (ourReturn.isEmpty()) {
+ throw new ResourceNotFoundException(theId);
+ }
return (Observation) ourReturn.get(0);
}
@Search()
- public List search() {
+ public List search(@OptionalParam(name = "subject") ReferenceParam theSubject) {
ourHitMethod = true;
return ourReturn;
}
@@ -2764,6 +2971,7 @@ public class AuthorizationInterceptorR4Test {
}
+ @SuppressWarnings("unused")
public static class DummyPatientResourceProvider implements IResourceProvider {
@Create()
@@ -2861,6 +3069,9 @@ public class AuthorizationInterceptorR4Test {
@Read(version = true)
public Patient read(@IdParam IdType theId) {
ourHitMethod = true;
+ if (ourReturn.isEmpty()) {
+ throw new ResourceNotFoundException(theId);
+ }
return (Patient) ourReturn.get(0);
}
diff --git a/hapi-fhir-validation/src/main/java/org/hl7/fhir/r4/validation/InstanceValidator.java b/hapi-fhir-validation/src/main/java/org/hl7/fhir/r4/validation/InstanceValidator.java
index 83aba3e0cd3..359ba8fbabc 100644
--- a/hapi-fhir-validation/src/main/java/org/hl7/fhir/r4/validation/InstanceValidator.java
+++ b/hapi-fhir-validation/src/main/java/org/hl7/fhir/r4/validation/InstanceValidator.java
@@ -1917,7 +1917,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
bundle.getNamedChildren("entry", entries);
Element match = null;
for (Element we : entries) {
- if (we.getChildValue("fullUrl").equals(targetUrl)) {
+ if (targetUrl.equals(we.getChildValue("fullUrl"))) {
Element r = we.getNamedChild("resource");
if (version.isEmpty()) {
rule(errors, IssueType.FORBIDDEN, -1, -1, path, match==null, "Multiple matches in bundle for reference " + ref);
diff --git a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/FhirInstanceValidatorR4Test.java b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/FhirInstanceValidatorR4Test.java
index 0ae6332859d..4c852810973 100644
--- a/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/FhirInstanceValidatorR4Test.java
+++ b/hapi-fhir-validation/src/test/java/org/hl7/fhir/r4/validation/FhirInstanceValidatorR4Test.java
@@ -317,6 +317,15 @@ public class FhirInstanceValidatorR4Test {
}
+ @Test
+ public void testValidateBundleWithNoFullUrl() throws IOException {
+ String encoded = IOUtils.toString(FhirInstanceValidatorR4Test.class.getResourceAsStream("/r4/r4-caredove-bundle.json"));
+
+ ValidationResult output = myVal.validateWithResult(encoded);
+ List errors = logResultsAndReturnNonInformationalOnes(output);
+ assertEquals(44, errors.size());
+ }
+
@Test
public void testBase64Valid() {
Base64BinaryType value = new Base64BinaryType(new byte[] {2, 3, 4, 5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1});
diff --git a/hapi-fhir-validation/src/test/resources/r4/r4-caredove-bundle.json b/hapi-fhir-validation/src/test/resources/r4/r4-caredove-bundle.json
new file mode 100644
index 00000000000..d61690a4f95
--- /dev/null
+++ b/hapi-fhir-validation/src/test/resources/r4/r4-caredove-bundle.json
@@ -0,0 +1,815 @@
+{
+
+ "resourceType": "Bundle",
+
+ "type": "transaction",
+
+ "timestamp": "2018-03-09T15:21:51.2112Z",
+
+ "entry": [
+
+ {
+
+ "resource": {
+
+ "resourceType": "ServiceRequest",
+
+ "id": 1,
+
+ "text": {
+
+ "status": "generated",
+
+ "div": "Human readable HTML narrative of entire ServiceRequest and related resources goes here. For brevity sake, it is omitted here, but can be included in an actual transmission"
+
+ },
+
+ "status": "active",
+
+ "intent": "proposal",
+
+ "priority": "routine",
+
+ "subject": {
+
+ "reference": "Patient/1"
+
+ },
+
+ "authoredOn": "2018-03-09T15:21:51Z",
+
+ "requester": {
+
+ "reference": "PractitionerRole/1"
+
+ },
+
+ "performer": {
+
+ "reference": "https://www.caredove.com/FHIR3/HealthcareService/8654"
+
+ },
+
+ "reasonCode": [
+
+ {
+
+ "text": "Reason for referral narrative goes here"
+
+ }
+
+ ],
+
+ "supportingInfo": [
+
+ {
+
+ "reference": "DocumentReference/1"
+
+ }
+
+ ],
+
+ "note": [
+
+ {
+
+ "text": "Allergies: Penicillin \nSocial History: History of family conflict \nlow social interaction \nFood Allergies: Peanuts"
+
+ }
+
+ ]
+
+ },
+
+ "request": {
+
+ "method": "POST",
+
+ "url": "ServiceRequest"
+
+ }
+
+ },
+
+ {
+
+ "resource": {
+
+ "resourceType": "Patient",
+
+ "id": 1,
+
+ "identifier": [
+
+ {
+
+ "type": {
+
+ "coding": [
+
+ {
+
+ "code": "JHN",
+
+ "system": "http://hl7.org/fhir/v2/0203"
+
+ }
+
+ ],
+
+ "text": "Ontario PHN"
+
+ },
+
+ "value": "4455 044 033",
+
+ "system": "http://ehealthontario.ca/API/FHIR/NamingSystem/ca-on-patient-hcn",
+
+ "extension": [
+
+ {
+
+ "url": "https://www.caredove.com/FHIR3/StructureDefinition/caredove-healthcardversion",
+
+ "valueString": "H"
+
+ }
+
+ ]
+
+ }
+
+ ],
+
+ "name": [
+
+ {
+
+ "given": [
+
+ "John",
+
+ "Scott"
+
+ ],
+
+ "family": "Smith"
+
+ }
+
+ ],
+
+ "telecom": [
+
+ {
+
+ "system": "phone",
+
+ "value": "(555) 111-1111",
+
+ "use": "mobile",
+
+ "rank": 1
+
+ },
+
+ {
+
+ "system": "phone",
+
+ "value": "(555) 222-2222",
+
+ "rank": 2
+
+ },
+
+ {
+
+ "system": "email",
+
+ "value": "testpatient@caredove.com"
+
+ }
+
+ ],
+
+ "gender": "male",
+
+ "birthDate": "1928-06-29",
+
+ "address": [
+
+ {
+
+ "use": "home",
+
+ "type": "physical",
+
+ "line": [
+
+ "Unit 2",
+
+ "50 Albert St."
+
+ ],
+
+ "city": "Waterloo",
+
+ "state": "ON",
+
+ "postalCode": "K8N 1N1",
+
+ "country": "Can"
+
+ }
+
+ ],
+
+ "maritalStatus": {
+
+ "coding": [
+
+ {
+
+ "code": "M",
+
+ "display": "Married"
+
+ }
+
+ ],
+
+ "text": "Married"
+
+ },
+
+ "contact": [
+
+ {
+
+ "relationship": [
+
+ {
+
+ "text": "Alternate Contact"
+
+ }
+
+ ],
+
+ "name": {
+
+ "given": [
+
+ "Shemergency",
+
+ "Scott"
+
+ ],
+
+ "family": "McContact"
+
+ },
+
+ "telecom": [
+
+ {
+
+ "system": "phone",
+
+ "value": "(555) 111-1111",
+
+ "use": "mobile",
+
+ "rank": 1
+
+ },
+
+ {
+
+ "system": "phone",
+
+ "value": "(555) 222-2222",
+
+ "rank": 2
+
+ },
+
+ {
+
+ "system": "email",
+
+ "value": "testcontact@caredove.com"
+
+ }
+
+ ],
+
+ "address": {
+
+ "use": "home",
+
+ "type": "physical",
+
+ "line": [
+
+ "Unit 2",
+
+ "50 Albert St."
+
+ ],
+
+ "city": "Waterloo",
+
+ "state": "ON",
+
+ "postalCode": "32819",
+
+ "country": "Can"
+
+ },
+
+ "gender": "female"
+
+ }
+
+ ],
+
+ "communication": [
+
+ {
+
+ "language": {
+
+ "coding": [
+
+ {
+
+ "code": "en",
+
+ "display": "English"
+
+ }
+
+ ],
+
+ "text": "English"
+
+ },
+
+ "preferred": true
+
+ }
+
+ ],
+
+ "generalPractitioner": [
+
+ {
+
+ "reference": "PractitionerRole/2"
+
+ }
+
+ ]
+
+ },
+
+ "request": {
+
+ "method": "POST",
+
+ "url": "Patient"
+
+ }
+
+ },
+
+ {
+
+ "resource": {
+
+ "resourceType": "PractitionerRole",
+
+ "id": 1,
+
+ "practitioner": {
+
+ "reference": "Practitioner/1"
+
+ },
+
+ "organization": {
+
+ "reference": "Organization/1"
+
+ },
+
+ "location": [
+
+ {
+
+ "reference": "Location/1"
+
+ }
+
+ ],
+
+ "telecom": [
+
+ {
+
+ "system": "phone",
+
+ "value": "(555) 111-1111",
+
+ "use": "work"
+
+ },
+
+ {
+
+ "system": "email",
+
+ "value": "testsender@caredove.com",
+
+ "use": "work"
+
+ }
+
+ ]
+
+ },
+
+ "request": {
+
+ "method": "POST",
+
+ "url": "PractitionerRole"
+
+ }
+
+ },
+
+ {
+
+ "resource": {
+
+ "resourceType": "Practitioner",
+
+ "id": 1,
+
+ "name": [
+
+ {
+
+ "given": [
+
+ "Requesty"
+
+ ],
+
+ "family": "McSenderson"
+
+ }
+
+ ]
+
+ },
+
+ "request": {
+
+ "method": "POST",
+
+ "url": "Practitioner"
+
+ }
+
+ },
+
+ {
+
+ "resource": {
+
+ "resourceType": "Organization",
+
+ "id": 1,
+
+ "name": "North Sender Clinic"
+
+ },
+
+ "request": {
+
+ "method": "POST",
+
+ "url": "Organization"
+
+ }
+
+ },
+
+ {
+
+ "resource": {
+
+ "resourceType": "Location",
+
+ "id": 1,
+
+ "name": "Downtown Sender Hub",
+
+ "address": {
+
+ "use": "work",
+
+ "type": "physical",
+
+ "line": [
+
+ "Suite 11",
+
+ "11 King st. West"
+
+ ],
+
+ "city": "Kitchener",
+
+ "state": "ON",
+
+ "postalCode": "N2L 1T1",
+
+ "country": "Can"
+
+ }
+
+ },
+
+ "request": {
+
+ "method": "POST",
+
+ "url": "Location"
+
+ }
+
+ },
+
+ {
+
+ "resource": {
+
+ "resourceType": "PractitionerRole",
+
+ "id": 2,
+
+ "practitioner": {
+
+ "reference": "Practitioner/2"
+
+ },
+
+ "organization": {
+
+ "reference": "Organization/2"
+
+ },
+
+ "location": [
+
+ {
+
+ "reference": "Location/2"
+
+ }
+
+ ],
+
+ "telecom": [
+
+ {
+
+ "system": "phone",
+
+ "value": "(555) 222-2222",
+
+ "use": "work"
+
+ },
+
+ {
+
+ "system": "email",
+
+ "value": "familydoc@caredove.com",
+
+ "use": "work"
+
+ }
+
+ ]
+
+ },
+
+ "request": {
+
+ "method": "POST",
+
+ "url": "PractitionerRole"
+
+ }
+
+ },
+
+ {
+
+ "resource": {
+
+ "resourceType": "Practitioner",
+
+ "id": 2,
+
+ "name": [
+
+ {
+
+ "given": [
+
+ "Dr. Prim"
+
+ ],
+
+ "family": "Caredoc"
+
+ }
+
+ ]
+
+ },
+
+ "request": {
+
+ "method": "POST",
+
+ "url": "Practitioner"
+
+ }
+
+ },
+
+ {
+
+ "resource": {
+
+ "resourceType": "Organization",
+
+ "id": 2,
+
+ "name": "Star Family Health Team"
+
+ },
+
+ "request": {
+
+ "method": "POST",
+
+ "url": "Organization"
+
+ }
+
+ },
+
+ {
+
+ "resource": {
+
+ "resourceType": "DocumentReference",
+
+ "id": 1,
+
+ "status": "current",
+
+ "created": "2018-03-09T15:21:51.2112Z",
+
+ "description": "Filename or Document Title goes here",
+
+ "content": [
+
+ {
+
+ "attachment": "NEEDS WORK - ATTACHMENT DATA TYPE",
+
+ "format": "NEEDS WORK - FORMAT INFO"
+
+ }
+
+ ]
+
+ },
+
+ "request": {
+
+ "method": "POST",
+
+ "url": "Practitioner"
+
+ }
+
+ },
+
+ {
+
+ "resource": {
+
+ "resourceType": "Location",
+
+ "id": 2,
+
+ "name": "West Side GP Office",
+
+ "address": {
+
+ "use": "work",
+
+ "type": "physical",
+
+ "line": [
+
+ "22 Weber st. East"
+
+ ],
+
+ "city": "Kitchener",
+
+ "state": "ON",
+
+ "postalCode": "N2L 2T2",
+
+ "country": "Can"
+
+ }
+
+ },
+
+ "request": {
+
+ "method": "POST",
+
+ "url": "Location"
+
+ }
+
+ },
+
+ {
+
+ "resource": {
+
+ "resourceType": "Task",
+
+ "id": 1,
+
+ "basedOn" : {
+
+ "reference" : "ServiceRequest/1"
+
+ },
+
+ "status" : "requested",
+
+ "businessStatus " : {
+
+ "text" : "Waiting for preliminary review"
+
+ },
+
+ "intent" : "proposal",
+
+ "code" : {
+
+ "text" : "Process Request"
+
+ },
+
+ "description" : "Process and close this referral request",
+
+ "authoredOn" : "2018-03-09T15:21:51Z",
+
+ "lastModified" : "2018-03-09T15:21:51Z"
+
+ },
+
+ "request": {
+
+ "method": "POST",
+
+ "url": "Task"
+
+ }
+
+ }
+
+ ]
+
+}
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index f32569c36a6..88846479024 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -42,6 +42,30 @@
Spring-data (used by the JPA server) has been upgraded to version 2.0.7
(from version 1.11.6). Thanks to Roman Doboni for the pull request!
+
+ A crash in the validator was fixed: Validating a Bundle that did not have fullUrl entries
+ in a required spot caused a NullPointerException.
+
+
+ AuthorizationInterceptor now examines requests more closely in order
+ to block requests early that are not possibly going to return
+ allowable results when compartment rules are used. For example,
+ if an AuthorizationInterceptor is configured to allow only
+ read]]>
+ access to compartment
+ Patient/123]]>,
+ a search for
+ Observation?subject=987]]>
+ will now be blocked before the method handler is called. Previously
+ the search was performed and the results were examined in order to
+ determine whether they were all in the appropriate compartment, but
+ this incurs a performance cost, and means that this search would
+ successfully return an empty Bundle if no matches were present.
+
]]>
+ A new setting on AuthorizationInterceptor called
+ setFlags(flags)]]>
+ can be used to maintain the previous behaviour.
+