mirror of
https://github.com/hapifhir/hapi-fhir.git
synced 2025-03-09 14:33:32 +00:00
Further refine #762
This commit is contained in:
parent
db1d2d77cd
commit
4887f18bb3
@ -20,18 +20,6 @@ package ca.uhn.fhir.rest.server.interceptor.auth;
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||
@ -40,6 +28,21 @@ import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
|
||||
import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter;
|
||||
import ca.uhn.fhir.util.CoverageIgnore;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
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.IBaseParameters;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
|
||||
/**
|
||||
* This class is a base class for interceptors which can be used to
|
||||
@ -66,9 +69,8 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param theDefaultPolicy
|
||||
* The default policy if no rules apply (must not be null)
|
||||
*
|
||||
* @param theDefaultPolicy The default policy if no rules apply (must not be null)
|
||||
*/
|
||||
public AuthorizationInterceptor(PolicyEnum theDefaultPolicy) {
|
||||
this();
|
||||
@ -76,7 +78,7 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
||||
}
|
||||
|
||||
private void applyRulesAndFailIfDeny(RestOperationTypeEnum theOperation, RequestDetails theRequestDetails, IBaseResource theInputResource, IIdType theInputResourceId,
|
||||
IBaseResource theOutputResource) {
|
||||
IBaseResource theOutputResource) {
|
||||
Verdict decision = applyRulesAndReturnDecision(theOperation, theRequestDetails, theInputResource, theInputResourceId, theOutputResource);
|
||||
|
||||
if (decision.getDecision() == PolicyEnum.ALLOW) {
|
||||
@ -88,7 +90,7 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
||||
|
||||
@Override
|
||||
public Verdict applyRulesAndReturnDecision(RestOperationTypeEnum theOperation, RequestDetails theRequestDetails, IBaseResource theInputResource, IIdType theInputResourceId,
|
||||
IBaseResource theOutputResource) {
|
||||
IBaseResource theOutputResource) {
|
||||
List<IAuthRule> rules = buildRuleList(theRequestDetails);
|
||||
ourLog.trace("Applying {} rules to render an auth decision for operation {}", rules.size(), theOperation);
|
||||
|
||||
@ -117,9 +119,8 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
||||
* out who the current user is and then using a {@link RuleBuilder} to create
|
||||
* an appropriate rule chain.
|
||||
* </p>
|
||||
*
|
||||
* @param theRequestDetails
|
||||
* The individual request currently being applied
|
||||
*
|
||||
* @param theRequestDetails The individual request currently being applied
|
||||
*/
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new ArrayList<IAuthRule>();
|
||||
@ -127,63 +128,63 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
||||
|
||||
private OperationExamineDirection determineOperationDirection(RestOperationTypeEnum theOperation, IBaseResource theRequestResource) {
|
||||
switch (theOperation) {
|
||||
case ADD_TAGS:
|
||||
case DELETE_TAGS:
|
||||
case GET_TAGS:
|
||||
// These are DSTU1 operations and not relevant
|
||||
return OperationExamineDirection.NONE;
|
||||
case ADD_TAGS:
|
||||
case DELETE_TAGS:
|
||||
case GET_TAGS:
|
||||
// These are DSTU1 operations and not relevant
|
||||
return OperationExamineDirection.NONE;
|
||||
|
||||
case EXTENDED_OPERATION_INSTANCE:
|
||||
case EXTENDED_OPERATION_SERVER:
|
||||
case EXTENDED_OPERATION_TYPE:
|
||||
return OperationExamineDirection.BOTH;
|
||||
case EXTENDED_OPERATION_INSTANCE:
|
||||
case EXTENDED_OPERATION_SERVER:
|
||||
case EXTENDED_OPERATION_TYPE:
|
||||
return OperationExamineDirection.BOTH;
|
||||
|
||||
case METADATA:
|
||||
// Security does not apply to these operations
|
||||
return OperationExamineDirection.IN;
|
||||
case METADATA:
|
||||
// Security does not apply to these operations
|
||||
return OperationExamineDirection.IN;
|
||||
|
||||
case DELETE:
|
||||
// Delete is a special case
|
||||
return OperationExamineDirection.NONE;
|
||||
case DELETE:
|
||||
// Delete is a special case
|
||||
return OperationExamineDirection.NONE;
|
||||
|
||||
case CREATE:
|
||||
case UPDATE:
|
||||
case PATCH:
|
||||
// if (theRequestResource != null) {
|
||||
// if (theRequestResource.getIdElement() != null) {
|
||||
// if (theRequestResource.getIdElement().hasIdPart() == false) {
|
||||
// return OperationExamineDirection.IN_UNCATEGORIZED;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return OperationExamineDirection.IN;
|
||||
case CREATE:
|
||||
case UPDATE:
|
||||
case PATCH:
|
||||
// if (theRequestResource != null) {
|
||||
// if (theRequestResource.getIdElement() != null) {
|
||||
// if (theRequestResource.getIdElement().hasIdPart() == false) {
|
||||
// return OperationExamineDirection.IN_UNCATEGORIZED;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return OperationExamineDirection.IN;
|
||||
|
||||
case META:
|
||||
case META_ADD:
|
||||
case META_DELETE:
|
||||
// meta operations do not apply yet
|
||||
return OperationExamineDirection.NONE;
|
||||
case META:
|
||||
case META_ADD:
|
||||
case META_DELETE:
|
||||
// meta operations do not apply yet
|
||||
return OperationExamineDirection.NONE;
|
||||
|
||||
case GET_PAGE:
|
||||
case HISTORY_INSTANCE:
|
||||
case HISTORY_SYSTEM:
|
||||
case HISTORY_TYPE:
|
||||
case READ:
|
||||
case SEARCH_SYSTEM:
|
||||
case SEARCH_TYPE:
|
||||
case VREAD:
|
||||
return OperationExamineDirection.OUT;
|
||||
case GET_PAGE:
|
||||
case HISTORY_INSTANCE:
|
||||
case HISTORY_SYSTEM:
|
||||
case HISTORY_TYPE:
|
||||
case READ:
|
||||
case SEARCH_SYSTEM:
|
||||
case SEARCH_TYPE:
|
||||
case VREAD:
|
||||
return OperationExamineDirection.OUT;
|
||||
|
||||
case TRANSACTION:
|
||||
return OperationExamineDirection.BOTH;
|
||||
case TRANSACTION:
|
||||
return OperationExamineDirection.BOTH;
|
||||
|
||||
case VALIDATE:
|
||||
// Nothing yet
|
||||
return OperationExamineDirection.NONE;
|
||||
case VALIDATE:
|
||||
// Nothing yet
|
||||
return OperationExamineDirection.NONE;
|
||||
|
||||
default:
|
||||
// Should not happen
|
||||
throw new IllegalStateException("Unable to apply security to event of type " + theOperation);
|
||||
default:
|
||||
// Should not happen
|
||||
throw new IllegalStateException("Unable to apply security to event of type " + theOperation);
|
||||
}
|
||||
|
||||
}
|
||||
@ -195,6 +196,16 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
||||
return myDefaultPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* The default policy if no rules have been found to apply. Default value for this setting is {@link PolicyEnum#DENY}
|
||||
*
|
||||
* @param theDefaultPolicy The policy (must not be <code>null</code>)
|
||||
*/
|
||||
public void setDefaultPolicy(PolicyEnum theDefaultPolicy) {
|
||||
Validate.notNull(theDefaultPolicy, "theDefaultPolicy must not be null");
|
||||
myDefaultPolicy = theDefaultPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an access control verdict of {@link PolicyEnum#DENY}.
|
||||
* <p>
|
||||
@ -221,17 +232,17 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
||||
IIdType inputResourceId = null;
|
||||
|
||||
switch (determineOperationDirection(theOperation, theProcessedRequest.getResource())) {
|
||||
case IN:
|
||||
case BOTH:
|
||||
inputResource = theProcessedRequest.getResource();
|
||||
inputResourceId = theProcessedRequest.getId();
|
||||
break;
|
||||
case OUT:
|
||||
// inputResource = null;
|
||||
inputResourceId = theProcessedRequest.getId();
|
||||
break;
|
||||
case NONE:
|
||||
return;
|
||||
case IN:
|
||||
case BOTH:
|
||||
inputResource = theProcessedRequest.getResource();
|
||||
inputResourceId = theProcessedRequest.getId();
|
||||
break;
|
||||
case OUT:
|
||||
// inputResource = null;
|
||||
inputResourceId = theProcessedRequest.getId();
|
||||
break;
|
||||
case NONE:
|
||||
return;
|
||||
}
|
||||
|
||||
RequestDetails requestDetails = theProcessedRequest.getRequestDetails();
|
||||
@ -241,43 +252,39 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
||||
@Override
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, IBaseResource theResponseObject) {
|
||||
switch (determineOperationDirection(theRequestDetails.getRestOperationType(), null)) {
|
||||
case IN:
|
||||
case NONE:
|
||||
return true;
|
||||
case BOTH:
|
||||
case OUT:
|
||||
break;
|
||||
case IN:
|
||||
case NONE:
|
||||
return true;
|
||||
case BOTH:
|
||||
case OUT:
|
||||
break;
|
||||
}
|
||||
|
||||
FhirContext fhirContext = theRequestDetails.getServer().getFhirContext();
|
||||
List<IBaseResource> resources = Collections.emptyList();
|
||||
|
||||
switch (theRequestDetails.getRestOperationType()) {
|
||||
case SEARCH_SYSTEM:
|
||||
case SEARCH_TYPE:
|
||||
case HISTORY_INSTANCE:
|
||||
case HISTORY_SYSTEM:
|
||||
case HISTORY_TYPE:
|
||||
case TRANSACTION:
|
||||
case GET_PAGE:
|
||||
case EXTENDED_OPERATION_SERVER:
|
||||
case EXTENDED_OPERATION_TYPE:
|
||||
case EXTENDED_OPERATION_INSTANCE: {
|
||||
if (theResponseObject != null) {
|
||||
if (theResponseObject instanceof IBaseBundle) {
|
||||
resources = toListOfResourcesAndExcludeContainer(theResponseObject, fhirContext);
|
||||
} else if (theResponseObject instanceof IBaseParameters) {
|
||||
case SEARCH_SYSTEM:
|
||||
case SEARCH_TYPE:
|
||||
case HISTORY_INSTANCE:
|
||||
case HISTORY_SYSTEM:
|
||||
case HISTORY_TYPE:
|
||||
case TRANSACTION:
|
||||
case GET_PAGE:
|
||||
case EXTENDED_OPERATION_SERVER:
|
||||
case EXTENDED_OPERATION_TYPE:
|
||||
case EXTENDED_OPERATION_INSTANCE: {
|
||||
if (theResponseObject != null) {
|
||||
resources = toListOfResourcesAndExcludeContainer(theResponseObject, fhirContext);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (theResponseObject != null) {
|
||||
resources = Collections.singletonList(theResponseObject);
|
||||
default: {
|
||||
if (theResponseObject != null) {
|
||||
resources = Collections.singletonList(theResponseObject);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (IBaseResource nextResponse : resources) {
|
||||
@ -296,7 +303,7 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
||||
@CoverageIgnore
|
||||
@Override
|
||||
public boolean outgoingResponse(RequestDetails theRequestDetails, TagList theResponseObject, HttpServletRequest theServletRequest, HttpServletResponse theServletResponse)
|
||||
throws AuthenticationException {
|
||||
throws AuthenticationException {
|
||||
throw failForDstu1();
|
||||
}
|
||||
|
||||
@ -318,33 +325,38 @@ public class AuthorizationInterceptor extends ServerOperationInterceptorAdapter
|
||||
handleUserOperation(theRequest, theNewResource, RestOperationTypeEnum.UPDATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* The default policy if no rules have been found to apply. Default value for this setting is {@link PolicyEnum#DENY}
|
||||
*
|
||||
* @param theDefaultPolicy
|
||||
* The policy (must not be <code>null</code>)
|
||||
*/
|
||||
public void setDefaultPolicy(PolicyEnum theDefaultPolicy) {
|
||||
Validate.notNull(theDefaultPolicy, "theDefaultPolicy must not be null");
|
||||
myDefaultPolicy = theDefaultPolicy;
|
||||
}
|
||||
|
||||
private List<IBaseResource> toListOfResourcesAndExcludeContainer(IBaseResource theResponseObject, FhirContext fhirContext) {
|
||||
List<IBaseResource> resources;
|
||||
resources = fhirContext.newTerser().getAllPopulatedChildElementsOfType(theResponseObject, IBaseResource.class);
|
||||
|
||||
// Exclude the container
|
||||
if (resources.size() > 0 && resources.get(0) == theResponseObject) {
|
||||
resources = resources.subList(1, resources.size());
|
||||
}
|
||||
|
||||
return resources;
|
||||
}
|
||||
|
||||
private static UnsupportedOperationException failForDstu1() {
|
||||
return new UnsupportedOperationException("Use of this interceptor on DSTU1 servers is not supportd");
|
||||
}
|
||||
|
||||
static List<IBaseResource> toListOfResourcesAndExcludeContainer(IBaseResource theResponseObject, FhirContext fhirContext) {
|
||||
if (theResponseObject == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<IBaseResource> retVal;
|
||||
|
||||
boolean isContainer = false;
|
||||
if (theResponseObject instanceof IBaseBundle) {
|
||||
isContainer = true;
|
||||
} else if (theResponseObject instanceof IBaseParameters) {
|
||||
isContainer = true;
|
||||
}
|
||||
|
||||
if (!isContainer) {
|
||||
return Collections.singletonList(theResponseObject);
|
||||
}
|
||||
|
||||
retVal = fhirContext.newTerser().getAllPopulatedChildElementsOfType(theResponseObject, IBaseResource.class);
|
||||
|
||||
// Exclude the container
|
||||
if (retVal.size() > 0 && retVal.get(0) == theResponseObject) {
|
||||
retVal = retVal.subList(1, retVal.size());
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private enum OperationExamineDirection {
|
||||
BOTH,
|
||||
IN,
|
||||
|
@ -165,13 +165,15 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ {
|
||||
}
|
||||
return verdict;
|
||||
} else if (theOutputResource != null) {
|
||||
List<BundleEntryParts> inputResources = BundleUtil.toListOfEntries(ctx, (IBaseBundle) theInputResource);
|
||||
|
||||
List<IBaseResource> outputResources = AuthorizationInterceptor.toListOfResourcesAndExcludeContainer(theOutputResource, theRequestDetails.getFhirContext());
|
||||
|
||||
Verdict verdict = null;
|
||||
for (BundleEntryParts nextPart : inputResources) {
|
||||
if (nextPart.getResource() == null) {
|
||||
for (IBaseResource nextResource : outputResources) {
|
||||
if (nextResource == null) {
|
||||
continue;
|
||||
}
|
||||
Verdict newVerdict = theRuleApplier.applyRulesAndReturnDecision(RestOperationTypeEnum.READ, theRequestDetails, null, null, nextPart.getResource());
|
||||
Verdict newVerdict = theRuleApplier.applyRulesAndReturnDecision(RestOperationTypeEnum.READ, theRequestDetails, null, null, nextResource);
|
||||
if (newVerdict == null) {
|
||||
continue;
|
||||
} else if (verdict == null) {
|
||||
|
@ -52,11 +52,11 @@ import static org.junit.Assert.*;
|
||||
public class AuthorizationInterceptorR4Test {
|
||||
|
||||
private static final String ERR403 = "{\"resourceType\":\"OperationOutcome\",\"issue\":[{\"severity\":\"error\",\"code\":\"processing\",\"diagnostics\":\"Access denied by default policy (no applicable rules)\"}]}";
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(AuthorizationInterceptorR4Test.class);
|
||||
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(AuthorizationInterceptorR4Test.class);
|
||||
private static int ourPort;
|
||||
private static List<Resource> ourReturn;
|
||||
private static Server ourServer;
|
||||
@ -112,6 +112,77 @@ public class AuthorizationInterceptorR4Test {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private Bundle createTransactionWithPlaceholdersRequestBundle() {
|
||||
// Create a input that will be used as a transaction
|
||||
Bundle input = new Bundle();
|
||||
input.setType(Bundle.BundleType.TRANSACTION);
|
||||
|
||||
String encounterId = "123-123";
|
||||
String encounterSystem = "http://our.internal.code.system/encounter";
|
||||
Encounter encounter = new Encounter();
|
||||
|
||||
encounter.addIdentifier(new Identifier().setValue(encounterId)
|
||||
.setSystem(encounterSystem));
|
||||
|
||||
encounter.setStatus(Encounter.EncounterStatus.FINISHED);
|
||||
|
||||
Patient p = new Patient()
|
||||
.addIdentifier(new Identifier().setValue("321-321").setSystem("http://our.internal.code.system/patient"));
|
||||
p.setId(IdDt.newRandomUuid());
|
||||
|
||||
// add patient to input so its created
|
||||
input.addEntry()
|
||||
.setFullUrl(p.getId())
|
||||
.setResource(p)
|
||||
.getRequest()
|
||||
.setUrl("Patient")
|
||||
.setMethod(Bundle.HTTPVerb.POST);
|
||||
|
||||
Reference patientRef = new Reference(p.getId());
|
||||
|
||||
encounter.setSubject(patientRef);
|
||||
Condition condition = new Condition()
|
||||
.setCode(new CodeableConcept().addCoding(
|
||||
new Coding("http://hl7.org/fhir/icd-10", "S53.40", "FOREARM SPRAIN / STRAIN")))
|
||||
.setSubject(patientRef);
|
||||
|
||||
condition.setId(IdDt.newRandomUuid());
|
||||
|
||||
// add condition to input so its created
|
||||
input.addEntry()
|
||||
.setFullUrl(condition.getId())
|
||||
.setResource(condition)
|
||||
.getRequest()
|
||||
.setUrl("Condition")
|
||||
.setMethod(Bundle.HTTPVerb.POST);
|
||||
|
||||
Encounter.DiagnosisComponent dc = new Encounter.DiagnosisComponent();
|
||||
|
||||
dc.setCondition(new Reference(condition.getId()));
|
||||
encounter.addDiagnosis(dc);
|
||||
CodeableConcept reason = new CodeableConcept();
|
||||
reason.setText("SLIPPED ON FLOOR,PAIN L) ELBOW");
|
||||
encounter.addReason(reason);
|
||||
|
||||
// add encounter to input so its created
|
||||
input.addEntry()
|
||||
.setResource(encounter)
|
||||
.getRequest()
|
||||
.setUrl("Encounter")
|
||||
.setIfNoneExist("identifier=" + encounterSystem + "|" + encounterId)
|
||||
.setMethod(Bundle.HTTPVerb.POST);
|
||||
return input;
|
||||
}
|
||||
|
||||
private Bundle createTransactionWithPlaceholdersResponseBundle() {
|
||||
Bundle output = new Bundle();
|
||||
output.setType(Bundle.BundleType.TRANSACTIONRESPONSE);
|
||||
output.addEntry()
|
||||
.setResource(new Patient().setActive(true)) // don't give this an ID
|
||||
.getResponse().setLocation("/Patient/1");
|
||||
return output;
|
||||
}
|
||||
|
||||
private String extractResponseAndClose(HttpResponse status) throws IOException {
|
||||
if (status.getEntity() == null) {
|
||||
return null;
|
||||
@ -207,7 +278,7 @@ public class AuthorizationInterceptorR4Test {
|
||||
@Override
|
||||
public List<IAuthRule> 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();
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
@ -264,108 +335,6 @@ public class AuthorizationInterceptorR4Test {
|
||||
assertEquals(403, status.getStatusLine().getStatusCode());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See #762
|
||||
*/
|
||||
//@Test
|
||||
public void testInstanceRuleOkForResourceWithNoId2() throws IOException {
|
||||
|
||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.allow("transactions").transaction().withAnyOperation().andApplyNormalRules().andThen()
|
||||
.allow("write patient").write().resourcesOfType(Patient.class).withAnyId().andThen()
|
||||
.allow("write encounter").write().resourcesOfType(Encounter.class).withAnyId().andThen()
|
||||
.allow("write condition").write().resourcesOfType(Condition.class).withAnyId().andThen()
|
||||
.denyAll("deny all")
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Create a bundle that will be used as a transaction
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.setType(Bundle.BundleType.TRANSACTION);
|
||||
|
||||
|
||||
|
||||
String encounterId = "123-123";
|
||||
String encounterSystem = "http://our.internal.code.system/encounter";
|
||||
Encounter encounter = new Encounter();
|
||||
|
||||
encounter.addIdentifier(new Identifier().setValue(encounterId)
|
||||
.setSystem(encounterSystem));
|
||||
|
||||
encounter.setStatus(Encounter.EncounterStatus.FINISHED);
|
||||
|
||||
Patient p = new Patient()
|
||||
.addIdentifier(new Identifier().setValue("321-321").setSystem("http://our.internal.code.system/patient"));
|
||||
p.setId(IdDt.newRandomUuid());
|
||||
|
||||
// add patient to bundle so its created
|
||||
bundle.addEntry()
|
||||
.setFullUrl(p.getId())
|
||||
.setResource(p)
|
||||
.getRequest()
|
||||
.setUrl("Patient")
|
||||
.setMethod(Bundle.HTTPVerb.POST);
|
||||
|
||||
Reference patientRef = new Reference(p.getId());
|
||||
|
||||
encounter.setSubject(patientRef);
|
||||
Condition condition = new Condition()
|
||||
.setCode(new CodeableConcept().addCoding(
|
||||
new Coding("http://hl7.org/fhir/icd-10", "S53.40", "FOREARM SPRAIN / STRAIN")))
|
||||
.setSubject(patientRef);
|
||||
|
||||
condition.setId(IdDt.newRandomUuid());
|
||||
|
||||
// add condition to bundle so its created
|
||||
bundle.addEntry()
|
||||
.setFullUrl(condition.getId())
|
||||
.setResource(condition)
|
||||
.getRequest()
|
||||
.setUrl("Condition")
|
||||
.setMethod(Bundle.HTTPVerb.POST);
|
||||
|
||||
Encounter.DiagnosisComponent dc = new Encounter.DiagnosisComponent();
|
||||
|
||||
dc.setCondition(new Reference(condition.getId()));
|
||||
encounter.addDiagnosis(dc);
|
||||
CodeableConcept reason = new CodeableConcept();
|
||||
reason.setText("SLIPPED ON FLOOR,PAIN L) ELBOW");
|
||||
encounter.addReason(reason);
|
||||
|
||||
// add encounter to bundle so its created
|
||||
bundle.addEntry()
|
||||
.setResource(encounter)
|
||||
.getRequest()
|
||||
.setUrl("Encounter")
|
||||
.setIfNoneExist("identifier=" + encounterSystem + "|" + encounterId)
|
||||
.setMethod(Bundle.HTTPVerb.POST);
|
||||
|
||||
Bundle output = new Bundle();
|
||||
output.setType(Bundle.BundleType.TRANSACTIONRESPONSE);
|
||||
output.addEntry()
|
||||
.setResource(new Patient().setActive(true)) // don't give this an ID
|
||||
.getResponse().setLocation("/Patient/1");
|
||||
|
||||
|
||||
ourReturn = Collections.singletonList((Resource) output);
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/");
|
||||
httpPost.setEntity(createFhirResourceEntity(bundle));
|
||||
CloseableHttpResponse status = ourClient.execute(httpPost);
|
||||
String resp = extractResponseAndClose(status);
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
|
||||
ourLog.info(resp);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBatchWhenTransactionReadDenied() throws Exception {
|
||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@ -561,7 +530,7 @@ public class AuthorizationInterceptorR4Test {
|
||||
@Override
|
||||
public List<IAuthRule> 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();
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
@ -623,6 +592,113 @@ public class AuthorizationInterceptorR4Test {
|
||||
assertTrue(ourHitMethod);
|
||||
}
|
||||
|
||||
/**
|
||||
* See #762
|
||||
*/
|
||||
@Test
|
||||
public void testTransactionWithPlaceholderIdsResponseUnauthorized() throws IOException {
|
||||
|
||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.allow("transactions").transaction().withAnyOperation().andApplyNormalRules().andThen()
|
||||
.allow("write patient").write().resourcesOfType(Patient.class).withAnyId().andThen()
|
||||
.allow("write encounter").write().resourcesOfType(Encounter.class).withAnyId().andThen()
|
||||
.allow("write condition").write().resourcesOfType(Condition.class).withAnyId().andThen()
|
||||
.denyAll("deny all")
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
Bundle input = createTransactionWithPlaceholdersRequestBundle();
|
||||
Bundle output = createTransactionWithPlaceholdersResponseBundle();
|
||||
|
||||
ourReturn = Collections.singletonList((Resource) output);
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/");
|
||||
httpPost.setEntity(createFhirResourceEntity(input));
|
||||
CloseableHttpResponse status = ourClient.execute(httpPost);
|
||||
String resp = extractResponseAndClose(status);
|
||||
assertEquals(403, status.getStatusLine().getStatusCode());
|
||||
|
||||
ourLog.info(resp);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* See #762
|
||||
*/
|
||||
@Test
|
||||
public void testTransactionWithPlaceholderIdsResponseAuthorized() throws IOException {
|
||||
|
||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.allow("transactions").transaction().withAnyOperation().andApplyNormalRules().andThen()
|
||||
.allow("read patient").read().resourcesOfType(Patient.class).withAnyId().andThen()
|
||||
.allow("write patient").write().resourcesOfType(Patient.class).withAnyId().andThen()
|
||||
.allow("write encounter").write().resourcesOfType(Encounter.class).withAnyId().andThen()
|
||||
.allow("write condition").write().resourcesOfType(Condition.class).withAnyId().andThen()
|
||||
.denyAll("deny all")
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
Bundle input = createTransactionWithPlaceholdersRequestBundle();
|
||||
Bundle output = createTransactionWithPlaceholdersResponseBundle();
|
||||
|
||||
ourReturn = Collections.singletonList((Resource) output);
|
||||
HttpPost httpPost = new HttpPost("http://localhost:" + ourPort + "/");
|
||||
httpPost.setEntity(createFhirResourceEntity(input));
|
||||
CloseableHttpResponse status = ourClient.execute(httpPost);
|
||||
String resp = extractResponseAndClose(status);
|
||||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
|
||||
ourLog.info(resp);
|
||||
|
||||
}
|
||||
|
||||
@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 testMetadataAllow() throws Exception {
|
||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@ -865,8 +941,8 @@ public class AuthorizationInterceptorR4Test {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.allow("RULE 1").operation().named("opName").onAnyInstance().andThen()
|
||||
.build();
|
||||
.allow("RULE 1").operation().named("opName").onAnyInstance().andThen()
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
@ -1272,102 +1348,6 @@ public class AuthorizationInterceptorR4Test {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadPageRight() throws Exception {
|
||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> 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<IAuthRule> 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) {
|
||||
@ -1436,6 +1416,147 @@ public class AuthorizationInterceptorR4Test {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadByInstance() throws Exception {
|
||||
ourConditionalCreateId = "1";
|
||||
|
||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> 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);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadPageRight() throws Exception {
|
||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> 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<IAuthRule> 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 testTransactionWriteGood() throws Exception {
|
||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@ -1818,82 +1939,6 @@ public class AuthorizationInterceptorR4Test {
|
||||
|
||||
}
|
||||
|
||||
@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<IAuthRule> 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";
|
||||
@ -1949,48 +1994,39 @@ public class AuthorizationInterceptorR4Test {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadByInstance() throws Exception {
|
||||
public void testWritePatchByInstance() throws Exception {
|
||||
ourConditionalCreateId = "1";
|
||||
|
||||
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
|
||||
@Override
|
||||
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
|
||||
return new RuleBuilder()
|
||||
.allow("Rule 1").read().instance("Observation/900").andThen()
|
||||
.allow("Rule 1").read().instance("901").andThen()
|
||||
.allow("Rule 1").write().instance("Patient/900").andThen()
|
||||
.build();
|
||||
}
|
||||
});
|
||||
|
||||
HttpEntityEnclosingRequestBase httpPost;
|
||||
HttpResponse status;
|
||||
String response;
|
||||
HttpGet httpGet;
|
||||
|
||||
ourReturn = Collections.singletonList(createObservation(900, "Patient/1"));
|
||||
String input = "[ { \"op\": \"replace\", \"path\": \"/gender\", \"value\": \"male\" } ]";
|
||||
|
||||
ourHitMethod = false;
|
||||
httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation/900");
|
||||
status = ourClient.execute(httpGet);
|
||||
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(200, status.getStatusLine().getStatusCode());
|
||||
assertEquals(204, 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);
|
||||
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());
|
||||
assertEquals(ERR403, response);
|
||||
assertFalse(ourHitMethod);
|
||||
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@ -2220,6 +2256,14 @@ public class AuthorizationInterceptorR4Test {
|
||||
return (Parameters) new Parameters().setId("1");
|
||||
}
|
||||
|
||||
@Patch()
|
||||
public MethodOutcome patch(@IdParam IdType theId, @ResourceParam String theResource, PatchTypeEnum thePatchType) {
|
||||
ourHitMethod = true;
|
||||
|
||||
MethodOutcome retVal = new MethodOutcome();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@Read(version = true)
|
||||
public Patient read(@IdParam IdType theId) {
|
||||
ourHitMethod = true;
|
||||
@ -2252,17 +2296,9 @@ public class AuthorizationInterceptorR4Test {
|
||||
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) {
|
||||
@Validate.Mode ValidationModeEnum theMode, @Validate.Profile String theProfile, RequestDetails theRequestDetails) {
|
||||
ourHitMethod = true;
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
oo.addIssue().setDiagnostics("OK");
|
||||
@ -2271,7 +2307,7 @@ public class AuthorizationInterceptorR4Test {
|
||||
|
||||
@Validate
|
||||
public MethodOutcome validate(@ResourceParam Patient theResource, @ResourceParam String theRawResource, @ResourceParam EncodingEnum theEncoding, @Validate.Mode ValidationModeEnum theMode,
|
||||
@Validate.Profile String theProfile, RequestDetails theRequestDetails) {
|
||||
@Validate.Profile String theProfile, RequestDetails theRequestDetails) {
|
||||
ourHitMethod = true;
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
oo.addIssue().setDiagnostics("OK");
|
||||
|
Loading…
x
Reference in New Issue
Block a user