Merge branch 'rel_5_4'
This commit is contained in:
commit
926bf393d3
|
@ -82,6 +82,10 @@ public class FhirServerConfigCommon {
|
||||||
logger.error("----FhiServerConfigCommon: getDataSource: setting driver error: " + e.getMessage());
|
logger.error("----FhiServerConfigCommon: getDataSource: setting driver error: " + e.getMessage());
|
||||||
}
|
}
|
||||||
dataSource.setUrl(dbUrl);
|
dataSource.setUrl(dbUrl);
|
||||||
|
|
||||||
|
// A check for WS-2020-0287
|
||||||
|
assert dataSource.getJmxName() == null;
|
||||||
|
|
||||||
return dataSource;
|
return dataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
type: change
|
||||||
|
issue: 2648
|
||||||
|
title: "The ConsentInterceptor no longer fully runs on calls to `/metadata` or during the `$meta` operation."
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: fix
|
||||||
|
issue: 2654
|
||||||
|
title: "The id of ValueSet resources in ValueSet expansions was null. This has been corrected. The id of the expanded
|
||||||
|
value set is now the same as the id of the value set that was expanded."
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
type: change
|
||||||
|
issue: 2655
|
||||||
|
title: "Added a new configuration option to DaoConfig, `setInternalSynchronousSearchSize()`, this controls the loadSynchronousUpTo()
|
||||||
|
during internal operations such as delete with expunge, and certain CodeSystem searches."
|
|
@ -126,3 +126,7 @@ With this interceptor in place, the following header can be added to individual
|
||||||
```http
|
```http
|
||||||
X-Retry-On-Version-Conflict: retry; max-retries=100
|
X-Retry-On-Version-Conflict: retry; max-retries=100
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# Controlling Delete with Expunge size
|
||||||
|
|
||||||
|
During the delete with expunge operation there is an internal synchronous search which locates all the resources to be deleted. The default maximum size of this search is 10000. This can be configured via the [Internal Synchronous Search Size](/hapi-fhir/apidocs/hapi-fhir-jpaserver-api/ca/uhn/fhir/jpa/api/config/DaoConfig.html#setInternalSynchronousSearchSize(java.lang.Integer)) property.
|
||||||
|
|
|
@ -97,6 +97,7 @@ public class DaoConfig {
|
||||||
/**
|
/**
|
||||||
* Child Configurations
|
* Child Configurations
|
||||||
*/
|
*/
|
||||||
|
private static final Integer DEFAULT_INTERNAL_SYNCHRONOUS_SEARCH_SIZE = 10000;
|
||||||
|
|
||||||
private final ModelConfig myModelConfig = new ModelConfig();
|
private final ModelConfig myModelConfig = new ModelConfig();
|
||||||
/**
|
/**
|
||||||
|
@ -163,6 +164,7 @@ public class DaoConfig {
|
||||||
private boolean myFilterParameterEnabled = false;
|
private boolean myFilterParameterEnabled = false;
|
||||||
private StoreMetaSourceInformationEnum myStoreMetaSourceInformation = StoreMetaSourceInformationEnum.SOURCE_URI_AND_REQUEST_ID;
|
private StoreMetaSourceInformationEnum myStoreMetaSourceInformation = StoreMetaSourceInformationEnum.SOURCE_URI_AND_REQUEST_ID;
|
||||||
private HistoryCountModeEnum myHistoryCountMode = DEFAULT_HISTORY_COUNT_MODE;
|
private HistoryCountModeEnum myHistoryCountMode = DEFAULT_HISTORY_COUNT_MODE;
|
||||||
|
private int myInternalSynchronousSearchSize = DEFAULT_INTERNAL_SYNCHRONOUS_SEARCH_SIZE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* update setter javadoc if default changes
|
* update setter javadoc if default changes
|
||||||
|
@ -2217,6 +2219,31 @@ public class DaoConfig {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* This determines the internal search size that is run synchronously during operations such as:
|
||||||
|
* 1. Delete with _expunge parameter.
|
||||||
|
* 2. Searching for Code System IDs by System and Code
|
||||||
|
* </p>
|
||||||
|
* @since 5.4.0
|
||||||
|
*/
|
||||||
|
public Integer getInternalSynchronousSearchSize() {
|
||||||
|
return myInternalSynchronousSearchSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* This determines the internal search size that is run synchronously during operations such as:
|
||||||
|
* 1. Delete with _expunge parameter.
|
||||||
|
* 2. Searching for Code System IDs by System and Code
|
||||||
|
* </p>
|
||||||
|
* @since 5.4.0
|
||||||
|
*/
|
||||||
|
public void setInternalSynchronousSearchSize(Integer theInternalSynchronousSearchSize) {
|
||||||
|
myInternalSynchronousSearchSize = theInternalSynchronousSearchSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this is enabled (this is the default), this server will attempt to activate and run <b>Bulk Import</b>
|
* If this is enabled (this is the default), this server will attempt to activate and run <b>Bulk Import</b>
|
||||||
* batch jobs. Otherwise, this server will not.
|
* batch jobs. Otherwise, this server will not.
|
||||||
|
|
|
@ -1447,7 +1447,7 @@ public abstract class BaseHapiFhirResourceDao<T extends IBaseResource> extends B
|
||||||
@Override
|
@Override
|
||||||
public Set<ResourcePersistentId> searchForIds(SearchParameterMap theParams, RequestDetails theRequest) {
|
public Set<ResourcePersistentId> searchForIds(SearchParameterMap theParams, RequestDetails theRequest) {
|
||||||
return myTransactionService.execute(theRequest, tx -> {
|
return myTransactionService.execute(theRequest, tx -> {
|
||||||
theParams.setLoadSynchronousUpTo(10000);
|
theParams.setLoadSynchronousUpTo(myDaoConfig.getInternalSynchronousSearchSize());
|
||||||
|
|
||||||
ISearchBuilder builder = mySearchBuilderFactory.newSearchBuilder(this, getResourceName(), getResourceType());
|
ISearchBuilder builder = mySearchBuilderFactory.newSearchBuilder(this, getResourceName(), getResourceType());
|
||||||
|
|
||||||
|
|
|
@ -69,8 +69,6 @@ public class DeleteExpungeService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ResourceTableFKProvider myResourceTableFKProvider;
|
private ResourceTableFKProvider myResourceTableFKProvider;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IResourceTableDao myResourceTableDao;
|
|
||||||
@Autowired
|
|
||||||
private IResourceLinkDao myResourceLinkDao;
|
private IResourceLinkDao myResourceLinkDao;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IInterceptorBroadcaster myInterceptorBroadcaster;
|
private IInterceptorBroadcaster myInterceptorBroadcaster;
|
||||||
|
|
|
@ -61,7 +61,7 @@ import org.springframework.beans.factory.annotation.Required;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META;
|
import static ca.uhn.fhir.rest.server.provider.ProviderConstants.OPERATION_META;
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META_ADD;
|
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META_ADD;
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META_DELETE;
|
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META_DELETE;
|
||||||
|
|
||||||
|
|
|
@ -21,37 +21,7 @@ package ca.uhn.fhir.jpa.provider;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
|
||||||
import ca.uhn.fhir.model.api.IResource;
|
import ca.uhn.fhir.model.api.IResource;
|
||||||
import ca.uhn.fhir.model.dstu2.composite.MetaDt;
|
|
||||||
import ca.uhn.fhir.model.dstu2.resource.Parameters;
|
|
||||||
import ca.uhn.fhir.model.primitive.BooleanDt;
|
|
||||||
import ca.uhn.fhir.model.primitive.IdDt;
|
|
||||||
import ca.uhn.fhir.model.primitive.IntegerDt;
|
|
||||||
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Create;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Delete;
|
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Operation;
|
|
||||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Update;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Validate;
|
|
||||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
|
||||||
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_DELETED_RESOURCES;
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_EXPUNGE_PARAM_EXPUNGE_PREVIOUS_VERSIONS;
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_EXPUNGE_PARAM_LIMIT;
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META;
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META_ADD;
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META_DELETE;
|
|
||||||
|
|
||||||
public class JpaResourceProviderDstu2<T extends IResource> extends BaseJpaResourceProvider<T> {
|
public class JpaResourceProviderDstu2<T extends IResource> extends BaseJpaResourceProvider<T> {
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Transaction;
|
import ca.uhn.fhir.rest.annotation.Transaction;
|
||||||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import org.hl7.fhir.r4.model.IntegerType;
|
import org.hl7.fhir.r4.model.IntegerType;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -163,7 +164,7 @@ public class JpaSystemProviderDstu2 extends BaseJpaSystemProviderDstu2Plus<Bundl
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(name = JpaConstants.OPERATION_META, idempotent = true, returnParameters = {
|
@Operation(name = ProviderConstants.OPERATION_META, idempotent = true, returnParameters = {
|
||||||
@OperationParam(name = "return", type = MetaDt.class)
|
@OperationParam(name = "return", type = MetaDt.class)
|
||||||
})
|
})
|
||||||
public Parameters meta(RequestDetails theRequestDetails) {
|
public Parameters meta(RequestDetails theRequestDetails) {
|
||||||
|
|
|
@ -21,37 +21,9 @@ package ca.uhn.fhir.jpa.provider.dstu3;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
|
||||||
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProvider;
|
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProvider;
|
||||||
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Create;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Delete;
|
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Operation;
|
|
||||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Update;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Validate;
|
|
||||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
|
||||||
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|
||||||
import org.hl7.fhir.dstu3.model.BooleanType;
|
|
||||||
import org.hl7.fhir.dstu3.model.IdType;
|
|
||||||
import org.hl7.fhir.dstu3.model.IntegerType;
|
|
||||||
import org.hl7.fhir.dstu3.model.Meta;
|
|
||||||
import org.hl7.fhir.dstu3.model.Parameters;
|
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
|
||||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META;
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META_ADD;
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META_DELETE;
|
|
||||||
import static org.hl7.fhir.convertors.conv30_40.Parameters30_40.convertParameters;
|
import static org.hl7.fhir.convertors.conv30_40.Parameters30_40.convertParameters;
|
||||||
|
|
||||||
public class JpaResourceProviderDstu3<T extends IAnyResource> extends BaseJpaResourceProvider<T> {
|
public class JpaResourceProviderDstu3<T extends IAnyResource> extends BaseJpaResourceProvider<T> {
|
||||||
|
|
|
@ -1,42 +1,29 @@
|
||||||
package ca.uhn.fhir.jpa.provider.dstu3;
|
package ca.uhn.fhir.jpa.provider.dstu3;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
|
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
|
||||||
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
|
||||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||||
import ca.uhn.fhir.jpa.provider.BaseJpaSystemProviderDstu2Plus;
|
import ca.uhn.fhir.jpa.provider.BaseJpaSystemProviderDstu2Plus;
|
||||||
import ca.uhn.fhir.model.api.annotation.Description;
|
import ca.uhn.fhir.model.api.annotation.Description;
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Operation;
|
import ca.uhn.fhir.rest.annotation.Operation;
|
||||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Transaction;
|
import ca.uhn.fhir.rest.annotation.Transaction;
|
||||||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import org.hl7.fhir.dstu3.model.BooleanType;
|
|
||||||
import org.hl7.fhir.dstu3.model.Bundle;
|
import org.hl7.fhir.dstu3.model.Bundle;
|
||||||
import org.hl7.fhir.dstu3.model.DecimalType;
|
|
||||||
import org.hl7.fhir.dstu3.model.IntegerType;
|
import org.hl7.fhir.dstu3.model.IntegerType;
|
||||||
import org.hl7.fhir.dstu3.model.Meta;
|
import org.hl7.fhir.dstu3.model.Meta;
|
||||||
import org.hl7.fhir.dstu3.model.Parameters;
|
import org.hl7.fhir.dstu3.model.Parameters;
|
||||||
import org.hl7.fhir.dstu3.model.Parameters.ParametersParameterComponent;
|
|
||||||
import org.hl7.fhir.dstu3.model.StringType;
|
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
|
||||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
|
||||||
import static org.hl7.fhir.convertors.conv30_40.Parameters30_40.convertParameters;
|
import static org.hl7.fhir.convertors.conv30_40.Parameters30_40.convertParameters;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -174,7 +161,7 @@ public class JpaSystemProviderDstu3 extends BaseJpaSystemProviderDstu2Plus<Bundl
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(name = JpaConstants.OPERATION_META, idempotent = true, returnParameters = {
|
@Operation(name = ProviderConstants.OPERATION_META, idempotent = true, returnParameters = {
|
||||||
@OperationParam(name = "return", type = Meta.class)
|
@OperationParam(name = "return", type = Meta.class)
|
||||||
})
|
})
|
||||||
public Parameters meta(RequestDetails theRequestDetails) {
|
public Parameters meta(RequestDetails theRequestDetails) {
|
||||||
|
|
|
@ -21,35 +21,8 @@ package ca.uhn.fhir.jpa.provider.r4;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
|
||||||
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProvider;
|
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProvider;
|
||||||
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Create;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Delete;
|
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Operation;
|
|
||||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Update;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Validate;
|
|
||||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
|
||||||
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|
||||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
|
||||||
import org.hl7.fhir.r4.model.BooleanType;
|
|
||||||
import org.hl7.fhir.r4.model.IdType;
|
|
||||||
import org.hl7.fhir.r4.model.IntegerType;
|
|
||||||
import org.hl7.fhir.r4.model.Meta;
|
|
||||||
import org.hl7.fhir.r4.model.Parameters;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META;
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META_ADD;
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META_DELETE;
|
|
||||||
|
|
||||||
public class JpaResourceProviderR4<T extends IAnyResource> extends BaseJpaResourceProvider<T> {
|
public class JpaResourceProviderR4<T extends IAnyResource> extends BaseJpaResourceProvider<T> {
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Transaction;
|
import ca.uhn.fhir.rest.annotation.Transaction;
|
||||||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
|
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import org.hl7.fhir.r4.model.Bundle;
|
import org.hl7.fhir.r4.model.Bundle;
|
||||||
import org.hl7.fhir.r4.model.IntegerType;
|
import org.hl7.fhir.r4.model.IntegerType;
|
||||||
|
@ -159,7 +160,7 @@ public class JpaSystemProviderR4 extends BaseJpaSystemProviderDstu2Plus<Bundle,
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(name = JpaConstants.OPERATION_META, idempotent = true, returnParameters = {
|
@Operation(name = ProviderConstants.OPERATION_META, idempotent = true, returnParameters = {
|
||||||
@OperationParam(name = "return", type = Meta.class)
|
@OperationParam(name = "return", type = Meta.class)
|
||||||
})
|
})
|
||||||
public Parameters meta(RequestDetails theRequestDetails) {
|
public Parameters meta(RequestDetails theRequestDetails) {
|
||||||
|
|
|
@ -21,35 +21,8 @@ package ca.uhn.fhir.jpa.provider.r5;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
|
||||||
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProvider;
|
import ca.uhn.fhir.jpa.provider.BaseJpaResourceProvider;
|
||||||
import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Create;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Delete;
|
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Operation;
|
|
||||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.ResourceParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Update;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Validate;
|
|
||||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
|
||||||
import ca.uhn.fhir.rest.api.ValidationModeEnum;
|
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
|
||||||
import org.hl7.fhir.instance.model.api.IAnyResource;
|
import org.hl7.fhir.instance.model.api.IAnyResource;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
|
||||||
import org.hl7.fhir.r5.model.BooleanType;
|
|
||||||
import org.hl7.fhir.r5.model.IdType;
|
|
||||||
import org.hl7.fhir.r5.model.IntegerType;
|
|
||||||
import org.hl7.fhir.r5.model.Meta;
|
|
||||||
import org.hl7.fhir.r5.model.Parameters;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META;
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META_ADD;
|
|
||||||
import static ca.uhn.fhir.jpa.model.util.JpaConstants.OPERATION_META_DELETE;
|
|
||||||
|
|
||||||
public class JpaResourceProviderR5<T extends IAnyResource> extends BaseJpaResourceProvider<T> {
|
public class JpaResourceProviderR5<T extends IAnyResource> extends BaseJpaResourceProvider<T> {
|
||||||
|
|
||||||
|
|
|
@ -1,40 +1,29 @@
|
||||||
package ca.uhn.fhir.jpa.provider.r5;
|
package ca.uhn.fhir.jpa.provider.r5;
|
||||||
|
|
||||||
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
|
import ca.uhn.fhir.jpa.api.dao.IFhirSystemDao;
|
||||||
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
|
||||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||||
import ca.uhn.fhir.jpa.provider.BaseJpaSystemProviderDstu2Plus;
|
import ca.uhn.fhir.jpa.provider.BaseJpaSystemProviderDstu2Plus;
|
||||||
import ca.uhn.fhir.model.api.annotation.Description;
|
import ca.uhn.fhir.model.api.annotation.Description;
|
||||||
import ca.uhn.fhir.rest.annotation.IdParam;
|
|
||||||
import ca.uhn.fhir.rest.annotation.Operation;
|
import ca.uhn.fhir.rest.annotation.Operation;
|
||||||
import ca.uhn.fhir.rest.annotation.OperationParam;
|
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Transaction;
|
import ca.uhn.fhir.rest.annotation.Transaction;
|
||||||
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
import ca.uhn.fhir.rest.annotation.TransactionParam;
|
||||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.provider.ProviderConstants;
|
||||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
|
||||||
import org.hl7.fhir.r5.model.BooleanType;
|
|
||||||
import org.hl7.fhir.r5.model.Bundle;
|
import org.hl7.fhir.r5.model.Bundle;
|
||||||
import org.hl7.fhir.r5.model.DecimalType;
|
|
||||||
import org.hl7.fhir.r5.model.IntegerType;
|
import org.hl7.fhir.r5.model.IntegerType;
|
||||||
import org.hl7.fhir.r5.model.Meta;
|
import org.hl7.fhir.r5.model.Meta;
|
||||||
import org.hl7.fhir.r5.model.Parameters;
|
import org.hl7.fhir.r5.model.Parameters;
|
||||||
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
|
|
||||||
import org.hl7.fhir.r5.model.StringType;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
||||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* #%L
|
* #%L
|
||||||
|
@ -171,7 +160,7 @@ public class JpaSystemProviderR5 extends BaseJpaSystemProviderDstu2Plus<Bundle,
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(name = JpaConstants.OPERATION_META, idempotent = true, returnParameters = {
|
@Operation(name = ProviderConstants.OPERATION_META, idempotent = true, returnParameters = {
|
||||||
@OperationParam(name = "return", type = Meta.class)
|
@OperationParam(name = "return", type = Meta.class)
|
||||||
})
|
})
|
||||||
public Parameters meta(RequestDetails theRequestDetails) {
|
public Parameters meta(RequestDetails theRequestDetails) {
|
||||||
|
|
|
@ -420,6 +420,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueSet valueSet = new ValueSet();
|
ValueSet valueSet = new ValueSet();
|
||||||
|
valueSet.setId(theValueSetToExpand.getId());
|
||||||
valueSet.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
valueSet.setStatus(Enumerations.PublicationStatus.ACTIVE);
|
||||||
valueSet.setCompose(theValueSetToExpand.getCompose());
|
valueSet.setCompose(theValueSetToExpand.getCompose());
|
||||||
valueSet.setExpansion(accumulator);
|
valueSet.setExpansion(accumulator);
|
||||||
|
@ -1768,7 +1769,7 @@ public abstract class BaseTermReadSvcImpl implements ITermReadSvc {
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
ourLog.info("Pre-expanded ValueSet[{}] with URL[{}] - Saved {} concepts in {}", valueSet.getId(), valueSet.getUrl(), accumulator.getConceptsSaved(), sw.toString());
|
ourLog.info("Pre-expanded ValueSet[{}] with URL[{}] - Saved {} concepts in {}", valueSet.getId(), valueSet.getUrl(), accumulator.getConceptsSaved(), sw);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ourLog.error("Failed to pre-expand ValueSet: " + e.getMessage(), e);
|
ourLog.error("Failed to pre-expand ValueSet: " + e.getMessage(), e);
|
||||||
|
|
|
@ -4,6 +4,8 @@ import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||||
import ca.uhn.fhir.jpa.api.model.DeleteMethodOutcome;
|
import ca.uhn.fhir.jpa.api.model.DeleteMethodOutcome;
|
||||||
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
|
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
|
||||||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||||
|
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||||
|
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.hl7.fhir.r4.model.Organization;
|
import org.hl7.fhir.r4.model.Organization;
|
||||||
|
@ -16,8 +18,12 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.fail;
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
class DeleteExpungeServiceTest extends BaseJpaR4Test {
|
class DeleteExpungeServiceTest extends BaseJpaR4Test {
|
||||||
|
|
||||||
|
@ -29,6 +35,8 @@ class DeleteExpungeServiceTest extends BaseJpaR4Test {
|
||||||
myDaoConfig.setAllowMultipleDelete(true);
|
myDaoConfig.setAllowMultipleDelete(true);
|
||||||
myDaoConfig.setExpungeEnabled(true);
|
myDaoConfig.setExpungeEnabled(true);
|
||||||
myDaoConfig.setDeleteExpungeEnabled(true);
|
myDaoConfig.setDeleteExpungeEnabled(true);
|
||||||
|
myDaoConfig.setInternalSynchronousSearchSize(new DaoConfig().getInternalSynchronousSearchSize());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
|
@ -57,6 +65,31 @@ class DeleteExpungeServiceTest extends BaseJpaR4Test {
|
||||||
assertEquals(e.getMessage(), "DELETE with _expunge=true failed. Unable to delete " + organizationId.toVersionless() + " because " + patientId.toVersionless() + " refers to it via the path Patient.managingOrganization");
|
assertEquals(e.getMessage(), "DELETE with _expunge=true failed. Unable to delete " + organizationId.toVersionless() + " because " + patientId.toVersionless() + " refers to it via the path Patient.managingOrganization");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@Test
|
||||||
|
public void testDeleteExpungeRespectsSynchronousSize() {
|
||||||
|
//Given
|
||||||
|
myDaoConfig.setInternalSynchronousSearchSize(1);
|
||||||
|
Patient patient = new Patient();
|
||||||
|
myPatientDao.create(patient);
|
||||||
|
Patient otherPatient = new Patient();
|
||||||
|
myPatientDao.create(otherPatient);
|
||||||
|
|
||||||
|
//When
|
||||||
|
DeleteMethodOutcome deleteMethodOutcome = myPatientDao.deleteByUrl("Patient?" + JpaConstants.PARAM_DELETE_EXPUNGE + "=true", mySrd);
|
||||||
|
IBundleProvider remaining = myPatientDao.search(new SearchParameterMap().setLoadSynchronous(true));
|
||||||
|
|
||||||
|
//Then
|
||||||
|
assertThat(deleteMethodOutcome.getExpungedResourcesCount(), is(equalTo(1L)));
|
||||||
|
assertThat(remaining.size(), is(equalTo(1)));
|
||||||
|
|
||||||
|
//When
|
||||||
|
deleteMethodOutcome = myPatientDao.deleteByUrl("Patient?" + JpaConstants.PARAM_DELETE_EXPUNGE + "=true", mySrd);
|
||||||
|
remaining = myPatientDao.search(new SearchParameterMap().setLoadSynchronous(true));
|
||||||
|
|
||||||
|
//Then
|
||||||
|
assertThat(deleteMethodOutcome.getExpungedResourcesCount(), is(equalTo(1L)));
|
||||||
|
assertThat(remaining.size(), is(equalTo(0)));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDeleteExpungeNoThrowExceptionWhenLinkInSearchResults() {
|
public void testDeleteExpungeNoThrowExceptionWhenLinkInSearchResults() {
|
||||||
|
|
|
@ -162,6 +162,7 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
|
||||||
myDaoConfig.setEnforceReferentialIntegrityOnDelete(new DaoConfig().isEnforceReferentialIntegrityOnDelete());
|
myDaoConfig.setEnforceReferentialIntegrityOnDelete(new DaoConfig().isEnforceReferentialIntegrityOnDelete());
|
||||||
myDaoConfig.setEnforceReferenceTargetTypes(new DaoConfig().isEnforceReferenceTargetTypes());
|
myDaoConfig.setEnforceReferenceTargetTypes(new DaoConfig().isEnforceReferenceTargetTypes());
|
||||||
myDaoConfig.setIndexMissingFields(new DaoConfig().getIndexMissingFields());
|
myDaoConfig.setIndexMissingFields(new DaoConfig().getIndexMissingFields());
|
||||||
|
myDaoConfig.setInternalSynchronousSearchSize(new DaoConfig().getInternalSynchronousSearchSize());
|
||||||
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED);
|
myModelConfig.setNormalizedQuantitySearchLevel(NormalizedQuantitySearchLevel.NORMALIZED_QUANTITY_SEARCH_NOT_SUPPORTED);
|
||||||
myDaoConfig.setHistoryCountMode(DaoConfig.DEFAULT_HISTORY_COUNT_MODE);
|
myDaoConfig.setHistoryCountMode(DaoConfig.DEFAULT_HISTORY_COUNT_MODE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||||
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
|
||||||
import ca.uhn.fhir.jpa.entity.TermValueSet;
|
import ca.uhn.fhir.jpa.entity.TermValueSet;
|
||||||
import ca.uhn.fhir.jpa.entity.TermValueSetConcept;
|
import ca.uhn.fhir.jpa.entity.TermValueSetConcept;
|
||||||
import ca.uhn.fhir.jpa.entity.TermValueSetConceptDesignation;
|
|
||||||
import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum;
|
import ca.uhn.fhir.jpa.entity.TermValueSetPreExpansionStatusEnum;
|
||||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
||||||
|
@ -706,6 +705,7 @@ public class ResourceProviderR4ValueSetVerCSNoVerTest extends BaseResourceProvid
|
||||||
.execute();
|
.execute();
|
||||||
ourLog.info("Expanded: {}", myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expanded));
|
ourLog.info("Expanded: {}", myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(expanded));
|
||||||
assertEquals(1, expanded.getExpansion().getContains().size());
|
assertEquals(1, expanded.getExpansion().getContains().size());
|
||||||
|
assertNotNull(expanded.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -791,7 +791,7 @@ public class ResourceProviderR4ValueSetVerCSNoVerTest extends BaseResourceProvid
|
||||||
|
|
||||||
TermValueSet termValueSet = optionalValueSetByUrl.get();
|
TermValueSet termValueSet = optionalValueSetByUrl.get();
|
||||||
assertSame(optionalValueSetByResourcePid.get(), termValueSet);
|
assertSame(optionalValueSetByResourcePid.get(), termValueSet);
|
||||||
ourLog.info("ValueSet:\n" + termValueSet.toString());
|
ourLog.info("ValueSet:\n" + termValueSet);
|
||||||
assertEquals("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2", termValueSet.getUrl());
|
assertEquals("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2", termValueSet.getUrl());
|
||||||
assertEquals(theValueSetName, termValueSet.getName());
|
assertEquals(theValueSetName, termValueSet.getName());
|
||||||
assertEquals(0, termValueSet.getConcepts().size());
|
assertEquals(0, termValueSet.getConcepts().size());
|
||||||
|
@ -809,7 +809,7 @@ public class ResourceProviderR4ValueSetVerCSNoVerTest extends BaseResourceProvid
|
||||||
|
|
||||||
TermValueSet termValueSet = optionalValueSetByUrl.get();
|
TermValueSet termValueSet = optionalValueSetByUrl.get();
|
||||||
assertSame(optionalValueSetByResourcePid.get(), termValueSet);
|
assertSame(optionalValueSetByResourcePid.get(), termValueSet);
|
||||||
ourLog.info("ValueSet:\n" + termValueSet.toString());
|
ourLog.info("ValueSet:\n" + termValueSet);
|
||||||
assertEquals("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2", termValueSet.getUrl());
|
assertEquals("http://www.healthintersections.com.au/fhir/ValueSet/extensional-case-2", termValueSet.getUrl());
|
||||||
assertEquals(theValueSetName, termValueSet.getName());
|
assertEquals(theValueSetName, termValueSet.getName());
|
||||||
assertEquals(theCodeSystem.getConcept().size(), termValueSet.getConcepts().size());
|
assertEquals(theCodeSystem.getConcept().size(), termValueSet.getConcepts().size());
|
||||||
|
|
|
@ -122,6 +122,9 @@ public enum DriverTypeEnum {
|
||||||
dataSource.setUsername(theUsername);
|
dataSource.setUsername(theUsername);
|
||||||
dataSource.setPassword(thePassword);
|
dataSource.setPassword(thePassword);
|
||||||
|
|
||||||
|
// A check for WS-2020-0287
|
||||||
|
assert dataSource.getJmxName() == null;
|
||||||
|
|
||||||
return newConnectionProperties(dataSource);
|
return newConnectionProperties(dataSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,10 +93,6 @@ public class JpaConstants {
|
||||||
* Operation name for the $get-resource-counts operation
|
* Operation name for the $get-resource-counts operation
|
||||||
*/
|
*/
|
||||||
public static final String OPERATION_GET_RESOURCE_COUNTS = "$get-resource-counts";
|
public static final String OPERATION_GET_RESOURCE_COUNTS = "$get-resource-counts";
|
||||||
/**
|
|
||||||
* Operation name for the $meta operation
|
|
||||||
*/
|
|
||||||
public static final String OPERATION_META = "$meta";
|
|
||||||
/**
|
/**
|
||||||
* Operation name for the $validate operation
|
* Operation name for the $validate operation
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -44,6 +44,9 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import static ca.uhn.fhir.rest.api.Constants.URL_TOKEN_METADATA;
|
||||||
|
import static ca.uhn.fhir.rest.server.provider.ProviderConstants.OPERATION_META;
|
||||||
|
|
||||||
@Interceptor
|
@Interceptor
|
||||||
public class ConsentInterceptor {
|
public class ConsentInterceptor {
|
||||||
private static final AtomicInteger ourInstanceCount = new AtomicInteger(0);
|
private static final AtomicInteger ourInstanceCount = new AtomicInteger(0);
|
||||||
|
@ -94,6 +97,9 @@ public class ConsentInterceptor {
|
||||||
|
|
||||||
@Hook(value = Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED)
|
@Hook(value = Pointcut.SERVER_INCOMING_REQUEST_PRE_HANDLED)
|
||||||
public void interceptPreHandled(RequestDetails theRequestDetails) {
|
public void interceptPreHandled(RequestDetails theRequestDetails) {
|
||||||
|
if (isAllowListedRequest(theRequestDetails)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
ConsentOutcome outcome = myConsentService.startOperation(theRequestDetails, myContextConsentServices);
|
ConsentOutcome outcome = myConsentService.startOperation(theRequestDetails, myContextConsentServices);
|
||||||
Validate.notNull(outcome, "Consent service returned null outcome");
|
Validate.notNull(outcome, "Consent service returned null outcome");
|
||||||
|
|
||||||
|
@ -129,6 +135,9 @@ public class ConsentInterceptor {
|
||||||
if (isRequestAuthorized(theRequestDetails)) {
|
if (isRequestAuthorized(theRequestDetails)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isAllowListedRequest(theRequestDetails)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < thePreResourceAccessDetails.size(); i++) {
|
for (int i = 0; i < thePreResourceAccessDetails.size(); i++) {
|
||||||
IBaseResource nextResource = thePreResourceAccessDetails.getResource(i);
|
IBaseResource nextResource = thePreResourceAccessDetails.getResource(i);
|
||||||
|
@ -150,6 +159,9 @@ public class ConsentInterceptor {
|
||||||
if (isRequestAuthorized(theRequestDetails)) {
|
if (isRequestAuthorized(theRequestDetails)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isAllowListedRequest(theRequestDetails)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
IdentityHashMap<IBaseResource, Boolean> alreadySeenResources = getAlreadySeenResourcesMap(theRequestDetails);
|
IdentityHashMap<IBaseResource, Boolean> alreadySeenResources = getAlreadySeenResourcesMap(theRequestDetails);
|
||||||
|
|
||||||
for (int i = 0; i < thePreResourceShowDetails.size(); i++) {
|
for (int i = 0; i < thePreResourceShowDetails.size(); i++) {
|
||||||
|
@ -198,6 +210,9 @@ public class ConsentInterceptor {
|
||||||
if (isRequestAuthorized(theRequestDetails)) {
|
if (isRequestAuthorized(theRequestDetails)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isAllowListedRequest(theRequestDetails)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
IdentityHashMap<IBaseResource, Boolean> alreadySeenResources = getAlreadySeenResourcesMap(theRequestDetails);
|
IdentityHashMap<IBaseResource, Boolean> alreadySeenResources = getAlreadySeenResourcesMap(theRequestDetails);
|
||||||
|
|
||||||
|
@ -330,4 +345,16 @@ public class ConsentInterceptor {
|
||||||
}
|
}
|
||||||
return new ForbiddenOperationException("Rejected by consent service", operationOutcome);
|
return new ForbiddenOperationException("Rejected by consent service", operationOutcome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isAllowListedRequest(RequestDetails theRequestDetails) {
|
||||||
|
return isMetadataPath(theRequestDetails) || isMetaOperation(theRequestDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isMetaOperation(RequestDetails theRequestDetails) {
|
||||||
|
return OPERATION_META.equals(theRequestDetails.getOperation());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isMetadataPath(RequestDetails theRequestDetails) {
|
||||||
|
return URL_TOKEN_METADATA.equals(theRequestDetails.getRequestPath());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,4 +97,8 @@ public class ProviderConstants {
|
||||||
*/
|
*/
|
||||||
public static final String CQL_EVALUATE_MEASURE = "$evaluate-measure";
|
public static final String CQL_EVALUATE_MEASURE = "$evaluate-measure";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation name for the $meta operation
|
||||||
|
* */
|
||||||
|
public static final String OPERATION_META = "$meta";
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@ package ca.uhn.fhir.rest.server.interceptor;
|
||||||
|
|
||||||
import ca.uhn.fhir.context.FhirContext;
|
import ca.uhn.fhir.context.FhirContext;
|
||||||
import ca.uhn.fhir.context.api.BundleInclusionRule;
|
import ca.uhn.fhir.context.api.BundleInclusionRule;
|
||||||
|
import ca.uhn.fhir.rest.annotation.Operation;
|
||||||
|
import ca.uhn.fhir.rest.annotation.OperationParam;
|
||||||
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
import ca.uhn.fhir.rest.annotation.RequiredParam;
|
||||||
import ca.uhn.fhir.rest.annotation.Search;
|
import ca.uhn.fhir.rest.annotation.Search;
|
||||||
import ca.uhn.fhir.rest.api.Constants;
|
import ca.uhn.fhir.rest.api.Constants;
|
||||||
|
@ -11,11 +13,13 @@ import ca.uhn.fhir.rest.param.StringParam;
|
||||||
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
import ca.uhn.fhir.rest.server.FifoMemoryPagingProvider;
|
||||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||||
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
|
||||||
|
import ca.uhn.fhir.rest.server.interceptor.auth.SearchNarrowingInterceptorTest;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.consent.ConsentInterceptor;
|
import ca.uhn.fhir.rest.server.interceptor.consent.ConsentInterceptor;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.consent.ConsentOperationStatusEnum;
|
import ca.uhn.fhir.rest.server.interceptor.consent.ConsentOperationStatusEnum;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.consent.ConsentOutcome;
|
import ca.uhn.fhir.rest.server.interceptor.consent.ConsentOutcome;
|
||||||
import ca.uhn.fhir.rest.server.interceptor.consent.IConsentService;
|
import ca.uhn.fhir.rest.server.interceptor.consent.IConsentService;
|
||||||
import ca.uhn.fhir.rest.server.provider.HashMapResourceProvider;
|
import ca.uhn.fhir.rest.server.provider.HashMapResourceProvider;
|
||||||
|
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
@ -27,9 +31,11 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.servlet.ServletHandler;
|
import org.eclipse.jetty.servlet.ServletHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletHolder;
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.hl7.fhir.instance.model.api.IBaseParameters;
|
||||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||||
import org.hl7.fhir.r4.model.Bundle;
|
import org.hl7.fhir.r4.model.Bundle;
|
||||||
import org.hl7.fhir.r4.model.OperationOutcome;
|
import org.hl7.fhir.r4.model.OperationOutcome;
|
||||||
|
import org.hl7.fhir.r4.model.Parameters;
|
||||||
import org.hl7.fhir.r4.model.Patient;
|
import org.hl7.fhir.r4.model.Patient;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
@ -70,6 +76,7 @@ public class ConsentInterceptorTest {
|
||||||
private static Server ourServer;
|
private static Server ourServer;
|
||||||
private static DummyPatientResourceProvider ourPatientProvider;
|
private static DummyPatientResourceProvider ourPatientProvider;
|
||||||
private static IGenericClient ourFhirClient;
|
private static IGenericClient ourFhirClient;
|
||||||
|
private static DummySystemProvider ourSystemProvider;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private IConsentService myConsentSvc;
|
private IConsentService myConsentSvc;
|
||||||
|
@ -163,6 +170,28 @@ public class ConsentInterceptorTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMetadataCallHasChecksSkipped() throws IOException{
|
||||||
|
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/metadata");
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info("Response: {}", responseContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
httpGet = new HttpGet("http://localhost:" + ourPort + "/$meta");
|
||||||
|
try (CloseableHttpResponse status = ourClient.execute(httpGet)) {
|
||||||
|
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||||
|
String responseContent = IOUtils.toString(status.getEntity().getContent(), Charsets.UTF_8);
|
||||||
|
ourLog.info("Response: {}", responseContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
verify(myConsentSvc, times(0)).canSeeResource(any(), any(), any());
|
||||||
|
verify(myConsentSvc, times(0)).willSeeResource(any(), any(), any());
|
||||||
|
verify(myConsentSvc, times(0)).startOperation(any(), any());
|
||||||
|
verify(myConsentSvc, times(2)).completeOperationSuccess(any(), any());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSearch_SeeResourceAuthorizesOuterBundle() throws IOException {
|
public void testSearch_SeeResourceAuthorizesOuterBundle() throws IOException {
|
||||||
ourPatientProvider.store((Patient) new Patient().setActive(true).setId("PTA"));
|
ourPatientProvider.store((Patient) new Patient().setActive(true).setId("PTA"));
|
||||||
|
@ -457,11 +486,13 @@ public class ConsentInterceptorTest {
|
||||||
ourServer = new Server(0);
|
ourServer = new Server(0);
|
||||||
|
|
||||||
ourPatientProvider = new DummyPatientResourceProvider(ourCtx);
|
ourPatientProvider = new DummyPatientResourceProvider(ourCtx);
|
||||||
|
ourSystemProvider = new DummySystemProvider();
|
||||||
|
|
||||||
ServletHandler servletHandler = new ServletHandler();
|
ServletHandler servletHandler = new ServletHandler();
|
||||||
ourServlet = new RestfulServer(ourCtx);
|
ourServlet = new RestfulServer(ourCtx);
|
||||||
ourServlet.setDefaultPrettyPrint(true);
|
ourServlet.setDefaultPrettyPrint(true);
|
||||||
ourServlet.setResourceProviders(ourPatientProvider);
|
ourServlet.setResourceProviders(ourPatientProvider);
|
||||||
|
ourServlet.registerProvider(ourSystemProvider);
|
||||||
ourServlet.setBundleInclusionRule(BundleInclusionRule.BASED_ON_RESOURCE_PRESENCE);
|
ourServlet.setBundleInclusionRule(BundleInclusionRule.BASED_ON_RESOURCE_PRESENCE);
|
||||||
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
ServletHolder servletHolder = new ServletHolder(ourServlet);
|
||||||
servletHandler.addServletWithMapping(servletHolder, "/*");
|
servletHandler.addServletWithMapping(servletHolder, "/*");
|
||||||
|
@ -478,4 +509,15 @@ public class ConsentInterceptorTest {
|
||||||
ourFhirClient = ourCtx.newRestfulGenericClient("http://localhost:" + ourPort);
|
ourFhirClient = ourCtx.newRestfulGenericClient("http://localhost:" + ourPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class DummySystemProvider{
|
||||||
|
|
||||||
|
@Operation(name = "$meta", idempotent = true, returnParameters = {
|
||||||
|
@OperationParam(name = "return", typeName = "Meta")
|
||||||
|
})
|
||||||
|
public IBaseParameters meta(ServletRequestDetails theRequestDetails) {
|
||||||
|
Parameters retval = new Parameters();
|
||||||
|
retval.addParameter("Meta", "Yes");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue