001    /**
002     * Copyright 2005-2014 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.krad.document;
017    
018    import org.kuali.rice.kew.api.KewApiConstants;
019    import org.kuali.rice.kew.api.KewApiServiceLocator;
020    import org.kuali.rice.kew.api.WorkflowDocument;
021    import org.kuali.rice.kew.api.action.ActionType;
022    import org.kuali.rice.kew.api.doctype.ProcessDefinition;
023    import org.kuali.rice.kew.api.doctype.RoutePath;
024    import org.kuali.rice.kim.api.KimConstants;
025    import org.kuali.rice.kim.api.identity.Person;
026    import org.kuali.rice.krad.bo.DataObjectAuthorizerBase;
027    import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
028    import org.kuali.rice.krad.util.KRADConstants;
029    
030    import java.util.Collections;
031    import java.util.HashMap;
032    import java.util.Map;
033    
034    /**
035     * Default implementation for {@link DocumentAuthorizer} that perform KIM permission checks to authorize the actions
036     *
037     * @author Kuali Rice Team (rice.collab@kuali.org)
038     */
039    public class DocumentAuthorizerBase extends DataObjectAuthorizerBase implements DocumentAuthorizer {
040        private static final long serialVersionUID = -5354518767379472681L;
041    
042        public static final String PRE_ROUTING_ROUTE_NAME = "PreRoute";
043    
044        public final boolean canInitiate(String documentTypeName, Person user) {
045            String nameSpaceCode = KRADConstants.KUALI_RICE_SYSTEM_NAMESPACE;
046            Map<String, String> permissionDetails = new HashMap<String, String>();
047            permissionDetails.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, documentTypeName);
048    
049            return getPermissionService().isAuthorizedByTemplate(user.getPrincipalId(), nameSpaceCode,
050                    KimConstants.PermissionTemplateNames.INITIATE_DOCUMENT, permissionDetails,
051                    Collections.<String, String>emptyMap());
052        }
053    
054        public boolean canOpen(Document document, Person user) {
055            return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
056                    KimConstants.PermissionTemplateNames.OPEN_DOCUMENT, user.getPrincipalId());
057        }
058    
059        public boolean canEdit(Document document, Person user) {
060            return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
061                    KimConstants.PermissionTemplateNames.EDIT_DOCUMENT, user.getPrincipalId());
062        }
063    
064        public boolean canAnnotate(Document document, Person user) {
065            return canEdit(document, user);
066        }
067    
068        public boolean canReload(Document document, Person user) {
069            return true;
070        }
071    
072        public boolean canClose(Document document, Person user) {
073            return true;
074        }
075    
076        public boolean canSave(Document document, Person user) {
077            return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
078                    KimConstants.PermissionTemplateNames.SAVE_DOCUMENT, user.getPrincipalId());
079        }
080    
081        public boolean canRoute(Document document, Person user) {
082            return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
083                    KimConstants.PermissionTemplateNames.ROUTE_DOCUMENT, user.getPrincipalId());
084        }
085    
086        public boolean canCancel(Document document, Person user) {
087            return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
088                    KimConstants.PermissionTemplateNames.CANCEL_DOCUMENT, user.getPrincipalId());
089        }
090    
091        public boolean canRecall(Document document, Person user) {
092            return KewApiServiceLocator.getWorkflowDocumentActionsService().determineValidActions(document.getDocumentNumber(), user.getPrincipalId()).getValidActions().contains(ActionType.RECALL);
093        }
094    
095        public boolean canCopy(Document document, Person user) {
096            return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
097                    KimConstants.PermissionTemplateNames.COPY_DOCUMENT, user.getPrincipalId());
098        }
099    
100        public boolean canPerformRouteReport(Document document, Person user) {
101            return true;
102        }
103    
104        public boolean canBlanketApprove(Document document, Person user) {
105            return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
106                    KimConstants.PermissionTemplateNames.BLANKET_APPROVE_DOCUMENT, user.getPrincipalId());
107        }
108    
109        public boolean canApprove(Document document, Person user) {
110            return canTakeRequestedAction(document, KewApiConstants.ACTION_REQUEST_APPROVE_REQ, user);
111        }
112    
113        public boolean canDisapprove(Document document, Person user) {
114            return canApprove(document, user);
115        }
116    
117        public boolean canSendNoteFyi(Document document, Person user) {
118            return canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_FYI_REQ, user);
119        }
120    
121        public boolean canFyi(Document document, Person user) {
122            return canTakeRequestedAction(document, KewApiConstants.ACTION_REQUEST_FYI_REQ, user);
123        }
124    
125        public boolean canAcknowledge(Document document, Person user) {
126            return canTakeRequestedAction(document, KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, user);
127        }
128    
129        public boolean canReceiveAdHoc(Document document, Person user, String actionRequestCode) {
130            Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
131            additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_REQUEST_CD, actionRequestCode);
132    
133            return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
134                    KimConstants.PermissionTemplateNames.AD_HOC_REVIEW_DOCUMENT, user.getPrincipalId(),
135                    additionalPermissionDetails, null);
136        }
137    
138        public boolean canAddNoteAttachment(Document document, String attachmentTypeCode, Person user) {
139            Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
140            if (attachmentTypeCode != null) {
141                additionalPermissionDetails.put(KimConstants.AttributeConstants.ATTACHMENT_TYPE_CODE, attachmentTypeCode);
142            }
143    
144            return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
145                    KimConstants.PermissionTemplateNames.ADD_NOTE_ATTACHMENT, user.getPrincipalId(),
146                    additionalPermissionDetails, null);
147        }
148    
149        public boolean canDeleteNoteAttachment(Document document, String attachmentTypeCode,
150                String authorUniversalIdentifier, Person user) {
151            boolean canDeleteNoteAttachment = false;
152    
153            Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
154            if (attachmentTypeCode != null) {
155                additionalPermissionDetails.put(KimConstants.AttributeConstants.ATTACHMENT_TYPE_CODE, attachmentTypeCode);
156            }
157    
158            // first check permissions that does not restrict on the author
159            additionalPermissionDetails.put(KimConstants.AttributeConstants.CREATED_BY_SELF, "false");
160            canDeleteNoteAttachment = isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
161                    KimConstants.PermissionTemplateNames.DELETE_NOTE_ATTACHMENT, user.getPrincipalId(),
162                    additionalPermissionDetails, null);
163    
164            if (!canDeleteNoteAttachment) {
165                // check for permissions restricted by author
166                additionalPermissionDetails.put(KimConstants.AttributeConstants.CREATED_BY_SELF, "true");
167                canDeleteNoteAttachment = isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
168                        KimConstants.PermissionTemplateNames.DELETE_NOTE_ATTACHMENT, user.getPrincipalId(),
169                        additionalPermissionDetails, null);
170    
171                // if permission has been granted user must be the author
172                if (canDeleteNoteAttachment && !authorUniversalIdentifier.equals(user.getPrincipalId())) {
173                    canDeleteNoteAttachment = false;
174                }
175            }
176    
177            return canDeleteNoteAttachment;
178        }
179    
180        public boolean canViewNoteAttachment(Document document, String attachmentTypeCode, String authorUniversalIdentifier,
181                Person user) {
182            Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
183            if (attachmentTypeCode != null) {
184                additionalPermissionDetails.put(KimConstants.AttributeConstants.ATTACHMENT_TYPE_CODE, attachmentTypeCode);
185            }
186    
187            return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
188                    KimConstants.PermissionTemplateNames.VIEW_NOTE_ATTACHMENT, user.getPrincipalId(),
189                    additionalPermissionDetails, null);
190        }
191    
192        public boolean canSendAdHocRequests(Document document, String actionRequestCd, Person user) {
193            Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
194            if (actionRequestCd != null) {
195                additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_REQUEST_CD, actionRequestCd);
196            }
197    
198            return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
199                    KimConstants.PermissionTemplateNames.SEND_AD_HOC_REQUEST, user.getPrincipalId(),
200                    additionalPermissionDetails, null);
201        }
202    
203        public boolean canEditDocumentOverview(Document document, Person user) {
204            return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
205                    KimConstants.PermissionTemplateNames.EDIT_DOCUMENT, user.getPrincipalId()) && this.isDocumentInitiator(
206                    document, user);
207        }
208    
209        public boolean canSendAnyTypeAdHocRequests(Document document, Person user) {
210            if (canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_FYI_REQ, user)) {
211                RoutePath routePath = KewApiServiceLocator.getDocumentTypeService().getRoutePathForDocumentTypeName(
212                        document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
213                ProcessDefinition processDefinition = routePath.getPrimaryProcess();
214                if (processDefinition != null) {
215                    if (processDefinition.getInitialRouteNode() == null) {
216                        return false;
217                    }
218                } else {
219                    return false;
220                }
221    
222                return true;
223            } else if (canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, user)) {
224                return true;
225            }
226    
227            return canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_APPROVE_REQ, user);
228        }
229    
230        public boolean canTakeRequestedAction(Document document, String actionRequestCode, Person user) {
231            Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
232            additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_REQUEST_CD, actionRequestCode);
233    
234            return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
235                    KimConstants.PermissionTemplateNames.TAKE_REQUESTED_ACTION, user.getPrincipalId(),
236                    additionalPermissionDetails, null);
237        }
238    
239        @Override
240        protected void addPermissionDetails(Object dataObject, Map<String, String> attributes) {
241            super.addPermissionDetails(dataObject, attributes);
242    
243            if (dataObject instanceof Document) {
244                addStandardAttributes((Document) dataObject, attributes);
245            }
246        }
247    
248        @Override
249        protected void addRoleQualification(Object dataObject, Map<String, String> attributes) {
250            super.addRoleQualification(dataObject, attributes);
251    
252            if (dataObject instanceof Document) {
253                addStandardAttributes((Document) dataObject, attributes);
254            }
255        }
256    
257        protected void addStandardAttributes(Document document, Map<String, String> attributes) {
258            WorkflowDocument wd = document.getDocumentHeader().getWorkflowDocument();
259            attributes.put(KimConstants.AttributeConstants.DOCUMENT_NUMBER, document.getDocumentNumber());
260            attributes.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, wd.getDocumentTypeName());
261    
262            if (wd.isInitiated() || wd.isSaved()) {
263                attributes.put(KimConstants.AttributeConstants.ROUTE_NODE_NAME, PRE_ROUTING_ROUTE_NAME);
264            } else {
265                attributes.put(KimConstants.AttributeConstants.ROUTE_NODE_NAME,
266                        KRADServiceLocatorWeb.getWorkflowDocumentService().getCurrentRouteNodeNames(wd));
267            }
268    
269            attributes.put(KimConstants.AttributeConstants.ROUTE_STATUS_CODE, wd.getStatus().getCode());
270        }
271    
272        protected boolean isDocumentInitiator(Document document, Person user) {
273            WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
274    
275            return workflowDocument.getInitiatorPrincipalId().equalsIgnoreCase(user.getPrincipalId());
276        }
277    }