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