From 556058a7b76130a493b720931ca6d458d29cbd53 Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Sat, 25 Jun 2016 10:55:31 -0400 Subject: [PATCH] Tests passing --- .../ca/uhn/fhir/rest/api/MethodOutcome.java | 51 +++-------- .../uhn/fhir/rest/client/GenericClient.java | 2 +- .../BaseOutcomeReturningMethodBinding.java | 21 +---- .../ca/uhn/fhir/rest/method/MethodUtil.java | 4 +- .../rest/method/OperationMethodBinding.java | 2 +- .../fhir/rest/method/UpdateMethodBinding.java | 2 +- .../uhn/fhir/rest/server/RestfulServer.java | 3 - .../interceptor/IServerInterceptor.java | 44 +++++---- .../ca/uhn/fhir/cli/RunServerCommand.java | 14 ++- .../ca/uhn/fhir/jpa/demo/ContextHolder.java | 19 ++-- .../ca/uhn/fhir/jpa/demo/JpaServerDemo.java | 3 + .../server/util/JaxRsResponseDstu3Test.java | 4 - .../ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java | 16 ++-- .../fhir/jpa/dao/BaseHapiFhirResourceDao.java | 89 +++++++++++-------- .../fhir/jpa/dao/BaseHapiFhirSystemDao.java | 18 ++-- .../fhir/jpa/dao/FhirResourceDaoDstu2.java | 2 +- .../jpa/dao/FhirResourceDaoPatientDstu2.java | 4 +- ...ResourceDaoQuestionnaireResponseDstu2.java | 17 ++-- .../FhirResourceDaoSearchParameterDstu2.java | 7 +- .../dao/FhirResourceDaoSubscriptionDstu2.java | 19 ++-- .../uhn/fhir/jpa/dao/FhirSystemDaoDstu1.java | 4 +- .../uhn/fhir/jpa/dao/FhirSystemDaoDstu2.java | 6 +- .../ca/uhn/fhir/jpa/dao/IFhirResourceDao.java | 3 +- .../ca/uhn/fhir/jpa/dao/IFhirSystemDao.java | 2 +- .../dstu3/FhirResourceDaoCodeSystemDstu3.java | 7 +- .../jpa/dao/dstu3/FhirResourceDaoDstu3.java | 3 +- .../dstu3/FhirResourceDaoPatientDstu3.java | 4 +- .../FhirResourceDaoSearchParameterDstu3.java | 7 +- .../FhirResourceDaoSubscriptionDstu3.java | 13 ++- .../jpa/dao/dstu3/FhirSystemDaoDstu3.java | 6 +- .../jpa/provider/BaseJpaSystemProvider.java | 38 ++++---- .../BaseJpaSystemProviderDstu2Plus.java | 30 +++++++ .../jpa/provider/JpaSystemProviderDstu2.java | 14 +-- .../dstu3/JpaSystemProviderDstu3.java | 17 +--- .../TerminologyUploaderProviderDstu3.java | 4 +- .../SubscriptionWebsocketHandlerDstu2.java | 6 +- .../SubscriptionWebsocketHandlerDstu3.java | 6 +- ...quireManualActivationInterceptorDstu2.java | 2 +- ...quireManualActivationInterceptorDstu3.java | 3 +- .../FhirResourceDaoDstu2SubscriptionTest.java | 3 +- .../jpa/dao/dstu2/FhirSystemDaoDstu2Test.java | 6 +- .../FhirResourceDaoDstu3SearchFtTest.java | 2 +- .../FhirResourceDaoDstu3SubscriptionTest.java | 2 +- .../FhirResourceDaoDstu3TerminologyTest.java | 10 +-- .../jpa/dao/dstu3/FhirSystemDaoDstu3Test.java | 6 +- .../jpa/provider/SubscriptionsDstu2Test.java | 1 - .../fhir/jpa/term/TerminologySvcImplTest.java | 12 +-- .../uhn/fhirtest/config/TestDstu1Config.java | 8 +- .../uhn/fhirtest/config/TestDstu2Config.java | 6 ++ .../uhn/fhirtest/config/TestDstu3Config.java | 6 ++ .../PublicSecurityInterceptor.java | 61 +++++++++++++ .../AuthorizationInterceptorDstu2Test.java | 52 ++++++++++- ...i_authorizationinterceptor_read_normal.svg | 2 + ..._authorizationinterceptor_write_normal.svg | 2 + src/site/site.xml | 6 +- src/site/xdoc/doc_rest_server_security.xml | 51 ++++++++--- 56 files changed, 450 insertions(+), 302 deletions(-) create mode 100644 hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaSystemProviderDstu2Plus.java create mode 100644 hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/interceptor/PublicSecurityInterceptor.java create mode 100644 src/site/resources/images/hapi_authorizationinterceptor_read_normal.svg create mode 100644 src/site/resources/images/hapi_authorizationinterceptor_write_normal.svg diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/MethodOutcome.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/MethodOutcome.java index 9d5bbd43414..cde6942e331 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/MethodOutcome.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/MethodOutcome.java @@ -24,7 +24,6 @@ import org.hl7.fhir.instance.model.api.IBaseOperationOutcome; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; -import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.util.CoverageIgnore; public class MethodOutcome { @@ -33,7 +32,6 @@ public class MethodOutcome { private IIdType myId; private IBaseOperationOutcome myOperationOutcome; private IBaseResource myResource; - private IdDt myVersionId; /** * Constructor @@ -91,27 +89,6 @@ public class MethodOutcome { myCreated = theCreated; } - /** - * @deprecated Use the constructor which accepts a single IIdType parameter, and include the logical ID and version ID in that IIdType instance - */ - @Deprecated - @CoverageIgnore - public MethodOutcome(IIdType theId, IdDt theVersionId) { - myId = theId; - myVersionId = theVersionId; - } - - /** - * @deprecated Use the constructor which accepts a single IdDt parameter, and include the logical ID and version ID in that IdDt instance - */ - @Deprecated - @CoverageIgnore - public MethodOutcome(IIdType theId, IdDt theVersionId, IBaseOperationOutcome theBaseOperationOutcome) { - myId = theId; - myVersionId = theVersionId; - myOperationOutcome = theBaseOperationOutcome; - } - /** * Constructor * @@ -122,6 +99,16 @@ public class MethodOutcome { myId = theId; } + /** + * Constructor + * + * @param theOperationOutcome + * The operation outcome resource to return + */ + public MethodOutcome(IBaseOperationOutcome theOperationOutcome) { + myOperationOutcome = theOperationOutcome; + } + /** * This will be set to {@link Boolean#TRUE} for instance of MethodOutcome which are * returned to client instances, if the server has responded with an HTTP 201 Created. @@ -152,15 +139,6 @@ public class MethodOutcome { return myResource; } - /** - * @deprecated {@link MethodOutcome#getId()} should return the complete ID including version if it is available - */ - @Deprecated - @CoverageIgnore - public IdDt getVersionId() { - return myVersionId; - } - /** * If not null, indicates whether the resource was created (as opposed to being updated). This is generally not needed, since the server can assume based on the method being called whether the * result was a creation or an update. However, it can be useful if you are implementing an update method that does a create if the ID doesn't already exist. @@ -205,13 +183,4 @@ public class MethodOutcome { myResource = theResource; } - /** - * @deprecated Put the ID and version ID into the same IdDt instance and pass it to {@link #setId(IIdType)} - */ - @Deprecated - @CoverageIgnore - public void setVersionId(IdDt theVersionId) { - myVersionId = theVersionId; - } - } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java index 7d246881f68..8d3e964ca30 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/GenericClient.java @@ -1663,7 +1663,7 @@ public class GenericClient extends BaseClient implements IGenericClient { @Override public MethodOutcome invokeClient(String theResponseMimeType, Reader theResponseReader, int theResponseStatusCode, Map> theHeaders) throws BaseServerResponseException { - MethodOutcome response = MethodUtil.process2xxResponse(myContext, myResourceName, theResponseStatusCode, theResponseMimeType, theResponseReader, theHeaders); + MethodOutcome response = MethodUtil.process2xxResponse(myContext, theResponseStatusCode, theResponseMimeType, theResponseReader, theHeaders); if (theResponseStatusCode == Constants.STATUS_HTTP_201_CREATED) { response.setCreated(true); } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBinding.java index 59a22ff5e09..bcd7c825b7e 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBinding.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/BaseOutcomeReturningMethodBinding.java @@ -40,7 +40,6 @@ import org.hl7.fhir.instance.model.api.IIdType; import ca.uhn.fhir.context.ConfigurationException; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.model.api.IResource; -import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.parser.IParser; import ca.uhn.fhir.rest.api.MethodOutcome; import ca.uhn.fhir.rest.api.PreferReturnEnum; @@ -167,7 +166,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding -1) { - int idIndexStart = resourceIndex + resourceNamePart.length(); - int idIndexEnd = theLocationHeader.indexOf('/', idIndexStart); - if (idIndexEnd == -1) { - // nothing - } else { - String versionIdPart = "/_history/"; - int historyIdStart = theLocationHeader.indexOf(versionIdPart, idIndexEnd); - if (historyIdStart != -1) { - theOutcomeToPopulate.setVersionId(new IdDt(theLocationHeader.substring(historyIdStart + versionIdPart.length()))); - } - } - } } } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/MethodUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/MethodUtil.java index 384f92d477c..34445b4d835 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/MethodUtil.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/MethodUtil.java @@ -747,7 +747,7 @@ public class MethodUtil { } - public static MethodOutcome process2xxResponse(FhirContext theContext, String theResourceName, int theResponseStatusCode, String theResponseMimeType, Reader theResponseReader, Map> theHeaders) { + public static MethodOutcome process2xxResponse(FhirContext theContext, int theResponseStatusCode, String theResponseMimeType, Reader theResponseReader, Map> theHeaders) { List locationHeaders = new ArrayList(); List lh = theHeaders.get(Constants.HEADER_LOCATION_LC); if (lh != null) { @@ -761,7 +761,7 @@ public class MethodUtil { MethodOutcome retVal = new MethodOutcome(); if (locationHeaders != null && locationHeaders.size() > 0) { String locationHeader = locationHeaders.get(0); - BaseOutcomeReturningMethodBinding.parseContentLocation(theContext, retVal, theResourceName, locationHeader); + BaseOutcomeReturningMethodBinding.parseContentLocation(theContext, retVal, locationHeader); } if (theResponseStatusCode != Constants.STATUS_HTTP_204_NO_CONTENT) { EncodingEnum ct = EncodingEnum.forContentType(theResponseMimeType); diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OperationMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OperationMethodBinding.java index 81151e40c9d..534723a01a0 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OperationMethodBinding.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/OperationMethodBinding.java @@ -112,7 +112,7 @@ public class OperationMethodBinding extends BaseResourceReturningMethodBinding { myName = theOperationName; if (theContext.getVersion().getVersion().isEquivalentTo(FhirVersionEnum.DSTU1)) { - throw new ConfigurationException("@" + Operation.class.getSimpleName() + " methods are not supported on servers for FHIR version " + theContext.getVersion().getVersion().name()); + throw new ConfigurationException("@" + Operation.class.getSimpleName() + " methods are not supported on servers for FHIR version " + theContext.getVersion().getVersion().name() + " - Found one on class " + theMethod.getDeclaringClass().getName()); } if (theReturnTypeFromRp != null) { diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/UpdateMethodBinding.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/UpdateMethodBinding.java index 77bca6ce840..acef735e3e6 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/UpdateMethodBinding.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/method/UpdateMethodBinding.java @@ -83,7 +83,7 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe if (isNotBlank(locationHeader)) { MethodOutcome mo = new MethodOutcome(); - parseContentLocation(getContext(), mo, getResourceName(), locationHeader); + parseContentLocation(getContext(), mo, locationHeader); if (mo.getId() == null || mo.getId().isEmpty()) { throw new InvalidRequestException("Invalid Content-Location header for resource " + getResourceName() + ": " + locationHeader); } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java index a6a9319b3cb..ea41b928831 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/RestfulServer.java @@ -176,9 +176,6 @@ public class RestfulServer extends HttpServlet implements IRestfulServer implements IDao { } @SuppressWarnings("unchecked") - protected ResourceTable updateEntity(final IBaseResource theResource, ResourceTable theEntity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, boolean thePerformIndexing, - boolean theUpdateVersion, Date theUpdateTime, RequestDetails theRequestDetails) { + protected ResourceTable updateEntity(final IBaseResource theResource, ResourceTable theEntity, Date theDeletedTimestampOrNull, boolean thePerformIndexing, + boolean theUpdateVersion, Date theUpdateTime) { ourLog.info("Starting entity update"); /* @@ -1085,7 +1084,7 @@ public abstract class BaseHapiFhirDao implements IDao { */ if (theResource != null) { if (thePerformIndexing) { - validateResourceForStorage((T) theResource, theEntity, theRequestDetails); + validateResourceForStorage((T) theResource, theEntity); } String resourceType = myContext.getResourceDefinition(theResource).getName(); if (isNotBlank(theEntity.getResourceType()) && !theEntity.getResourceType().equals(resourceType)) { @@ -1394,9 +1393,8 @@ public abstract class BaseHapiFhirDao implements IDao { return theEntity; } - protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable entity, boolean theUpdateHistory, Date theDeletedTimestampOrNull, Date theUpdateTime, - RequestDetails theRequestDetails) { - return updateEntity(theResource, entity, theUpdateHistory, theDeletedTimestampOrNull, true, true, theUpdateTime, theRequestDetails); + protected ResourceTable updateEntity(IBaseResource theResource, ResourceTable entity, Date theDeletedTimestampOrNull, Date theUpdateTime) { + return updateEntity(theResource, entity, theDeletedTimestampOrNull, true, true, theUpdateTime); } protected void validateDeleteConflictsEmptyOrThrowException(List theDeleteConflicts) { @@ -1423,10 +1421,8 @@ public abstract class BaseHapiFhirDao implements IDao { * The resource that is about to be persisted * @param theEntityToSave * TODO - * @param theRequestDetails - * TODO */ - protected void validateResourceForStorage(T theResource, ResourceTable theEntityToSave, RequestDetails theRequestDetails) { + protected void validateResourceForStorage(T theResource, ResourceTable theEntityToSave) { Object tag = null; if (theResource instanceof IResource) { IResource res = (IResource) theResource; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java index 648f8285719..dc1a608192e 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java @@ -197,20 +197,26 @@ public abstract class BaseHapiFhirResourceDao extends B validateOkToDelete(deleteConflicts, entity); // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(theId, theId.getResourceType(), getContext(), theRequestDetails); - notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails); - + if (theRequestDetails != null) { + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theId.getResourceType(), theId); + notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails); + } + Date updateTime = new Date(); - ResourceTable savedEntity = updateEntity(null, entity, true, updateTime, updateTime, theRequestDetails); + ResourceTable savedEntity = updateEntity(null, entity, updateTime, updateTime); // Notify JPA interceptors - T resourceToDelete = toResource(myResourceType, entity, false); - theRequestDetails.getRequestOperationCallback().resourceDeleted(resourceToDelete); - for (IServerInterceptor next : getConfig().getInterceptors()) { - if (next instanceof IJpaServerInterceptor) { - ((IJpaServerInterceptor) next).resourceDeleted(requestDetails, entity); + if (theRequestDetails != null) { + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theId.getResourceType(), theId); + T resourceToDelete = toResource(myResourceType, entity, false); + theRequestDetails.getRequestOperationCallback().resourceDeleted(resourceToDelete); + for (IServerInterceptor next : getConfig().getInterceptors()) { + if (next instanceof IJpaServerInterceptor) { + ((IJpaServerInterceptor) next).resourceDeleted(requestDetails, entity); + } } } + return savedEntity; } @@ -245,12 +251,12 @@ public abstract class BaseHapiFhirResourceDao extends B // Notify interceptors IdDt idToDelete = entity.getIdDt(); - ActionRequestDetails requestDetails = new ActionRequestDetails(idToDelete, idToDelete.getResourceType(), getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, idToDelete.getResourceType(), idToDelete); notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails); // Perform delete Date updateTime = new Date(); - updateEntity(null, entity, true, updateTime, updateTime, theRequestDetails); + updateEntity(null, entity, updateTime, updateTime); // Notify JPA interceptors T resourceToDelete = toResource(myResourceType, entity, false); @@ -322,21 +328,26 @@ public abstract class BaseHapiFhirResourceDao extends B } // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(theResource.getIdElement(), toResourceName(theResource), theResource, getContext(), theRequestDetails); - notifyInterceptors(RestOperationTypeEnum.CREATE, requestDetails); - + if (theRequestDetails != null) { + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theResource); + notifyInterceptors(RestOperationTypeEnum.CREATE, requestDetails); + } + // Perform actual DB update - updateEntity(theResource, entity, false, null, thePerformIndexing, true, theUpdateTime, theRequestDetails); + updateEntity(theResource, entity, null, thePerformIndexing, true, theUpdateTime); theResource.setId(entity.getIdDt()); // Notify JPA interceptors - theRequestDetails.getRequestOperationCallback().resourceCreated(theResource); - for (IServerInterceptor next : getConfig().getInterceptors()) { - if (next instanceof IJpaServerInterceptor) { - ((IJpaServerInterceptor) next).resourceCreated(requestDetails, entity); + if (theRequestDetails != null) { + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getContext(), theResource); + theRequestDetails.getRequestOperationCallback().resourceCreated(theResource); + for (IServerInterceptor next : getConfig().getInterceptors()) { + if (next instanceof IJpaServerInterceptor) { + ((IJpaServerInterceptor) next).resourceCreated(requestDetails, entity); + } } } - + DaoMethodOutcome outcome = toMethodOutcome(entity, theResource).setCreated(true); String msg = getContext().getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "successfulCreate", outcome.getId(), w.getMillisAndRestart()); @@ -401,7 +412,7 @@ public abstract class BaseHapiFhirResourceDao extends B @Override public TagList getAllResourceTags(RequestDetails theRequestDetails) { // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails); notifyInterceptors(RestOperationTypeEnum.GET_TAGS, requestDetails); StopWatch w = new StopWatch(); @@ -424,7 +435,7 @@ public abstract class BaseHapiFhirResourceDao extends B @Override public TagList getTags(IIdType theResourceId, RequestDetails theRequestDetails) { // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, null, getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, null, theResourceId); notifyInterceptors(RestOperationTypeEnum.GET_TAGS, requestDetails); StopWatch w = new StopWatch(); @@ -436,7 +447,7 @@ public abstract class BaseHapiFhirResourceDao extends B @Override public IBundleProvider history(Date theSince, Date theUntil, RequestDetails theRequestDetails) { // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails); notifyInterceptors(RestOperationTypeEnum.HISTORY_TYPE, requestDetails); StopWatch w = new StopWatch(); @@ -448,7 +459,7 @@ public abstract class BaseHapiFhirResourceDao extends B @Override public IBundleProvider history(final IIdType theId, final Date theSince, Date theUntil, RequestDetails theRequestDetails) { // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName(), getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theId); notifyInterceptors(RestOperationTypeEnum.HISTORY_INSTANCE, requestDetails); StopWatch w = new StopWatch(); @@ -547,7 +558,7 @@ public abstract class BaseHapiFhirResourceDao extends B @Override public MT metaAddOperation(IIdType theResourceId, MT theMetaAdd, RequestDetails theRequestDetails) { // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, getResourceName(), getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theResourceId); notifyInterceptors(RestOperationTypeEnum.META_ADD, requestDetails); StopWatch w = new StopWatch(); @@ -577,7 +588,7 @@ public abstract class BaseHapiFhirResourceDao extends B @Override public MT metaDeleteOperation(IIdType theResourceId, MT theMetaDel, RequestDetails theRequestDetails) { // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(theResourceId, getResourceName(), getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theResourceId); notifyInterceptors(RestOperationTypeEnum.META_DELETE, requestDetails); StopWatch w = new StopWatch(); @@ -609,7 +620,7 @@ public abstract class BaseHapiFhirResourceDao extends B @Override public MT metaGetOperation(Class theType, IIdType theId, RequestDetails theRequestDetails) { // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName(), getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theId); notifyInterceptors(RestOperationTypeEnum.META, requestDetails); Set tagDefs = new HashSet(); @@ -628,7 +639,7 @@ public abstract class BaseHapiFhirResourceDao extends B @Override public MT metaGetOperation(Class theType, RequestDetails theRequestDetails) { // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), null); notifyInterceptors(RestOperationTypeEnum.META, requestDetails); String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t WHERE t.myResourceType = :res_type)"; @@ -704,10 +715,12 @@ public abstract class BaseHapiFhirResourceDao extends B validateResourceTypeAndThrowIllegalArgumentException(theId); // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName(), getContext(), theRequestDetails); - RestOperationTypeEnum operationType = theId.hasVersionIdPart() ? RestOperationTypeEnum.VREAD : RestOperationTypeEnum.READ; - notifyInterceptors(operationType, requestDetails); - + if (theRequestDetails != null) { + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theId); + RestOperationTypeEnum operationType = theId.hasVersionIdPart() ? RestOperationTypeEnum.VREAD : RestOperationTypeEnum.READ; + notifyInterceptors(operationType, requestDetails); + } + StopWatch w = new StopWatch(); BaseHasResource entity = readEntity(theId); validateResourceType(entity); @@ -790,14 +803,14 @@ public abstract class BaseHapiFhirResourceDao extends B } @Override - public void reindex(T theResource, ResourceTable theEntity, RequestDetails theRequestDetails) { - updateEntity(theResource, theEntity, false, null, true, false, theEntity.getUpdatedDate(), theRequestDetails); + public void reindex(T theResource, ResourceTable theEntity) { + updateEntity(theResource, theEntity, null, true, false, theEntity.getUpdatedDate()); } @Override public void removeTag(IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm, RequestDetails theRequestDetails) { // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(theId, getResourceName(), getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), theId); notifyInterceptors(RestOperationTypeEnum.DELETE_TAGS, requestDetails); StopWatch w = new StopWatch(); @@ -838,7 +851,7 @@ public abstract class BaseHapiFhirResourceDao extends B @Override public IBundleProvider search(final SearchParameterMap theParams) { // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext(), theParams.getRequestDetails()); + ActionRequestDetails requestDetails = new ActionRequestDetails(theParams.getRequestDetails(), getContext(), getResourceName(), null); notifyInterceptors(RestOperationTypeEnum.SEARCH_TYPE, requestDetails); SearchBuilder builder = new SearchBuilder(getContext(), myEntityManager, myPlatformTransactionManager, mySearchDao, mySearchResultDao, this, myResourceIndexedSearchParamUriDao, myForcedIdDao, @@ -1010,11 +1023,11 @@ public abstract class BaseHapiFhirResourceDao extends B } // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(resourceId, getResourceName(), theResource, getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, theResource, getResourceName(), resourceId); notifyInterceptors(RestOperationTypeEnum.UPDATE, requestDetails); // Perform update - ResourceTable savedEntity = updateEntity(theResource, entity, true, null, thePerformIndexing, true, new Date(), theRequestDetails); + ResourceTable savedEntity = updateEntity(theResource, entity, null, thePerformIndexing, true, new Date()); // Notify interceptors theRequestDetails.getRequestOperationCallback().resourceUpdated(theResource); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java index a068a68b921..9391b6443a2 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java @@ -79,21 +79,21 @@ public abstract class BaseHapiFhirSystemDao extends BaseHapiFhirDao() { @SuppressWarnings("unchecked") @Override @@ -135,7 +135,7 @@ public abstract class BaseHapiFhirSystemDao extends BaseHapiFhirDao extends BaseHapiFhirDao extends BaseHapiFhirDao extends BaseHapiFhirDao extends BaseHapiFhirResou @Override public MethodOutcome validate(T theResource, IIdType theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile, RequestDetails theRequestDetails) { - ActionRequestDetails requestDetails = new ActionRequestDetails(theId, null, theResource, getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, theResource, null, theId); notifyInterceptors(RestOperationTypeEnum.VALIDATE, requestDetails); if (theMode == ValidationModeEnum.DELETE) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoPatientDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoPatientDstu2.java index 958c3e4210d..793aa6aa17c 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoPatientDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoPatientDstu2.java @@ -73,7 +73,7 @@ public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2im @Override public IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequestDetails) { // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), null); notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE, requestDetails); return doEverythingOperation(theId, theCount, theLastUpdated, theSort, theContent, theNarrative); @@ -82,7 +82,7 @@ public class FhirResourceDaoPatientDstu2 extends FhirResourceDaoDstu2im @Override public IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, IPrimitiveType theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequestDetails) { // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), null); notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, requestDetails); return doEverythingOperation(null, theCount, theLastUpdated, theSort, theContent, theNarrative); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoQuestionnaireResponseDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoQuestionnaireResponseDstu2.java index 2685aacb398..0af33df83f4 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoQuestionnaireResponseDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoQuestionnaireResponseDstu2.java @@ -35,7 +35,6 @@ import ca.uhn.fhir.model.dstu2.resource.OperationOutcome; import ca.uhn.fhir.model.dstu2.resource.Questionnaire; import ca.uhn.fhir.model.dstu2.resource.QuestionnaireResponse; import ca.uhn.fhir.model.dstu2.resource.ValueSet; -import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.validation.FhirValidator; @@ -64,8 +63,8 @@ public class FhirResourceDaoQuestionnaireResponseDstu2 extends FhirResourceDaoDs } @Override - protected void validateResourceForStorage(QuestionnaireResponse theResource, ResourceTable theEntityToSave, RequestDetails theRequestDetails) { - super.validateResourceForStorage(theResource, theEntityToSave, theRequestDetails); + protected void validateResourceForStorage(QuestionnaireResponse theResource, ResourceTable theEntityToSave) { + super.validateResourceForStorage(theResource, theEntityToSave); if (!myValidateResponses) { return; } @@ -80,7 +79,7 @@ public class FhirResourceDaoQuestionnaireResponseDstu2 extends FhirResourceDaoDs val.setValidateAgainstStandardSchematron(false); FhirQuestionnaireResponseValidator module = new FhirQuestionnaireResponseValidator(); - module.setResourceLoader(new JpaResourceLoader(theRequestDetails)); + module.setResourceLoader(new JpaResourceLoader()); val.registerValidatorModule(module); ValidationResult result = val.validateWithResult(myRefImplCtx.newJsonParser().parseResource(getContext().newJsonParser().encodeResourceToString(qa))); @@ -92,10 +91,8 @@ public class FhirResourceDaoQuestionnaireResponseDstu2 extends FhirResourceDaoDs public class JpaResourceLoader implements IResourceLoader { - private RequestDetails myRequestDetails; - - public JpaResourceLoader(RequestDetails theRequestDetails) { - myRequestDetails = theRequestDetails; + public JpaResourceLoader() { + super(); } @Override @@ -107,7 +104,7 @@ public class FhirResourceDaoQuestionnaireResponseDstu2 extends FhirResourceDaoDs */ if ("ValueSet".equals(theType.getSimpleName())) { IFhirResourceDao dao = getDao(ValueSet.class); - ValueSet in = dao.read(theId, myRequestDetails); + ValueSet in = dao.read(theId, null); String encoded = getContext().newJsonParser().encodeResourceToString(in); // TODO: this is temporary until structures-dstu2 catches up to structures-hl7org.dstu2 @@ -116,7 +113,7 @@ public class FhirResourceDaoQuestionnaireResponseDstu2 extends FhirResourceDaoDs return myRefImplCtx.newJsonParser().parseResource(theType, encoded); } else if ("Questionnaire".equals(theType.getSimpleName())) { IFhirResourceDao dao = getDao(Questionnaire.class); - Questionnaire vs = dao.read(theId, myRequestDetails); + Questionnaire vs = dao.read(theId, null); return myRefImplCtx.newJsonParser().parseResource(theType, getContext().newJsonParser().encodeResourceToString(vs)); } else { // Should not happen, validator will only ask for these two diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoSearchParameterDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoSearchParameterDstu2.java index b4c053e4d07..8aedacf6397 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoSearchParameterDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoSearchParameterDstu2.java @@ -27,8 +27,6 @@ import org.springframework.scheduling.annotation.Scheduled; import ca.uhn.fhir.model.dstu2.composite.MetaDt; import ca.uhn.fhir.model.dstu2.resource.Bundle; import ca.uhn.fhir.model.dstu2.resource.SearchParameter; -import ca.uhn.fhir.rest.method.RequestDetails; -import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; public class FhirResourceDaoSearchParameterDstu2 extends FhirResourceDaoDstu2implements IFhirResourceDaoSearchParameter { @@ -48,10 +46,9 @@ public class FhirResourceDaoSearchParameterDstu2 extends FhirResourceDaoDstu2 0; i++) { - count = mySystemDao.performReindexingPass(100, requestDetails); + count = mySystemDao.performReindexingPass(100); try { Thread.sleep(DateUtils.MILLIS_PER_SECOND); } catch (InterruptedException e) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoSubscriptionDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoSubscriptionDstu2.java index 9d0ffbbeb32..7dd8a586b13 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoSubscriptionDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirResourceDaoSubscriptionDstu2.java @@ -52,7 +52,6 @@ import ca.uhn.fhir.jpa.entity.SubscriptionFlaggedResource; import ca.uhn.fhir.jpa.entity.SubscriptionTable; import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum; -import ca.uhn.fhir.model.dstu.valueset.QuantityCompararatorEnum; import ca.uhn.fhir.model.dstu2.resource.Subscription; import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum; import ca.uhn.fhir.model.primitive.IdDt; @@ -60,9 +59,9 @@ import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.rest.api.SortOrderEnum; import ca.uhn.fhir.rest.api.SortSpec; -import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.param.DateParam; import ca.uhn.fhir.rest.param.DateRangeParam; +import ca.uhn.fhir.rest.param.ParamPrefixEnum; import ca.uhn.fhir.rest.server.Constants; import ca.uhn.fhir.rest.server.IBundleProvider; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; @@ -162,8 +161,8 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2 dao = getDao(resourceDef.getImplementingClass()); @@ -252,7 +251,7 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2() { @Override public Void doInTransaction(TransactionStatus theStatus) { - delete(subscriptionId, new ServletRequestDetails()); + delete(subscriptionId, null); return null; } }); @@ -260,9 +259,9 @@ public class FhirResourceDaoSubscriptionDstu2 extends FhirResourceDaoDstu2, M ourLog.info("Beginning transaction with {} resources", theResources.size()); // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails); notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails); long start = System.currentTimeMillis(); @@ -270,7 +270,7 @@ public class FhirSystemDaoDstu1 extends BaseHapiFhirSystemDao, M ResourceMetadataKeyEnum.DELETED_AT.put(resource, new InstantDt(deletedTimestampOrNull)); } - updateEntity(resource, table, table.getId() != null, deletedTimestampOrNull, updateTime, theRequestDetails); + updateEntity(resource, table, deletedTimestampOrNull, updateTime); } long delay = System.currentTimeMillis() - start; diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2.java index c3bb1fa05c9..3e56c194241 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2.java @@ -200,7 +200,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao { @Override public MetaDt metaGetOperation(RequestDetails theRequestDetails) { // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails); notifyInterceptors(RestOperationTypeEnum.META, requestDetails); String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t)"; @@ -259,7 +259,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao { @Transactional(propagation = Propagation.REQUIRED) @Override public Bundle transaction(RequestDetails theRequestDetails, Bundle theRequest) { - ActionRequestDetails requestDetails = new ActionRequestDetails(null, "Bundle", theRequest, getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, theRequest, "Bundle", null); notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails); String actionName = "Transaction"; @@ -474,7 +474,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao { InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(nextResource); Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null; - updateEntity(nextResource, nextOutcome.getEntity(), false, deletedTimestampOrNull, true, false, updateTime, theRequestDetails); + updateEntity(nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, true, false, updateTime); } myEntityManager.flush(); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/IFhirResourceDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/IFhirResourceDao.java index 1be0d79d477..dd44dfc8818 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/IFhirResourceDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/IFhirResourceDao.java @@ -143,9 +143,8 @@ public interface IFhirResourceDao extends IDao { /** * Updates index tables associated with the given resource. Does not create a new * version or update the resource's update time. - * @param theRequestDetails TODO */ - void reindex(T theResource, ResourceTable theEntity, RequestDetails theRequestDetails); + void reindex(T theResource, ResourceTable theEntity); void removeTag(IIdType theId, TagTypeEnum theTagType, String theScheme, String theTerm, RequestDetails theRequestDetails); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/IFhirSystemDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/IFhirSystemDao.java index cbb4831e0c6..b5f6ea52be6 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/IFhirSystemDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/IFhirSystemDao.java @@ -62,7 +62,7 @@ public interface IFhirSystemDao extends IDao { */ MT metaGetOperation(RequestDetails theRequestDetails); - int performReindexingPass(Integer theCount, RequestDetails theRequestDetails); + int performReindexingPass(Integer theCount); T transaction(RequestDetails theRequestDetails, T theResources); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoCodeSystemDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoCodeSystemDstu3.java index 53d8144b41d..5681974830f 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoCodeSystemDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoCodeSystemDstu3.java @@ -35,7 +35,6 @@ import org.hl7.fhir.dstu3.model.CodeSystem.ConceptDefinitionComponent; import org.hl7.fhir.dstu3.model.CodeableConcept; import org.hl7.fhir.dstu3.model.Coding; import org.hl7.fhir.dstu3.model.IdType; -import org.hl7.fhir.dstu3.model.ValueSet.ValueSetExpansionContainsComponent; import org.hl7.fhir.instance.model.api.IBaseResource; import org.hl7.fhir.instance.model.api.IIdType; import org.hl7.fhir.instance.model.api.IPrimitiveType; @@ -198,9 +197,9 @@ public class FhirResourceDaoCodeSystemDstu3 extends FhirResourceDaoDstu3 extends BaseHapiFhirRe @Override public MethodOutcome validate(T theResource, IIdType theId, String theRawResource, EncodingEnum theEncoding, ValidationModeEnum theMode, String theProfile, RequestDetails theRequestDetails) { - ActionRequestDetails requestDetails = new ActionRequestDetails(theId, null, theResource, getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, theResource, null, theId); notifyInterceptors(RestOperationTypeEnum.VALIDATE, requestDetails); if (theMode == ValidationModeEnum.DELETE) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoPatientDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoPatientDstu3.java index b7160e8e9cf..6dfeb25f0ad 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoPatientDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoPatientDstu3.java @@ -72,7 +72,7 @@ public class FhirResourceDaoPatientDstu3 extends FhirResourceDaoDstu3im @Override public IBundleProvider patientInstanceEverything(HttpServletRequest theServletRequest, IIdType theId, IPrimitiveType theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequestDetails) { // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), null); notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_INSTANCE, requestDetails); return doEverythingOperation(theId, theCount, theLastUpdated, theSort, theContent, theNarrative); @@ -81,7 +81,7 @@ public class FhirResourceDaoPatientDstu3 extends FhirResourceDaoDstu3im @Override public IBundleProvider patientTypeEverything(HttpServletRequest theServletRequest, IPrimitiveType theCount, DateRangeParam theLastUpdated, SortSpec theSort, StringAndListParam theContent, StringAndListParam theNarrative, RequestDetails theRequestDetails) { // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(null, getResourceName(), getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, getResourceName(), null); notifyInterceptors(RestOperationTypeEnum.EXTENDED_OPERATION_TYPE, requestDetails); return doEverythingOperation(null, theCount, theLastUpdated, theSort, theContent, theNarrative); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoSearchParameterDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoSearchParameterDstu3.java index b6490c883c4..24cc8493071 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoSearchParameterDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoSearchParameterDstu3.java @@ -29,8 +29,6 @@ import org.springframework.scheduling.annotation.Scheduled; import ca.uhn.fhir.jpa.dao.IFhirResourceDaoSearchParameter; import ca.uhn.fhir.jpa.dao.IFhirSystemDao; -import ca.uhn.fhir.rest.method.RequestDetails; -import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3implements IFhirResourceDaoSearchParameter { @@ -50,10 +48,9 @@ public class FhirResourceDaoSearchParameterDstu3 extends FhirResourceDaoDstu3 0; i++) { - count = mySystemDao.performReindexingPass(100, requestDetails); + count = mySystemDao.performReindexingPass(100); try { Thread.sleep(DateUtils.MILLIS_PER_SECOND); } catch (InterruptedException e) { diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoSubscriptionDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoSubscriptionDstu3.java index a61288de7a9..6a7296f2bb0 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoSubscriptionDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoSubscriptionDstu3.java @@ -64,7 +64,6 @@ import ca.uhn.fhir.model.primitive.InstantDt; import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.rest.api.SortOrderEnum; import ca.uhn.fhir.rest.api.SortSpec; -import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.param.DateParam; import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.server.Constants; @@ -257,7 +256,7 @@ public class FhirResourceDaoSubscriptionDstu3 extends FhirResourceDaoDstu3() { @Override public Void doInTransaction(TransactionStatus theStatus) { - delete(subscriptionId, new ServletRequestDetails()); + delete(subscriptionId, null); return null; } }); @@ -265,9 +264,9 @@ public class FhirResourceDaoSubscriptionDstu3 extends FhirResourceDaoDstu3 { @Override public Meta metaGetOperation(RequestDetails theRequestDetails) { // Notify interceptors - ActionRequestDetails requestDetails = new ActionRequestDetails(null, null, getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails); notifyInterceptors(RestOperationTypeEnum.META, requestDetails); String sql = "SELECT d FROM TagDefinition d WHERE d.myId IN (SELECT DISTINCT t.myTagId FROM ResourceTag t)"; @@ -264,7 +264,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao { @Transactional(propagation = Propagation.REQUIRED) @Override public Bundle transaction(RequestDetails theRequestDetails, Bundle theRequest) { - ActionRequestDetails requestDetails = new ActionRequestDetails(null, "Bundle", theRequest, getContext(), theRequestDetails); + ActionRequestDetails requestDetails = new ActionRequestDetails(theRequestDetails, theRequest, "Bundle", null); notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails); String actionName = "Transaction"; @@ -488,7 +488,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao { IPrimitiveType deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get((IAnyResource) nextResource); Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null; - updateEntity(nextResource, nextOutcome.getEntity(), false, deletedTimestampOrNull, true, false, updateTime, theRequestDetails); + updateEntity(nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, true, false, updateTime); } myEntityManager.flush(); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaSystemProvider.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaSystemProvider.java index 6420142436a..3abe39bae35 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaSystemProvider.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaSystemProvider.java @@ -24,6 +24,9 @@ import java.util.Date; import javax.servlet.http.HttpServletRequest; +import org.hl7.fhir.instance.model.api.IBaseParameters; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IPrimitiveType; import org.springframework.beans.factory.annotation.Required; import ca.uhn.fhir.jpa.dao.IFhirSystemDao; @@ -31,22 +34,36 @@ import ca.uhn.fhir.model.api.TagList; import ca.uhn.fhir.rest.annotation.At; import ca.uhn.fhir.rest.annotation.GetTags; import ca.uhn.fhir.rest.annotation.History; +import ca.uhn.fhir.rest.annotation.Operation; +import ca.uhn.fhir.rest.annotation.OperationParam; import ca.uhn.fhir.rest.annotation.Since; import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.param.DateRangeParam; import ca.uhn.fhir.rest.server.IBundleProvider; +import ca.uhn.fhir.util.ParametersUtil; public class BaseJpaSystemProvider extends BaseJpaProvider { + public static final String MARK_ALL_RESOURCES_FOR_REINDEXING = "$mark-all-resources-for-reindexing"; + private IFhirSystemDao myDao; public BaseJpaSystemProvider() { // nothing } - @Required - public void setDao(IFhirSystemDao theDao) { - myDao = theDao; + @GetTags + public TagList getAllTagsOnServer(HttpServletRequest theRequest, RequestDetails theRequestDetails) { + startRequest(theRequest); + try { + return myDao.getAllTags(theRequestDetails); + } finally { + endRequest(theRequest); + } + } + + protected IFhirSystemDao getDao() { + return myDao; } @History @@ -60,18 +77,9 @@ public class BaseJpaSystemProvider extends BaseJpaProvider { } } - protected IFhirSystemDao getDao() { - return myDao; - } - - @GetTags - public TagList getAllTagsOnServer(HttpServletRequest theRequest, RequestDetails theRequestDetails) { - startRequest(theRequest); - try { - return myDao.getAllTags(theRequestDetails); - } finally { - endRequest(theRequest); - } + @Required + public void setDao(IFhirSystemDao theDao) { + myDao = theDao; } } diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaSystemProviderDstu2Plus.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaSystemProviderDstu2Plus.java new file mode 100644 index 00000000000..cadce02eaba --- /dev/null +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/BaseJpaSystemProviderDstu2Plus.java @@ -0,0 +1,30 @@ +package ca.uhn.fhir.jpa.provider; + +import org.hl7.fhir.instance.model.api.IBaseParameters; +import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.instance.model.api.IPrimitiveType; + +import ca.uhn.fhir.rest.annotation.Operation; +import ca.uhn.fhir.rest.annotation.OperationParam; +import ca.uhn.fhir.util.ParametersUtil; + +public abstract class BaseJpaSystemProviderDstu2Plus extends BaseJpaSystemProvider { + + //@formatter:off + @Operation(name=MARK_ALL_RESOURCES_FOR_REINDEXING, idempotent=true, returnParameters= { + @OperationParam(name="status") + }) + //@formatter:on + public IBaseResource markAllResourcesForReindexing() { + int count = getDao().markAllResourcesForReindexing(); + + IBaseParameters retVal = ParametersUtil.newInstance(getContext()); + + IPrimitiveType string = ParametersUtil.createString(getContext(), "Marked " + count + " resources"); + ParametersUtil.addParameterToParameters(getContext(), retVal, string, "status"); + + return retVal; + } + + +} diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/JpaSystemProviderDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/JpaSystemProviderDstu2.java index 9b06c270cd8..748999c21bc 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/JpaSystemProviderDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/JpaSystemProviderDstu2.java @@ -50,7 +50,7 @@ import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; -public class JpaSystemProviderDstu2 extends BaseJpaSystemProvider { +public class JpaSystemProviderDstu2 extends BaseJpaSystemProviderDstu2Plus { @Autowired() @Qualifier("mySystemDaoDstu2") @@ -169,18 +169,6 @@ public class JpaSystemProviderDstu2 extends BaseJpaSystemProvider { +public class JpaSystemProviderDstu3 extends BaseJpaSystemProviderDstu2Plus { @Autowired() @Qualifier("mySystemDaoDstu3") @@ -170,19 +170,6 @@ public class JpaSystemProviderDstu3 extends BaseJpaSystemProvider return retVal; } - //@formatter:off - @Operation(name="$mark-all-resources-for-reindexing", idempotent=true, returnParameters= { - @OperationParam(name="count", type=IntegerType.class) - }) - //@formatter:on - public Parameters markAllResourcesForReindexing() { - int count = mySystemDao.markAllResourcesForReindexing(); - - Parameters retVal = new Parameters(); - retVal.addParameter().setName("count").setValue(new IntegerType(count)); - return retVal; - } - //@formatter:off @Operation(name="$meta", idempotent=true, returnParameters= { @OperationParam(name="return", type=Meta.class) diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/TerminologyUploaderProviderDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/TerminologyUploaderProviderDstu3.java index 06162186e2d..62d20c9420d 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/TerminologyUploaderProviderDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/dstu3/TerminologyUploaderProviderDstu3.java @@ -48,13 +48,15 @@ import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; public class TerminologyUploaderProviderDstu3 extends BaseJpaProvider { + public static final String UPLOAD_EXTERNAL_CODE_SYSTEM = "$upload-external-code-system"; + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(TerminologyUploaderProviderDstu3.class); @Autowired private IHapiTerminologyLoaderSvc myTerminologyLoaderSvc; //@formatter:off - @Operation(name = "$upload-external-code-system", idempotent = false, returnParameters= { + @Operation(name = UPLOAD_EXTERNAL_CODE_SYSTEM, idempotent = false, returnParameters= { @OperationParam(name="conceptCount", type=IntegerType.class, min=1) }) public Parameters uploadExternalCodeSystem( diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu2.java index adadb621aa2..5acbf713d8d 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu2.java @@ -146,7 +146,7 @@ public class SubscriptionWebsocketHandlerDstu2 extends TextWebSocketHandler impl public void closing() { ourLog.info("Deleting subscription {}", mySubscriptionId); try { - mySubscriptionDao.delete(mySubscriptionId, new ServletRequestDetails()); + mySubscriptionDao.delete(mySubscriptionId, null); } catch (Exception e) { handleFailure(e); } @@ -233,7 +233,7 @@ public class SubscriptionWebsocketHandlerDstu2 extends TextWebSocketHandler impl } try { - Subscription subscription = mySubscriptionDao.read(id, new ServletRequestDetails()); + Subscription subscription = mySubscriptionDao.read(id, null); mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id); mySubscriptionId = subscription.getIdElement(); myState = new BoundStaticSubscipriptionState(theSession); @@ -270,7 +270,7 @@ public class SubscriptionWebsocketHandlerDstu2 extends TextWebSocketHandler impl } } - IIdType id = mySubscriptionDao.create(subscription, new ServletRequestDetails()).getId(); + IIdType id = mySubscriptionDao.create(subscription, null).getId(); mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id); mySubscriptionId = subscription.getIdElement(); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu3.java index d5c8c54bb71..459a1736f0a 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionWebsocketHandlerDstu3.java @@ -146,7 +146,7 @@ public class SubscriptionWebsocketHandlerDstu3 extends TextWebSocketHandler impl public void closing() { ourLog.info("Deleting subscription {}", mySubscriptionId); try { - mySubscriptionDao.delete(mySubscriptionId, new ServletRequestDetails()); + mySubscriptionDao.delete(mySubscriptionId, null); } catch (Exception e) { handleFailure(e); } @@ -233,7 +233,7 @@ public class SubscriptionWebsocketHandlerDstu3 extends TextWebSocketHandler impl } try { - Subscription subscription = mySubscriptionDao.read(id, new ServletRequestDetails()); + Subscription subscription = mySubscriptionDao.read(id, null); mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id); mySubscriptionId = subscription.getIdElement(); myState = new BoundStaticSubscipriptionState(theSession); @@ -270,7 +270,7 @@ public class SubscriptionWebsocketHandlerDstu3 extends TextWebSocketHandler impl } } - IIdType id = mySubscriptionDao.create(subscription, new ServletRequestDetails()).getId(); + IIdType id = mySubscriptionDao.create(subscription, null).getId(); mySubscriptionPid = mySubscriptionDao.getSubscriptionTablePidForSubscriptionResource(id); mySubscriptionId = subscription.getIdElement(); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/SubscriptionsRequireManualActivationInterceptorDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/SubscriptionsRequireManualActivationInterceptorDstu2.java index a1e4ef0d4d1..178060961dd 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/SubscriptionsRequireManualActivationInterceptorDstu2.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/SubscriptionsRequireManualActivationInterceptorDstu2.java @@ -101,7 +101,7 @@ public class SubscriptionsRequireManualActivationInterceptorDstu2 extends Interc if (requestId != null && requestId.hasIdPart()) { Subscription existing; try { - existing = myDao.read(requestId, new ServletRequestDetails()); + existing = myDao.read(requestId, null); SubscriptionStatusEnum existingStatus = existing.getStatusElement().getValueAsEnum(); if (existingStatus != newStatus) { verifyActiveStatus(subscription, newStatus, existingStatus); diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/SubscriptionsRequireManualActivationInterceptorDstu3.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/SubscriptionsRequireManualActivationInterceptorDstu3.java index f485f2af619..ccf80bc9fb1 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/SubscriptionsRequireManualActivationInterceptorDstu3.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/SubscriptionsRequireManualActivationInterceptorDstu3.java @@ -38,7 +38,6 @@ import ca.uhn.fhir.rest.api.RestOperationTypeEnum; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.interceptor.InterceptorAdapter; -import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.util.CoverageIgnore; /** @@ -102,7 +101,7 @@ public class SubscriptionsRequireManualActivationInterceptorDstu3 extends Interc if (requestId != null && requestId.hasIdPart()) { Subscription existing; try { - existing = myDao.read(requestId, new ServletRequestDetails()); + existing = myDao.read(requestId, null); SubscriptionStatus existingStatus = existing.getStatusElement().getValue(); if (existingStatus != newStatus) { verifyActiveStatus(subscription, newStatus, existingStatus); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SubscriptionTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SubscriptionTest.java index c1a9ca5128c..3ed297540d3 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SubscriptionTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SubscriptionTest.java @@ -39,7 +39,6 @@ import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum; import ca.uhn.fhir.rest.server.IBundleProvider; import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; -import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.util.TestUtil; public class FhirResourceDaoDstu2SubscriptionTest extends BaseJpaDstu2Test { @@ -390,7 +389,7 @@ public class FhirResourceDaoDstu2SubscriptionTest extends BaseJpaDstu2Test { */ mySystemDao.markAllResourcesForReindexing(); - mySystemDao.performReindexingPass(100, mySrd); + mySystemDao.performReindexingPass(100); assertEquals(0, mySubscriptionDao.pollForNewUndeliveredResources()); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirSystemDaoDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirSystemDaoDstu2Test.java index c0952b4aa4e..ec59edb957e 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirSystemDaoDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirSystemDaoDstu2Test.java @@ -101,7 +101,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest { }); assertEquals(null, entity.getIndexStatus()); - mySystemDao.performReindexingPass(null, mySrd); + mySystemDao.performReindexingPass(null); entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback() { @Override @@ -112,7 +112,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest { assertEquals(Long.valueOf(1), entity.getIndexStatus()); // Just make sure this doesn't cause a choke - mySystemDao.performReindexingPass(100000, mySrd); + mySystemDao.performReindexingPass(100000); // Try making the resource unparseable @@ -134,7 +134,7 @@ public class FhirSystemDaoDstu2Test extends BaseJpaDstu2SystemTest { } }); - mySystemDao.performReindexingPass(null, mySrd); + mySystemDao.performReindexingPass(null); entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback() { @Override diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchFtTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchFtTest.java index 3da1eaefb26..84751e66e63 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchFtTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchFtTest.java @@ -81,7 +81,7 @@ public class FhirResourceDaoDstu3SearchFtTest extends BaseJpaDstu3Test { } private ServletRequestDetails mockSrd() { - return new ServletRequestDetails(); + return mySrd; } @Test diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SubscriptionTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SubscriptionTest.java index 820a0b52d1e..2174d3d2581 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SubscriptionTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SubscriptionTest.java @@ -390,7 +390,7 @@ public class FhirResourceDaoDstu3SubscriptionTest extends BaseJpaDstu3Test { */ mySystemDao.markAllResourcesForReindexing(); - mySystemDao.performReindexingPass(100, mySrd); + mySystemDao.performReindexingPass(100); assertEquals(0, mySubscriptionDao.pollForNewUndeliveredResources()); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java index 509b270e921..559a38f4a42 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3TerminologyTest.java @@ -68,7 +68,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { .addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code AB")); //@formatter:on - IIdType id = myCodeSystemDao.create(codeSystem, new ServletRequestDetails()).getId().toUnqualified(); + IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); Set codes = myTermSvc.findCodesBelow(id.getIdPartAsLong(), id.getVersionIdPartAsLong(), "A"); assertThat(toCodes(codes), containsInAnyOrder("A", "AA", "AB")); @@ -177,7 +177,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { CodeSystem codeSystem = new CodeSystem(); codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); - IIdType id = myCodeSystemDao.create(codeSystem, new ServletRequestDetails()).getId().toUnqualified(); + IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong()); @@ -571,7 +571,7 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { .addConcept(new ConceptDefinitionComponent().setCode("BA").setDisplay("Code BA")) .addConcept(new ConceptDefinitionComponent().setCode("BB").setDisplay("Code BB")); //@formatter:on - myCodeSystemDao.create(codeSystem, new ServletRequestDetails()); + myCodeSystemDao.create(codeSystem, mySrd); createLocalVs(codeSystem); } @@ -590,13 +590,13 @@ public class FhirResourceDaoDstu3TerminologyTest extends BaseJpaDstu3Test { CodeSystem codeSystem = new CodeSystem(); codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setContent(CodeSystemContentMode.COMPLETE); - IIdType id = myCodeSystemDao.create(codeSystem, new ServletRequestDetails()).getId().toUnqualified(); + IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); codeSystem = new CodeSystem(); codeSystem.setUrl(URL_MY_CODE_SYSTEM); codeSystem.setContent(CodeSystemContentMode.COMPLETE); try { - myCodeSystemDao.create(codeSystem, new ServletRequestDetails()); + myCodeSystemDao.create(codeSystem, mySrd); fail(); } catch (UnprocessableEntityException e) { assertEquals("Can not create multiple code systems with URI \"http://example.com/my_code_system\", already have one with resource ID: CodeSystem/" + id.getIdPart(), e.getMessage()); diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirSystemDaoDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirSystemDaoDstu3Test.java index 6e2a2243d85..94796de42eb 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirSystemDaoDstu3Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirSystemDaoDstu3Test.java @@ -191,7 +191,7 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest { }); assertEquals(null, entity.getIndexStatus()); - mySystemDao.performReindexingPass(null, mySrd); + mySystemDao.performReindexingPass(null); entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback() { @Override @@ -202,7 +202,7 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest { assertEquals(Long.valueOf(1), entity.getIndexStatus()); // Just make sure this doesn't cause a choke - mySystemDao.performReindexingPass(100000, mySrd); + mySystemDao.performReindexingPass(100000); // Try making the resource unparseable @@ -224,7 +224,7 @@ public class FhirSystemDaoDstu3Test extends BaseJpaDstu3SystemTest { } }); - mySystemDao.performReindexingPass(null, mySrd); + mySystemDao.performReindexingPass(null); entity = new TransactionTemplate(myTxManager).execute(new TransactionCallback() { @Override diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/SubscriptionsDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/SubscriptionsDstu2Test.java index 8581ae9f1c0..d5e6d8dff6c 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/SubscriptionsDstu2Test.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/SubscriptionsDstu2Test.java @@ -32,7 +32,6 @@ import ca.uhn.fhir.model.dstu2.valueset.SubscriptionStatusEnum; import ca.uhn.fhir.model.primitive.IdDt; import ca.uhn.fhir.rest.server.EncodingEnum; import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; -import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails; import ca.uhn.fhir.util.TestUtil; public class SubscriptionsDstu2Test extends BaseResourceProviderDstu2Test { diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplTest.java index 26a905b98c4..6a00ef14a64 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplTest.java @@ -42,7 +42,7 @@ public class TerminologySvcImplTest extends BaseJpaDstu3Test { CodeSystem codeSystem = new CodeSystem(); codeSystem.setUrl(CS_URL); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); - IIdType id = myCodeSystemDao.create(codeSystem, new ServletRequestDetails()).getId().toUnqualified(); + IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong()); @@ -109,14 +109,14 @@ public class TerminologySvcImplTest extends BaseJpaDstu3Test { assertThat(mySystemDao.markAllResourcesForReindexing(), greaterThan(0)); - assertThat(mySystemDao.performReindexingPass(100, mySrd), greaterThan(0)); + assertThat(mySystemDao.performReindexingPass(100), greaterThan(0)); } private IIdType createCodeSystem() { CodeSystem codeSystem = new CodeSystem(); codeSystem.setUrl(CS_URL); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); - IIdType id = myCodeSystemDao.create(codeSystem, new ServletRequestDetails()).getId().toUnqualified(); + IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong()); @@ -173,7 +173,7 @@ public class TerminologySvcImplTest extends BaseJpaDstu3Test { CodeSystem codeSystem = new CodeSystem(); codeSystem.setUrl(CS_URL); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); - IIdType id = myCodeSystemDao.create(codeSystem, new ServletRequestDetails()).getId().toUnqualified(); + IIdType id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); ResourceTable table = myResourceTableDao.findOne(id.getIdPartAsLong()); @@ -187,7 +187,7 @@ public class TerminologySvcImplTest extends BaseJpaDstu3Test { cs = new TermCodeSystemVersion(); TermConcept parentA = new TermConcept(cs, "ParentA"); cs.getConcepts().add(parentA); - id = myCodeSystemDao.update(codeSystem, new ServletRequestDetails()).getId().toUnqualified(); + id = myCodeSystemDao.update(codeSystem, mySrd).getId().toUnqualified(); table = myResourceTableDao.findOne(id.getIdPartAsLong()); cs.setResource(table); cs.setResourceVersionId(table.getVersion()); @@ -197,7 +197,7 @@ public class TerminologySvcImplTest extends BaseJpaDstu3Test { codeSystem = new CodeSystem(); codeSystem.setUrl(CS_URL); codeSystem.setContent(CodeSystemContentMode.NOTPRESENT); - id = myCodeSystemDao.create(codeSystem, new ServletRequestDetails()).getId().toUnqualified(); + id = myCodeSystemDao.create(codeSystem, mySrd).getId().toUnqualified(); table = myResourceTableDao.findOne(id.getIdPartAsLong()); cs.setResource(table); cs.setResourceVersionId(table.getVersion()); diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu1Config.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu1Config.java index 8b8896627c2..019ef853c72 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu1Config.java +++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu1Config.java @@ -10,7 +10,6 @@ import org.hibernate.jpa.HibernatePersistenceProvider; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.Import; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.orm.jpa.JpaTransactionManager; @@ -19,6 +18,8 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu1; import ca.uhn.fhir.jpa.dao.DaoConfig; +import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; +import ca.uhn.fhirtest.interceptor.PublicSecurityInterceptor; @Configuration @Import(CommonConfig.class) @@ -38,6 +39,11 @@ public class TestDstu1Config extends BaseJavaConfigDstu1 { return new PropertySourcesPlaceholderConfigurer(); } + @Bean + public IServerInterceptor securityInterceptor() { + return new PublicSecurityInterceptor(); + } + @Bean() public DaoConfig daoConfig() { DaoConfig retVal = new DaoConfig(); diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu2Config.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu2Config.java index 69380db0ce5..7ab13bed574 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu2Config.java +++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu2Config.java @@ -23,6 +23,7 @@ import ca.uhn.fhir.jpa.config.BaseJavaConfigDstu2; import ca.uhn.fhir.jpa.dao.DaoConfig; import ca.uhn.fhir.jpa.util.SubscriptionsRequireManualActivationInterceptorDstu2; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; +import ca.uhn.fhirtest.interceptor.PublicSecurityInterceptor; @Configuration @Import(CommonConfig.class) @@ -46,6 +47,11 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 { return new PropertySourcesPlaceholderConfigurer(); } + @Bean + public IServerInterceptor securityInterceptor() { + return new PublicSecurityInterceptor(); + } + @Bean() public DaoConfig daoConfig() { DaoConfig retVal = new DaoConfig(); diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu3Config.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu3Config.java index c41e4c64935..a7499b3f3bd 100644 --- a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu3Config.java +++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/config/TestDstu3Config.java @@ -28,6 +28,7 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor; import ca.uhn.fhir.rest.server.interceptor.ResponseValidatingInterceptor; import ca.uhn.fhir.validation.ResultSeverityEnum; +import ca.uhn.fhirtest.interceptor.PublicSecurityInterceptor; @Configuration @Import(CommonConfig.class) @@ -57,6 +58,11 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 { return retVal; } + @Bean + public IServerInterceptor securityInterceptor() { + return new PublicSecurityInterceptor(); + } + @Bean(name = "myPersistenceDataSourceDstu3", destroyMethod = "close") @DependsOn("dbServer") public DataSource dataSource() { diff --git a/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/interceptor/PublicSecurityInterceptor.java b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/interceptor/PublicSecurityInterceptor.java new file mode 100644 index 00000000000..a4ba1392df6 --- /dev/null +++ b/hapi-fhir-jpaserver-uhnfhirtest/src/main/java/ca/uhn/fhirtest/interceptor/PublicSecurityInterceptor.java @@ -0,0 +1,61 @@ +package ca.uhn.fhirtest.interceptor; + +import static org.apache.commons.lang3.StringUtils.isBlank; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +import ca.uhn.fhir.jpa.provider.BaseJpaSystemProvider; +import ca.uhn.fhir.jpa.provider.dstu3.TerminologyUploaderProviderDstu3; +import ca.uhn.fhir.rest.method.RequestDetails; +import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException; +import ca.uhn.fhir.rest.server.interceptor.auth.AuthorizationInterceptor; +import ca.uhn.fhir.rest.server.interceptor.auth.IAuthRule; +import ca.uhn.fhir.rest.server.interceptor.auth.RuleBuilder; + +public class PublicSecurityInterceptor extends AuthorizationInterceptor { + + private HashSet myTokens; + private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(PublicSecurityInterceptor.class); + + public PublicSecurityInterceptor() { + String passwordsString = System.getProperty("fhir.tdlpass"); + String[] passwords = passwordsString.split(","); + myTokens = new HashSet(Arrays.asList(passwords)); + + ourLog.info("We have {} valid security tokens", myTokens.size()); + } + + @Override + public List buildRuleList(RequestDetails theRequestDetails) { + String authHeader = theRequestDetails.getHeader("Authorization"); + + //@formatter:off + if (isBlank(authHeader)) { + return new RuleBuilder() + .deny().operation().named(BaseJpaSystemProvider.MARK_ALL_RESOURCES_FOR_REINDEXING).onServer().andThen() + .deny().operation().named(TerminologyUploaderProviderDstu3.UPLOAD_EXTERNAL_CODE_SYSTEM).onServer().andThen() + .allowAll() + .build(); + } + //@formatter:off + + if (!authHeader.startsWith("Bearer ")) { + throw new ForbiddenOperationException("Invalid bearer token, must be in the form \"Authorization: Bearer [token]\""); + } + + String token = authHeader.substring("Bearer ".length()).trim(); + if (!myTokens.contains(token)) { + ourLog.error("Invalid token '{}' - Valid are: {}", token, myTokens); + throw new ForbiddenOperationException("Unknown/expired bearer token"); + } + + ourLog.info("User logged in with bearer token: " + token.substring(0, 4) + "..."); + + return new RuleBuilder() + .allowAll() + .build(); + } + +} diff --git a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorDstu2Test.java b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorDstu2Test.java index 307e3da1217..643b8ec11cb 100644 --- a/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorDstu2Test.java +++ b/hapi-fhir-structures-dstu2/src/test/java/ca/uhn/fhir/rest/server/interceptor/auth/AuthorizationInterceptorDstu2Test.java @@ -1,5 +1,6 @@ package ca.uhn.fhir.rest.server.interceptor.auth; +import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -32,7 +33,6 @@ import org.hl7.fhir.instance.model.api.IBaseResource; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import ca.uhn.fhir.context.FhirContext; @@ -40,11 +40,13 @@ import ca.uhn.fhir.model.api.IResource; import ca.uhn.fhir.model.dstu2.composite.ResourceReferenceDt; import ca.uhn.fhir.model.dstu2.resource.Bundle; import ca.uhn.fhir.model.dstu2.resource.Observation; +import ca.uhn.fhir.model.dstu2.resource.OperationOutcome; import ca.uhn.fhir.model.dstu2.resource.Parameters; import ca.uhn.fhir.model.dstu2.resource.Patient; import ca.uhn.fhir.model.dstu2.valueset.BundleTypeEnum; import ca.uhn.fhir.model.dstu2.valueset.HTTPVerbEnum; import ca.uhn.fhir.model.primitive.IdDt; +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; @@ -55,14 +57,18 @@ import ca.uhn.fhir.rest.annotation.Search; import ca.uhn.fhir.rest.annotation.Transaction; import ca.uhn.fhir.rest.annotation.TransactionParam; import ca.uhn.fhir.rest.annotation.Update; +import ca.uhn.fhir.rest.annotation.Validate; import ca.uhn.fhir.rest.api.MethodOutcome; +import ca.uhn.fhir.rest.api.ValidationModeEnum; import ca.uhn.fhir.rest.method.IRequestOperationCallback; import ca.uhn.fhir.rest.method.RequestDetails; import ca.uhn.fhir.rest.server.AddProfileTagEnum; import ca.uhn.fhir.rest.server.Constants; +import ca.uhn.fhir.rest.server.EncodingEnum; import ca.uhn.fhir.rest.server.IResourceProvider; import ca.uhn.fhir.rest.server.RestfulServer; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor; +import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails; import ca.uhn.fhir.util.PortUtil; import ca.uhn.fhir.util.TestUtil; @@ -158,6 +164,14 @@ public class AuthorizationInterceptorDstu2Test { assertThat(response, containsString("Access denied by rule: Rule 1")); assertEquals(403, status.getStatusLine().getStatusCode()); assertTrue(ourHitMethod); + + ourHitMethod = false; + httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$validate"); + status = ourClient.execute(httpGet); + extractResponseAndClose(status); + assertEquals(200, status.getStatusLine().getStatusCode()); + assertTrue(ourHitMethod); + } @Test @@ -404,6 +418,15 @@ public class AuthorizationInterceptorDstu2Test { assertThat(response, containsString("Access denied by rule: Default Rule")); assertEquals(403, status.getStatusLine().getStatusCode()); assertTrue(ourHitMethod); + + ourHitMethod = false; + httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1/$validate"); + status = ourClient.execute(httpGet); + response = extractResponseAndClose(status); + ourLog.info(response); + assertThat(response, containsString("Access denied by rule: Default Rule")); + assertEquals(403, status.getStatusLine().getStatusCode()); + assertFalse(ourHitMethod); } @Test @@ -990,7 +1013,13 @@ public class AuthorizationInterceptorDstu2Test { public static class DummyPatientResourceProvider implements IResourceProvider { @Create() - public MethodOutcome create(@ResourceParam Patient theResource) { + public MethodOutcome create(@ResourceParam Patient theResource, @ConditionalUrlParam String theConditionalUrl, RequestDetails theRequestDetails) { + + if (isNotBlank(theConditionalUrl)) { + ActionRequestDetails subRequest = new ActionRequestDetails(theRequestDetails); + + } + ourHitMethod = true; theResource.setId("Patient/1/_history/1"); MethodOutcome retVal = new MethodOutcome(); @@ -999,6 +1028,7 @@ public class AuthorizationInterceptorDstu2Test { return retVal; } + @Delete() public MethodOutcome delete(IRequestOperationCallback theRequestOperationCallback, @IdParam IdDt theId) { ourHitMethod = true; @@ -1009,6 +1039,24 @@ public class AuthorizationInterceptorDstu2Test { return retVal; } + @Validate + public MethodOutcome validate(@ResourceParam Patient theResource, @ResourceParam String theRawResource, @ResourceParam EncodingEnum theEncoding, @Validate.Mode ValidationModeEnum theMode, + @Validate.Profile String theProfile, RequestDetails theRequestDetails) { + ourHitMethod = true; + OperationOutcome oo = new OperationOutcome(); + oo.addIssue().setDiagnostics("OK"); + return new MethodOutcome(oo); + } + + @Validate + public MethodOutcome validate(@ResourceParam Patient theResource, @IdParam IdDt theId, @ResourceParam String theRawResource, @ResourceParam EncodingEnum theEncoding, @Validate.Mode ValidationModeEnum theMode, + @Validate.Profile String theProfile, RequestDetails theRequestDetails) { + ourHitMethod = true; + OperationOutcome oo = new OperationOutcome(); + oo.addIssue().setDiagnostics("OK"); + return new MethodOutcome(oo); + } + @Override public Class getResourceType() { return Patient.class; diff --git a/src/site/resources/images/hapi_authorizationinterceptor_read_normal.svg b/src/site/resources/images/hapi_authorizationinterceptor_read_normal.svg new file mode 100644 index 00000000000..5a4bac103c1 --- /dev/null +++ b/src/site/resources/images/hapi_authorizationinterceptor_read_normal.svg @@ -0,0 +1,2 @@ + +
RestfulServer
RestfulServer
Authorization
Interceptor
[Not supported by viewer]
ResourceProvider
(user code)
ResourceProvider<div>(user code)</div>
read/search/etc
read/search/etc
authorize?
authorize?
invoke
invoke
return
return
200 OK
200 OK
authorize?
authorize?
invoke
invoke
return
return
Successful
Read
[Not supported by viewer]
Denied
Read
[Not supported by viewer]
Return value isĀ 
checked before
actually returning
[Not supported by viewer]
Client
Client
read/search/etc
read/search/etc
403 FORBIDDEN
403 FORBIDDEN
\ No newline at end of file diff --git a/src/site/resources/images/hapi_authorizationinterceptor_write_normal.svg b/src/site/resources/images/hapi_authorizationinterceptor_write_normal.svg new file mode 100644 index 00000000000..cb9aee69a3d --- /dev/null +++ b/src/site/resources/images/hapi_authorizationinterceptor_write_normal.svg @@ -0,0 +1,2 @@ + +
RestfulServer
RestfulServer
Client
Client
write
write
Authorization
Interceptor
[Not supported by viewer]
authorize?
authorize?
ResourceProvider
(user code)
ResourceProvider<div>(user code)</div>
return
return
authorize?
authorize?
invoke
invoke
return
return
200 OK
200 OK
write
write
403 FORBIDDEN
403 FORBIDDEN
Successful
Write
[Not supported by viewer]
Denied
Write
[Not supported by viewer]
Operation is checked
before passing
to ResourceProvider
[Not supported by viewer]
\ No newline at end of file diff --git a/src/site/site.xml b/src/site/site.xml index d008088cdac..c66a8366a76 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -3,7 +3,7 @@ xmlns="http://maven.apache.org/DECORATION/1.3.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/DECORATION/1.3.0 http://maven.apache.org/xsd/decoration-1.3.0.xsd" - name="HAPI"> + name="HAPI FHIR"> - + @@ -218,7 +218,7 @@ HAPI FHIR ]]> - http://jamesagnew.github.io/hapi-fhir/ + http://hapifhir.io/ %2$s - HAPI FHIR diff --git a/src/site/xdoc/doc_rest_server_security.xml b/src/site/xdoc/doc_rest_server_security.xml index e201e5d4cbc..a39aae6fbde 100644 --- a/src/site/xdoc/doc_rest_server_security.xml +++ b/src/site/xdoc/doc_rest_server_security.xml @@ -118,23 +118,54 @@ the response from the server in order to determine whether "read" operations are legal.

+ + + + +

- This approach has limitations however: If a request has a conditional operation, - such as a delete operation which uses a search URL, or a create operation which - uses an If-None-Exist header, the interceptor will not know the - actual target until the server actually processes the request. + When authorizing a read operation, the AuthorizationInterceptor + always allows client code to execute and generate a response. + It then examines the response that would be returned before + actually returning it to the client, and if rules do not permit + that data to be shown to the client the interceptor aborts the + request.

+

- For better security, individual resource providers should notify interceptors - about their actual targets in the event of any "write" operations (create, - operations embedded in transactions, etc.) + Note that there are performance implications to this mechanism, + since an unauthorized user can still cause the server to fetch data + even if they won't get to see it. This mechanism should be comprehensive + however, since it will prevent clients from using various features + in FHIR (e.g. _include or _revinclude) to + "trick" the server into showing them date they shouldn't be allowed to + see.

+

- The mechanism for doing this isn't yet fully documented, this will be improved - over the next release cycle (post 1.5). Please get in touch on our google group - if you want to help! + See the following diagram for an example of how this works.

+ Write Authorization + +
+ + + +

+ Write operations (create, update, etc.) are typically authorized + by the interceptor by examining the parsed URL and making a decision + about whether to authorize the operation before allowing Resource Provider + code to proceed. This means that client code will not have a chance to execute + and create resources that the client does not have permissions to create. +

+ +

+ See the following diagram for an example of how this works. +

+ + Write Authorization +