From 5bbe69cd314d6ef2d138a3f2e490fafe57dc3509 Mon Sep 17 00:00:00 2001 From: Tadgh Date: Wed, 15 Sep 2021 21:17:03 -0400 Subject: [PATCH] Move into data class --- .../fhir/docs/AuthorizationInterceptors.java | 5 +-- ...AdditionalCompartmentSearchParameters.java | 34 +++++++++++++++++++ .../IAuthRuleBuilderRuleOpClassifier.java | 8 +++-- .../server/interceptor/auth/RuleBuilder.java | 12 +++---- .../server/interceptor/auth/RuleImplOp.java | 26 +++----------- .../auth/AuthorizationInterceptorR4Test.java | 5 +-- 6 files changed, 56 insertions(+), 34 deletions(-) create mode 100644 hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/AdditionalCompartmentSearchParameters.java diff --git a/hapi-fhir-docs/src/main/java/ca/uhn/hapi/fhir/docs/AuthorizationInterceptors.java b/hapi-fhir-docs/src/main/java/ca/uhn/hapi/fhir/docs/AuthorizationInterceptors.java index cdc90c9fb1a..4ce9fd1420a 100644 --- a/hapi-fhir-docs/src/main/java/ca/uhn/hapi/fhir/docs/AuthorizationInterceptors.java +++ b/hapi-fhir-docs/src/main/java/ca/uhn/hapi/fhir/docs/AuthorizationInterceptors.java @@ -210,9 +210,10 @@ public class AuthorizationInterceptors { new AuthorizationInterceptor(PolicyEnum.DENY) { @Override public List buildRuleList(RequestDetails theRequestDetails) { - List additionalCompartmentSpNames = Collections.singletonList("device:patient"); + AdditionalCompartmentSearchParameters additionalSearchParams = new AdditionalCompartmentSearchParameters(); + additionalSearchParams.addSearchParameters("device", "patient"); return new RuleBuilder() - .allow().read().allResources().inCompartmentWithAdditionalSearchParams("Patient", new IdType("Patient/123"), additionalCompartmentSpNames) + .allow().read().allResources().inCompartmentWithAdditionalSearchParams("Patient", new IdType("Patient/123"), additionalSearchParams) .build(); } }; diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/AdditionalCompartmentSearchParameters.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/AdditionalCompartmentSearchParameters.java new file mode 100644 index 00000000000..3fd2eaa4369 --- /dev/null +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/AdditionalCompartmentSearchParameters.java @@ -0,0 +1,34 @@ +package ca.uhn.fhir.rest.server.interceptor.auth; + +import javax.annotation.Nonnull; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + * This class is used in RuleBuilder, as a way to provide a compartment permission additional resource search params that + * are to be included as "in" the given compartment. For example, if you were to populate this map with + * [device -> ["patient"] + * and apply it to compartment Patient/123, then any device with Patient/123 as its patient would be considered "in" + * the compartment, despite the fact that device is technically not part of the compartment definition for patient. + */ +public class AdditionalCompartmentSearchParameters { + private Map> myResourceTypeToParameterCodeMap; + + public AdditionalCompartmentSearchParameters() { + myResourceTypeToParameterCodeMap = new HashMap<>(); + } + + public void addSearchParameters(@Nonnull String theResourceType, @Nonnull String... theParameterCodes) { + Arrays.stream(theParameterCodes).forEach(code -> { + myResourceTypeToParameterCodeMap.computeIfAbsent(theResourceType.toLowerCase(), (key) -> new HashSet<>()).add(code.toLowerCase()); + }); + } + + public Set getSearchParamNamesForResourceType(@Nonnull String theResourceType) { + return myResourceTypeToParameterCodeMap.computeIfAbsent(theResourceType.toLowerCase(), (key) -> new HashSet<>()); + } +} diff --git a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/IAuthRuleBuilderRuleOpClassifier.java b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/IAuthRuleBuilderRuleOpClassifier.java index 70342ccd79b..401d281b6ee 100644 --- a/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/IAuthRuleBuilderRuleOpClassifier.java +++ b/hapi-fhir-server/src/main/java/ca/uhn/fhir/rest/server/interceptor/auth/IAuthRuleBuilderRuleOpClassifier.java @@ -64,7 +64,9 @@ public interface IAuthRuleBuilderRuleOpClassifier { * @param theOwner The owner of the compartment. Note that both the resource type and ID must be populated in this ID. * @param theAdditionalTypeSearchParamNames A list of strings for additional resource types and search parameters which count as being in the compartment, in the form "resourcetype:search-parameter-name". */ - IAuthRuleBuilderRuleOpClassifierFinished inCompartmentWithAdditionalSearchParams(String theCompartmentName, IIdType theOwner, List theAdditionalTypeSearchParamNames); + IAuthRuleBuilderRuleOpClassifierFinished inCompartmentWithAdditionalSearchParams(String theCompartmentName, IIdType theOwner, AdditionalCompartmentSearchParameters theAdditionalTypeSearchParamNames); + + /** * Rule applies to resources in the given compartment. *

@@ -101,10 +103,10 @@ public interface IAuthRuleBuilderRuleOpClassifier { * * @param theCompartmentName The name of the compartment (must not be null or blank) * @param theOwners The owners of the compartment. Note that both the resource type and ID must be populated in these IDs. - * @param theAdditionalTypeSearchParamNames A list of strings for additional resource types and search parameters which count as being in the compartment, in the form "resourcetype:search-parameter-name". + * @param theAdditionalTypeSearchParamNames A {@link AdditionalCompartmentSearchParameters} which allows you to expand the search space for what is considered "in" the compartment. * **/ - IAuthRuleBuilderRuleOpClassifierFinished inCompartmentWithAdditionalSearchParams(String theCompartmentName, Collection theOwners, List theAdditionalTypeSearchParamNames); + IAuthRuleBuilderRuleOpClassifierFinished inCompartmentWithAdditionalSearchParams(String theCompartmentName, Collection theOwners, AdditionalCompartmentSearchParameters theAdditionalTypeSearchParamNames); /** 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 a4447bff1bd..92587a062b9 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 @@ -451,7 +451,7 @@ public class RuleBuilder implements IAuthRuleBuilder { private Collection myInCompartmentOwners; private Collection myAppliesToInstances; private RuleImplOp myRule; - private List myAdditionalSearchParamsForCompartmentTypes = new ArrayList<>(); + private AdditionalCompartmentSearchParameters myAdditionalSearchParamsForCompartmentTypes = new AdditionalCompartmentSearchParameters(); /** * Constructor @@ -492,11 +492,11 @@ public class RuleBuilder implements IAuthRuleBuilder { @Override public IAuthRuleBuilderRuleOpClassifierFinished inCompartment(String theCompartmentName, Collection theOwners) { - return inCompartmentWithAdditionalSearchParams(theCompartmentName, theOwners, new ArrayList<>()); + return inCompartmentWithAdditionalSearchParams(theCompartmentName, theOwners, new AdditionalCompartmentSearchParameters()); } @Override - public IAuthRuleBuilderRuleOpClassifierFinished inCompartmentWithAdditionalSearchParams(String theCompartmentName, Collection theOwners, List theAdditionalTypeSearchParamNames) { + public IAuthRuleBuilderRuleOpClassifierFinished inCompartmentWithAdditionalSearchParams(String theCompartmentName, Collection theOwners, AdditionalCompartmentSearchParameters theAdditionalTypeSearchParams) { Validate.notBlank(theCompartmentName, "theCompartmentName must not be null"); Validate.notNull(theOwners, "theOwners must not be null"); Validate.noNullElements(theOwners, "theOwners must not contain any null elements"); @@ -505,18 +505,18 @@ public class RuleBuilder implements IAuthRuleBuilder { } myInCompartmentName = theCompartmentName; myInCompartmentOwners = theOwners; - myAdditionalSearchParamsForCompartmentTypes = theAdditionalTypeSearchParamNames; + myAdditionalSearchParamsForCompartmentTypes = theAdditionalTypeSearchParams; myClassifierType = ClassifierTypeEnum.IN_COMPARTMENT; return finished(); } @Override public IAuthRuleBuilderRuleOpClassifierFinished inCompartment(String theCompartmentName, IIdType theOwner) { - return inCompartmentWithAdditionalSearchParams(theCompartmentName, theOwner, new ArrayList<>()); + return inCompartmentWithAdditionalSearchParams(theCompartmentName, theOwner, new AdditionalCompartmentSearchParameters()); } @Override - public IAuthRuleBuilderRuleOpClassifierFinished inCompartmentWithAdditionalSearchParams(String theCompartmentName, IIdType theOwner, List theAdditionalTypeSearchParamNames) { + public IAuthRuleBuilderRuleOpClassifierFinished inCompartmentWithAdditionalSearchParams(String theCompartmentName, IIdType theOwner, AdditionalCompartmentSearchParameters theAdditionalTypeSearchParamNames) { Validate.notBlank(theCompartmentName, "theCompartmentName must not be null"); Validate.notNull(theOwner, "theOwner must not be null"); validateOwner(theOwner); 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 ee9a13ded3f..697a48c75c9 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 @@ -18,7 +18,6 @@ import ca.uhn.fhir.util.UrlUtil; import ca.uhn.fhir.util.bundle.BundleEntryParts; import com.google.common.annotations.VisibleForTesting; import org.apache.commons.lang3.StringUtils; -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; @@ -29,8 +28,6 @@ import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -73,8 +70,7 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ { private Collection myAppliesToInstances; private boolean myAppliesToDeleteCascade; private boolean myAppliesToDeleteExpunge; - private boolean myDeviceIncludedInPatientCompartment; - private Map> myAdditionalCompartmentSearchParamMap; + private AdditionalCompartmentSearchParameters myAdditionalCompartmentSearchParamMap; /** * Constructor @@ -346,7 +342,7 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ { Set additionalSearchParamNames = null; if (myAdditionalCompartmentSearchParamMap != null) { - additionalSearchParamNames = myAdditionalCompartmentSearchParamMap.get(ctx.getResourceType(target.resource).toLowerCase()); + additionalSearchParamNames = myAdditionalCompartmentSearchParamMap.getSearchParamNamesForResourceType(ctx.getResourceType(target.resource)); } if (t.isSourceInCompartmentForTarget(myClassifierCompartmentName, target.resource, next, additionalSearchParamNames)) { foundMatch = true; @@ -385,7 +381,7 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ { List params = sourceDef.getSearchParamsForCompartmentName(compartmentOwnerResourceType); - Set additionalParamNames = myAdditionalCompartmentSearchParamMap.getOrDefault(sourceDef.getName().toLowerCase(), new HashSet<>()); + Set additionalParamNames = myAdditionalCompartmentSearchParamMap.getSearchParamNamesForResourceType(sourceDef.getName()); List additionalParams = additionalParamNames.stream().map(sourceDef::getSearchParam).collect(Collectors.toList()); if (params == null || params.isEmpty()) { params = additionalParams; @@ -677,10 +673,6 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ { myAppliesToDeleteExpunge = theAppliesToDeleteExpunge; } - void setDeviceIncludedInPatientCompartment(boolean theDeviceIncludedInPatientCompartment) { - myDeviceIncludedInPatientCompartment = theDeviceIncludedInPatientCompartment; - } - public void addClassifierCompartmentOwner(IIdType theOwner) { List newList = new ArrayList<>(myClassifierCompartmentOwners); newList.add(theOwner); @@ -707,15 +699,7 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ { } } - public void setAdditionalSearchParamsForCompartmentTypes(List theTypeAndParams) { - if (myAdditionalCompartmentSearchParamMap == null) { - myAdditionalCompartmentSearchParamMap = new HashMap<>(); - } - - for (String typeAndParam: theTypeAndParams) { - String[] split = typeAndParam.split(":"); - Validate.isTrue(split.length == 2); - myAdditionalCompartmentSearchParamMap.computeIfAbsent(split[0].toLowerCase(), (v) -> new HashSet<>()).add(split[1].toLowerCase()); - } + public void setAdditionalSearchParamsForCompartmentTypes(AdditionalCompartmentSearchParameters theAdditionalParameters) { + myAdditionalCompartmentSearchParamMap = theAdditionalParameters; } } diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorR4Test.java index 88c2e3cf377..cda03b1d43f 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorR4Test.java @@ -382,13 +382,14 @@ public class AuthorizationInterceptorR4Test { ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) { @Override public List buildRuleList(RequestDetails theRequestDetails) { - List bonusPatientCompartmentSearchParams = Collections.singletonList("device:patient"); + AdditionalCompartmentSearchParameters additionalCompartmentSearchParameters = new AdditionalCompartmentSearchParameters(); + additionalCompartmentSearchParameters.addSearchParameters("device", "patient"); List relatedIds = new ArrayList<>(); relatedIds.add(new IdType("Patient/123")); relatedIds.add(new IdType("Patient/456")); return new RuleBuilder() .allow().read().allResources() - .inCompartmentWithAdditionalSearchParams("Patient", relatedIds, bonusPatientCompartmentSearchParams) + .inCompartmentWithAdditionalSearchParams("Patient", relatedIds, additionalCompartmentSearchParameters) .andThen().denyAll() .build(); }