SearchBuilder should not allow $everything operation to follow links to Group or List resources (#5283)
* SearchBuilder should not allow $everything operation to follow links to Group or List resources - tests * SearchBuilder should not allow $everything operation to follow links to Group or List resources - implementation * SearchBuilder should not allow $everything operation to follow links to Group or List resources - spotless check fix and changelog added * Add a new permission: FHIR_OP_PATIENT_EVERYTHING_ACCESS_ALL for $everything operation - fixes Co-authored-by: James Agnew <jamesagnew@gmail.com> * MongoIncludeSvc should not allow $everything operation to follow links to Group or List resources - fixes * MongoIncludeSvc should not allow $everything operation to follow links to Group or List resources - fixes --------- Co-authored-by: James Agnew <jamesagnew@gmail.com>
This commit is contained in:
parent
03ebabad5b
commit
fe8c6c066e
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
type: add
|
||||||
|
issue: 5275
|
||||||
|
title: "Added an API that allows to configure permission rules for operations with access to all resources.
|
||||||
|
This permission is needed to allow a search across the entire patient's record in the scope of the $everything operation to access all
|
||||||
|
resources that references input Patient, including resources outside of the patient's compartment."
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
type: fix
|
||||||
|
issue: 5275
|
||||||
|
title: "Previously, when calling `$everything` operation on a Patient instance, it was possible to retrieve data related
|
||||||
|
to another patient via a List or Group resources. This has been fixed."
|
||||||
|
|
|
@ -129,6 +129,7 @@ import javax.persistence.Tuple;
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
|
|
||||||
|
import static ca.uhn.fhir.jpa.model.util.JpaConstants.UNDESIRED_RESOURCE_LINKAGES_FOR_EVERYTHING_ON_PATIENT_INSTANCE;
|
||||||
import static ca.uhn.fhir.jpa.search.builder.QueryStack.LOCATION_POSITION;
|
import static ca.uhn.fhir.jpa.search.builder.QueryStack.LOCATION_POSITION;
|
||||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||||
|
@ -1380,7 +1381,8 @@ public class SearchBuilder implements ISearchBuilder<JpaPid> {
|
||||||
if (myParams != null
|
if (myParams != null
|
||||||
&& myParams.getEverythingMode() == SearchParameterMap.EverythingModeEnum.PATIENT_INSTANCE) {
|
&& myParams.getEverythingMode() == SearchParameterMap.EverythingModeEnum.PATIENT_INSTANCE) {
|
||||||
sqlBuilder.append(" AND r.myTargetResourceType != 'Patient'");
|
sqlBuilder.append(" AND r.myTargetResourceType != 'Patient'");
|
||||||
sqlBuilder.append(" AND r.mySourceResourceType != 'Provenance'");
|
sqlBuilder.append(UNDESIRED_RESOURCE_LINKAGES_FOR_EVERYTHING_ON_PATIENT_INSTANCE.stream()
|
||||||
|
.collect(Collectors.joining("', '", " AND r.mySourceResourceType NOT IN ('", "')")));
|
||||||
}
|
}
|
||||||
if (hasDesiredResourceTypes) {
|
if (hasDesiredResourceTypes) {
|
||||||
sqlBuilder.append(" AND r.myTargetResourceType IN (:desired_target_resource_types)");
|
sqlBuilder.append(" AND r.myTargetResourceType IN (:desired_target_resource_types)");
|
||||||
|
|
|
@ -23,6 +23,8 @@ import ca.uhn.fhir.rest.api.Constants;
|
||||||
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
|
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
|
||||||
import ca.uhn.fhir.util.HapiExtensions;
|
import ca.uhn.fhir.util.HapiExtensions;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class JpaConstants {
|
public class JpaConstants {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -306,7 +308,8 @@ public class JpaConstants {
|
||||||
public static final String BULK_META_EXTENSION_JOB_ID = "https://hapifhir.org/NamingSystem/bulk-export-job-id";
|
public static final String BULK_META_EXTENSION_JOB_ID = "https://hapifhir.org/NamingSystem/bulk-export-job-id";
|
||||||
public static final String BULK_META_EXTENSION_RESOURCE_TYPE =
|
public static final String BULK_META_EXTENSION_RESOURCE_TYPE =
|
||||||
"https://hapifhir.org/NamingSystem/bulk-export-binary-resource-type";
|
"https://hapifhir.org/NamingSystem/bulk-export-binary-resource-type";
|
||||||
|
public static final Set<String> UNDESIRED_RESOURCE_LINKAGES_FOR_EVERYTHING_ON_PATIENT_INSTANCE =
|
||||||
|
Set.of("Provenance", "List", "Group");
|
||||||
/**
|
/**
|
||||||
* Non-instantiable
|
* Non-instantiable
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -20,9 +20,11 @@ import org.hl7.fhir.r4.model.Composition;
|
||||||
import org.hl7.fhir.r4.model.Condition;
|
import org.hl7.fhir.r4.model.Condition;
|
||||||
import org.hl7.fhir.r4.model.Device;
|
import org.hl7.fhir.r4.model.Device;
|
||||||
import org.hl7.fhir.r4.model.Encounter;
|
import org.hl7.fhir.r4.model.Encounter;
|
||||||
|
import org.hl7.fhir.r4.model.Group;
|
||||||
import org.hl7.fhir.r4.model.IdType;
|
import org.hl7.fhir.r4.model.IdType;
|
||||||
import org.hl7.fhir.r4.model.InstantType;
|
import org.hl7.fhir.r4.model.InstantType;
|
||||||
import org.hl7.fhir.r4.model.IntegerType;
|
import org.hl7.fhir.r4.model.IntegerType;
|
||||||
|
import org.hl7.fhir.r4.model.ListResource;
|
||||||
import org.hl7.fhir.r4.model.Location;
|
import org.hl7.fhir.r4.model.Location;
|
||||||
import org.hl7.fhir.r4.model.Medication;
|
import org.hl7.fhir.r4.model.Medication;
|
||||||
import org.hl7.fhir.r4.model.MedicationRequest;
|
import org.hl7.fhir.r4.model.MedicationRequest;
|
||||||
|
@ -977,13 +979,7 @@ public class ResourceProviderR4EverythingTest extends BaseResourceProviderR4Test
|
||||||
|
|
||||||
myFhirContext.getRestfulClientFactory().setSocketTimeout(300 * 1000);
|
myFhirContext.getRestfulClientFactory().setSocketTimeout(300 * 1000);
|
||||||
|
|
||||||
Bundle response = myClient
|
Bundle response = executeEverythingOperationOnInstance(id);
|
||||||
.operation()
|
|
||||||
.onInstance(id)
|
|
||||||
.named("everything")
|
|
||||||
.withNoParameters(Parameters.class)
|
|
||||||
.returnResourceType(Bundle.class)
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
assertEquals(1, response.getEntry().size());
|
assertEquals(1, response.getEntry().size());
|
||||||
}
|
}
|
||||||
|
@ -1126,13 +1122,7 @@ public class ResourceProviderR4EverythingTest extends BaseResourceProviderR4Test
|
||||||
prov.addTarget().setReference(badPid);
|
prov.addTarget().setReference(badPid);
|
||||||
String provid = myProvenanceDao.create(prov, mySrd).getId().toUnqualifiedVersionless().getValue();
|
String provid = myProvenanceDao.create(prov, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||||
|
|
||||||
Bundle response = myClient
|
Bundle response = executeEverythingOperationOnInstance(new IdType(goodPid));
|
||||||
.operation()
|
|
||||||
.onInstance(new IdType(goodPid))
|
|
||||||
.named("everything")
|
|
||||||
.withNoParameters(Parameters.class)
|
|
||||||
.returnResourceType(Bundle.class)
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
List<String> ids = toUnqualifiedVersionlessIdValues(response);
|
List<String> ids = toUnqualifiedVersionlessIdValues(response);
|
||||||
// We should not pick up other resources via the provenance
|
// We should not pick up other resources via the provenance
|
||||||
|
@ -1208,19 +1198,69 @@ public class ResourceProviderR4EverythingTest extends BaseResourceProviderR4Test
|
||||||
notDesiredProvenance.addTarget().setReference(compositionId);
|
notDesiredProvenance.addTarget().setReference(compositionId);
|
||||||
final String notDesiredProvenanceId = myProvenanceDao.create(notDesiredProvenance, mySrd).getId().toUnqualifiedVersionless().getValue();
|
final String notDesiredProvenanceId = myProvenanceDao.create(notDesiredProvenance, mySrd).getId().toUnqualifiedVersionless().getValue();
|
||||||
|
|
||||||
final Bundle response = myClient
|
final Bundle response = executeEverythingOperationOnInstance(new IdType(desiredPid));
|
||||||
.operation()
|
|
||||||
.onInstance(new IdType(desiredPid))
|
|
||||||
.named("everything")
|
|
||||||
.withNoParameters(Parameters.class)
|
|
||||||
.returnResourceType(Bundle.class)
|
|
||||||
.execute();
|
|
||||||
|
|
||||||
final List<String> actualResourceIds = toUnqualifiedVersionlessIdValues(response);
|
final List<String> actualResourceIds = toUnqualifiedVersionlessIdValues(response);
|
||||||
// We should not pick up other resources via the notDesiredProvenance
|
// We should not pick up other resources via the notDesiredProvenance
|
||||||
assertThat(actualResourceIds, containsInAnyOrder(desiredPid, desiredObservationId, desiredProvenanceId));
|
assertThat(actualResourceIds, containsInAnyOrder(desiredPid, desiredObservationId, desiredProvenanceId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEverything_withPatientLinkedByList_returnOnlyDesiredResources() {
|
||||||
|
// setup
|
||||||
|
IIdType desiredPid = createPatient(withActiveTrue());
|
||||||
|
IIdType desiredObservationId = createObservationForPatient(desiredPid, "1");
|
||||||
|
|
||||||
|
IIdType notDesiredPid = createPatient(withActiveTrue());
|
||||||
|
IIdType notDesiredObservationId = createObservationForPatient(notDesiredPid, "1");
|
||||||
|
|
||||||
|
ListResource list = new ListResource();
|
||||||
|
Arrays.asList(desiredPid, desiredObservationId, notDesiredPid, notDesiredObservationId)
|
||||||
|
.forEach(resourceIdType -> list.addEntry().getItem().setReferenceElement(resourceIdType));
|
||||||
|
|
||||||
|
IIdType listId = myListDao.create(list).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
// execute
|
||||||
|
Bundle response = executeEverythingOperationOnInstance(desiredPid);
|
||||||
|
|
||||||
|
List<IIdType> actualResourceIds = toUnqualifiedVersionlessIds(response);
|
||||||
|
// verify - we should not pick up other resources linked by List
|
||||||
|
assertThat(actualResourceIds, containsInAnyOrder(desiredPid, desiredObservationId, listId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEverything_withPatientLinkedByGroup_returnOnlyDesiredResources() {
|
||||||
|
// setup
|
||||||
|
IIdType desiredPractitionerId = createPractitioner(withActiveTrue());
|
||||||
|
IIdType desiredPid = createPatient(withActiveTrue(), withReference("generalPractitioner", desiredPractitionerId));
|
||||||
|
|
||||||
|
IIdType notDesiredPractitionerId = createPractitioner(withActiveTrue());
|
||||||
|
IIdType notDesiredPid = createPatient(withActiveTrue(), withReference("generalPractitioner", notDesiredPractitionerId));
|
||||||
|
|
||||||
|
Group group = new Group();
|
||||||
|
Arrays.asList(desiredPid, desiredPractitionerId, notDesiredPid, notDesiredPractitionerId)
|
||||||
|
.forEach(resourceIdType -> group.addMember().getEntity().setReferenceElement(resourceIdType));
|
||||||
|
|
||||||
|
IIdType groupId = myGroupDao.create(group).getId().toUnqualifiedVersionless();
|
||||||
|
|
||||||
|
// execute
|
||||||
|
Bundle response = executeEverythingOperationOnInstance(desiredPid);
|
||||||
|
|
||||||
|
List<IIdType> actualResourceIds = toUnqualifiedVersionlessIds(response);
|
||||||
|
// verify - we should not pick up other resources linked by Group
|
||||||
|
assertThat(actualResourceIds, containsInAnyOrder(desiredPid, desiredPractitionerId, groupId));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bundle executeEverythingOperationOnInstance(IIdType theInstanceIdType) {
|
||||||
|
return myClient
|
||||||
|
.operation()
|
||||||
|
.onInstance(theInstanceIdType)
|
||||||
|
.named("everything")
|
||||||
|
.withNoParameters(Parameters.class)
|
||||||
|
.returnResourceType(Bundle.class)
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
private IIdType createOrganization(String methodName, String s) {
|
private IIdType createOrganization(String methodName, String s) {
|
||||||
Organization o1 = new Organization();
|
Organization o1 = new Organization();
|
||||||
o1.setName(methodName + s);
|
o1.setName(methodName + s);
|
||||||
|
|
|
@ -144,6 +144,7 @@ import org.hl7.fhir.r4.model.ExplanationOfBenefit;
|
||||||
import org.hl7.fhir.r4.model.Group;
|
import org.hl7.fhir.r4.model.Group;
|
||||||
import org.hl7.fhir.r4.model.Immunization;
|
import org.hl7.fhir.r4.model.Immunization;
|
||||||
import org.hl7.fhir.r4.model.ImmunizationRecommendation;
|
import org.hl7.fhir.r4.model.ImmunizationRecommendation;
|
||||||
|
import org.hl7.fhir.r4.model.ListResource;
|
||||||
import org.hl7.fhir.r4.model.Location;
|
import org.hl7.fhir.r4.model.Location;
|
||||||
import org.hl7.fhir.r4.model.Media;
|
import org.hl7.fhir.r4.model.Media;
|
||||||
import org.hl7.fhir.r4.model.Medication;
|
import org.hl7.fhir.r4.model.Medication;
|
||||||
|
@ -339,6 +340,9 @@ public abstract class BaseJpaR4Test extends BaseJpaTest implements ITestDataBuil
|
||||||
@Qualifier("myGroupDaoR4")
|
@Qualifier("myGroupDaoR4")
|
||||||
protected IFhirResourceDao<Group> myGroupDao;
|
protected IFhirResourceDao<Group> myGroupDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@Qualifier("myListDaoR4")
|
||||||
|
protected IFhirResourceDao<ListResource> myListDao;
|
||||||
|
@Autowired
|
||||||
@Qualifier("myMolecularSequenceDaoR4")
|
@Qualifier("myMolecularSequenceDaoR4")
|
||||||
protected IFhirResourceDao<MolecularSequence> myMolecularSequenceDao;
|
protected IFhirResourceDao<MolecularSequence> myMolecularSequenceDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
|
|
|
@ -26,6 +26,14 @@ public interface IAuthRuleBuilderOperationNamedAndScoped {
|
||||||
*/
|
*/
|
||||||
IAuthRuleBuilderRuleOpClassifierFinished andAllowAllResponses();
|
IAuthRuleBuilderRuleOpClassifierFinished andAllowAllResponses();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Responses for this operation will not be checked and access to all resources is allowed. This
|
||||||
|
* is intended for operations which are known to fetch a graph of resources that is known to be
|
||||||
|
* safe, such as `$everything` which may access and fetch resources outside the patient's compartment
|
||||||
|
* but enforces safety in what it fetches via strict SQL queries.
|
||||||
|
*/
|
||||||
|
IAuthRuleBuilderRuleOpClassifierFinished andAllowAllResponsesWithAllResourcesAccess();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responses for this operation must be authorized by other rules. For example, if this
|
* Responses for this operation must be authorized by other rules. For example, if this
|
||||||
* rule is authorizing the Patient $everything operation, there must be a separate
|
* rule is authorizing the Patient $everything operation, there must be a separate
|
||||||
|
|
|
@ -24,12 +24,14 @@ import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||||
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor.Verdict;
|
import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor.Verdict;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
class OperationRule extends BaseRule implements IAuthRule {
|
class OperationRule extends BaseRule implements IAuthRule {
|
||||||
private String myOperationName;
|
private String myOperationName;
|
||||||
|
@ -41,6 +43,7 @@ class OperationRule extends BaseRule implements IAuthRule {
|
||||||
private boolean myAppliesToAnyInstance;
|
private boolean myAppliesToAnyInstance;
|
||||||
private boolean myAppliesAtAnyLevel;
|
private boolean myAppliesAtAnyLevel;
|
||||||
private boolean myAllowAllResponses;
|
private boolean myAllowAllResponses;
|
||||||
|
private boolean myAllowAllResourcesAccess;
|
||||||
|
|
||||||
OperationRule(String theRuleName) {
|
OperationRule(String theRuleName) {
|
||||||
super(theRuleName);
|
super(theRuleName);
|
||||||
|
@ -54,6 +57,10 @@ class OperationRule extends BaseRule implements IAuthRule {
|
||||||
myAllowAllResponses = true;
|
myAllowAllResponses = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void allowAllResourcesAccess() {
|
||||||
|
myAllowAllResourcesAccess = true;
|
||||||
|
}
|
||||||
|
|
||||||
void appliesToAnyInstance() {
|
void appliesToAnyInstance() {
|
||||||
myAppliesToAnyInstance = true;
|
myAppliesToAnyInstance = true;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +100,7 @@ class OperationRule extends BaseRule implements IAuthRule {
|
||||||
// Operation rules apply to the execution of the operation itself, not to side effects like
|
// Operation rules apply to the execution of the operation itself, not to side effects like
|
||||||
// loading resources (that will presumably be reflected in the response). Those loads need
|
// loading resources (that will presumably be reflected in the response). Those loads need
|
||||||
// to be explicitly authorized
|
// to be explicitly authorized
|
||||||
if (isResourceAccess(thePointcut)) {
|
if (!myAllowAllResourcesAccess && isResourceAccess(thePointcut)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,4 +265,25 @@ class OperationRule extends BaseRule implements IAuthRule {
|
||||||
boolean isAllowAllResponses() {
|
boolean isAllowAllResponses() {
|
||||||
return myAllowAllResponses;
|
return myAllowAllResponses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isAllowAllResourcesAccess() {
|
||||||
|
return myAllowAllResourcesAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nonnull
|
||||||
|
protected ToStringBuilder toStringBuilder() {
|
||||||
|
ToStringBuilder builder = super.toStringBuilder();
|
||||||
|
builder.append("op", myOperationName);
|
||||||
|
builder.append("appliesToServer", myAppliesToServer);
|
||||||
|
builder.append("appliesToTypes", myAppliesToTypes);
|
||||||
|
builder.append("appliesToIds", myAppliesToIds);
|
||||||
|
builder.append("appliesToInstancesOfType", myAppliesToInstancesOfType);
|
||||||
|
builder.append("appliesToAnyType", myAppliesToAnyType);
|
||||||
|
builder.append("appliesToAnyInstance", myAppliesToAnyInstance);
|
||||||
|
builder.append("appliesAtAnyLevel", myAppliesAtAnyLevel);
|
||||||
|
builder.append("allowAllResponses", myAllowAllResponses);
|
||||||
|
builder.append("allowAllResourcesAccess", myAllowAllResourcesAccess);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -777,6 +777,14 @@ public class RuleBuilder implements IAuthRuleBuilder {
|
||||||
return new RuleBuilderFinished(myRule);
|
return new RuleBuilderFinished(myRule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IAuthRuleBuilderRuleOpClassifierFinished andAllowAllResponsesWithAllResourcesAccess() {
|
||||||
|
myRule.allowAllResponses();
|
||||||
|
myRule.allowAllResourcesAccess();
|
||||||
|
myRules.add(myRule);
|
||||||
|
return new RuleBuilderFinished(myRule);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IAuthRuleBuilderRuleOpClassifierFinished andRequireExplicitResponseAuthorization() {
|
public IAuthRuleBuilderRuleOpClassifierFinished andRequireExplicitResponseAuthorization() {
|
||||||
myRules.add(myRule);
|
myRules.add(myRule);
|
||||||
|
|
|
@ -21,8 +21,10 @@ package ca.uhn.fhir.rest.server.interceptor.auth;
|
||||||
|
|
||||||
import ca.uhn.fhir.rest.api.server.bulk.BulkExportJobParameters;
|
import ca.uhn.fhir.rest.api.server.bulk.BulkExportJobParameters;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public final class OperationRuleTestUtil {
|
public final class OperationRuleTestUtil {
|
||||||
private OperationRuleTestUtil() {}
|
private OperationRuleTestUtil() {}
|
||||||
|
@ -51,10 +53,18 @@ public final class OperationRuleTestUtil {
|
||||||
return ((OperationRule) theRule).getAppliesToInstancesOfType();
|
return ((OperationRule) theRule).getAppliesToInstancesOfType();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isAllowResourceAccess(IAuthRule theRule) {
|
||||||
|
return ((OperationRule) theRule).isAllowAllResourcesAccess();
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isAllowAllResponses(IAuthRule theRule) {
|
public static boolean isAllowAllResponses(IAuthRule theRule) {
|
||||||
return ((OperationRule) theRule).isAllowAllResponses();
|
return ((OperationRule) theRule).isAllowAllResponses();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<IIdType> getAppliesToIds(IAuthRule theRule) {
|
||||||
|
return ((OperationRule) theRule).getAppliesToIds();
|
||||||
|
}
|
||||||
|
|
||||||
public static String getGroupId(IAuthRule theRule) {
|
public static String getGroupId(IAuthRule theRule) {
|
||||||
return ((RuleBulkExportImpl) theRule).getGroupId();
|
return ((RuleBulkExportImpl) theRule).getGroupId();
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,6 +231,10 @@ public interface ITestDataBuilder {
|
||||||
return createResource("Organization", theModifiers);
|
return createResource("Organization", theModifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default IIdType createPractitioner(ICreationArgument... theModifiers) {
|
||||||
|
return createResource("Practitioner", theModifiers);
|
||||||
|
}
|
||||||
|
|
||||||
default IIdType createResource(String theResourceType, ICreationArgument... theModifiers) {
|
default IIdType createResource(String theResourceType, ICreationArgument... theModifiers) {
|
||||||
IBaseResource resource = buildResource(theResourceType, theModifiers);
|
IBaseResource resource = buildResource(theResourceType, theModifiers);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue