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.apache.commons.lang.StringUtils;
19  import org.apache.commons.logging.Log;
20  import org.apache.commons.logging.LogFactory;
21  import org.kuali.rice.kew.api.WorkflowDocument;
22  import org.kuali.rice.kim.api.KimConstants;
23  import org.kuali.rice.kim.api.identity.Person;
24  import org.kuali.rice.krad.UserSessionUtils;
25  import org.kuali.rice.krad.datadictionary.AttributeSecurity;
26  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
27  import org.kuali.rice.krad.uif.field.DataField;
28  import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
29  import org.kuali.rice.krad.uif.view.View;
30  import org.kuali.rice.krad.uif.view.ViewAuthorizerBase;
31  import org.kuali.rice.krad.uif.view.ViewModel;
32  import org.kuali.rice.krad.util.GlobalVariables;
33  import org.kuali.rice.krad.util.KRADConstants;
34  import org.kuali.rice.krad.util.KRADUtils;
35  import org.kuali.rice.krad.util.ObjectUtils;
36  import org.kuali.rice.krad.web.form.DocumentFormBase;
37  
38  import java.util.HashMap;
39  import java.util.Map;
40  import java.util.Set;
41  
42  /**
43   * Implementation of {@link org.kuali.rice.krad.uif.view.ViewAuthorizer} for
44   * {@link org.kuali.rice.krad.uif.view.DocumentView} instances
45   *
46   * <p>
47   * Performs KIM permission checks for the various document actions such as save, approve, cancel
48   * </p>
49   *
50   * <p>
51   * By default delegates to the {@link DocumentAuthorizer} configured for the document in the data dictionary
52   * </p>
53   *
54   * @author Kuali Rice Team (rice.collab@kuali.org)
55   */
56  public class DocumentViewAuthorizerBase extends ViewAuthorizerBase implements DocumentAuthorizer {
57      private static final long serialVersionUID = 3800780934223224565L;
58  
59      protected static Log LOG = LogFactory.getLog(DocumentViewAuthorizerBase.class);
60  
61      public static final String PRE_ROUTING_ROUTE_NAME = "PreRoute";
62  
63      private DocumentAuthorizer documentAuthorizer;
64  
65      /**
66       * @see org.kuali.rice.krad.uif.view.ViewAuthorizer#getActionFlags(org.kuali.rice.krad.uif.view.View,
67       *      org.kuali.rice.krad.uif.view.ViewModel, org.kuali.rice.kim.api.identity.Person,
68       *      java.util.Set<java.lang.String>)
69       */
70      @Override
71      public Set<String> getActionFlags(View view, ViewModel model, Person user, Set<String> actions) {
72          Document document = ((DocumentFormBase) model).getDocument();
73  
74          if (LOG.isDebugEnabled()) {
75              LOG.debug("calling DocumentAuthorizerBase.getDocumentActionFlags for document '"
76                      + document.getDocumentNumber()
77                      + "'. user '"
78                      + user.getPrincipalName()
79                      + "'");
80          }
81  
82          if (actions.contains(KRADConstants.KUALI_ACTION_CAN_EDIT) && !canEdit(document, user)) {
83              actions.remove(KRADConstants.KUALI_ACTION_CAN_EDIT);
84          }
85  
86          if (actions.contains(KRADConstants.KUALI_ACTION_CAN_COPY) && !canCopy(document, user)) {
87              actions.remove(KRADConstants.KUALI_ACTION_CAN_COPY);
88          }
89  
90          if (actions.contains(KRADConstants.KUALI_ACTION_CAN_CLOSE) && !canClose(document, user)) {
91              actions.remove(KRADConstants.KUALI_ACTION_CAN_CLOSE);
92          }
93  
94          if (actions.contains(KRADConstants.KUALI_ACTION_CAN_RELOAD) && !canReload(document, user)) {
95              actions.remove(KRADConstants.KUALI_ACTION_CAN_RELOAD);
96          }
97  
98          if (actions.contains(KRADConstants.KUALI_ACTION_CAN_BLANKET_APPROVE) && !canBlanketApprove(document, user)) {
99              actions.remove(KRADConstants.KUALI_ACTION_CAN_BLANKET_APPROVE);
100         }
101 
102         if (actions.contains(KRADConstants.KUALI_ACTION_CAN_CANCEL) && !canCancel(document, user)) {
103             actions.remove(KRADConstants.KUALI_ACTION_CAN_CANCEL);
104         }
105 
106         if (actions.contains(KRADConstants.KUALI_ACTION_CAN_RECALL) && !canRecall(document, user)) {
107             actions.remove(KRADConstants.KUALI_ACTION_CAN_RECALL);
108         }
109 
110         if (actions.contains(KRADConstants.KUALI_ACTION_CAN_SAVE) && !canSave(document, user)) {
111             actions.remove(KRADConstants.KUALI_ACTION_CAN_SAVE);
112         }
113 
114         if (actions.contains(KRADConstants.KUALI_ACTION_CAN_ROUTE) && !canRoute(document, user)) {
115             actions.remove(KRADConstants.KUALI_ACTION_CAN_ROUTE);
116         }
117 
118         if (actions.contains(KRADConstants.KUALI_ACTION_CAN_ACKNOWLEDGE) && !canAcknowledge(document, user)) {
119             actions.remove(KRADConstants.KUALI_ACTION_CAN_ACKNOWLEDGE);
120         }
121 
122         if (actions.contains(KRADConstants.KUALI_ACTION_CAN_FYI) && !canFyi(document, user)) {
123             actions.remove(KRADConstants.KUALI_ACTION_CAN_FYI);
124         }
125 
126         if (actions.contains(KRADConstants.KUALI_ACTION_CAN_APPROVE) && !canApprove(document, user)) {
127             actions.remove(KRADConstants.KUALI_ACTION_CAN_APPROVE);
128         }
129 
130         if (actions.contains(KRADConstants.KUALI_ACTION_CAN_DISAPPROVE) && !canDisapprove(document, user)) {
131             actions.remove(KRADConstants.KUALI_ACTION_CAN_DISAPPROVE);
132         }
133 
134         if (!canSendAnyTypeAdHocRequests(document, user)) {
135             actions.remove(KRADConstants.KUALI_ACTION_CAN_ADD_ADHOC_REQUESTS);
136             actions.remove(KRADConstants.KUALI_ACTION_CAN_SEND_ADHOC_REQUESTS);
137             actions.remove(KRADConstants.KUALI_ACTION_CAN_SEND_NOTE_FYI);
138         }
139 
140         if (actions.contains(KRADConstants.KUALI_ACTION_CAN_SEND_NOTE_FYI) && !canSendNoteFyi(document, user)) {
141             actions.remove(KRADConstants.KUALI_ACTION_CAN_SEND_NOTE_FYI);
142         }
143 
144         if (actions.contains(KRADConstants.KUALI_ACTION_CAN_ANNOTATE) && !canAnnotate(document, user)) {
145             actions.remove(KRADConstants.KUALI_ACTION_CAN_ANNOTATE);
146         }
147 
148         if (actions.contains(KRADConstants.KUALI_ACTION_CAN_EDIT_DOCUMENT_OVERVIEW) && !canEditDocumentOverview(
149                 document, user)) {
150             actions.remove(KRADConstants.KUALI_ACTION_CAN_EDIT_DOCUMENT_OVERVIEW);
151         }
152 
153         if (actions.contains(KRADConstants.KUALI_ACTION_PERFORM_ROUTE_REPORT) && !canPerformRouteReport(document,
154                 user)) {
155             actions.remove(KRADConstants.KUALI_ACTION_PERFORM_ROUTE_REPORT);
156         }
157 
158         return actions;
159     }
160 
161     public final boolean canInitiate(String documentTypeName, Person user) {
162         return getDocumentAuthorizer().canInitiate(documentTypeName, user);
163     }
164 
165     public final boolean canOpen(Document document, Person user) {
166         return getDocumentAuthorizer().canOpen(document, user);
167     }
168 
169     @Override
170     public boolean canOpenView(View view, ViewModel model, Person user) {
171         DocumentFormBase documentForm = (DocumentFormBase) model;
172 
173         return super.canOpenView(view, model, user) && canOpen(documentForm.getDocument(), user);
174     }
175 
176     public boolean canEdit(Document document, Person user) {
177         return getDocumentAuthorizer().canEdit(document, user);
178     }
179 
180     @Override
181     public boolean canEditView(View view, ViewModel model, Person user) {
182         DocumentFormBase documentForm = (DocumentFormBase) model;
183 
184         return super.canEditView(view, model, user) && canEdit(documentForm.getDocument(), user);
185     }
186 
187     /**
188      * @see org.kuali.rice.krad.uif.view.ViewAuthorizer#canUnmaskField(org.kuali.rice.krad.uif.view.View, org.kuali.rice.krad.uif.view.ViewModel,
189      * org.kuali.rice.krad.uif.field.DataField, java.lang.String, org.kuali.rice.kim.api.identity.Person)
190      */
191     public boolean canUnmaskField(View view, ViewModel model, DataField field, String propertyName, Person user) {
192         // check mask authz flag is set
193         AttributeSecurity attributeSecurity = field.getDataFieldSecurity().getAttributeSecurity();
194         if (attributeSecurity == null || !attributeSecurity.isMask()) {
195             return true;
196         }
197 
198         // don't mask empty fields when user is the initiator (allows document creation when masked field exists)
199         String fieldValue = ObjectPropertyUtils.getPropertyValue(model, field.getBindingInfo().getBindingPath());
200         if (StringUtils.isBlank(fieldValue) && isInitiator(model, user)) {
201             return true;
202         }
203 
204         return super.canUnmaskField(view, model, field, propertyName, user);
205     }
206 
207     /**
208      * Checks if the user is the initiator for the current document
209      *
210      * @param model object containing the view data
211      * @param user user we are authorizing
212      * @return true if user is the initiator, false otherwise
213      */
214     protected boolean isInitiator(ViewModel model, Person user) {
215             WorkflowDocument workflowDocument = UserSessionUtils.getWorkflowDocument(GlobalVariables.getUserSession(),
216                     ((DocumentFormBase) model).getDocument().getDocumentNumber());
217             return StringUtils.equals(user.getPrincipalId(), workflowDocument.getInitiatorPrincipalId());
218     }
219 
220 
221     public boolean canAnnotate(Document document, Person user) {
222         return getDocumentAuthorizer().canAnnotate(document, user);
223     }
224 
225     public boolean canReload(Document document, Person user) {
226         return getDocumentAuthorizer().canReload(document, user);
227     }
228 
229     public boolean canClose(Document document, Person user) {
230         return getDocumentAuthorizer().canClose(document, user);
231     }
232 
233     public boolean canSave(Document document, Person user) {
234         return getDocumentAuthorizer().canSave(document, user);
235     }
236 
237     public boolean canRoute(Document document, Person user) {
238         return getDocumentAuthorizer().canRoute(document, user);
239     }
240 
241     public boolean canCancel(Document document, Person user) {
242         return getDocumentAuthorizer().canCancel(document, user);
243     }
244 
245     public boolean canRecall(Document document, Person user) {
246         return getDocumentAuthorizer().canRecall(document, user);
247     }
248 
249     public boolean canCopy(Document document, Person user) {
250         return getDocumentAuthorizer().canCopy(document, user);
251     }
252 
253     public boolean canPerformRouteReport(Document document, Person user) {
254         return getDocumentAuthorizer().canPerformRouteReport(document, user);
255     }
256 
257     public boolean canBlanketApprove(Document document, Person user) {
258         return getDocumentAuthorizer().canBlanketApprove(document, user);
259     }
260 
261     public boolean canApprove(Document document, Person user) {
262         return getDocumentAuthorizer().canApprove(document, user);
263     }
264 
265     public boolean canDisapprove(Document document, Person user) {
266         return getDocumentAuthorizer().canDisapprove(document, user);
267     }
268 
269     public boolean canSendNoteFyi(Document document, Person user) {
270         return getDocumentAuthorizer().canSendNoteFyi(document, user);
271     }
272 
273     public boolean canFyi(Document document, Person user) {
274         return getDocumentAuthorizer().canFyi(document, user);
275     }
276 
277     public boolean canAcknowledge(Document document, Person user) {
278         return getDocumentAuthorizer().canAcknowledge(document, user);
279     }
280 
281     public final boolean canReceiveAdHoc(Document document, Person user, String actionRequestCode) {
282         return getDocumentAuthorizer().canReceiveAdHoc(document, user, actionRequestCode);
283     }
284 
285     public final boolean canAddNoteAttachment(Document document, String attachmentTypeCode, Person user) {
286         return getDocumentAuthorizer().canAddNoteAttachment(document, attachmentTypeCode, user);
287     }
288 
289     public final boolean canDeleteNoteAttachment(Document document, String attachmentTypeCode,
290             String authorUniversalIdentifier, Person user) {
291         return getDocumentAuthorizer().canDeleteNoteAttachment(document, attachmentTypeCode, authorUniversalIdentifier,
292                 user);
293     }
294 
295     public final boolean canViewNoteAttachment(Document document, String attachmentTypeCode,
296             String authorUniversalIdentifier, Person user) {
297         return getDocumentAuthorizer().canViewNoteAttachment(document, attachmentTypeCode, authorUniversalIdentifier,
298                 user);
299     }
300 
301     public final boolean canSendAdHocRequests(Document document, String actionRequestCd, Person user) {
302         return getDocumentAuthorizer().canSendAdHocRequests(document, actionRequestCd, user);
303     }
304 
305     public boolean canEditDocumentOverview(Document document, Person user) {
306         return getDocumentAuthorizer().canEditDocumentOverview(document, user);
307     }
308 
309     public boolean canSendAnyTypeAdHocRequests(Document document, Person user) {
310         return getDocumentAuthorizer().canSendAnyTypeAdHocRequests(document, user);
311     }
312 
313     public boolean canTakeRequestedAction(Document document, String actionRequestCode, Person user) {
314         return getDocumentAuthorizer().canTakeRequestedAction(document, actionRequestCode, user);
315     }
316 
317     @Override
318     protected void addPermissionDetails(Object dataObject, Map<String, String> attributes) {
319         super.addPermissionDetails(dataObject, attributes);
320 
321         if (dataObject instanceof Document) {
322             addStandardAttributes((Document) dataObject, attributes);
323         }
324     }
325 
326     @Override
327     protected void addRoleQualification(Object dataObject, Map<String, String> attributes) {
328         super.addRoleQualification(dataObject, attributes);
329 
330         if (dataObject instanceof Document) {
331             addStandardAttributes((Document) dataObject, attributes);
332         }
333     }
334 
335     protected void addStandardAttributes(Document document, Map<String, String> attributes) {
336         WorkflowDocument wd = document.getDocumentHeader().getWorkflowDocument();
337         attributes.put(KimConstants.AttributeConstants.DOCUMENT_NUMBER, document.getDocumentNumber());
338         attributes.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, wd.getDocumentTypeName());
339 
340         if (wd.isInitiated() || wd.isSaved()) {
341             attributes.put(KimConstants.AttributeConstants.ROUTE_NODE_NAME, PRE_ROUTING_ROUTE_NAME);
342         } else {
343             attributes.put(KimConstants.AttributeConstants.ROUTE_NODE_NAME,
344                     KRADServiceLocatorWeb.getWorkflowDocumentService().getCurrentRouteNodeNames(wd));
345         }
346 
347         attributes.put(KimConstants.AttributeConstants.ROUTE_STATUS_CODE, wd.getStatus().getCode());
348     }
349 
350     protected boolean isDocumentInitiator(Document document, Person user) {
351         WorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
352 
353         return workflowDocument.getInitiatorPrincipalId().equalsIgnoreCase(user.getPrincipalId());
354     }
355 
356     public DocumentAuthorizer getDocumentAuthorizer() {
357         return documentAuthorizer;
358     }
359 
360     public void setDocumentAuthorizer(DocumentAuthorizer documentAuthorizer) {
361         this.documentAuthorizer = documentAuthorizer;
362     }
363 
364     public void setDocumentAuthorizerClass(Class<? extends DocumentAuthorizer> documentAuthorizerClass) {
365         this.documentAuthorizer = ObjectUtils.newInstance(documentAuthorizerClass);
366     }
367 }