fixed an issue with matching compartments to lists of ids (#2761)

* fixed an issue with matching compartments to lists of ids

* change log
This commit is contained in:
Ken Stevens 2021-06-26 20:24:28 -04:00 committed by GitHub
parent ea98e62656
commit 5565bf9930
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 92 additions and 10 deletions

View File

@ -0,0 +1,5 @@
---
type: fix
issue: 2761
title: "When searching for ExplanationOfBenefit?patient=123,456, the compartment authorization interceptor was treating
'123,456' as a single id rather than as a list of ids. This has been corrected."

View File

@ -38,6 +38,7 @@ import org.hl7.fhir.r4.model.CodeableConcept;
import org.hl7.fhir.r4.model.Coding; import org.hl7.fhir.r4.model.Coding;
import org.hl7.fhir.r4.model.Condition; import org.hl7.fhir.r4.model.Condition;
import org.hl7.fhir.r4.model.Encounter; import org.hl7.fhir.r4.model.Encounter;
import org.hl7.fhir.r4.model.ExplanationOfBenefit;
import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Identifier; import org.hl7.fhir.r4.model.Identifier;
import org.hl7.fhir.r4.model.Observation; import org.hl7.fhir.r4.model.Observation;
@ -1473,12 +1474,12 @@ public class AuthorizationInterceptorJpaR4Test extends BaseResourceProviderR4Tes
return new RuleBuilder() return new RuleBuilder()
.allow() .allow()
.read() .read()
.resourcesOfType(Patient.class) .allResources()
.inCompartment("Patient", p1id) .inCompartment("Patient", p1id)
.andThen() .andThen()
.allow() .allow()
.read() .read()
.resourcesOfType(Patient.class) .allResources()
.inCompartment("Patient", p2id) .inCompartment("Patient", p2id)
.andThen() .andThen()
.denyAll() .denyAll()
@ -1503,6 +1504,80 @@ public class AuthorizationInterceptorJpaR4Test extends BaseResourceProviderR4Tes
} }
} }
@Test
public void testReadCompartmentTwoPatientIdsTwoEOBs() {
Patient patient1 = new Patient();
patient1.setActive(true);
IIdType p1id = myPatientDao.create(patient1).getId().toUnqualifiedVersionless();
ExplanationOfBenefit eob1 = new ExplanationOfBenefit();
eob1.setPatient(new Reference(p1id));
myExplanationOfBenefitDao.create(eob1);
Patient patient2 = new Patient();
patient2.setActive(true);
IIdType p2id = myPatientDao.create(patient2).getId().toUnqualifiedVersionless();
ExplanationOfBenefit eob2 = new ExplanationOfBenefit();
eob2.setPatient(new Reference(p2id));
myExplanationOfBenefitDao.create(eob2);
Patient patient3 = new Patient();
patient3.setActive(true);
IIdType p3id = myPatientDao.create(patient3).getId().toUnqualifiedVersionless();
ExplanationOfBenefit eob3 = new ExplanationOfBenefit();
eob3.setPatient(new Reference(p3id));
myExplanationOfBenefitDao.create(eob3);
ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
@Override
public List<IAuthRule> buildRuleList(RequestDetails theRequestDetails) {
return new RuleBuilder()
.allow()
.read()
.allResources()
.inCompartment("Patient", p1id)
.andThen()
.allow()
.read()
.allResources()
.inCompartment("Patient", p2id)
.andThen()
.denyAll()
.build();
}
});
{
String url = "/ExplanationOfBenefit?patient=" + p1id.getIdPart();
Bundle result = myClient.search().byUrl(url).returnBundle(Bundle.class).execute();
assertEquals(1, result.getTotal());
}
{
String url = "/ExplanationOfBenefit?patient=" + p2id.getIdPart();
Bundle result = myClient.search().byUrl(url).returnBundle(Bundle.class).execute();
assertEquals(1, result.getTotal());
}
{
String url = "/ExplanationOfBenefit?patient=" + p1id.getIdPart() + "," + p2id.getIdPart();
Bundle result = myClient.search().byUrl(url).returnBundle(Bundle.class).execute();
assertEquals(2, result.getTotal());
}
{
String url = "/ExplanationOfBenefit?patient=" + p1id.getIdPart() + "," + p3id.getIdPart();
try {
Bundle result = myClient.search().byUrl(url).returnBundle(Bundle.class).execute();
fail();
} catch (ForbiddenOperationException e) {
assertThat(e.getMessage(), startsWith("HTTP 403 Forbidden: Access denied by rule"));
}
}
}
@Test @Test
public void testDeleteExpungeBlocked() { public void testDeleteExpungeBlocked() {
// Create Patient, and Observation that refers to it // Create Patient, and Observation that refers to it

View File

@ -524,7 +524,6 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ {
} else if (getMode() == PolicyEnum.ALLOW) { } else if (getMode() == PolicyEnum.ALLOW) {
return newVerdict(theOperation, theRequestDetails, theInputResource, theInputResourceId, theOutputResource); return newVerdict(theOperation, theRequestDetails, theInputResource, theInputResourceId, theOutputResource);
} }
break;
} }
} }
} }
@ -546,17 +545,20 @@ class RuleImplOp extends BaseRule /* implements IAuthRule */ {
String[] values = theSearchParams.get(theSearchParamName); String[] values = theSearchParams.get(theSearchParamName);
if (values != null) { if (values != null) {
for (String nextParameterValue : values) { for (String nextParameterValue : values) {
if (nextParameterValue.equals(theCompartmentOwner.getValue())) { QualifiedParamList orParamList = QualifiedParamList.splitQueryStringByCommasIgnoreEscape(null, nextParameterValue);
for (String next : orParamList) {
if (next.equals(theCompartmentOwner.getValue())) {
verdict = newVerdict(theOperation, theRequestDetails, theInputResource, theInputResourceId, theOutputResource); verdict = newVerdict(theOperation, theRequestDetails, theInputResource, theInputResourceId, theOutputResource);
break; break;
} }
if (nextParameterValue.equals(theCompartmentOwner.getIdPart())) { if (next.equals(theCompartmentOwner.getIdPart())) {
verdict = newVerdict(theOperation, theRequestDetails, theInputResource, theInputResourceId, theOutputResource); verdict = newVerdict(theOperation, theRequestDetails, theInputResource, theInputResourceId, theOutputResource);
break; break;
} }
} }
} }
} }
}
return verdict; return verdict;
} }