View Javadoc

1   /*
2    * Copyright 2007-2008 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.kns.service.impl;
17  
18  import java.util.Collection;
19  import java.util.HashMap;
20  import java.util.Iterator;
21  import java.util.List;
22  import java.util.Map;
23  
24  import org.apache.commons.beanutils.PropertyUtils;
25  import org.apache.commons.lang.StringUtils;
26  import org.kuali.rice.kim.bo.Person;
27  import org.kuali.rice.kim.bo.impl.KimAttributes;
28  import org.kuali.rice.kim.bo.types.dto.AttributeSet;
29  import org.kuali.rice.kim.service.IdentityManagementService;
30  import org.kuali.rice.kim.service.KIMServiceLocator;
31  import org.kuali.rice.kim.util.KimCommonUtils;
32  import org.kuali.rice.kim.util.KimConstants;
33  import org.kuali.rice.kns.authorization.BusinessObjectAuthorizer;
34  import org.kuali.rice.kns.authorization.BusinessObjectRestrictions;
35  import org.kuali.rice.kns.authorization.BusinessObjectRestrictionsBase;
36  import org.kuali.rice.kns.authorization.InquiryOrMaintenanceDocumentAuthorizer;
37  import org.kuali.rice.kns.authorization.InquiryOrMaintenanceDocumentPresentationController;
38  import org.kuali.rice.kns.authorization.InquiryOrMaintenanceDocumentRestrictions;
39  import org.kuali.rice.kns.authorization.InquiryOrMaintenanceDocumentRestrictionsBase;
40  import org.kuali.rice.kns.bo.BusinessObject;
41  import org.kuali.rice.kns.datadictionary.AttributeDefinition;
42  import org.kuali.rice.kns.datadictionary.AttributeSecurity;
43  import org.kuali.rice.kns.datadictionary.BusinessObjectEntry;
44  import org.kuali.rice.kns.datadictionary.FieldDefinition;
45  import org.kuali.rice.kns.datadictionary.InquiryCollectionDefinition;
46  import org.kuali.rice.kns.datadictionary.InquirySectionDefinition;
47  import org.kuali.rice.kns.datadictionary.MaintainableCollectionDefinition;
48  import org.kuali.rice.kns.datadictionary.MaintainableItemDefinition;
49  import org.kuali.rice.kns.datadictionary.MaintainableSectionDefinition;
50  import org.kuali.rice.kns.datadictionary.MaintenanceDocumentEntry;
51  import org.kuali.rice.kns.document.Document;
52  import org.kuali.rice.kns.document.MaintenanceDocument;
53  import org.kuali.rice.kns.document.authorization.DocumentAuthorizer;
54  import org.kuali.rice.kns.document.authorization.DocumentPresentationController;
55  import org.kuali.rice.kns.document.authorization.MaintenanceDocumentAuthorizer;
56  import org.kuali.rice.kns.document.authorization.MaintenanceDocumentPresentationController;
57  import org.kuali.rice.kns.document.authorization.MaintenanceDocumentRestrictions;
58  import org.kuali.rice.kns.document.authorization.MaintenanceDocumentRestrictionsBase;
59  import org.kuali.rice.kns.inquiry.InquiryAuthorizer;
60  import org.kuali.rice.kns.inquiry.InquiryPresentationController;
61  import org.kuali.rice.kns.inquiry.InquiryRestrictions;
62  import org.kuali.rice.kns.service.BusinessObjectAuthorizationService;
63  import org.kuali.rice.kns.service.BusinessObjectDictionaryService;
64  import org.kuali.rice.kns.service.DataDictionaryService;
65  import org.kuali.rice.kns.service.DocumentHelperService;
66  import org.kuali.rice.kns.service.KNSServiceLocator;
67  import org.kuali.rice.kns.service.KualiConfigurationService;
68  import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
69  import org.kuali.rice.kns.util.KNSConstants;
70  import org.kuali.rice.kns.util.ObjectUtils;
71  
72  public class BusinessObjectAuthorizationServiceImpl implements
73  		BusinessObjectAuthorizationService {
74  	private DataDictionaryService dataDictionaryService;
75  	private IdentityManagementService identityManagementService;
76  	private BusinessObjectDictionaryService businessObjectDictionaryService;
77  	private DocumentHelperService documentHelperService;
78  	private MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService;
79  	private KualiConfigurationService kualiConfigurationService;
80  	
81  	public BusinessObjectRestrictions getLookupResultRestrictions(
82  			BusinessObject businessObject, Person user) {
83  		BusinessObjectRestrictions businessObjectRestrictions = new BusinessObjectRestrictionsBase();
84  		considerBusinessObjectFieldUnmaskAuthorization(businessObject, user,
85  				businessObjectRestrictions, "", null);
86  		return businessObjectRestrictions;
87  	}
88  
89  	public InquiryRestrictions getInquiryRestrictions(
90  			BusinessObject businessObject, Person user) {
91  		InquiryRestrictions inquiryRestrictions = new InquiryOrMaintenanceDocumentRestrictionsBase();
92  		BusinessObjectEntry businessObjectEntry = getDataDictionaryService()
93  				.getDataDictionary().getBusinessObjectEntry(
94  						businessObject.getClass().getName());
95  		InquiryPresentationController inquiryPresentationController = getBusinessObjectDictionaryService()
96  				.getInquiryPresentationController(businessObject.getClass());
97  		InquiryAuthorizer inquiryAuthorizer = getBusinessObjectDictionaryService()
98  				.getInquiryAuthorizer(businessObject.getClass());
99  		considerBusinessObjectFieldUnmaskAuthorization(businessObject, user,
100 				inquiryRestrictions, "", null);
101 		considerBusinessObjectFieldViewAuthorization(businessObjectEntry,
102 				businessObject, null, user, inquiryAuthorizer, inquiryRestrictions,
103 				"");
104 		considerInquiryOrMaintenanceDocumentPresentationController(
105 				inquiryPresentationController, businessObject,
106 				inquiryRestrictions);
107 		considerInquiryOrMaintenanceDocumentAuthorizer(inquiryAuthorizer,
108 				businessObject, user, inquiryRestrictions);
109 		for (InquirySectionDefinition inquirySectionDefinition : businessObjectEntry.getInquiryDefinition().getInquirySections()) {
110 			if (inquirySectionDefinition.getInquiryCollections() != null) {
111 				addInquirableItemRestrictions(inquirySectionDefinition.getInquiryCollections().values(), inquiryAuthorizer, 
112 						inquiryRestrictions, businessObject, businessObject, "", user);
113 			}
114 			// Collections may also be stored in the inquiry fields, so we need to parse through that
115 			List<FieldDefinition> inquiryFields = inquirySectionDefinition.getInquiryFields();
116 			if (inquiryFields != null) {
117 				for (FieldDefinition fieldDefinition : inquiryFields) {
118 					addInquirableItemRestrictions(inquiryFields, inquiryAuthorizer, 
119 							inquiryRestrictions, businessObject, businessObject, "", user);
120 				}
121 			}
122 		}
123 		
124 		return inquiryRestrictions;
125 	}
126 
127 	public MaintenanceDocumentRestrictions getMaintenanceDocumentRestrictions(
128 			MaintenanceDocument maintenanceDocument, Person user) {
129 
130 		MaintenanceDocumentRestrictions maintenanceDocumentRestrictions = new MaintenanceDocumentRestrictionsBase();
131 		BusinessObjectEntry businessObjectEntry = getDataDictionaryService()
132 				.getDataDictionary().getBusinessObjectEntry(
133 						maintenanceDocument.getNewMaintainableObject()
134 								.getBusinessObject().getClass().getName());
135 		MaintenanceDocumentPresentationController maintenanceDocumentPresentationController = (MaintenanceDocumentPresentationController) getDocumentHelperService()
136 				.getDocumentPresentationController(maintenanceDocument);
137 		MaintenanceDocumentAuthorizer maintenanceDocumentAuthorizer = (MaintenanceDocumentAuthorizer) getDocumentHelperService()
138 				.getDocumentAuthorizer(maintenanceDocument);
139 		considerBusinessObjectFieldUnmaskAuthorization(maintenanceDocument
140 				.getNewMaintainableObject().getBusinessObject(), user,
141 				maintenanceDocumentRestrictions, "", maintenanceDocument );
142 		considerBusinessObjectFieldViewAuthorization(businessObjectEntry,
143 				maintenanceDocument.getNewMaintainableObject().getBusinessObject(),
144 				null, user, maintenanceDocumentAuthorizer,
145 				maintenanceDocumentRestrictions, "");
146 		considerBusinessObjectFieldModifyAuthorization(businessObjectEntry,
147 				maintenanceDocument.getNewMaintainableObject().getBusinessObject(),
148 				null, user, maintenanceDocumentAuthorizer,
149 				maintenanceDocumentRestrictions, "");
150 		considerCustomButtonFieldAuthorization(businessObjectEntry,
151 				maintenanceDocument.getNewMaintainableObject().getBusinessObject(),
152 				null, user, maintenanceDocumentAuthorizer,
153 				maintenanceDocumentRestrictions, "");
154 		considerInquiryOrMaintenanceDocumentPresentationController(
155 				maintenanceDocumentPresentationController, maintenanceDocument,
156 				maintenanceDocumentRestrictions);
157 		considerInquiryOrMaintenanceDocumentAuthorizer(
158 				maintenanceDocumentAuthorizer, maintenanceDocument, user,
159 				maintenanceDocumentRestrictions);
160 		considerMaintenanceDocumentPresentationController(
161 				maintenanceDocumentPresentationController, maintenanceDocument,
162 				maintenanceDocumentRestrictions);
163 		considerMaintenanceDocumentAuthorizer(maintenanceDocumentAuthorizer,
164 				maintenanceDocument, user, maintenanceDocumentRestrictions);
165 		
166 		MaintenanceDocumentEntry maintenanceDocumentEntry = getMaintenanceDocumentDictionaryService().getMaintenanceDocumentEntry(maintenanceDocument
167 				.getDocumentHeader().getWorkflowDocument().getDocumentType());
168 		for (MaintainableSectionDefinition maintainableSectionDefinition : maintenanceDocumentEntry.getMaintainableSections()) {
169 			addMaintainableItemRestrictions(maintainableSectionDefinition.getMaintainableItems(), maintenanceDocumentAuthorizer, maintenanceDocumentRestrictions,
170 					maintenanceDocument, maintenanceDocument.getNewMaintainableObject().getBusinessObject(), "", user);
171 		}
172 		return maintenanceDocumentRestrictions;
173 	}
174 
175 	protected void considerBusinessObjectFieldUnmaskAuthorization(
176 			BusinessObject businessObject, Person user,
177 			BusinessObjectRestrictions businessObjectRestrictions,
178 			String propertyPrefix, Document document ) {
179 		BusinessObjectEntry businessObjectEntry = getDataDictionaryService()
180 				.getDataDictionary().getBusinessObjectEntry(
181 						businessObject.getClass().getName());
182 		for (String attributeName : businessObjectEntry.getAttributeNames()) {
183 			AttributeDefinition attributeDefinition = businessObjectEntry
184 					.getAttributeDefinition(attributeName);
185 			if (attributeDefinition.getAttributeSecurity() != null) {
186 				if (attributeDefinition.getAttributeSecurity().isMask()
187 						&& !canFullyUnmaskField(user,
188 								businessObject.getClass(), attributeName, document)) {
189 					businessObjectRestrictions.addFullyMaskedField(
190 							propertyPrefix + attributeName, attributeDefinition
191 									.getAttributeSecurity().getMaskFormatter());
192 				}
193 				if (attributeDefinition.getAttributeSecurity().isPartialMask()
194 						&& !canPartiallyUnmaskField(user, businessObject
195 								.getClass(), attributeName, document)) {
196 					businessObjectRestrictions.addPartiallyMaskedField(
197 							propertyPrefix + attributeName, attributeDefinition
198 									.getAttributeSecurity()
199 									.getPartialMaskFormatter());
200 				}
201 			}
202 		}
203 	}
204 
205 	/**
206 	 * @param businessObjectEntry if collectionItemBusinessObject is not null, then it is the DD entry for collectionItemBusinessObject.
207 	 * Otherwise, it is the entry for primaryBusinessObject
208 	 * @param primaryBusinessObject the top-level BO that is being inquiried or maintained
209 	 * @param collectionItemBusinessObject an element of a collection under the primaryBusinessObject that we are evaluating view auths for
210 	 * @param user the logged in user
211 	 * @param businessObjectAuthorizer
212 	 * @param inquiryOrMaintenanceDocumentRestrictions
213 	 * @param propertyPrefix
214 	 */
215 	protected void considerBusinessObjectFieldViewAuthorization(
216 			BusinessObjectEntry businessObjectEntry,
217 			BusinessObject primaryBusinessObject,
218 			BusinessObject collectionItemBusinessObject,
219 			Person user,
220 			BusinessObjectAuthorizer businessObjectAuthorizer,
221 			InquiryOrMaintenanceDocumentRestrictions inquiryOrMaintenanceDocumentRestrictions,
222 			String propertyPrefix) {
223 		for (String attributeName : businessObjectEntry.getAttributeNames()) {
224 			AttributeDefinition attributeDefinition = businessObjectEntry
225 					.getAttributeDefinition(attributeName);
226 			if (attributeDefinition.getAttributeSecurity() != null) {
227 				if (attributeDefinition.getAttributeSecurity().isHide()) {
228 					AttributeSet collectionItemPermissionDetails = new AttributeSet();
229 					AttributeSet collectionItemRoleQualifications = null;
230 					if (ObjectUtils.isNotNull(collectionItemBusinessObject)) {
231 						collectionItemPermissionDetails.putAll(getFieldPermissionDetails(collectionItemBusinessObject, attributeName));
232 						collectionItemPermissionDetails.putAll(businessObjectAuthorizer.
233 								getCollectionItemPermissionDetails(collectionItemBusinessObject));
234 						collectionItemRoleQualifications = new AttributeSet(businessObjectAuthorizer.
235 								getCollectionItemRoleQualifications(collectionItemBusinessObject));
236 					}
237 					else {
238 						collectionItemPermissionDetails.putAll(getFieldPermissionDetails(primaryBusinessObject, attributeName));
239 					}
240 					if (!businessObjectAuthorizer
241 							.isAuthorizedByTemplate(
242 									primaryBusinessObject,
243 									KNSConstants.KNS_NAMESPACE,
244 									KimConstants.PermissionTemplateNames.VIEW_FIELD,
245 									user.getPrincipalId(),
246 									collectionItemPermissionDetails,
247 									collectionItemRoleQualifications)) {
248 						inquiryOrMaintenanceDocumentRestrictions
249 								.addHiddenField(propertyPrefix + attributeName);
250 					}
251 				}
252 			}
253 		}
254 	}
255 
256 	/**
257 	 * @param businessObjectEntry if collectionItemBusinessObject is not null, then it is the DD entry for collectionItemBusinessObject.
258 	 * Otherwise, it is the entry for primaryBusinessObject
259 	 * @param primaryBusinessObject the top-level BO that is being inquiried or maintained
260 	 * @param collectionItemBusinessObject an element of a collection under the primaryBusinessObject that we are evaluating view auths for
261 	 * @param user the logged in user
262 	 * @param businessObjectAuthorizer
263 	 * @param inquiryOrMaintenanceDocumentRestrictions
264 	 * @param propertyPrefix
265 	 */
266 	protected void considerBusinessObjectFieldModifyAuthorization(
267 			BusinessObjectEntry businessObjectEntry,
268 			BusinessObject primaryBusinessObject,
269 			BusinessObject collectionItemBusinessObject, Person user,
270 			BusinessObjectAuthorizer businessObjectAuthorizer,
271 			MaintenanceDocumentRestrictions maintenanceDocumentRestrictions,
272 			String propertyPrefix) {
273 		for (String attributeName : businessObjectEntry.getAttributeNames()) {
274 			AttributeDefinition attributeDefinition = businessObjectEntry
275 					.getAttributeDefinition(attributeName);
276 			if (attributeDefinition.getAttributeSecurity() != null) {
277 				AttributeSet collectionItemPermissionDetails = new AttributeSet();
278 				AttributeSet collectionItemRoleQualifications = null;
279 				if (ObjectUtils.isNotNull(collectionItemBusinessObject)) {
280 					collectionItemPermissionDetails.putAll(getFieldPermissionDetails(collectionItemBusinessObject, attributeName));
281 					collectionItemPermissionDetails.putAll(businessObjectAuthorizer.
282 							getCollectionItemPermissionDetails(collectionItemBusinessObject));
283 					collectionItemRoleQualifications = new AttributeSet(businessObjectAuthorizer.
284 							getCollectionItemRoleQualifications(collectionItemBusinessObject));
285 				}
286 				else {
287 					collectionItemPermissionDetails.putAll(getFieldPermissionDetails(primaryBusinessObject, attributeName));
288 				}
289 				if (attributeDefinition.getAttributeSecurity().isReadOnly()) {
290 					if (!businessObjectAuthorizer
291 								.isAuthorizedByTemplate(
292 										primaryBusinessObject,
293 										KNSConstants.KNS_NAMESPACE,
294 										KimConstants.PermissionTemplateNames.MODIFY_FIELD,
295 										user.getPrincipalId(),
296 										collectionItemPermissionDetails,
297 										collectionItemRoleQualifications)) {
298 						maintenanceDocumentRestrictions
299 								.addReadOnlyField(propertyPrefix + attributeName);
300 					}
301 				}
302 			}
303 		}
304 	}
305 	
306 	/**
307 	 * @param businessObjectEntry if collectionItemBusinessObject is not null, then it is the DD entry for collectionItemBusinessObject.
308 	 * Otherwise, it is the entry for primaryBusinessObject
309 	 * @param primaryBusinessObject the top-level BO that is being inquiried or maintained
310 	 * @param collectionItemBusinessObject an element of a collection under the primaryBusinessObject that we are evaluating view auths for
311 	 * @param user the logged in user
312 	 * @param businessObjectAuthorizer
313 	 * @param inquiryOrMaintenanceDocumentRestrictions
314 	 * @param propertyPrefix
315 	 */
316 	protected void considerCustomButtonFieldAuthorization(
317 			BusinessObjectEntry businessObjectEntry,
318 			BusinessObject primaryBusinessObject,
319 			BusinessObject collectionItemBusinessObject,
320 			Person user,
321 			BusinessObjectAuthorizer businessObjectAuthorizer,
322 			MaintenanceDocumentRestrictions maintenanceDocumentRestrictions,
323 			String propertyPrefix) {
324 		for (String attributeName : businessObjectEntry.getAttributeNames()) {
325 			AttributeDefinition attributeDefinition = businessObjectEntry
326 					.getAttributeDefinition(attributeName);
327 			if (attributeDefinition.getControl().isButton()) {
328 				AttributeSet collectionItemPermissionDetails = new AttributeSet();
329 				AttributeSet collectionItemRoleQualifications = null;
330 				if (ObjectUtils.isNotNull(collectionItemBusinessObject)) {
331 					collectionItemPermissionDetails.putAll(getButtonFieldPermissionDetails(collectionItemBusinessObject, attributeName));
332 					collectionItemPermissionDetails.putAll(businessObjectAuthorizer.
333 							getCollectionItemPermissionDetails(collectionItemBusinessObject));
334 					collectionItemRoleQualifications = new AttributeSet(businessObjectAuthorizer.
335 							getCollectionItemRoleQualifications(collectionItemBusinessObject));
336 				}
337 				else {
338 					getButtonFieldPermissionDetails(primaryBusinessObject, attributeName);
339 				}
340 				
341 				if (!businessObjectAuthorizer
342 						.isAuthorizedByTemplate(
343 								primaryBusinessObject,
344 								KNSConstants.KNS_NAMESPACE,
345 								KimConstants.PermissionTemplateNames.PERFORM_CUSTOM_MAINTENANCE_DOCUMENT_FUNCTION,
346 								user.getPrincipalId(),
347 								collectionItemPermissionDetails,
348 								collectionItemRoleQualifications)) {
349 					maintenanceDocumentRestrictions
350 							.addHiddenField(propertyPrefix + attributeName);
351 				}
352 			}
353 		}
354 	}
355 
356 	protected void considerInquiryOrMaintenanceDocumentPresentationController(
357 			InquiryOrMaintenanceDocumentPresentationController businessObjectPresentationController,
358 			BusinessObject businessObject,
359 			InquiryOrMaintenanceDocumentRestrictions inquiryOrMaintenanceDocumentRestrictions) {
360 		for (String attributeName : businessObjectPresentationController
361 				.getConditionallyHiddenPropertyNames(businessObject)) {
362 			inquiryOrMaintenanceDocumentRestrictions
363 					.addHiddenField(attributeName);
364 		}
365 		for (String sectionId : businessObjectPresentationController
366 				.getConditionallyHiddenSectionIds(businessObject)) {
367 			inquiryOrMaintenanceDocumentRestrictions
368 					.addHiddenSectionId(sectionId);
369 		}
370 	}
371 
372 	protected void considerInquiryOrMaintenanceDocumentAuthorizer(
373 			InquiryOrMaintenanceDocumentAuthorizer authorizer,
374 			BusinessObject businessObject, Person user,
375 			InquiryOrMaintenanceDocumentRestrictions restrictions) {
376 		for (String sectionId : authorizer
377 				.getSecurePotentiallyHiddenSectionIds()) {
378 			Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
379 			additionalPermissionDetails
380 					.put(KimAttributes.SECTION_ID, sectionId);
381 			if (!authorizer.isAuthorizedByTemplate(businessObject,
382 					KNSConstants.KNS_NAMESPACE,
383 					KimConstants.PermissionTemplateNames.VIEW_SECTION, user
384 							.getPrincipalId(), additionalPermissionDetails,
385 					null)) {
386 				restrictions.addHiddenSectionId(sectionId);
387 			}
388 		}
389 	}
390 
391 	protected void considerMaintenanceDocumentPresentationController(
392 			MaintenanceDocumentPresentationController presentationController,
393 			MaintenanceDocument document,
394 			MaintenanceDocumentRestrictions restrictions) {
395 		for (String attributeName : presentationController
396 				.getConditionallyReadOnlyPropertyNames(document)) {
397 			restrictions.addReadOnlyField(attributeName);
398 		}
399 		for (String sectionId : presentationController
400 				.getConditionallyReadOnlySectionIds(document)) {
401 			restrictions.addReadOnlySectionId(sectionId);
402 		}
403 	}
404 
405 	protected void considerMaintenanceDocumentAuthorizer(
406 			MaintenanceDocumentAuthorizer authorizer,
407 			MaintenanceDocument document, Person user,
408 			MaintenanceDocumentRestrictions restrictions) {
409 		for (String sectionId : authorizer
410 				.getSecurePotentiallyReadOnlySectionIds()) {
411 			Map<String, String> additionalPermissionDetails = new HashMap<String, String>();
412 			additionalPermissionDetails
413 					.put(KimAttributes.SECTION_ID, sectionId);
414 			if (!authorizer.isAuthorizedByTemplate(document,
415 					KNSConstants.KNS_NAMESPACE,
416 					KimConstants.PermissionTemplateNames.MODIFY_SECTION, user
417 							.getPrincipalId(), additionalPermissionDetails,
418 					null)) {
419 				restrictions.addReadOnlySectionId(sectionId);
420 			}
421 		}
422 	}
423 
424 	@SuppressWarnings("unchecked")
425 	protected void addInquirableItemRestrictions(Collection sectionDefinitions,
426 			InquiryAuthorizer authorizer, InquiryRestrictions restrictions,
427 			BusinessObject primaryBusinessObject,
428 			BusinessObject businessObject, String propertyPrefix, Person user) {
429 		for (Object inquirableItemDefinition : sectionDefinitions) {
430 			if (inquirableItemDefinition instanceof InquiryCollectionDefinition) {
431 				InquiryCollectionDefinition inquiryCollectionDefinition = (InquiryCollectionDefinition) inquirableItemDefinition;
432 				BusinessObjectEntry collectionBusinessObjectEntry = getDataDictionaryService()
433 						.getDataDictionary().getBusinessObjectEntry(
434 								inquiryCollectionDefinition.getBusinessObjectClass().getName());
435 
436 				try {
437 					Collection<BusinessObject> collection = (Collection<BusinessObject>) PropertyUtils
438 							.getProperty(businessObject,
439 									inquiryCollectionDefinition.getName());
440 					int i = 0;
441 					for (Iterator<BusinessObject> iterator = collection.iterator(); iterator
442 							.hasNext();) {
443 						String newPropertyPrefix = propertyPrefix + inquiryCollectionDefinition.getName() + "[" + i + "].";
444 						BusinessObject collectionItemBusinessObject = iterator.next();
445 						considerBusinessObjectFieldUnmaskAuthorization(
446 								collectionItemBusinessObject, user, restrictions,
447 								newPropertyPrefix, null);
448 						considerBusinessObjectFieldViewAuthorization(
449 								collectionBusinessObjectEntry, primaryBusinessObject, collectionItemBusinessObject,
450 								user, authorizer, restrictions, newPropertyPrefix);
451 						addInquirableItemRestrictions(
452 								inquiryCollectionDefinition
453 										.getInquiryCollections(),
454 								authorizer,
455 								restrictions,
456 								primaryBusinessObject,
457 								collectionItemBusinessObject,
458 								newPropertyPrefix,
459 								user);
460 						i++;
461 					}
462 				} catch (Exception e) {
463 					throw new RuntimeException(
464 							"Unable to resolve collection property: "
465 									+ businessObject.getClass() + ":"
466 									+ inquiryCollectionDefinition.getName(), e);
467 				}
468 			}
469 		}
470 	}
471 
472 	@SuppressWarnings("unchecked")
473 	protected void addMaintainableItemRestrictions(List<? extends MaintainableItemDefinition> itemDefinitions,
474 			MaintenanceDocumentAuthorizer authorizer,
475 			MaintenanceDocumentRestrictions restrictions,
476 			MaintenanceDocument maintenanceDocument,
477 			BusinessObject businessObject, String propertyPrefix, Person user) {
478 		for (MaintainableItemDefinition maintainableItemDefinition : itemDefinitions) {
479 			if (maintainableItemDefinition instanceof MaintainableCollectionDefinition) {
480 				try {
481 					MaintainableCollectionDefinition maintainableCollectionDefinition = (MaintainableCollectionDefinition) maintainableItemDefinition;
482 					
483 					Collection<BusinessObject> collection = (Collection<BusinessObject>) ObjectUtils
484 							.getNestedValue(businessObject,
485 									maintainableItemDefinition.getName());
486 					BusinessObjectEntry collectionBusinessObjectEntry = getDataDictionaryService()
487 							.getDataDictionary().getBusinessObjectEntry(
488 									maintainableCollectionDefinition.getBusinessObjectClass().getName());
489 					if (collection != null) {
490 				    	int i = 0;
491 			     		for (Iterator<BusinessObject> iterator = collection.iterator(); iterator
492 							.hasNext();) {
493 			     			String newPropertyPrefix = propertyPrefix + maintainableItemDefinition.getName() + "[" + i + "].";
494 					    	BusinessObject collectionBusinessObject = iterator.next();
495 					    	considerBusinessObjectFieldUnmaskAuthorization(
496 								collectionBusinessObject, user, restrictions,
497 								newPropertyPrefix, maintenanceDocument);
498 					    	considerBusinessObjectFieldViewAuthorization(
499 								collectionBusinessObjectEntry, maintenanceDocument, collectionBusinessObject, user,
500 								authorizer, restrictions, newPropertyPrefix);
501 					    	considerBusinessObjectFieldModifyAuthorization(
502 								collectionBusinessObjectEntry, maintenanceDocument, collectionBusinessObject, user,
503 								authorizer, restrictions, newPropertyPrefix);
504 					    	addMaintainableItemRestrictions(
505 								((MaintainableCollectionDefinition) maintainableItemDefinition)
506 										.getMaintainableCollections(),
507 								authorizer, restrictions, maintenanceDocument,
508 								collectionBusinessObject, newPropertyPrefix,
509 								user);
510 				     		addMaintainableItemRestrictions(
511 								((MaintainableCollectionDefinition) maintainableItemDefinition)
512 										.getMaintainableFields(), authorizer,
513 								restrictions, maintenanceDocument,
514 								collectionBusinessObject, newPropertyPrefix,
515 								user);
516 					    	i++;
517 				    	}
518 					}
519 				} catch (Exception e) {
520 					throw new RuntimeException(
521 							"Unable to resolve collection property: "
522 									+ businessObject.getClass() + ":"
523 									+ maintainableItemDefinition.getName(), e);
524 				}
525 			}
526 		}
527 	}
528 	
529 	public <T extends BusinessObject> boolean canFullyUnmaskField(Person user,
530 			Class<T> businessObjectClass, String fieldName, Document document) {
531 		// KFSMI-5095
532 		if(isNonProductionEnvAndUnmaskingTurnedOff())
533 			return false;
534 
535 		if(user==null || StringUtils.isEmpty(user.getPrincipalId())) 
536 			return false;
537 		Boolean result = null;
538 		if (document != null) { // if a document was passed, evaluate the permission in the context of a document
539 			try { // try/catch and fallthrough is a fix for KULRICE-3365
540 				result = getDocumentHelperService().getDocumentAuthorizer( document )
541 				.isAuthorizedByTemplate( document, 
542 						KNSConstants.KNS_NAMESPACE, 
543 						KimConstants.PermissionTemplateNames.FULL_UNMASK_FIELD, 
544 						user.getPrincipalId(), getFieldPermissionDetails(businessObjectClass, fieldName), null  );
545 			} catch (IllegalArgumentException e) { 
546 				// document didn't have needed metadata
547 				// TODO: this requires intimate knowledge of DocumentHelperServiceImpl 
548 			} 
549 		}
550 		if (result == null) { 
551 			result = getIdentityManagementService().isAuthorizedByTemplateName(
552 					user.getPrincipalId(),
553 					KNSConstants.KNS_NAMESPACE,
554 					KimConstants.PermissionTemplateNames.FULL_UNMASK_FIELD,
555 					new AttributeSet(getFieldPermissionDetails(businessObjectClass, fieldName)), 
556 					null);
557 		}
558 		return result; // should be safe to return Boolean here since the only circumstances that
559 		               // will leave it null will result in an exception being thrown above.
560 	}
561 
562 	public <T extends BusinessObject> boolean canPartiallyUnmaskField(
563 			Person user, Class<T> businessObjectClass, String fieldName, Document document) {
564 		// KFSMI-5095
565 		if(isNonProductionEnvAndUnmaskingTurnedOff())
566 			return false;
567 		
568 		if(user==null || StringUtils.isEmpty(user.getPrincipalId())) 
569 			return false;
570 
571 		if ( document == null ) {
572 			return getIdentityManagementService().isAuthorizedByTemplateName(
573 					user.getPrincipalId(),
574 					KNSConstants.KNS_NAMESPACE,
575 					KimConstants.PermissionTemplateNames.PARTIAL_UNMASK_FIELD,
576 					new AttributeSet(getFieldPermissionDetails(businessObjectClass,fieldName)), 
577 					null);
578 		} else { // if a document was passed, evaluate the permission in the context of a document
579 			return getDocumentHelperService().getDocumentAuthorizer( document )
580 					.isAuthorizedByTemplate( document, 
581 											 KNSConstants.KNS_NAMESPACE, 
582 											 KimConstants.PermissionTemplateNames.PARTIAL_UNMASK_FIELD, 
583 											 user.getPrincipalId(), getFieldPermissionDetails(businessObjectClass, fieldName), null  );
584 		}
585 	}
586 	
587 	public <T extends BusinessObject> boolean canCreate(Class<T> boClass, Person user, String docTypeName){
588 		DocumentPresentationController documentPresentationController = getDocumentHelperService().getDocumentPresentationController(docTypeName);
589 	    boolean canCreate = ((MaintenanceDocumentPresentationController) documentPresentationController).canCreate(boClass);
590 	    if(canCreate){
591 			DocumentAuthorizer documentAuthorizer = getDocumentHelperService().getDocumentAuthorizer(docTypeName);
592 	    	canCreate = ((MaintenanceDocumentAuthorizer) documentAuthorizer).canCreate(boClass, user);
593 	    }
594 		return canCreate;
595 	}
596 	
597 	public boolean canMaintain(BusinessObject businessObject, Person user,
598 			String docTypeName) {
599 		return ((MaintenanceDocumentAuthorizer) getDocumentHelperService()
600 				.getDocumentAuthorizer(docTypeName)).canMaintain(
601 				businessObject, user);
602 	}
603 
604 	protected <T extends BusinessObject> Map<String, String> getFieldPermissionDetails(
605 			Class<T> businessObjectClass, String attributeName) {
606 		try {
607 			return getFieldPermissionDetails(businessObjectClass.newInstance(),
608 					attributeName);
609 		} catch (Exception e) {
610 			throw new RuntimeException(
611 					"The getPermissionDetails method of BusinessObjectAuthorizationServiceImpl was unable to instantiate the businessObjectClass"
612 							+ businessObjectClass, e);
613 		}
614 	}
615 
616 	protected Map<String, String> getFieldPermissionDetails(
617 			BusinessObject businessObject, String attributeName) {
618 		Map<String, String> permissionDetails = null;
619 		String namespaceCode = null;
620 		String componentName = null;
621 		String propertyName = null;
622 		// JHK: commenting out for KFSMI-2398 - permission checks need to be done at the level specified
623 		// that is, if the parent object specifies the security, that object should be used for the 
624 		// component
625 //		if (attributeName.contains(".")) {
626 //			try {
627 //				permissionDetails = KimCommonUtils
628 //						.getNamespaceAndComponentSimpleName(PropertyUtils
629 //								.getPropertyType(businessObject, attributeName
630 //										.substring(0, attributeName
631 //												.lastIndexOf("."))));
632 //			} catch (Exception e) {
633 //				throw new RuntimeException(
634 //						"Unable to discover nested business object class: "
635 //								+ businessObject.getClass() + " : "
636 //								+ attributeName, e);
637 //			}
638 //			permissionDetails.put(KimAttributes.PROPERTY_NAME, attributeName
639 //					.substring(attributeName.indexOf(".") + 1));
640 //		} else {
641 			permissionDetails = KimCommonUtils
642 					.getNamespaceAndComponentSimpleName(businessObject
643 							.getClass());
644 			permissionDetails.put(KimAttributes.PROPERTY_NAME, attributeName);
645 //		}
646 		return permissionDetails;
647 	}
648 	
649 	protected Map<String, String> getButtonFieldPermissionDetails(
650 			BusinessObject businessObject, String attributeName) {
651 		Map<String, String> permissionDetails = new AttributeSet();
652 		if (attributeName.contains(".")) {
653 			permissionDetails.put(KimAttributes.BUTTON_NAME, attributeName);
654 		} else {
655 			permissionDetails.put(KimAttributes.BUTTON_NAME, attributeName);
656 		}
657 		return permissionDetails;
658 	}
659 
660 	private DataDictionaryService getDataDictionaryService() {
661 		if (dataDictionaryService == null) {
662 			dataDictionaryService = KNSServiceLocator
663 					.getDataDictionaryService();
664 		}
665 		return dataDictionaryService;
666 	}
667 
668 	private IdentityManagementService getIdentityManagementService() {
669 		if (identityManagementService == null) {
670 			identityManagementService = KIMServiceLocator
671 					.getIdentityManagementService();
672 		}
673 		return identityManagementService;
674 	}
675 
676 	private BusinessObjectDictionaryService getBusinessObjectDictionaryService() {
677 		if (businessObjectDictionaryService == null) {
678 			businessObjectDictionaryService = KNSServiceLocator
679 					.getBusinessObjectDictionaryService();
680 		}
681 		return businessObjectDictionaryService;
682 	}
683 
684 	private DocumentHelperService getDocumentHelperService() {
685 		if (documentHelperService == null) {
686 			documentHelperService = KNSServiceLocator.getDocumentHelperService();
687 		}
688 		return documentHelperService;
689 	}
690 
691 	private MaintenanceDocumentDictionaryService getMaintenanceDocumentDictionaryService() {
692 		if (maintenanceDocumentDictionaryService == null) {
693 			maintenanceDocumentDictionaryService = KNSServiceLocator
694 					.getMaintenanceDocumentDictionaryService();
695 		}
696 		return maintenanceDocumentDictionaryService;
697 	}
698 
699 	private KualiConfigurationService getKualiConfigurationService() {
700 		if (kualiConfigurationService == null) {
701 			kualiConfigurationService = KNSServiceLocator.getKualiConfigurationService();
702 		}
703 		return kualiConfigurationService;
704 	}
705 	
706 	/**
707 	 * @see org.kuali.rice.kns.service.BusinessObjectAuthorizationService#attributeValueNeedsToBeEncryptedOnFormsAndLinks(java.lang.Class, java.lang.String)
708 	 */
709 	public boolean attributeValueNeedsToBeEncryptedOnFormsAndLinks(
710 			Class<? extends BusinessObject> businessObjectClass,
711 			String attributeName) {
712 		AttributeSecurity attributeSecurity = getDataDictionaryService().getAttributeSecurity(businessObjectClass.getName(), attributeName);
713 		return attributeSecurity != null && attributeSecurity.hasRestrictionThatRemovesValueFromUI();
714 	}
715 
716 	private boolean isNonProductionEnvAndUnmaskingTurnedOff(){
717 		return !getKualiConfigurationService().isProductionEnvironment() && 
718 				!getKualiConfigurationService().getPropertyAsBoolean(KNSConstants.ENABLE_NONPRODUCTION_UNMASKING);
719 	}
720 
721 }