Move into data class

This commit is contained in:
Tadgh 2021-09-15 21:17:03 -04:00
parent 0a9d5344e3
commit 5bbe69cd31
6 changed files with 56 additions and 34 deletions

View File

@ -210,9 +210,10 @@ public class AuthorizationInterceptors {
new AuthorizationInterceptor(PolicyEnum.DENY) {
@Override
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
List<String> 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();
}
};

View File

@ -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<String, Set<String>> 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<String> getSearchParamNamesForResourceType(@Nonnull String theResourceType) {
return myResourceTypeToParameterCodeMap.computeIfAbsent(theResourceType.toLowerCase(), (key) -> new HashSet<>());
}
}

View File

@ -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<String> theAdditionalTypeSearchParamNames);
IAuthRuleBuilderRuleOpClassifierFinished inCompartmentWithAdditionalSearchParams(String theCompartmentName, IIdType theOwner, AdditionalCompartmentSearchParameters theAdditionalTypeSearchParamNames);
/**
* Rule applies to resources in the given compartment.
* <p>
@ -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<? extends IIdType> theOwners, List<String> theAdditionalTypeSearchParamNames);
IAuthRuleBuilderRuleOpClassifierFinished inCompartmentWithAdditionalSearchParams(String theCompartmentName, Collection<? extends IIdType> theOwners, AdditionalCompartmentSearchParameters theAdditionalTypeSearchParamNames);
/**

View File

@ -451,7 +451,7 @@ public class RuleBuilder implements IAuthRuleBuilder {
private Collection<? extends IIdType> myInCompartmentOwners;
private Collection<IIdType> myAppliesToInstances;
private RuleImplOp myRule;
private List<String> 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<? extends IIdType> theOwners) {
return inCompartmentWithAdditionalSearchParams(theCompartmentName, theOwners, new ArrayList<>());
return inCompartmentWithAdditionalSearchParams(theCompartmentName, theOwners, new AdditionalCompartmentSearchParameters());
}
@Override
public IAuthRuleBuilderRuleOpClassifierFinished inCompartmentWithAdditionalSearchParams(String theCompartmentName, Collection<? extends IIdType> theOwners, List<String> theAdditionalTypeSearchParamNames) {
public IAuthRuleBuilderRuleOpClassifierFinished inCompartmentWithAdditionalSearchParams(String theCompartmentName, Collection<? extends IIdType> 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<String> 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);

View File

@ -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<IIdType> myAppliesToInstances;
private boolean myAppliesToDeleteCascade;
private boolean myAppliesToDeleteExpunge;
private boolean myDeviceIncludedInPatientCompartment;
private Map<String, Set<String>> myAdditionalCompartmentSearchParamMap;
private AdditionalCompartmentSearchParameters myAdditionalCompartmentSearchParamMap;
/**
* Constructor
@ -346,7 +342,7 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ {
Set<String> 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<RuntimeSearchParam> params = sourceDef.getSearchParamsForCompartmentName(compartmentOwnerResourceType);
Set<String> additionalParamNames = myAdditionalCompartmentSearchParamMap.getOrDefault(sourceDef.getName().toLowerCase(), new HashSet<>());
Set<String> additionalParamNames = myAdditionalCompartmentSearchParamMap.getSearchParamNamesForResourceType(sourceDef.getName());
List<RuntimeSearchParam> 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<IIdType> newList = new ArrayList<>(myClassifierCompartmentOwners);
newList.add(theOwner);
@ -707,15 +699,7 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ {
}
}
public void setAdditionalSearchParamsForCompartmentTypes(List<String> 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;
}
}

View File

@ -382,13 +382,14 @@ public class AuthorizationInterceptorR4Test {
ourServlet.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
@Override
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
List<String> bonusPatientCompartmentSearchParams = Collections.singletonList("device:patient");
AdditionalCompartmentSearchParameters additionalCompartmentSearchParameters = new AdditionalCompartmentSearchParameters();
additionalCompartmentSearchParameters.addSearchParameters("device", "patient");
List<IdType> 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();
}