001package ca.uhn.fhir.rest.server.interceptor.auth;
002
003/*-
004 * #%L
005 * HAPI FHIR - Server Framework
006 * %%
007 * Copyright (C) 2014 - 2023 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.interceptor.api.Pointcut;
024import ca.uhn.fhir.model.primitive.IdDt;
025import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
026import ca.uhn.fhir.rest.api.server.RequestDetails;
027import ca.uhn.fhir.rest.api.server.bulk.BulkDataExportOptions;
028import org.hl7.fhir.instance.model.api.IBaseResource;
029import org.hl7.fhir.instance.model.api.IIdType;
030
031import java.util.Collection;
032import java.util.Objects;
033import java.util.Set;
034
035import static org.apache.commons.collections4.CollectionUtils.isEmpty;
036import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;
037import static org.apache.commons.lang3.StringUtils.isNotBlank;
038
039public class RuleBulkExportImpl extends BaseRule {
040        private String myGroupId;
041        private BulkDataExportOptions.ExportStyle myWantExportStyle;
042        private Collection<String> myResourceTypes;
043        private boolean myWantAnyStyle;
044
045        RuleBulkExportImpl(String theRuleName) {
046                super(theRuleName);
047        }
048
049        @Override
050        public AuthorizationInterceptor.Verdict applyRule(RestOperationTypeEnum theOperation, RequestDetails theRequestDetails, IBaseResource theInputResource, IIdType theInputResourceId, IBaseResource theOutputResource, IRuleApplier theRuleApplier, Set<AuthorizationFlagsEnum> theFlags, Pointcut thePointcut) {
051                if (thePointcut != Pointcut.STORAGE_INITIATE_BULK_EXPORT) {
052                        return null;
053                }
054
055                if (theRequestDetails == null) {
056                        return null;
057                }
058
059                BulkDataExportOptions options = (BulkDataExportOptions) theRequestDetails.getAttribute(AuthorizationInterceptor.REQUEST_ATTRIBUTE_BULK_DATA_EXPORT_OPTIONS);
060
061                if (!myWantAnyStyle && options.getExportStyle() != myWantExportStyle) {
062                        return null;
063                }
064
065                if (isNotEmpty(myResourceTypes)) {
066                        if (isEmpty(options.getResourceTypes())) {
067                                return null;
068                        }
069                        for (String next : options.getResourceTypes()) {
070                                if (!myResourceTypes.contains(next)) {
071                                        return new AuthorizationInterceptor.Verdict(PolicyEnum.DENY,this);
072                                }
073                        }
074                }
075
076                if (myWantAnyStyle || myWantExportStyle == BulkDataExportOptions.ExportStyle.SYSTEM) {
077                        return newVerdict(theOperation, theRequestDetails, theInputResource, theInputResourceId, theOutputResource, theRuleApplier);
078                }
079
080                if (isNotBlank(myGroupId) && options.getGroupId() != null) {
081                        String expectedGroupId = new IdDt(myGroupId).toUnqualifiedVersionless().getValue();
082                        String actualGroupId = options.getGroupId().toUnqualifiedVersionless().getValue();
083                        if (Objects.equals(expectedGroupId, actualGroupId)) {
084                                return newVerdict(theOperation, theRequestDetails, theInputResource, theInputResourceId, theOutputResource, theRuleApplier);
085                        }
086                }
087                return null;
088        }
089
090        public void setAppliesToGroupExportOnGroup(String theGroupId) {
091                myWantExportStyle = BulkDataExportOptions.ExportStyle.GROUP;
092                myGroupId = theGroupId;
093        }
094
095        public void setAppliesToPatientExportOnGroup(String theGroupId) {
096                myWantExportStyle = BulkDataExportOptions.ExportStyle.PATIENT;
097                myGroupId = theGroupId;
098        }
099
100        public void setAppliesToSystem() {
101                myWantExportStyle = BulkDataExportOptions.ExportStyle.SYSTEM;
102        }
103
104        public void setResourceTypes(Collection<String> theResourceTypes) {
105                myResourceTypes = theResourceTypes;
106        }
107
108        public void setAppliesToAny() {
109                myWantAnyStyle = true;
110        }
111
112        String getGroupId() {
113                return myGroupId;
114        }
115
116        BulkDataExportOptions.ExportStyle getWantExportStyle() {
117                return myWantExportStyle;
118        }
119}