View Javadoc

1   /**
2    * Copyright 2005-2012 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.kim.api.KimConstants;
27  import org.kuali.rice.kim.api.identity.Person;
28  import org.kuali.rice.kns.bo.authorization.BusinessObjectAuthorizerBase;
29  import org.kuali.rice.krad.document.Document;
30  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
31  import org.kuali.rice.krad.util.KRADConstants;
32  
33  import java.util.Collections;
34  import java.util.HashMap;
35  import java.util.Map;
36  import java.util.Set;
37  
38  /**
39   * DocumentAuthorizer containing common, reusable document-level authorization
40   * code.
41   */
42  public class DocumentAuthorizerBase extends BusinessObjectAuthorizerBase implements DocumentAuthorizer {
43      protected static Log LOG = LogFactory.getLog(DocumentAuthorizerBase.class);
44  
45      public static final String PRE_ROUTING_ROUTE_NAME = "PreRoute";
46      public static final String EDIT_MODE_DEFAULT_TRUE_VALUE = "TRUE";
47      public static final String USER_SESSION_METHOD_TO_CALL_OBJECT_KEY = "METHOD_TO_CALL_KEYS_METHOD_OBJECT_KEY";
48      public static final String USER_SESSION_METHOD_TO_CALL_COMPLETE_OBJECT_KEY =
49              "METHOD_TO_CALL_KEYS_COMPLETE_OBJECT_KEY";
50      public static final String USER_SESSION_METHOD_TO_CALL_COMPLETE_MARKER = "_EXITING";
51  
52      /**
53       * Individual document families will need to reimplement this according to
54       * their own needs; this version should be good enough to be usable during
55       * initial development.
56       */
57      public Set<String> getDocumentActions(Document document, Person user, Set<String> documentActions) {
58          if (LOG.isDebugEnabled()) {
59              LOG.debug("calling DocumentAuthorizerBase.getDocumentActionFlags for document '"
60                      + document.getDocumentNumber()
61                      + "'. user '"
62                      + user.getPrincipalName()
63                      + "'");
64          }
65          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_EDIT) && !canEdit(document, user)) {
66              documentActions.remove(KRADConstants.KUALI_ACTION_CAN_EDIT);
67          }
68  
69          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_COPY) && !canCopy(document, user)) {
70              documentActions.remove(KRADConstants.KUALI_ACTION_CAN_COPY);
71          }
72  
73          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_CLOSE) && !canClose(document, user)) {
74              documentActions.remove(KRADConstants.KUALI_ACTION_CAN_CLOSE);
75          }
76  
77          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_RELOAD) && !canReload(document, user)) {
78              documentActions.remove(KRADConstants.KUALI_ACTION_CAN_RELOAD);
79          }
80  
81          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_BLANKET_APPROVE) && !canBlanketApprove(document, user)) {
82              documentActions.remove(KRADConstants.KUALI_ACTION_CAN_BLANKET_APPROVE);
83          }
84  
85          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_CANCEL) && !canCancel(document, user)) {
86              documentActions.remove(KRADConstants.KUALI_ACTION_CAN_CANCEL);
87          }
88  
89          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_RECALL) && !canRecall(document, user)) {
90              documentActions.remove(KRADConstants.KUALI_ACTION_CAN_RECALL);
91          }
92  
93          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_SAVE) && !canSave(document, user)) {
94              documentActions.remove(KRADConstants.KUALI_ACTION_CAN_SAVE);
95          }
96  
97          if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_ROUTE) && !canRoute(document, user)) {
98              documentActions.remove(KRADConstants.KUALI_ACTION_CAN_ROUTE);
99          }
100 
101         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_ACKNOWLEDGE) && !canAcknowledge(document, user)) {
102             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_ACKNOWLEDGE);
103         }
104 
105         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_FYI) && !canFyi(document, user)) {
106             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_FYI);
107         }
108 
109         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_APPROVE) && !canApprove(document, user)) {
110             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_APPROVE);
111         }
112 
113         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_DISAPPROVE) && !canDisapprove(document, user)) {
114             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_DISAPPROVE);
115         }
116 
117         if (!canSendAnyTypeAdHocRequests(document, user)) {
118             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_ADD_ADHOC_REQUESTS);
119             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_SEND_ADHOC_REQUESTS);
120             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_SEND_NOTE_FYI);
121         }
122 
123         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_SEND_NOTE_FYI) && !canSendNoteFyi(document, user)) {
124             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_SEND_NOTE_FYI);
125         }
126 
127         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_ANNOTATE) && !canAnnotate(document, user)) {
128             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_ANNOTATE);
129         }
130 
131         if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_EDIT_DOCUMENT_OVERVIEW) && !canEditDocumentOverview(
132                 document, user)) {
133             documentActions.remove(KRADConstants.KUALI_ACTION_CAN_EDIT_DOCUMENT_OVERVIEW);
134         }
135 
136         if (documentActions.contains(KRADConstants.KUALI_ACTION_PERFORM_ROUTE_REPORT) && !canPerformRouteReport(document,
137                 user)) {
138             documentActions.remove(KRADConstants.KUALI_ACTION_PERFORM_ROUTE_REPORT);
139         }
140 
141         return documentActions;
142     }
143 
144     public boolean canInitiate(String documentTypeName, Person user) {
145         String nameSpaceCode = KRADConstants.KUALI_RICE_SYSTEM_NAMESPACE;
146         Map<String, String> permissionDetails = new HashMap<String, String>();
147         permissionDetails.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, documentTypeName);
148         return getPermissionService().isAuthorizedByTemplate(user.getPrincipalId(), nameSpaceCode,
149                 KimConstants.PermissionTemplateNames.INITIATE_DOCUMENT, permissionDetails,
150                 Collections.<String, String>emptyMap());
151     }
152 
153     public boolean canEdit(Document document, Person user) {
154         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
155                 KimConstants.PermissionTemplateNames.EDIT_DOCUMENT, user.getPrincipalId());
156     }
157 
158     public boolean canAnnotate(Document document, Person user) {
159         return canEdit(document, user);
160     }
161 
162     public boolean canReload(Document document, Person user) {
163         return true;
164     }
165 
166     public boolean canClose(Document document, Person user) {
167         return true;
168     }
169 
170     public boolean canSave(Document document, Person user) {
171         return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
172                 KimConstants.PermissionTemplateNames.SAVE_DOCUMENT, user.getPrincipalId());
173     }
174 
175     public boolean canRoute(Document document, Person user) {
176         return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
177                 KimConstants.PermissionTemplateNames.ROUTE_DOCUMENT, user.getPrincipalId());
178     }
179 
180     public boolean canCancel(Document document, Person user) {
181         return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
182                 KimConstants.PermissionTemplateNames.CANCEL_DOCUMENT, user.getPrincipalId());
183     }
184 
185     public boolean canRecall(Document document, Person user) {
186         return KewApiServiceLocator.getWorkflowDocumentActionsService().determineValidActions(document.getDocumentNumber(), user.getPrincipalId()).getValidActions().contains(ActionType.RECALL);
187     }
188 
189     public boolean canCopy(Document document, Person user) {
190         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
191                 KimConstants.PermissionTemplateNames.COPY_DOCUMENT, user.getPrincipalId());
192     }
193 
194     public boolean canPerformRouteReport(Document document, Person user) {
195         return true;
196     }
197 
198     public boolean canBlanketApprove(Document document, Person user) {
199         return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
200                 KimConstants.PermissionTemplateNames.BLANKET_APPROVE_DOCUMENT, user.getPrincipalId());
201     }
202 
203     public boolean canApprove(Document document, Person user) {
204         return canTakeRequestedAction(document, KewApiConstants.ACTION_REQUEST_APPROVE_REQ, user);
205     }
206 
207     public boolean canDisapprove(Document document, Person user) {
208         return canApprove(document, user);
209     }
210 
211     public boolean canSendNoteFyi(Document document, Person user) {
212         return canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_FYI_REQ, user);
213     }
214 
215     public boolean canFyi(Document document, Person user) {
216         return canTakeRequestedAction(document, KewApiConstants.ACTION_REQUEST_FYI_REQ, user);
217     }
218 
219     public boolean canAcknowledge(Document document, Person user) {
220         return canTakeRequestedAction(document, KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, user);
221     }
222 
223     public boolean canReceiveAdHoc(Document document, Person user, String actionRequestCode) {
224         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
225         additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_REQUEST_CD, actionRequestCode);
226         return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
227                 KimConstants.PermissionTemplateNames.AD_HOC_REVIEW_DOCUMENT, user.getPrincipalId(),
228                 additionalPermissionDetails, Collections.<String, String>emptyMap());
229     }
230 
231     public boolean canOpen(Document document, Person user) {
232         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
233                 KimConstants.PermissionTemplateNames.OPEN_DOCUMENT, user.getPrincipalId());
234     }
235 
236     public boolean canAddNoteAttachment(Document document, String attachmentTypeCode, Person user) {
237         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
238         if (attachmentTypeCode != null) {
239             additionalPermissionDetails.put(KimConstants.AttributeConstants.ATTACHMENT_TYPE_CODE, attachmentTypeCode);
240         }
241         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
242                 KimConstants.PermissionTemplateNames.ADD_NOTE_ATTACHMENT, user.getPrincipalId(),
243                 additionalPermissionDetails, Collections.<String, String>emptyMap());
244     }
245 
246     public boolean canDeleteNoteAttachment(Document document, String attachmentTypeCode, String createdBySelfOnly,
247             Person user) {
248         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
249         if (attachmentTypeCode != null) {
250             additionalPermissionDetails.put(KimConstants.AttributeConstants.ATTACHMENT_TYPE_CODE, attachmentTypeCode);
251         }
252         additionalPermissionDetails.put(KimConstants.AttributeConstants.CREATED_BY_SELF, createdBySelfOnly);
253         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
254                 KimConstants.PermissionTemplateNames.DELETE_NOTE_ATTACHMENT, user.getPrincipalId(),
255                 additionalPermissionDetails, Collections.<String, String>emptyMap());
256     }
257 
258     public boolean canViewNoteAttachment(Document document, String attachmentTypeCode, Person user) {
259         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
260         if (attachmentTypeCode != null) {
261             additionalPermissionDetails.put(KimConstants.AttributeConstants.ATTACHMENT_TYPE_CODE, attachmentTypeCode);
262         }
263         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
264                 KimConstants.PermissionTemplateNames.VIEW_NOTE_ATTACHMENT, user.getPrincipalId(),
265                 additionalPermissionDetails, Collections.<String, String>emptyMap());
266     }
267 
268     public boolean canViewNoteAttachment(Document document, String attachmentTypeCode, String authorUniversalIdentifier,
269             Person user) {
270         return canViewNoteAttachment(document, attachmentTypeCode, user);
271     }
272 
273     public boolean canSendAdHocRequests(Document document, String actionRequestCd, Person user) {
274         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
275         if (actionRequestCd != null) {
276             additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_REQUEST_CD, actionRequestCd);
277         }
278         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
279                 KimConstants.PermissionTemplateNames.SEND_AD_HOC_REQUEST, user.getPrincipalId(),
280                 additionalPermissionDetails, Collections.<String, String>emptyMap());
281     }
282 
283     public boolean canEditDocumentOverview(Document document, Person user) {
284         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
285                 KimConstants.PermissionTemplateNames.EDIT_DOCUMENT, user.getPrincipalId()) && this.isDocumentInitiator(
286                 document, user);
287     }
288 
289     public boolean canSendAnyTypeAdHocRequests(Document document, Person user) {
290         if (canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_FYI_REQ, user)) {
291             RoutePath routePath = KewApiServiceLocator.getDocumentTypeService().getRoutePathForDocumentTypeName(
292                     document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
293             ProcessDefinition processDefinition = routePath.getPrimaryProcess();
294             if (processDefinition != null) {
295                 if (processDefinition.getInitialRouteNode() == null) {
296                     return false;
297                 }
298             } else {
299                 return false;
300             }
301             return true;
302         } else if (canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, user)) {
303             return true;
304         }
305         return canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_APPROVE_REQ, user);
306     }
307 
308     public boolean canTakeRequestedAction(Document document, String actionRequestCode, Person user) {
309         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
310         additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_REQUEST_CD, actionRequestCode);
311         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
312                 KimConstants.PermissionTemplateNames.TAKE_REQUESTED_ACTION, user.getPrincipalId(),
313                 additionalPermissionDetails, Collections.<String, String>emptyMap());
314     }
315 
316     @Override
317     protected void addPermissionDetails(Object dataObject, Map<String, String> attributes) {
318         super.addPermissionDetails(dataObject, attributes);
319         if (dataObject instanceof Document) {
320             addStandardAttributes((Document) dataObject, attributes);
321         }
322     }
323 
324     @Override
325     protected void addRoleQualification(Object dataObject, Map<String, String> attributes) {
326         super.addRoleQualification(dataObject, attributes);
327         if (dataObject instanceof Document) {
328             addStandardAttributes((Document) dataObject, attributes);
329         }
330     }
331 
332     protected void addStandardAttributes(Document document, Map<String, String> attributes) {
333         WorkflowDocument wd = document.getDocumentHeader().getWorkflowDocument();
334         attributes.put(KimConstants.AttributeConstants.DOCUMENT_NUMBER, document.getDocumentNumber());
335         attributes.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, wd.getDocumentTypeName());
336         if (wd.isInitiated() || wd.isSaved()) {
337             attributes.put(KimConstants.AttributeConstants.ROUTE_NODE_NAME, PRE_ROUTING_ROUTE_NAME);
338         } else {
339             attributes.put(KimConstants.AttributeConstants.ROUTE_NODE_NAME,
340                     KRADServiceLocatorWeb.getWorkflowDocumentService().getCurrentRouteNodeNames(wd));
341         }
342         attributes.put(KimConstants.AttributeConstants.ROUTE_STATUS_CODE, wd.getStatus().getCode());
343     }
344 
345     protected boolean isDocumentInitiator(Document document, Person user) {
346         WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
347         return workflowDocument.getInitiatorPrincipalId().equalsIgnoreCase(user.getPrincipalId());
348     }
349 
350 }