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.auth; 021 022import ca.uhn.fhir.rest.api.RestOperationTypeEnum; 023import ca.uhn.fhir.rest.api.server.RequestDetails; 024import jakarta.annotation.Nonnull; 025import jakarta.annotation.Nullable; 026import org.apache.commons.lang3.Validate; 027import org.hl7.fhir.instance.model.api.IBaseResource; 028import org.hl7.fhir.instance.model.api.IIdType; 029 030/** 031 * Allows user-supplied logic for authorization rules. 032 * <p> 033 * THIS IS AN EXPERIMENTAL API! Feedback is welcome, and this API 034 * may change. 035 * 036 * @since 3.4.0 037 */ 038public interface IAuthRuleTester { 039 /** 040 * A request object to make this easier to extend. 041 */ 042 class RuleTestRequest { 043 // fake record pattern 044 /** the mode of the calling rule context */ 045 @Nonnull 046 public final PolicyEnum mode; 047 /** 048 * The FHIR operation being performed. 049 * Note that this is not necessarily the same as the value obtained from invoking 050 * {@link RequestDetails#getRestOperationType()} on {@literal requestDetails} 051 * because multiple operations can be nested within 052 * an HTTP request using FHIR transaction and batch operations 053 */ 054 @Nonnull 055 public final RestOperationTypeEnum operation; 056 057 @Nonnull 058 public final RequestDetails requestDetails; 059 060 @Nullable 061 public final IIdType resourceId; 062 063 @Nullable 064 public final IBaseResource resource; 065 /** supplier for support services */ 066 @Nonnull 067 public final IRuleApplier ruleApplier; 068 069 public RuleTestRequest( 070 PolicyEnum theMode, 071 @Nonnull RestOperationTypeEnum theOperation, 072 @Nonnull RequestDetails theRequestDetails, 073 @Nullable IIdType theResourceId, 074 @Nullable IBaseResource theResource, 075 @Nonnull IRuleApplier theRuleApplier) { 076 Validate.notNull(theMode); 077 Validate.notNull(theOperation); 078 Validate.notNull(theRequestDetails); 079 Validate.notNull(theRuleApplier); 080 mode = theMode; 081 operation = theOperation; 082 requestDetails = theRequestDetails; 083 resource = theResource; 084 if (theResourceId == null && resource != null) { 085 resourceId = resource.getIdElement(); 086 } else { 087 resourceId = theResourceId; 088 } 089 ruleApplier = theRuleApplier; 090 } 091 } 092 093 /** 094 * User supplied logic called just before the parent rule renders a verdict on the operation 095 * or input resource. 096 * 097 * Returning true will allow the verdict continue. 098 * Returning false will block the verdict and cause the rule to abstain (i.e. return null). 099 * 100 * <p> 101 * THIS IS AN EXPERIMENTAL API! Feedback is welcome, and this API 102 * may change. 103 * 104 * @param theRequest The details of the operation or an INPUT resource to evaluate 105 * @return true if the verdict should continue 106 * @since 6.1.0 107 */ 108 default boolean matches(RuleTestRequest theRequest) { 109 return this.matches( 110 theRequest.operation, theRequest.requestDetails, theRequest.resourceId, theRequest.resource); 111 } 112 113 /** 114 * DO NOT IMPLEMENT - Old api. {@link #matches(RuleTestRequest)} instead. 115 * @deprecated 116 */ 117 @Deprecated(since = "6.1.0") 118 default boolean matches( 119 RestOperationTypeEnum theOperation, 120 RequestDetails theRequestDetails, 121 IIdType theInputResourceId, 122 IBaseResource theInputResource) { 123 return true; 124 } 125 126 /** 127 * User supplied logic called just before the parent rule renders a verdict on an output resource. 128 * 129 * Returning true will allow the verdict continue. 130 * Returning false will block the verdict and cause the rule to abstain (i.e. return null). 131 * 132 * <p> 133 * THIS IS AN EXPERIMENTAL API! Feedback is welcome, and this API 134 * may change. 135 * 136 * @param theRequest The details of the operation or an INPUT resource to evaluate 137 * @return true if the verdict should continue 138 * @since 6.1.0 */ 139 default boolean matchesOutput(RuleTestRequest theRequest) { 140 return this.matchesOutput(theRequest.operation, theRequest.requestDetails, theRequest.resource); 141 } 142 143 /** 144 * DO NOT IMPLEMENT - Old api. {@link #matches(RuleTestRequest)} instead. 145 * @deprecated 146 */ 147 @Deprecated(since = "6.1.0") 148 default boolean matchesOutput( 149 RestOperationTypeEnum theOperation, RequestDetails theRequestDetails, IBaseResource theOutputResource) { 150 return true; 151 } 152}