View Javadoc
1   /**
2    * Copyright 2005-2015 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kns.document.authorization;
17  
18  import org.apache.commons.logging.Log;
19  import org.apache.commons.logging.LogFactory;
20  import org.kuali.rice.kew.api.KewApiConstants;
21  import org.kuali.rice.kew.api.KewApiServiceLocator;
22  import org.kuali.rice.kew.api.WorkflowDocument;
23  import org.kuali.rice.kew.api.action.ActionType;
24  import org.kuali.rice.kew.api.doctype.ProcessDefinition;
25  import org.kuali.rice.kew.api.doctype.RoutePath;
26  import org.kuali.rice.kew.api.document.node.RouteNodeInstance;
27  import org.kuali.rice.kim.api.KimConstants;
28  import org.kuali.rice.kim.api.identity.Person;
29  import org.kuali.rice.kns.bo.authorization.BusinessObjectAuthorizerBase;
30  import org.kuali.rice.krad.document.Document;
31  import org.kuali.rice.krad.document.DocumentRequestAuthorizationCache;
32  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
33  import org.kuali.rice.krad.util.KRADConstants;
34  
35  import java.util.Collections;
36  import java.util.HashMap;
37  import java.util.List;
38  import java.util.Map;
39  import java.util.Set;
40  
41  /**
42   * DocumentAuthorizer containing common, reusable document-level authorization
43   * code.
44   *
45   * @deprecated Use {@link org.kuali.rice.krad.document.DocumentAuthorizerBase}.
46   */
47  @Deprecated
48  public class DocumentAuthorizerBase extends BusinessObjectAuthorizerBase implements DocumentAuthorizer {
49      protected static Log LOG = LogFactory.getLog(DocumentAuthorizerBase.class);
50  
51      public static final String PRE_ROUTING_ROUTE_NAME = "PreRoute";
52      public static final String EDIT_MODE_DEFAULT_TRUE_VALUE = "TRUE";
53      public static final String USER_SESSION_METHOD_TO_CALL_OBJECT_KEY = "METHOD_TO_CALL_KEYS_METHOD_OBJECT_KEY";
54      public static final String USER_SESSION_METHOD_TO_CALL_COMPLETE_OBJECT_KEY =
55              "METHOD_TO_CALL_KEYS_COMPLETE_OBJECT_KEY";
56      public static final String USER_SESSION_METHOD_TO_CALL_COMPLETE_MARKER = "_EXITING";
57  
58      /**
59       * Individual document families will need to reimplement this according to
60       * their own needs; this version should be good enough to be usable during
61       * initial development.
62       */
63      public Set<String> getDocumentActions(Document document, Person user, Set<String> documentActions) {
64          if (LOG.isDebugEnabled()) {
65              LOG.debug("calling DocumentAuthorizerBase.getDocumentActionFlags for document '"
66                      + document.getDocumentNumber()
67                      + "'. user '"
68                      + user.getPrincipalName()
69                      + "'");
70          }
71          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_EDIT) && !canEdit(document, user)) {
72              documentActions.remove(KRADConstants.KUALI_ACTION_CAN_EDIT);
73          }
74  
75          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_COPY) && !canCopy(document, user)) {
76              documentActions.remove(KRADConstants.KUALI_ACTION_CAN_COPY);
77          }
78  
79          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_CLOSE) && !canClose(document, user)) {
80              documentActions.remove(KRADConstants.KUALI_ACTION_CAN_CLOSE);
81          }
82  
83          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_RELOAD) && !canReload(document, user)) {
84              documentActions.remove(KRADConstants.KUALI_ACTION_CAN_RELOAD);
85          }
86  
87          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_BLANKET_APPROVE) && !canBlanketApprove(document, user)) {
88              documentActions.remove(KRADConstants.KUALI_ACTION_CAN_BLANKET_APPROVE);
89          }
90  
91          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_CANCEL) && !canCancel(document, user)) {
92              documentActions.remove(KRADConstants.KUALI_ACTION_CAN_CANCEL);
93          }
94  
95          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_RECALL) && !canRecall(document, user)) {
96              documentActions.remove(KRADConstants.KUALI_ACTION_CAN_RECALL);
97          }
98  
99          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_SAVE) && !canSave(document, user)) {
100             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_SAVE);
101         }
102 
103         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_ROUTE) && !canRoute(document, user)) {
104             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_ROUTE);
105         }
106 
107         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_ACKNOWLEDGE) && !canAcknowledge(document, user)) {
108             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_ACKNOWLEDGE);
109         }
110 
111         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_FYI) && !canFyi(document, user)) {
112             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_FYI);
113         }
114 
115         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_APPROVE) && !canApprove(document, user)) {
116             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_APPROVE);
117         }
118 
119         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_DISAPPROVE) && !canDisapprove(document, user)) {
120             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_DISAPPROVE);
121         }
122 
123         if (!canSendAnyTypeAdHocRequests(document, user)) {
124             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_ADD_ADHOC_REQUESTS);
125             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_SEND_ADHOC_REQUESTS);
126             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_SEND_NOTE_FYI);
127         }
128 
129         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_SEND_NOTE_FYI) && !canSendNoteFyi(document, user)) {
130             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_SEND_NOTE_FYI);
131         }
132 
133         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_ANNOTATE) && !canAnnotate(document, user)) {
134             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_ANNOTATE);
135         }
136 
137         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_EDIT_DOCUMENT_OVERVIEW) && !canEditDocumentOverview(
138                 document, user)) {
139             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_EDIT_DOCUMENT_OVERVIEW);
140         }
141 
142         if (documentActions.contains(KRADConstants.KUALI_ACTION_PERFORM_ROUTE_REPORT) && !canPerformRouteReport(document,
143                 user)) {
144             documentActions.remove(KRADConstants.KUALI_ACTION_PERFORM_ROUTE_REPORT);
145         }
146 
147         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_SUPER_USER_TAKE_ACTION) && !canSuperUserTakeAction(document, user)) {
148             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_SUPER_USER_TAKE_ACTION);
149         }
150 
151         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_SUPER_USER_APPROVE) && !canSuperUserApprove(document, user)) {
152             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_SUPER_USER_APPROVE);
153         }
154 
155         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_SUPER_USER_DISAPPROVE) && !canSuperUserDisapprove(document, user)) {
156             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_SUPER_USER_DISAPPROVE);
157         }
158 
159         return documentActions;
160     }
161 
162     public boolean canInitiate(String documentTypeName, Person user) {
163         String nameSpaceCode = KRADConstants.KUALI_RICE_SYSTEM_NAMESPACE;
164         Map<String, String> permissionDetails = new HashMap<String, String>();
165         permissionDetails.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, documentTypeName);
166         return getPermissionService().isAuthorizedByTemplate(user.getPrincipalId(), nameSpaceCode,
167                 KimConstants.PermissionTemplateNames.INITIATE_DOCUMENT, permissionDetails,
168                 Collections.<String, String>emptyMap());
169     }
170 
171     public boolean canEdit(Document document, Person user) {
172         // KULRICE-7864: document can be editable on adhoc route for completion 
173         return document.getDocumentHeader().getWorkflowDocument().isCompletionRequested()
174                 || isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE, KimConstants.PermissionTemplateNames.EDIT_DOCUMENT, user.getPrincipalId());
175     }
176 
177     public boolean canAnnotate(Document document, Person user) {
178         return canEdit(document, user);
179     }
180 
181     public boolean canReload(Document document, Person user) {
182         return true;
183     }
184 
185     public boolean canClose(Document document, Person user) {
186         return true;
187     }
188 
189     public boolean canSave(Document document, Person user) {
190         return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
191                 KimConstants.PermissionTemplateNames.SAVE_DOCUMENT, user.getPrincipalId());
192     }
193 
194     public boolean canRoute(Document document, Person user) {
195         return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
196                 KimConstants.PermissionTemplateNames.ROUTE_DOCUMENT, user.getPrincipalId());
197     }
198 
199     public boolean canCancel(Document document, Person user) {
200         // KULRICE-8762: CANCEL button should be enabled for a person who is doing COMPLETE action 
201         boolean isCompletionRequested = document.getDocumentHeader().getWorkflowDocument().isCompletionRequested();
202         return isCompletionRequested || isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
203                 KimConstants.PermissionTemplateNames.CANCEL_DOCUMENT, user.getPrincipalId());
204     }
205 
206     public boolean canRecall(Document document, Person user) {
207         return KewApiServiceLocator.getWorkflowDocumentActionsService().determineValidActions(document.getDocumentNumber(), user.getPrincipalId()).getValidActions().contains(ActionType.RECALL);
208     }
209 
210     public boolean canCopy(Document document, Person user) {
211         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
212                 KimConstants.PermissionTemplateNames.COPY_DOCUMENT, user.getPrincipalId());
213     }
214 
215     public boolean canPerformRouteReport(Document document, Person user) {
216         return true;
217     }
218 
219     public boolean canBlanketApprove(Document document, Person user) {
220         return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
221                 KimConstants.PermissionTemplateNames.BLANKET_APPROVE_DOCUMENT, user.getPrincipalId());
222     }
223 
224     public boolean canApprove(Document document, Person user) {
225         return canTakeRequestedAction(document, KewApiConstants.ACTION_REQUEST_APPROVE_REQ, user);
226     }
227 
228     public boolean canDisapprove(Document document, Person user) {
229         return canApprove(document, user);
230     }
231 
232     public boolean canSendNoteFyi(Document document, Person user) {
233         return canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_FYI_REQ, user);
234     }
235 
236     public boolean canFyi(Document document, Person user) {
237         return canTakeRequestedAction(document, KewApiConstants.ACTION_REQUEST_FYI_REQ, user);
238     }
239 
240     public boolean canAcknowledge(Document document, Person user) {
241         return canTakeRequestedAction(document, KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, user);
242     }
243 
244     public boolean canReceiveAdHoc(Document document, Person user, String actionRequestCode) {
245         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
246         additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_REQUEST_CD, actionRequestCode);
247         return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
248                 KimConstants.PermissionTemplateNames.AD_HOC_REVIEW_DOCUMENT, user.getPrincipalId(),
249                 additionalPermissionDetails, Collections.<String, String>emptyMap());
250     }
251 
252     public boolean canOpen(Document document, Person user) {
253         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
254                 KimConstants.PermissionTemplateNames.OPEN_DOCUMENT, user.getPrincipalId());
255     }
256 
257     public boolean canAddNoteAttachment(Document document, String attachmentTypeCode, Person user) {
258         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
259         if (attachmentTypeCode != null) {
260             additionalPermissionDetails.put(KimConstants.AttributeConstants.ATTACHMENT_TYPE_CODE, attachmentTypeCode);
261         }
262         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
263                 KimConstants.PermissionTemplateNames.ADD_NOTE_ATTACHMENT, user.getPrincipalId(),
264                 additionalPermissionDetails, Collections.<String, String>emptyMap());
265     }
266 
267     public boolean canDeleteNoteAttachment(Document document, String attachmentTypeCode, String createdBySelfOnly,
268             Person user) {
269         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
270         if (attachmentTypeCode != null) {
271             additionalPermissionDetails.put(KimConstants.AttributeConstants.ATTACHMENT_TYPE_CODE, attachmentTypeCode);
272         }
273         additionalPermissionDetails.put(KimConstants.AttributeConstants.CREATED_BY_SELF, createdBySelfOnly);
274         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
275                 KimConstants.PermissionTemplateNames.DELETE_NOTE_ATTACHMENT, user.getPrincipalId(),
276                 additionalPermissionDetails, Collections.<String, String>emptyMap());
277     }
278 
279     public boolean canViewNoteAttachment(Document document, String attachmentTypeCode, Person user) {
280         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
281         if (attachmentTypeCode != null) {
282             additionalPermissionDetails.put(KimConstants.AttributeConstants.ATTACHMENT_TYPE_CODE, attachmentTypeCode);
283         }
284         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
285                 KimConstants.PermissionTemplateNames.VIEW_NOTE_ATTACHMENT, user.getPrincipalId(),
286                 additionalPermissionDetails, Collections.<String, String>emptyMap());
287     }
288 
289     public boolean canViewNoteAttachment(Document document, String attachmentTypeCode, String authorUniversalIdentifier,
290             Person user) {
291         return canViewNoteAttachment(document, attachmentTypeCode, user);
292     }
293 
294     public boolean canSendAdHocRequests(Document document, String actionRequestCd, Person user) {
295         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
296         if (actionRequestCd != null) {
297             additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_REQUEST_CD, actionRequestCd);
298         }
299         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
300                 KimConstants.PermissionTemplateNames.SEND_AD_HOC_REQUEST, user.getPrincipalId(),
301                 additionalPermissionDetails, Collections.<String, String>emptyMap());
302     }
303 
304     public boolean canEditDocumentOverview(Document document, Person user) {
305         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
306                 KimConstants.PermissionTemplateNames.EDIT_DOCUMENT, user.getPrincipalId()) && this.isDocumentInitiator(
307                 document, user);
308     }
309 
310     public boolean canSendAnyTypeAdHocRequests(Document document, Person user) {
311         if (canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_FYI_REQ, user)) {
312             RoutePath routePath = KewApiServiceLocator.getDocumentTypeService().getRoutePathForDocumentTypeName(
313                     document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
314             ProcessDefinition processDefinition = routePath.getPrimaryProcess();
315             if (processDefinition != null) {
316                 if (processDefinition.getInitialRouteNode() == null) {
317                     return false;
318                 }
319             } else {
320                 return false;
321             }
322             return true;
323         } else if (canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, user)) {
324             return true;
325         }
326         return canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_APPROVE_REQ, user);
327     }
328 
329     public boolean canTakeRequestedAction(Document document, String actionRequestCode, Person user) {
330         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
331         additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_REQUEST_CD, actionRequestCode);
332         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
333                 KimConstants.PermissionTemplateNames.TAKE_REQUESTED_ACTION, user.getPrincipalId(),
334                 additionalPermissionDetails, Collections.<String, String>emptyMap());
335     }
336 
337     /**
338      * {@inheritDoc}
339      */
340     @Override
341     public boolean canSuperUserTakeAction(Document document, Person user) {
342         if (!document.getDocumentHeader().hasWorkflowDocument()) {
343             return false;
344         }
345 
346         String principalId = user.getPrincipalId();
347 
348         String documentTypeId = document.getDocumentHeader().getWorkflowDocument().getDocumentTypeId();
349         if (KewApiServiceLocator.getDocumentTypeService().isSuperUserForDocumentTypeId(principalId, documentTypeId)) {
350             return true;
351         }
352 
353         String documentTypeName = document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName();
354         List<RouteNodeInstance> routeNodeInstances = document.getDocumentHeader().getWorkflowDocument().getRouteNodeInstances();
355         String documentStatus =  document.getDocumentHeader().getWorkflowDocument().getStatus().getCode();
356         return KewApiServiceLocator.getDocumentTypeService().canSuperUserApproveSingleActionRequest(
357                 principalId, documentTypeName, routeNodeInstances, documentStatus);
358     }
359 
360     /**
361      * {@inheritDoc}
362      */
363     @Override
364     public boolean canSuperUserApprove(Document document, Person user) {
365         if (!document.getDocumentHeader().hasWorkflowDocument()) {
366             return false;
367         }
368 
369         String principalId = user.getPrincipalId();
370 
371         String documentTypeId = document.getDocumentHeader().getWorkflowDocument().getDocumentTypeId();
372         if (KewApiServiceLocator.getDocumentTypeService().isSuperUserForDocumentTypeId(principalId, documentTypeId)) {
373             return true;
374         }
375 
376         String documentTypeName = document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName();
377         List<RouteNodeInstance> routeNodeInstances = document.getDocumentHeader().getWorkflowDocument().getRouteNodeInstances();
378         String documentStatus =  document.getDocumentHeader().getWorkflowDocument().getStatus().getCode();
379         return KewApiServiceLocator.getDocumentTypeService().canSuperUserApproveDocument(
380                 principalId, documentTypeName, routeNodeInstances, documentStatus);
381     }
382 
383     /**
384      * {@inheritDoc}
385      */
386     @Override
387     public boolean canSuperUserDisapprove(Document document, Person user) {
388         if (!document.getDocumentHeader().hasWorkflowDocument()) {
389             return false;
390         }
391 
392         String principalId = user.getPrincipalId();
393 
394         String documentTypeId = document.getDocumentHeader().getWorkflowDocument().getDocumentTypeId();
395         if (KewApiServiceLocator.getDocumentTypeService().isSuperUserForDocumentTypeId(principalId, documentTypeId)) {
396             return true;
397         }
398 
399         String documentTypeName = document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName();
400         List<RouteNodeInstance> routeNodeInstances = document.getDocumentHeader().getWorkflowDocument().getRouteNodeInstances();
401         String documentStatus =  document.getDocumentHeader().getWorkflowDocument().getStatus().getCode();
402         return KewApiServiceLocator.getDocumentTypeService().canSuperUserDisapproveDocument(
403                 principalId, documentTypeName, routeNodeInstances, documentStatus);
404     }
405 
406     @Override
407     protected void addPermissionDetails(Object dataObject, Map<String, String> attributes) {
408         super.addPermissionDetails(dataObject, attributes);
409         if (dataObject instanceof Document) {
410             addStandardAttributes((Document) dataObject, attributes);
411         }
412     }
413 
414     @Override
415     protected void addRoleQualification(Object dataObject, Map<String, String> attributes) {
416         super.addRoleQualification(dataObject, attributes);
417         if (dataObject instanceof Document) {
418             addStandardAttributes((Document) dataObject, attributes);
419         }
420     }
421 
422     protected void addStandardAttributes(Document document, Map<String, String> attributes) {
423         WorkflowDocument wd = document.getDocumentHeader().getWorkflowDocument();
424         attributes.put(KimConstants.AttributeConstants.DOCUMENT_NUMBER, document.getDocumentNumber());
425         attributes.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, wd.getDocumentTypeName());
426         if (wd.isInitiated() || wd.isSaved()) {
427             attributes.put(KimConstants.AttributeConstants.ROUTE_NODE_NAME, PRE_ROUTING_ROUTE_NAME);
428         } else {
429             attributes.put(KimConstants.AttributeConstants.ROUTE_NODE_NAME,
430                     KRADServiceLocatorWeb.getWorkflowDocumentService().getCurrentRouteNodeNames(wd));
431         }
432         attributes.put(KimConstants.AttributeConstants.ROUTE_STATUS_CODE, wd.getStatus().getCode());
433     }
434 
435     protected boolean isDocumentInitiator(Document document, Person user) {
436         WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
437         return workflowDocument.getInitiatorPrincipalId().equalsIgnoreCase(user.getPrincipalId());
438     }
439 
440     @Override
441     public void setDocumentRequestAuthorizationCache(
442             DocumentRequestAuthorizationCache documentRequestAuthorizationCache) {
443         // noop
444     }
445 }