View Javadoc

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