View Javadoc
1   /**
2    * Copyright 2005-2016 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.krad.document;
17  
18  import org.kuali.rice.kew.api.KewApiConstants;
19  import org.kuali.rice.kew.api.KewApiServiceLocator;
20  import org.kuali.rice.kew.api.WorkflowDocument;
21  import org.kuali.rice.kew.api.action.ActionType;
22  import org.kuali.rice.kew.api.doctype.ProcessDefinition;
23  import org.kuali.rice.kew.api.doctype.RoutePath;
24  import org.kuali.rice.kew.api.document.node.RouteNodeInstance;
25  import org.kuali.rice.kim.api.KimConstants;
26  import org.kuali.rice.kim.api.identity.Person;
27  import org.kuali.rice.krad.bo.DataObjectAuthorizerBase;
28  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
29  import org.kuali.rice.krad.util.KRADConstants;
30  
31  import java.util.Collections;
32  import java.util.HashMap;
33  import java.util.List;
34  import java.util.Map;
35  
36  /**
37   * Default implementation for {@link DocumentAuthorizer} that perform KIM permission checks to authorize the actions
38   *
39   * @author Kuali Rice Team (rice.collab@kuali.org)
40   */
41  public class DocumentAuthorizerBase extends DataObjectAuthorizerBase implements DocumentAuthorizer {
42      private static final long serialVersionUID = -5354518767379472681L;
43  
44      private DocumentRequestAuthorizationCache documentRequestAuthorizationCache;
45  
46      public static final String PRE_ROUTING_ROUTE_NAME = "PreRoute";
47  
48      public final boolean canInitiate(String documentTypeName, Person user) {
49          String nameSpaceCode = KRADConstants.KUALI_RICE_SYSTEM_NAMESPACE;
50          Map<String, String> permissionDetails = new HashMap<String, String>();
51          permissionDetails.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, documentTypeName);
52  
53          return getPermissionService().isAuthorizedByTemplate(user.getPrincipalId(), nameSpaceCode,
54                  KimConstants.PermissionTemplateNames.INITIATE_DOCUMENT, permissionDetails,
55                  Collections.<String, String>emptyMap());
56      }
57  
58      public boolean canOpen(Document document, Person user) {
59          return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
60                  KimConstants.PermissionTemplateNames.OPEN_DOCUMENT, user.getPrincipalId());
61      }
62  
63      public boolean canEdit(Document document, Person user) {
64          return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
65                  KimConstants.PermissionTemplateNames.EDIT_DOCUMENT, user.getPrincipalId());
66      }
67  
68      public boolean canAnnotate(Document document, Person user) {
69          return canAddNoteAttachment(document, null, user);
70      }
71  
72      public boolean canReload(Document document, Person user) {
73          return true;
74      }
75  
76      public boolean canClose(Document document, Person user) {
77          return false;
78      }
79  
80      public boolean canSave(Document document, Person user) {
81          return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
82                  KimConstants.PermissionTemplateNames.SAVE_DOCUMENT, user.getPrincipalId());
83      }
84  
85      public boolean canRoute(Document document, Person user) {
86          return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
87                  KimConstants.PermissionTemplateNames.ROUTE_DOCUMENT, user.getPrincipalId());
88      }
89  
90      public boolean canCancel(Document document, Person user) {
91          boolean isCompletionRequested = document.getDocumentHeader().getWorkflowDocument().isCompletionRequested();
92  
93          return isCompletionRequested || isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
94                  KimConstants.PermissionTemplateNames.CANCEL_DOCUMENT, user.getPrincipalId());
95      }
96  
97      public boolean canRecall(Document document, Person user) {
98          return getDocumentRequestAuthorizationCache(document).getWorkflowDocumentInfo().isValidAction(
99                  ActionType.RECALL);
100     }
101 
102     public boolean canCopy(Document document, Person user) {
103         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
104                 KimConstants.PermissionTemplateNames.COPY_DOCUMENT, user.getPrincipalId());
105     }
106 
107     public boolean canPerformRouteReport(Document document, Person user) {
108         return true;
109     }
110 
111     public boolean canBlanketApprove(Document document, Person user) {
112         return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
113                 KimConstants.PermissionTemplateNames.BLANKET_APPROVE_DOCUMENT, user.getPrincipalId());
114     }
115 
116     public boolean canApprove(Document document, Person user) {
117         return canTakeRequestedAction(document, KewApiConstants.ACTION_REQUEST_APPROVE_REQ, user);
118     }
119 
120     public boolean canDisapprove(Document document, Person user) {
121         return canApprove(document, user);
122     }
123 
124     public boolean canSendNoteFyi(Document document, Person user) {
125         return canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_FYI_REQ, user);
126     }
127 
128     public boolean canFyi(Document document, Person user) {
129         return canTakeRequestedAction(document, KewApiConstants.ACTION_REQUEST_FYI_REQ, user);
130     }
131 
132     public boolean canAcknowledge(Document document, Person user) {
133         return canTakeRequestedAction(document, KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, user);
134     }
135 
136     public boolean canReceiveAdHoc(Document document, Person user, String actionRequestCode) {
137         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
138         additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_REQUEST_CD, actionRequestCode);
139 
140         return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE,
141                 KimConstants.PermissionTemplateNames.AD_HOC_REVIEW_DOCUMENT, user.getPrincipalId(),
142                 additionalPermissionDetails, null);
143     }
144 
145     public boolean canAddNoteAttachment(Document document, String attachmentTypeCode, Person user) {
146         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
147         if (attachmentTypeCode != null) {
148             additionalPermissionDetails.put(KimConstants.AttributeConstants.ATTACHMENT_TYPE_CODE, attachmentTypeCode);
149         }
150 
151         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
152                 KimConstants.PermissionTemplateNames.ADD_NOTE_ATTACHMENT, user.getPrincipalId(),
153                 additionalPermissionDetails, null);
154     }
155 
156     public boolean canDeleteNoteAttachment(Document document, String attachmentTypeCode,
157             String authorUniversalIdentifier, Person user) {
158         boolean canDeleteNoteAttachment = false;
159 
160         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
161         if (attachmentTypeCode != null) {
162             additionalPermissionDetails.put(KimConstants.AttributeConstants.ATTACHMENT_TYPE_CODE, attachmentTypeCode);
163         }
164 
165         // first check permissions that does not restrict on the author
166         additionalPermissionDetails.put(KimConstants.AttributeConstants.CREATED_BY_SELF, "false");
167         canDeleteNoteAttachment = isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
168                 KimConstants.PermissionTemplateNames.DELETE_NOTE_ATTACHMENT, user.getPrincipalId(),
169                 additionalPermissionDetails, null);
170 
171         if (!canDeleteNoteAttachment) {
172             // check for permissions restricted by author
173             additionalPermissionDetails.put(KimConstants.AttributeConstants.CREATED_BY_SELF, "true");
174             canDeleteNoteAttachment = isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
175                     KimConstants.PermissionTemplateNames.DELETE_NOTE_ATTACHMENT, user.getPrincipalId(),
176                     additionalPermissionDetails, null);
177 
178             // if permission has been granted user must be the author
179             if (canDeleteNoteAttachment && !authorUniversalIdentifier.equals(user.getPrincipalId())) {
180                 canDeleteNoteAttachment = false;
181             }
182         }
183 
184         return canDeleteNoteAttachment;
185     }
186 
187     public boolean canViewNoteAttachment(Document document, String attachmentTypeCode, Person user) {
188         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
189         if (attachmentTypeCode != null) {
190             additionalPermissionDetails.put(KimConstants.AttributeConstants.ATTACHMENT_TYPE_CODE, attachmentTypeCode);
191         }
192 
193         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
194                 KimConstants.PermissionTemplateNames.VIEW_NOTE_ATTACHMENT, user.getPrincipalId(),
195                 additionalPermissionDetails, null);
196     }
197 
198     @Deprecated
199     public boolean canViewNoteAttachment(Document document, String attachmentTypeCode, String authorUniversalIdentifier,
200             Person user) {
201         return canViewNoteAttachment(document, attachmentTypeCode, user);
202     }
203 
204     public boolean canSendAdHocRequests(Document document, String actionRequestCd, Person user) {
205         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
206         if (actionRequestCd != null) {
207             additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_REQUEST_CD, actionRequestCd);
208         }
209 
210         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
211                 KimConstants.PermissionTemplateNames.SEND_AD_HOC_REQUEST, user.getPrincipalId(),
212                 additionalPermissionDetails, null);
213     }
214 
215     public boolean canEditDocumentOverview(Document document, Person user) {
216         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
217                 KimConstants.PermissionTemplateNames.EDIT_DOCUMENT, user.getPrincipalId()) && this.isDocumentInitiator(
218                 document, user);
219     }
220 
221     public boolean canSendAnyTypeAdHocRequests(Document document, Person user) {
222         if (canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_FYI_REQ, user)) {
223             RoutePath routePath = KewApiServiceLocator.getDocumentTypeService().getRoutePathForDocumentTypeName(
224                     document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
225             ProcessDefinition processDefinition = routePath.getPrimaryProcess();
226             if (processDefinition != null) {
227                 if (processDefinition.getInitialRouteNode() == null) {
228                     return false;
229                 }
230             } else {
231                 return false;
232             }
233 
234             return true;
235         } else if (canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, user)) {
236             return true;
237         }
238 
239         return canSendAdHocRequests(document, KewApiConstants.ACTION_REQUEST_APPROVE_REQ, user);
240     }
241 
242     public boolean canTakeRequestedAction(Document document, String actionRequestCode, Person user) {
243         Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
244         additionalPermissionDetails.put(KimConstants.AttributeConstants.ACTION_REQUEST_CD, actionRequestCode);
245 
246         return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE,
247                 KimConstants.PermissionTemplateNames.TAKE_REQUESTED_ACTION, user.getPrincipalId(),
248                 additionalPermissionDetails, null);
249     }
250 
251     public boolean canSuperUserTakeAction(Document document, Person user) {
252         if (!document.getDocumentHeader().hasWorkflowDocument()) {
253             return false;
254         }
255 
256         String principalId = user.getPrincipalId();
257 
258         String documentTypeId = document.getDocumentHeader().getWorkflowDocument().getDocumentTypeId();
259         if (KewApiServiceLocator.getDocumentTypeService().isSuperUserForDocumentTypeId(principalId, documentTypeId)) {
260             return true;
261         }
262 
263         String documentTypeName = document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName();
264         List<RouteNodeInstance> routeNodeInstances = document.getDocumentHeader().getWorkflowDocument().getRouteNodeInstances();
265         String documentStatus =  document.getDocumentHeader().getWorkflowDocument().getStatus().getCode();
266         return KewApiServiceLocator.getDocumentTypeService().canSuperUserApproveSingleActionRequest(
267                 principalId, documentTypeName, routeNodeInstances, documentStatus);
268     }
269 
270     public boolean canSuperUserApprove(Document document, Person user) {
271         if (!document.getDocumentHeader().hasWorkflowDocument()) {
272             return false;
273         }
274 
275         String principalId = user.getPrincipalId();
276 
277         String documentTypeId = document.getDocumentHeader().getWorkflowDocument().getDocumentTypeId();
278         if (KewApiServiceLocator.getDocumentTypeService().isSuperUserForDocumentTypeId(principalId, documentTypeId)) {
279             return true;
280         }
281 
282         String documentTypeName = document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName();
283         List<RouteNodeInstance> routeNodeInstances = document.getDocumentHeader().getWorkflowDocument().getRouteNodeInstances();
284         String documentStatus =  document.getDocumentHeader().getWorkflowDocument().getStatus().getCode();
285         return KewApiServiceLocator.getDocumentTypeService().canSuperUserApproveDocument(
286                 principalId, documentTypeName, routeNodeInstances, documentStatus);
287     }
288 
289     public boolean canSuperUserDisapprove(Document document, Person user) {
290         if (!document.getDocumentHeader().hasWorkflowDocument()) {
291             return false;
292         }
293 
294         String principalId = user.getPrincipalId();
295 
296         String documentTypeId = document.getDocumentHeader().getWorkflowDocument().getDocumentTypeId();
297         if (KewApiServiceLocator.getDocumentTypeService().isSuperUserForDocumentTypeId(principalId, documentTypeId)) {
298             return true;
299         }
300 
301         String documentTypeName = document.getDocumentHeader().getWorkflowDocument().getDocumentTypeName();
302         List<RouteNodeInstance> routeNodeInstances = document.getDocumentHeader().getWorkflowDocument().getRouteNodeInstances();
303         String documentStatus =  document.getDocumentHeader().getWorkflowDocument().getStatus().getCode();
304         return KewApiServiceLocator.getDocumentTypeService().canSuperUserDisapproveDocument(
305                 principalId, documentTypeName, routeNodeInstances, documentStatus);
306     }
307 
308     @Override
309     protected void addPermissionDetails(Object dataObject, Map<String, String> attributes) {
310         super.addPermissionDetails(dataObject, attributes);
311 
312         if (dataObject instanceof Document) {
313             addStandardAttributes((Document) dataObject, attributes);
314         }
315     }
316 
317     @Override
318     protected void addRoleQualification(Object dataObject, Map<String, String> attributes) {
319         super.addRoleQualification(dataObject, attributes);
320 
321         if (dataObject instanceof Document) {
322             addStandardAttributes((Document) dataObject, attributes);
323         }
324     }
325 
326     protected void addStandardAttributes(Document document, Map<String, String> attributes) {
327         WorkflowDocument wd = document.getDocumentHeader().getWorkflowDocument();
328         attributes.put(KimConstants.AttributeConstants.DOCUMENT_NUMBER, document.getDocumentNumber());
329         attributes.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, wd.getDocumentTypeName());
330 
331         if (wd.isInitiated() || wd.isSaved()) {
332             attributes.put(KimConstants.AttributeConstants.ROUTE_NODE_NAME, PRE_ROUTING_ROUTE_NAME);
333         } else {
334             attributes.put(KimConstants.AttributeConstants.ROUTE_NODE_NAME,
335                     KRADServiceLocatorWeb.getWorkflowDocumentService().getCurrentRouteNodeNames(wd));
336         }
337 
338         attributes.put(KimConstants.AttributeConstants.ROUTE_STATUS_CODE, wd.getStatus().getCode());
339     }
340 
341     protected boolean isDocumentInitiator(Document document, Person user) {
342         WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
343 
344         return workflowDocument.getInitiatorPrincipalId().equalsIgnoreCase(user.getPrincipalId());
345     }
346 
347     protected DocumentRequestAuthorizationCache getDocumentRequestAuthorizationCache(Document document) {
348         if (this.documentRequestAuthorizationCache == null) {
349             this.documentRequestAuthorizationCache = new DocumentRequestAuthorizationCache();
350         }
351 
352         if (this.documentRequestAuthorizationCache.getWorkflowDocumentInfo() == null) {
353             this.documentRequestAuthorizationCache.createWorkflowDocumentInfo(
354                     document.getDocumentHeader().getWorkflowDocument());
355         }
356 
357         return this.documentRequestAuthorizationCache;
358     }
359 
360     /**
361      * {@inheritDoc}
362      */
363     @Override
364     public void setDocumentRequestAuthorizationCache(
365             DocumentRequestAuthorizationCache documentRequestAuthorizationCache) {
366          this.documentRequestAuthorizationCache = documentRequestAuthorizationCache;
367     }
368 }