001package ca.uhn.fhir.rest.server.interceptor.consent;
002
003/*-
004 * #%L
005 * HAPI FHIR - Server Framework
006 * %%
007 * Copyright (C) 2014 - 2022 Smile CDR, Inc.
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import ca.uhn.fhir.rest.api.server.RequestDetails;
024import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException;
025import org.hl7.fhir.instance.model.api.IBaseResource;
026
027/**
028 * This interface is intended to be implemented as the user-defined contract for
029 * the {@link ConsentInterceptor}.
030 * <p>
031 * Note: Since HAPI FHIR 5.1.0, methods in this interface have default methods that return {@link ConsentOutcome#PROCEED}
032 * </p>
033 * <p>
034 * See <a href="https://hapifhir.io/hapi-fhir/docs/security/consent_interceptor.html">Consent Interceptor</a> for
035 * more information on this interceptor.
036 * </p>
037 */
038public interface IConsentService {
039
040        /**
041         * This method is called when an operation is initially beginning, before any
042         * significant processing occurs. The service may use this method to decide
043         * whether the request needs to be reviewed further or not.
044         *
045         * @param theRequestDetails  Contains details about the operation that is
046         *                           beginning, including details about the request type,
047         *                           URL, etc. Note that the RequestDetails has a generic
048         *                           Map (see {@link RequestDetails#getUserData()}) that
049         *                           can be used to store information and state to be
050         *                           passed between methods in the consent service.
051         * @param theContextServices An object passed in by the consent framework that
052         *                           provides utility functions relevant to acting on
053         *                           consent directives.
054         * @return An outcome object. See {@link ConsentOutcome}
055         */
056        default ConsentOutcome startOperation(RequestDetails theRequestDetails, IConsentContextServices theContextServices) {
057                return ConsentOutcome.PROCEED;
058        }
059
060        /**
061         * This method will be invoked once prior to invoking {@link #canSeeResource(RequestDetails, IBaseResource, IConsentContextServices)}
062         * and can be used to skip that phase.
063         * <p>
064         * If this method returns {@literal false} (default is {@literal true}) {@link #willSeeResource(RequestDetails, IBaseResource, IConsentContextServices)}
065         * will be invoked for this request, but {@link #canSeeResource(RequestDetails, IBaseResource, IConsentContextServices)} will not.
066         * </p>
067         *
068         * @param theRequestDetails  Contains details about the operation that is
069         *                           beginning, including details about the request type,
070         *                           URL, etc. Note that the RequestDetails has a generic
071         *                           Map (see {@link RequestDetails#getUserData()}) that
072         *                           can be used to store information and state to be
073         *                           passed between methods in the consent service.
074         * @param theContextServices An object passed in by the consent framework that
075         *                           provides utility functions relevant to acting on
076         *                           consent directives.
077         * @return Returns {@literal false} to avoid calling {@link #canSeeResource(RequestDetails, IBaseResource, IConsentContextServices)}
078         * @since 6.0.0
079         */
080        default boolean shouldProcessCanSeeResource(RequestDetails theRequestDetails, IConsentContextServices theContextServices) {
081                return true;
082        }
083
084        /**
085         * This method is called if a user may potentially see a resource via READ
086         * operations, SEARCH operations, etc. This method may make decisions about
087         * whether or not the user should be permitted to see the resource.
088         * <p>
089         * Implementations should make no attempt to modify the returned result within
090         * this method. For modification use cases (e.g. masking for consent rules) the
091         * user should use the {@link #willSeeResource(RequestDetails, IBaseResource, IConsentContextServices)}
092         * method to actually make changes. This method is intended to only
093         * to make decisions.
094         * </p>
095         * <p>
096         * In addition, the {@link ConsentOutcome} must return one of the following
097         * statuses:
098         * </p>
099         * <ul>
100         * <li>{@link ConsentOperationStatusEnum#AUTHORIZED}: The resource will be returned to the client. If multiple consent service implementation are present, no further implementations will be invoked for this resource. {@link #willSeeResource(RequestDetails, IBaseResource, IConsentContextServices)} will not be invoked for this resource.</li>
101         * <li>{@link ConsentOperationStatusEnum#PROCEED}: The resource will be returned to the client.</li>
102         * <li>{@link ConsentOperationStatusEnum#REJECT}: The resource will be stripped from the response. If multiple consent service implementation are present, no further implementations will be invoked for this resource. {@link #willSeeResource(RequestDetails, IBaseResource, IConsentContextServices)} will not be invoked for this resource.</li>
103         * </ul>
104         * </p>
105         * <p>
106         *    There are two methods the consent service may use to suppress or modify response resources:
107         * </p>
108         * <ul>
109         *    <li>{@link #canSeeResource(RequestDetails, IBaseResource, IConsentContextServices)} should be used to remove resources from results in scenarios where it is important to not reveal existence of those resources. It is called prior to any paging logic, so result pages will still be normal sized even if results are filtered.</li>
110         *    <li>{@link #willSeeResource(RequestDetails, IBaseResource, IConsentContextServices)} should be used to filter individual elements from resources, or to remove entire resources in cases where it is not important to conceal their existence. It is called after paging logic, so any resources removed by this method may result in abnormally sized result pages. However, removing resourced using this method may also perform better so it is preferable for use in cases where revealing resource existence is not a concern.</li>
111         * </ul>
112         * <p>
113         * <b>Performance note:</b> Note that this method should be efficient, since it will be called once
114         * for every resource potentially returned (e.g. by searches). If this method
115         * takes a significant amount of time to execute, performance on the server
116         * will suffer.
117         * </p>
118         *
119         *
120         * @param theRequestDetails  Contains details about the operation that is
121         *                           beginning, including details about the request type,
122         *                           URL, etc. Note that the RequestDetails has a generic
123         *                           Map (see {@link RequestDetails#getUserData()}) that
124         *                           can be used to store information and state to be
125         *                           passed between methods in the consent service.
126         * @param theResource        The resource that will be exposed
127         * @param theContextServices An object passed in by the consent framework that
128         *                           provides utility functions relevant to acting on
129         *                           consent directives.
130         * @return An outcome object. See {@link ConsentOutcome}. Note that this method is not allowed
131         * to modify the response object, so an error will be thrown if {@link ConsentOutcome#getResource()}
132         * returns a non-null response.
133         */
134        default ConsentOutcome canSeeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
135                return ConsentOutcome.PROCEED;
136        }
137
138        /**
139         * This method is called if a user is about to see a resource, either completely
140         * or partially. In other words, if the user is going to see any part of this resource
141         * via READ operations, SEARCH operations, etc., this method is
142         * called. This method may modify the resource in order to filter/mask aspects of
143         * the contents, or even to enrich it.
144         * <p>
145         * The returning {@link ConsentOutcome} may optionally replace the resource
146         * with a different resource (including an OperationOutcome) by calling the
147         * resource property on the {@link ConsentOutcome}.
148         * </p>
149         * <p>
150         * In addition, the {@link ConsentOutcome} must return one of the following
151         * statuses:
152         * </p>
153         * <ul>
154         * <li>{@link ConsentOperationStatusEnum#AUTHORIZED}: The resource will be returned to the client. If multiple consent service implementation are present, no further implementations will be invoked for this resource.</li>
155         * <li>{@link ConsentOperationStatusEnum#PROCEED}: The resource will be returned to the client.</li>
156         * <li>{@link ConsentOperationStatusEnum#REJECT}: The resource will not be returned to the client. If multiple consent service implementation are present, no further implementations will be invoked for this resource.</li>
157         * </ul>
158         *
159         * @param theRequestDetails  Contains details about the operation that is
160         *                           beginning, including details about the request type,
161         *                           URL, etc. Note that the RequestDetails has a generic
162         *                           Map (see {@link RequestDetails#getUserData()}) that
163         *                           can be used to store information and state to be
164         *                           passed between methods in the consent service.
165         * @param theResource        The resource that will be exposed
166         * @param theContextServices An object passed in by the consent framework that
167         *                           provides utility functions relevant to acting on
168         *                           consent directives.
169         * @return An outcome object. See method documentation for a description.
170         * @see #canSeeResource(RequestDetails, IBaseResource, IConsentContextServices) for a description of the difference between these two methods.
171         */
172        default ConsentOutcome willSeeResource(RequestDetails theRequestDetails, IBaseResource theResource, IConsentContextServices theContextServices) {
173                return ConsentOutcome.PROCEED;
174        }
175
176        /**
177         * This method is called when an operation is complete. It can be used to perform
178         * any necessary cleanup, flush audit events, etc.
179         * <p>
180         * This method is not called if the request failed. {@link #completeOperationFailure(RequestDetails, BaseServerResponseException, IConsentContextServices)}
181         * will be called instead in that case.
182         * </p>
183         *
184         * @param theRequestDetails  Contains details about the operation that is
185         *                           beginning, including details about the request type,
186         *                           URL, etc. Note that the RequestDetails has a generic
187         *                           Map (see {@link RequestDetails#getUserData()}) that
188         *                           can be used to store information and state to be
189         *                           passed between methods in the consent service.
190         * @param theContextServices An object passed in by the consent framework that
191         *                           provides utility functions relevant to acting on
192         *                           consent directives.
193         * @see #completeOperationFailure(RequestDetails, BaseServerResponseException, IConsentContextServices)
194         */
195        default void completeOperationSuccess(RequestDetails theRequestDetails, IConsentContextServices theContextServices) {
196        }
197
198        /**
199         * This method is called when an operation is complete. It can be used to perform
200         * any necessary cleanup, flush audit events, etc.
201         * <p>
202         * This method will be called if the request did not complete successfully, instead of
203         * {@link #completeOperationSuccess(RequestDetails, IConsentContextServices)}. Typically this means that
204         * the operation failed and a failure is being returned to the client.
205         * </p>
206         *
207         * @param theRequestDetails  Contains details about the operation that is
208         *                           beginning, including details about the request type,
209         *                           URL, etc. Note that the RequestDetails has a generic
210         *                           Map (see {@link RequestDetails#getUserData()}) that
211         *                           can be used to store information and state to be
212         *                           passed between methods in the consent service.
213         * @param theContextServices An object passed in by the consent framework that
214         *                           provides utility functions relevant to acting on
215         *                           consent directives.
216         * @see #completeOperationSuccess(RequestDetails, IConsentContextServices)
217         */
218        default void completeOperationFailure(RequestDetails theRequestDetails, BaseServerResponseException theException, IConsentContextServices theContextServices) {
219        }
220}