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}