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.krad.document; 017 018import org.kuali.rice.kew.api.KewApiConstants; 019import org.kuali.rice.kew.api.KewApiServiceLocator; 020import org.kuali.rice.kew.api.WorkflowDocument; 021import org.kuali.rice.kew.api.action.ActionType; 022import org.kuali.rice.kew.api.doctype.ProcessDefinition; 023import org.kuali.rice.kew.api.doctype.RoutePath; 024import org.kuali.rice.kew.api.document.node.RouteNodeInstance; 025import org.kuali.rice.kim.api.KimConstants; 026import org.kuali.rice.kim.api.identity.Person; 027import org.kuali.rice.krad.bo.DataObjectAuthorizerBase; 028import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 029import org.kuali.rice.krad.util.KRADConstants; 030 031import java.util.Collections; 032import java.util.HashMap; 033import java.util.List; 034import java.util.Map; 035 036/** 037 * Default implementation for {@link DocumentAuthorizer} that perform KIM permission checks to authorize the actions 038 * 039 * @author Kuali Rice Team (rice.collab@kuali.org) 040 */ 041public class DocumentAuthorizerBase extends DataObjectAuthorizerBase implements DocumentAuthorizer { 042 private static final long serialVersionUID = -5354518767379472681L; 043 044 private DocumentRequestAuthorizationCache documentRequestAuthorizationCache; 045 046 public static final String PRE_ROUTING_ROUTE_NAME = "PreRoute"; 047 048 public final boolean canInitiate(String documentTypeName, Person user) { 049 String nameSpaceCode = KRADConstants.KUALI_RICE_SYSTEM_NAMESPACE; 050 Map<String, String> permissionDetails = new HashMap<String, String>(); 051 permissionDetails.put(KimConstants.AttributeConstants.DOCUMENT_TYPE_NAME, documentTypeName); 052 053 return getPermissionService().isAuthorizedByTemplate(user.getPrincipalId(), nameSpaceCode, 054 KimConstants.PermissionTemplateNames.INITIATE_DOCUMENT, permissionDetails, 055 Collections.<String, String>emptyMap()); 056 } 057 058 public boolean canOpen(Document document, Person user) { 059 return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE, 060 KimConstants.PermissionTemplateNames.OPEN_DOCUMENT, user.getPrincipalId()); 061 } 062 063 public boolean canEdit(Document document, Person user) { 064 return isAuthorizedByTemplate(document, KRADConstants.KNS_NAMESPACE, 065 KimConstants.PermissionTemplateNames.EDIT_DOCUMENT, user.getPrincipalId()); 066 } 067 068 public boolean canAnnotate(Document document, Person user) { 069 return canAddNoteAttachment(document, null, user); 070 } 071 072 public boolean canReload(Document document, Person user) { 073 return true; 074 } 075 076 public boolean canClose(Document document, Person user) { 077 return false; 078 } 079 080 public boolean canSave(Document document, Person user) { 081 return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE, 082 KimConstants.PermissionTemplateNames.SAVE_DOCUMENT, user.getPrincipalId()); 083 } 084 085 public boolean canRoute(Document document, Person user) { 086 return isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE, 087 KimConstants.PermissionTemplateNames.ROUTE_DOCUMENT, user.getPrincipalId()); 088 } 089 090 public boolean canCancel(Document document, Person user) { 091 boolean isCompletionRequested = document.getDocumentHeader().getWorkflowDocument().isCompletionRequested(); 092 093 return isCompletionRequested || isAuthorizedByTemplate(document, KRADConstants.KUALI_RICE_WORKFLOW_NAMESPACE, 094 KimConstants.PermissionTemplateNames.CANCEL_DOCUMENT, user.getPrincipalId()); 095 } 096 097 public boolean canRecall(Document document, Person user) { 098 return getDocumentRequestAuthorizationCache(document).getWorkflowDocumentInfo().isValidAction( 099 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}