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 058a85e0c12..ef003145009 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 @@ -525,14 +525,6 @@ public class RuleBuilder implements IAuthRuleBuilder { rule.setOp(RuleOpEnum.TRANSACTION); rule.setTransactionAppliesToOp(TransactionAppliesToEnum.ANY_OPERATION); myRules.add(rule); - - // Allow batch - rule = new RuleImplOp(myRuleName); - rule.setMode(myRuleMode); - rule.setOp(RuleOpEnum.BATCH); - rule.setTransactionAppliesToOp(TransactionAppliesToEnum.ANY_OPERATION); - myRules.add(rule); - return new RuleBuilderFinished(rule); } 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 6b8cda78b27..fd1bf304169 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 @@ -35,9 +35,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. @@ -174,7 +174,6 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ { return null; } break; - case BATCH: case TRANSACTION: if (!(theOperation == RestOperationTypeEnum.TRANSACTION)) { return null; @@ -185,12 +184,16 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ { } List inputResources = BundleUtil.toListOfEntries(ctx, (IBaseBundle) theInputResource); Verdict verdict = null; + + boolean allComponentsAreGets = true; for (BundleEntryParts nextPart : inputResources) { IBaseResource inputResource = nextPart.getResource(); RestOperationTypeEnum operation = null; if (nextPart.getRequestType() == RequestTypeEnum.GET) { continue; + } else { + allComponentsAreGets = false; } if (nextPart.getRequestType() == RequestTypeEnum.POST) { operation = RestOperationTypeEnum.CREATE; @@ -219,6 +222,15 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ { verdict = newVerdict; } } + + /* + * If we're handling a transaction with all gets and nothing else, we'll + * be applying security on the way out + */ + if (allComponentsAreGets) { + return newVerdict(); + } + return verdict; } else if (theOutputResource != null) { @@ -453,9 +465,8 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ { //noinspection EnumSwitchStatementWhichMissesCases switch (theOp) { case TRANSACTION: - return "transaction".equals(bundleType); - case BATCH: - return "batch".equals(bundleType); + return "transaction".equals(bundleType) + || "batch".equals(bundleType); default: return false; } diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleOpEnum.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleOpEnum.java index 6ec6a79a8d6..4104086bb65 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleOpEnum.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/RuleOpEnum.java @@ -24,11 +24,13 @@ enum RuleOpEnum { READ, WRITE, ALLOW_ALL, - DENY_ALL, + DENY_ALL, + /** + * Transaction applies to both transaction and batch + */ TRANSACTION, METADATA, - BATCH, - DELETE, + DELETE, OPERATION, PATCH } 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 d1fcb352631..e40dac56220 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 @@ -499,6 +499,45 @@ public class AuthorizationInterceptorR4Test { status = ourClient.execute(httpPost); extractResponseAndClose(status); assertEquals(200, status.getStatusLine().getStatusCode()); + + + + } + + @Test + public void testBatchAllowedWithGets() 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(); + } + }); + + HttpPost httpPost; + HttpResponse status; + + // Bundle with GETs + + Bundle input = new Bundle(); + input.setType(Bundle.BundleType.BATCH); + input.addEntry().getRequest().setUrl("Patient?").setMethod(Bundle.HTTPVerb.GET); + + Bundle output = new Bundle(); + output.setType(Bundle.BundleType.TRANSACTIONRESPONSE); + output.addEntry().getResponse().setLocation("/Patient/1"); + + ourReturn = Collections.singletonList(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 diff --git a/src/changes/changes.xml b/src/changes/changes.xml index e06eb146ba0..a40474af6da 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -100,6 +100,11 @@ permission is granted. This has been corrected so that transaction() allows both batch and transaction requests to proceed. + + The AuthorizationInterceptor was previously not able to authorize the FHIR + batch operation. As of this version, when authorizing a transaction operation + (via the transaction() rule), both batch and transaction will be allowed. +