fix false rule matches (#2762)
* fixed an issue with matching compartments to lists of ids * change log * Added extra guards against false rule matches. * changelog * fix inCompartment * cleanup
This commit is contained in:
parent
5565bf9930
commit
9500a1a7de
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 2762
|
||||
title: "A regression was introduced in 2760 where a READ compartment could get collapsed into a WRITE compartment. This has been corrected."
|
|
@ -507,23 +507,23 @@ public class RuleBuilder implements IAuthRuleBuilder {
|
|||
Validate.notBlank(theCompartmentName, "theCompartmentName must not be null");
|
||||
Validate.notNull(theOwner, "theOwner must not be null");
|
||||
validateOwner(theOwner);
|
||||
Optional<RuleImplOp> oRule = findRuleByAppliesToAndCompartmentName(theCompartmentName);
|
||||
myClassifierType = ClassifierTypeEnum.IN_COMPARTMENT;
|
||||
myInCompartmentName = theCompartmentName;
|
||||
Optional<RuleImplOp> oRule = findMatchingRule();
|
||||
if (oRule.isPresent()) {
|
||||
RuleImplOp rule = oRule.get();
|
||||
rule.addClassifierCompartmentOwner(theOwner);
|
||||
return new RuleBuilderFinished(rule);
|
||||
}
|
||||
myInCompartmentName = theCompartmentName;
|
||||
myInCompartmentOwners = Collections.singletonList(theOwner);
|
||||
myClassifierType = ClassifierTypeEnum.IN_COMPARTMENT;
|
||||
return finished();
|
||||
}
|
||||
|
||||
private Optional<RuleImplOp> findRuleByAppliesToAndCompartmentName(String theCompartmentName) {
|
||||
private Optional<RuleImplOp> findMatchingRule() {
|
||||
return myRules.stream()
|
||||
.filter(RuleImplOp.class::isInstance)
|
||||
.map(RuleImplOp.class::cast)
|
||||
.filter(rule -> rule.matches(myAppliesTo, myAppliesToInstances, myAppliesToTypes, theCompartmentName))
|
||||
.filter(rule -> rule.matches(myRuleOp, myAppliesTo, myAppliesToInstances, myAppliesToTypes, myClassifierType, myInCompartmentName))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
|
|
|
@ -639,7 +639,13 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ {
|
|||
myClassifierCompartmentOwners = newList;
|
||||
}
|
||||
|
||||
public boolean matches(AppliesTypeEnum theAppliesTo, Collection<IIdType> theAppliesToInstances, Set<String> theAppliesToTypes, String theCompartmentName) {
|
||||
public boolean matches(RuleOpEnum theRuleOp, AppliesTypeEnum theAppliesTo, Collection<IIdType> theAppliesToInstances, Set<String> theAppliesToTypes, ClassifierTypeEnum theClassifierType, String theCompartmentName) {
|
||||
if (theRuleOp != myOp ||
|
||||
theAppliesTo != myAppliesTo ||
|
||||
theClassifierType != myClassifierType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (theAppliesTo) {
|
||||
case TYPES:
|
||||
return theAppliesToTypes.equals(myAppliesToTypes) && theCompartmentName.equals(myClassifierCompartmentName);
|
||||
|
|
|
@ -1,11 +1,95 @@
|
|||
package ca.uhn.fhir.rest.server.interceptor.auth;
|
||||
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class RuleImplOpTest {
|
||||
|
||||
public static final String COMPARTMENT_NAME = "Patient";
|
||||
private static final ClassifierTypeEnum CLASSIFIER_TYPE = ClassifierTypeEnum.IN_COMPARTMENT;
|
||||
|
||||
@Test
|
||||
public void testToString() {
|
||||
new RuleImplOp("").toString();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchesTypes() {
|
||||
RuleImplOp aRuleOp = new RuleImplOp("a");
|
||||
aRuleOp.setOp(RuleOpEnum.READ);
|
||||
aRuleOp.setAppliesTo(AppliesTypeEnum.TYPES);
|
||||
aRuleOp.setClassifierType(CLASSIFIER_TYPE);
|
||||
Set<String> types = new HashSet<>();
|
||||
types.add("ABC");
|
||||
types.add("DEF");
|
||||
aRuleOp.setAppliesToTypes(types);
|
||||
aRuleOp.setClassifierCompartmentName(COMPARTMENT_NAME);
|
||||
|
||||
Set<String> matchTypes = new HashSet<>();
|
||||
matchTypes.add("ABC");
|
||||
matchTypes.add("DEF");
|
||||
|
||||
Set<String> noMatchTypes = new HashSet<>();
|
||||
noMatchTypes.add("ABC");
|
||||
noMatchTypes.add("XYZ");
|
||||
|
||||
assertTrue(aRuleOp.matches(RuleOpEnum.READ, AppliesTypeEnum.TYPES, Collections.emptyList(), matchTypes, CLASSIFIER_TYPE, "Patient"));
|
||||
assertFalse(aRuleOp.matches(RuleOpEnum.READ, AppliesTypeEnum.TYPES, Collections.emptyList(), noMatchTypes, CLASSIFIER_TYPE, "Patient"));
|
||||
assertFalse(aRuleOp.matches(RuleOpEnum.READ, AppliesTypeEnum.TYPES, Collections.emptyList(), Collections.emptySet(), CLASSIFIER_TYPE, "Patient"));
|
||||
assertFalse(aRuleOp.matches(RuleOpEnum.WRITE, AppliesTypeEnum.TYPES, Collections.emptyList(), matchTypes, CLASSIFIER_TYPE, "Patient"));
|
||||
assertFalse(aRuleOp.matches(RuleOpEnum.READ, AppliesTypeEnum.INSTANCES, Collections.emptyList(), matchTypes, CLASSIFIER_TYPE, "Patient"));
|
||||
assertFalse(aRuleOp.matches(RuleOpEnum.READ, AppliesTypeEnum.TYPES, Collections.emptyList(), matchTypes, CLASSIFIER_TYPE, "Observation"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchesInstances() {
|
||||
RuleImplOp aRuleOp = new RuleImplOp("a");
|
||||
aRuleOp.setOp(RuleOpEnum.READ);
|
||||
aRuleOp.setAppliesTo(AppliesTypeEnum.INSTANCES);
|
||||
aRuleOp.setClassifierType(CLASSIFIER_TYPE);
|
||||
List<IIdType> instances = new ArrayList<>();
|
||||
instances.add(new IdDt("ABC"));
|
||||
instances.add(new IdDt("DEF"));
|
||||
aRuleOp.setAppliesToInstances(instances);
|
||||
aRuleOp.setClassifierCompartmentName(COMPARTMENT_NAME);
|
||||
|
||||
List<IIdType> matchInstances = new ArrayList<>();
|
||||
matchInstances.add(new IdDt("ABC"));
|
||||
matchInstances.add(new IdDt("DEF"));
|
||||
|
||||
List<IIdType> noMatchInstances = new ArrayList<>();
|
||||
noMatchInstances.add(new IdDt("ABC"));
|
||||
noMatchInstances.add(new IdDt("XYZ"));
|
||||
|
||||
assertTrue(aRuleOp.matches(RuleOpEnum.READ, AppliesTypeEnum.INSTANCES, matchInstances, Collections.emptySet(), CLASSIFIER_TYPE, "Patient"));
|
||||
assertFalse(aRuleOp.matches(RuleOpEnum.READ, AppliesTypeEnum.INSTANCES, noMatchInstances, Collections.emptySet(), CLASSIFIER_TYPE, "Patient"));
|
||||
assertFalse(aRuleOp.matches(RuleOpEnum.READ, AppliesTypeEnum.INSTANCES, Collections.emptyList(), Collections.emptySet(), CLASSIFIER_TYPE, "Patient"));
|
||||
assertFalse(aRuleOp.matches(RuleOpEnum.WRITE, AppliesTypeEnum.INSTANCES, matchInstances, Collections.emptySet(), CLASSIFIER_TYPE, "Patient"));
|
||||
assertFalse(aRuleOp.matches(RuleOpEnum.READ, AppliesTypeEnum.TYPES, matchInstances, Collections.emptySet(), CLASSIFIER_TYPE, "Patient"));
|
||||
assertFalse(aRuleOp.matches(RuleOpEnum.READ, AppliesTypeEnum.INSTANCES, matchInstances, Collections.emptySet(), CLASSIFIER_TYPE, "Observation"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchesAllResources() {
|
||||
RuleImplOp aRuleOp = new RuleImplOp("a");
|
||||
aRuleOp.setOp(RuleOpEnum.READ);
|
||||
aRuleOp.setAppliesTo(AppliesTypeEnum.ALL_RESOURCES);
|
||||
aRuleOp.setClassifierType(CLASSIFIER_TYPE);
|
||||
aRuleOp.setClassifierCompartmentName("Patient");
|
||||
|
||||
assertTrue(aRuleOp.matches(RuleOpEnum.READ, AppliesTypeEnum.ALL_RESOURCES, Collections.emptyList(), Collections.emptySet(), CLASSIFIER_TYPE, "Patient"));
|
||||
assertFalse(aRuleOp.matches(RuleOpEnum.WRITE, AppliesTypeEnum.ALL_RESOURCES, Collections.emptyList(), Collections.emptySet(), CLASSIFIER_TYPE, "Patient"));
|
||||
assertFalse(aRuleOp.matches(RuleOpEnum.READ, AppliesTypeEnum.TYPES, Collections.emptyList(), Collections.emptySet(), CLASSIFIER_TYPE, "Patient"));
|
||||
assertFalse(aRuleOp.matches(RuleOpEnum.READ, AppliesTypeEnum.ALL_RESOURCES, Collections.emptyList(), Collections.emptySet(), CLASSIFIER_TYPE, "Observation"));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue