001/** 002 * Copyright 2005-2018 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 */ 016package org.kuali.rice.kns.document.authorization; 017 018import org.apache.commons.logging.Log; 019import org.apache.commons.logging.LogFactory; 020import org.kuali.rice.kew.api.KewApiConstants; 021import org.kuali.rice.kew.api.KewApiServiceLocator; 022import org.kuali.rice.kew.api.WorkflowDocument; 023import org.kuali.rice.kew.api.action.ActionType; 024import org.kuali.rice.kew.api.doctype.ProcessDefinition; 025import org.kuali.rice.kew.api.doctype.RoutePath; 026import org.kuali.rice.kew.api.document.node.RouteNodeInstance; 027import org.kuali.rice.kim.api.KimConstants; 028import org.kuali.rice.kim.api.identity.Person; 029import org.kuali.rice.kns.bo.authorization.BusinessObjectAuthorizerBase; 030import org.kuali.rice.krad.document.Document; 031import org.kuali.rice.krad.document.DocumentRequestAuthorizationCache; 032import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 033import org.kuali.rice.krad.util.KRADConstants; 034 035import java.util.Collections; 036import java.util.HashMap; 037import java.util.List; 038import java.util.Map; 039import java.util.Set; 040 041/** 042 * DocumentAuthorizer containing common, reusable document-level authorization 043 * code. 044 * 045 * @deprecated Use {@link org.kuali.rice.krad.document.DocumentAuthorizerBase}. 046 */ 047@Deprecated 048public class DocumentAuthorizerBase extends BusinessObjectAuthorizerBase implements DocumentAuthorizer { 049 protected static Log LOG = LogFactory.getLog(DocumentAuthorizerBase.class); 050 051 public static final String PRE_ROUTING_ROUTE_NAME = "PreRoute"; 052 public static final String EDIT_MODE_DEFAULT_TRUE_VALUE = "TRUE"; 053 public static final String USER_SESSION_METHOD_TO_CALL_OBJECT_KEY = "METHOD_TO_CALL_KEYS_METHOD_OBJECT_KEY"; 054 public static final String USER_SESSION_METHOD_TO_CALL_COMPLETE_OBJECT_KEY = 055 "METHOD_TO_CALL_KEYS_COMPLETE_OBJECT_KEY"; 056 public static final String USER_SESSION_METHOD_TO_CALL_COMPLETE_MARKER = "_EXITING"; 057 058 /** 059 * Individual document families will need to reimplement this according to 060 * their own needs; this version should be good enough to be usable during 061 * initial development. 062 */ 063 public Set<String> getDocumentActions(Document document, Person user, Set<String> documentActions) { 064 if (LOG.isDebugEnabled()) { 065 LOG.debug("calling DocumentAuthorizerBase.getDocumentActionFlags for document '" 066 + document.getDocumentNumber() 067 + "'. user '" 068 + user.getPrincipalName() 069 + "'"); 070 } 071 if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_EDIT) && !canEdit(document, user)) { 072 documentActions.remove(KRADConstants.KUALI_ACTION_CAN_EDIT); 073 } 074 075 if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_COPY) && !canCopy(document, user)) { 076 documentActions.remove(KRADConstants.KUALI_ACTION_CAN_COPY); 077 } 078 079 if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_CLOSE) && !canClose(document, user)) { 080 documentActions.remove(KRADConstants.KUALI_ACTION_CAN_CLOSE); 081 } 082 083 if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_RELOAD) && !canReload(document, user)) { 084 documentActions.remove(KRADConstants.KUALI_ACTION_CAN_RELOAD); 085 } 086 087 if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_BLANKET_APPROVE) && !canBlanketApprove(document, user)) { 088 documentActions.remove(KRADConstants.KUALI_ACTION_CAN_BLANKET_APPROVE); 089 } 090 091 if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_CANCEL) && !canCancel(document, user)) { 092 documentActions.remove(KRADConstants.KUALI_ACTION_CAN_CANCEL); 093 } 094 095 if (documentActions.contains(KRADConstants.KUALI_ACTION_CAN_RECALL) && !canRecall(document, user)) { 096 documentActions.remove(KRADConstants.KUALI_ACTION_CAN_RECALL); 097 } 098 099 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}