001 /*
002 * Copyright 2011 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 */
016 package org.kuali.kfs.sec.service.impl;
017
018 import java.util.ArrayList;
019 import java.util.HashMap;
020 import java.util.Iterator;
021 import java.util.List;
022 import java.util.Map;
023
024 import org.apache.commons.lang.StringUtils;
025 import org.kuali.kfs.integration.cg.ContractsAndGrantsModuleService;
026 import org.kuali.kfs.sec.SecConstants;
027 import org.kuali.kfs.sec.SecConstants.SecurityTemplateNames;
028 import org.kuali.kfs.sec.businessobject.AccessSecurityRestrictionInfo;
029 import org.kuali.kfs.sec.datadictionary.AccessSecurityAttributeRestrictionEntry;
030 import org.kuali.kfs.sec.identity.SecKimAttributes;
031 import org.kuali.kfs.sec.service.AccessPermissionEvaluator;
032 import org.kuali.kfs.sec.service.AccessSecurityService;
033 import org.kuali.kfs.sys.KFSConstants;
034 import org.kuali.kfs.sys.businessobject.AccountingLine;
035 import org.kuali.kfs.sys.businessobject.SourceAccountingLine;
036 import org.kuali.kfs.sys.businessobject.TargetAccountingLine;
037 import org.kuali.kfs.sys.businessobject.datadictionary.FinancialSystemBusinessObjectEntry;
038 import org.kuali.kfs.sys.document.AccountingDocument;
039 import org.kuali.rice.kim.bo.Person;
040 import org.kuali.rice.kim.bo.role.dto.KimPermissionInfo;
041 import org.kuali.rice.kim.bo.role.dto.KimPermissionTemplateInfo;
042 import org.kuali.rice.kim.bo.types.dto.AttributeSet;
043 import org.kuali.rice.kim.service.PermissionService;
044 import org.kuali.rice.kim.service.RoleManagementService;
045 import org.kuali.rice.kns.bo.BusinessObject;
046 import org.kuali.rice.kns.bo.PersistableBusinessObject;
047 import org.kuali.rice.kns.datadictionary.AttributeDefinition;
048 import org.kuali.rice.kns.service.DataDictionaryService;
049 import org.kuali.rice.kns.service.ParameterService;
050 import org.kuali.rice.kns.util.ObjectUtils;
051 import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument;
052
053
054 /**
055 * @see org.kuali.kfs.sec.service.AccessSecurityService
056 */
057 public class AccessSecurityServiceImpl implements AccessSecurityService {
058 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AccessSecurityServiceImpl.class);
059
060 protected DataDictionaryService dataDictionaryService;
061 protected ParameterService parameterService;
062 protected PermissionService permissionService;
063 protected RoleManagementService roleManagementService;
064 protected ContractsAndGrantsModuleService contractsAndGrantsModuleService;
065
066 /**
067 * @see org.kuali.kfs.sec.service.AccessSecurityService#applySecurityRestrictionsForGLInquiry(java.util.List,
068 * org.kuali.rice.kim.bo.Person)
069 */
070 public void applySecurityRestrictionsForGLInquiry(List<? extends BusinessObject> results, Person person) {
071 AttributeSet additionalPermissionDetails = new AttributeSet();
072 additionalPermissionDetails.put(SecKimAttributes.NAMESPACE_CODE, KFSConstants.ParameterNamespaces.GL);
073
074 applySecurityRestrictions(results, person, getInquiryWithFieldValueTemplateId(), additionalPermissionDetails);
075 }
076
077 /**
078 * @see org.kuali.kfs.sec.service.AccessSecurityService#applySecurityRestrictionsForLaborInquiry(java.util.List,
079 * org.kuali.rice.kim.bo.Person)
080 */
081 public void applySecurityRestrictionsForLaborInquiry(List<? extends BusinessObject> results, Person person) {
082 AttributeSet additionalPermissionDetails = new AttributeSet();
083 additionalPermissionDetails.put(SecKimAttributes.NAMESPACE_CODE, SecConstants.LABOR_MODULE_NAMESPACE_CODE);
084
085 applySecurityRestrictions(results, person, getInquiryWithFieldValueTemplateId(), additionalPermissionDetails);
086 }
087
088 /**
089 * @see org.kuali.kfs.sec.service.AccessSecurityService#applySecurityRestrictionsForLookup(java.util.List,
090 * org.kuali.rice.kim.bo.Person)
091 */
092 public void applySecurityRestrictionsForLookup(List<? extends BusinessObject> results, Person person) {
093 applySecurityRestrictions(results, person, getLookupWithFieldValueTemplateId(), null);
094 }
095
096 /**
097 * @see org.kuali.kfs.sec.service.AccessSecurityService#applySecurityRestrictions(java.util.List, org.kuali.rice.kim.bo.Person,
098 * java.lang.String, org.kuali.rice.kim.bo.types.dto.AttributeSet)
099 */
100 public void applySecurityRestrictions(List<? extends BusinessObject> results, Person person, String templateId, AttributeSet additionalPermissionDetails) {
101 if (!isAccessSecurityEnabled()) {
102 return;
103 }
104
105 if (results == null || results.isEmpty()) {
106 return;
107 }
108
109 // evaluate permissions against business object instances
110 List<BusinessObject> restrictedRecords = new ArrayList();
111 for (BusinessObject businessObject : results) {
112 boolean accessAllowed = evaluateSecurityPermissionsByTemplate(businessObject, businessObject.getClass(), person, templateId, additionalPermissionDetails, null);
113 if (!accessAllowed) {
114 restrictedRecords.add(businessObject);
115 }
116 }
117
118 // remove restricted records from result list
119 for (BusinessObject businessObject : restrictedRecords) {
120 results.remove(businessObject);
121 }
122 }
123
124 /**
125 * @see org.kuali.kfs.sec.service.AccessSecurityService#checkSecurityRestrictionsForBusinessObject(org.kuali.rice.kns.bo.BusinessObject,
126 * org.kuali.rice.kim.bo.Person, org.kuali.kfs.sec.businessobject.AccessSecurityRestrictionInfo)
127 */
128 public boolean checkSecurityRestrictionsForBusinessObject(BusinessObject businessObject, Person person, AccessSecurityRestrictionInfo restrictionInfo) {
129 return evaluateSecurityPermissionsByTemplate(businessObject, businessObject.getClass(), person, getLookupWithFieldValueTemplateId(), null, restrictionInfo);
130 }
131
132 /**
133 * @see org.kuali.kfs.sec.service.AccessSecurityService#canEditDocument(org.kuali.kfs.sys.document.AccountingDocument,
134 * org.kuali.rice.kim.bo.Person)
135 */
136 public boolean canEditDocument(AccountingDocument document, Person person) {
137 return evaluateSecurityOnAccountingLinesByTemplate(document, person, getEditDocumentWithFieldValueTemplateId(), null);
138 }
139
140 /**
141 * @see org.kuali.kfs.sec.service.AccessSecurityService#canEditDocumentAccountingLine(org.kuali.kfs.sys.document.AccountingDocument,
142 * org.kuali.kfs.sys.businessobject.AccountingLine, org.kuali.rice.kim.bo.Person,
143 * org.kuali.kfs.sec.businessobject.AccessSecurityRestrictionInfo)
144 */
145 public boolean canEditDocumentAccountingLine(AccountingDocument document, AccountingLine accountingLine, Person person, AccessSecurityRestrictionInfo restrictionInfo) {
146 // check for edit line overrides
147 boolean meetsOverrideCondition = checkForEditLineOverrides(document, accountingLine, person);
148 if (meetsOverrideCondition) {
149 return true;
150 }
151
152 Class entryClass = SourceAccountingLine.class;
153 if (TargetAccountingLine.class.isAssignableFrom(accountingLine.getClass())) {
154 entryClass = TargetAccountingLine.class;
155 }
156
157 if (restrictionInfo != null) {
158 restrictionInfo.setDocumentNumber(document.getDocumentNumber());
159 }
160
161 return evaluateSecurityPermissionsByTemplate(accountingLine, entryClass, person, getEditAccountingLineWithFieldValueTemplateId(), getDocumentTypeDetail(document), restrictionInfo);
162 }
163
164 /**
165 * @see org.kuali.kfs.sec.service.AccessSecurityService#canEditDocumentAccountingLine(org.kuali.kfs.sys.document.AccountingDocument,
166 * org.kuali.kfs.sys.businessobject.AccountingLine, org.kuali.rice.kim.bo.Person)
167 */
168 public boolean canEditDocumentAccountingLine(AccountingDocument document, AccountingLine accountingLine, Person person) {
169 return canEditDocumentAccountingLine(document, accountingLine, person, new AccessSecurityRestrictionInfo());
170 }
171
172 /**
173 * @see org.kuali.kfs.sec.service.AccessSecurityService#canViewDocument(org.kuali.kfs.sys.document.AccountingDocument,
174 * org.kuali.rice.kim.bo.Person, org.kuali.kfs.sec.businessobject.AccessSecurityRestrictionInfo)
175 */
176 public boolean canViewDocument(AccountingDocument document, Person person, AccessSecurityRestrictionInfo restrictionInfo) {
177 // any workflow requests override view document access permissions
178 boolean hasWorkflowRequests = checkForWorkflowRoutingRequests(document, person);
179 if (hasWorkflowRequests) {
180 return true;
181 }
182
183 // check for parameter overrides
184 boolean meetsOverrideCondition = checkForViewDocumentOverrides(document, person);
185 if (meetsOverrideCondition) {
186 return true;
187 }
188
189 if (restrictionInfo != null) {
190 restrictionInfo.setDocumentNumber(document.getDocumentNumber());
191 }
192
193 return evaluateSecurityOnAccountingLinesByTemplate(document, person, getViewDocumentWithFieldValueTemplateId(), restrictionInfo);
194 }
195
196 /**
197 * @see org.kuali.kfs.sec.service.AccessSecurityService#canViewDocumentAccountingLine(org.kuali.kfs.sys.document.AccountingDocument,
198 * org.kuali.kfs.sys.businessobject.AccountingLine, org.kuali.rice.kim.bo.Person)
199 */
200 public boolean canViewDocumentAccountingLine(AccountingDocument document, AccountingLine accountingLine, Person person) {
201 // check for view line overrides
202 boolean meetsOverrideCondition = checkForViewLineOverrides(document, accountingLine, person);
203 if (meetsOverrideCondition) {
204 return true;
205 }
206
207 Class entryClass = SourceAccountingLine.class;
208 if (TargetAccountingLine.class.isAssignableFrom(accountingLine.getClass())) {
209 entryClass = TargetAccountingLine.class;
210 }
211
212 return evaluateSecurityPermissionsByTemplate(accountingLine, entryClass, person, getViewAccountingLineWithFieldValueTemplateId(), getDocumentTypeDetail(document), null);
213 }
214
215 /**
216 * @see org.kuali.kfs.sec.service.AccessSecurityService#canViewDocumentNotesAttachments(org.kuali.kfs.sys.document.AccountingDocument,
217 * org.kuali.rice.kim.bo.Person)
218 */
219 public boolean canViewDocumentNotesAttachments(AccountingDocument document, Person person) {
220 // check for parameter overrides
221 boolean meetsOverrideCondition = checkForViewDocumentOverrides(document, person);
222 if (meetsOverrideCondition) {
223 return true;
224 }
225
226 return evaluateSecurityOnAccountingLinesByTemplate(document, person, getViewNotesAttachmentsWithFieldValueTemplateId(), null);
227 }
228
229 /**
230 * Iterates through source and target accounting lines for the given document and evaluates any permissions with the given
231 * template id against the accounting line values
232 *
233 * @param document AccountingDocument instance with accounting lines to check, doc type of instance is used for retrieving
234 * permissions
235 * @param person the user who we are checking access for
236 * @param templateId KIM template id for the permissions to check
237 * @param restrictionInfo Object providing information on a restriction if one is found
238 * @return boolean true if all accounting lines pass permissions, false if at least one accounting line does not pass
239 */
240 protected boolean evaluateSecurityOnAccountingLinesByTemplate(AccountingDocument document, Person person, String templateId, AccessSecurityRestrictionInfo restrictionInfo) {
241 boolean success = true;
242
243 if (!isAccessSecurityEnabled()) {
244 return success;
245 }
246
247 AttributeSet permissionDetails = getDocumentTypeDetail(document);
248
249 // check source lines
250 for (Iterator iterator = document.getSourceAccountingLines().iterator(); iterator.hasNext();) {
251 AccountingLine accountingLine = (AccountingLine) iterator.next();
252
253 // check for overrides
254 boolean meetsOverrideCondition = false;
255 if (templateId.equals(getViewDocumentWithFieldValueTemplateId())) {
256 meetsOverrideCondition = checkForViewLineOverrides(document, accountingLine, person);
257 }
258 else {
259 meetsOverrideCondition = checkForEditLineOverrides(document, accountingLine, person);
260 }
261
262 if (meetsOverrideCondition) {
263 continue;
264 }
265
266 success = evaluateSecurityPermissionsByTemplate(accountingLine, SourceAccountingLine.class, person, templateId, permissionDetails, restrictionInfo);
267 if (!success) {
268 break;
269 }
270 }
271
272 // if source lines are ok, check target lines
273 if (success) {
274 for (Iterator iterator = document.getTargetAccountingLines().iterator(); iterator.hasNext();) {
275 AccountingLine accountingLine = (AccountingLine) iterator.next();
276
277 // check for overrides
278 boolean meetsOverrideCondition = false;
279 if (templateId.equals(getViewDocumentWithFieldValueTemplateId())) {
280 meetsOverrideCondition = checkForViewLineOverrides(document, accountingLine, person);
281 }
282 else {
283 meetsOverrideCondition = checkForEditLineOverrides(document, accountingLine, person);
284 }
285
286 if (meetsOverrideCondition) {
287 continue;
288 }
289
290 success = evaluateSecurityPermissionsByTemplate(accountingLine, TargetAccountingLine.class, person, templateId, permissionDetails, restrictionInfo);
291 if (!success) {
292 break;
293 }
294 }
295 }
296
297 return success;
298 }
299
300 /**
301 * Checks for any workflow requests (approve, acknowledge, fyi) for the document to the given person
302 *
303 * @param document Document to check for routing requests
304 * @param person Person to check for routing requests
305 * @return boolean true if there are workflow requests, false if not
306 */
307 protected boolean checkForWorkflowRoutingRequests(AccountingDocument document, Person person) {
308 KualiWorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
309
310 if (workflowDocument.isApprovalRequested() || workflowDocument.isAcknowledgeRequested() || workflowDocument.isFYIRequested()) {
311 return true;
312 }
313
314 return false;
315 }
316
317 /**
318 * Checks parameter overrides for view document permission. Currently only have initiator override parameter
319 *
320 * @param document Document that we are checking permissions for
321 * @param person Person we are checking permissions for
322 * @return boolean true if overrides are turned on and the person meets the override conditions, false if overrides are not
323 * turned on or the person does not meet condition
324 */
325 protected boolean checkForViewDocumentOverrides(AccountingDocument document, Person person) {
326 KualiWorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
327
328 boolean alwaysAllowInitiatorAccess = parameterService.getIndicatorParameter(SecConstants.ACCESS_SECURITY_NAMESPACE_CODE, SecConstants.ALL_PARAMETER_DETAIL_COMPONENT, SecConstants.SecurityParameterNames.ALWAYS_ALLOW_INITIATOR_DOCUMENT_ACCESS_IND);
329 if (alwaysAllowInitiatorAccess) {
330 if (StringUtils.equals(workflowDocument.getInitiatorPrincipalId(), person.getPrincipalId())) {
331 return true;
332 }
333 }
334
335 return false;
336 }
337
338 /**
339 * Checks parameter overrides for view line permission. Currently only have initiator, fiscal officer, and principal
340 * investigator overrides
341 *
342 * @param document Document that we are checking permissions for
343 * @param person Person we are checking permissions for
344 * @param line AccountingLine we are checking permissions for
345 * @return boolean true if any override is turned on and the person meets the override conditions, false otherwise
346 */
347 protected boolean checkForViewLineOverrides(AccountingDocument document, AccountingLine line, Person person) {
348 KualiWorkflowDocument workflowDocument = document.getDocumentHeader().getWorkflowDocument();
349
350 // initiator override
351 boolean alwaysAllowInitiatorAccess = parameterService.getIndicatorParameter(SecConstants.ACCESS_SECURITY_NAMESPACE_CODE, SecConstants.ALL_PARAMETER_DETAIL_COMPONENT, SecConstants.SecurityParameterNames.ALWAYS_ALLOW_INITIATOR_LINE_ACCESS_IND);
352 if (alwaysAllowInitiatorAccess) {
353 if (StringUtils.equals(workflowDocument.getInitiatorPrincipalId(), person.getPrincipalId())) {
354 return true;
355 }
356 }
357
358 // account must be not be empty for further override checks
359 if (line.getAccount() == null) {
360 return false;
361 }
362
363 // fiscal officer override
364 boolean alwaysAllowFOAccess = parameterService.getIndicatorParameter(SecConstants.ACCESS_SECURITY_NAMESPACE_CODE, SecConstants.ALL_PARAMETER_DETAIL_COMPONENT, SecConstants.SecurityParameterNames.ALWAYS_ALLOW_FISCAL_OFFICER_LINE_ACCESS_IND);
365 if (alwaysAllowFOAccess) {
366 if (StringUtils.equals(line.getAccount().getAccountFiscalOfficerSystemIdentifier(), person.getPrincipalId())) {
367 return true;
368 }
369 }
370
371 // pi override
372 boolean alwaysAllowPIAccess = parameterService.getIndicatorParameter(SecConstants.ACCESS_SECURITY_NAMESPACE_CODE, SecConstants.ALL_PARAMETER_DETAIL_COMPONENT, SecConstants.SecurityParameterNames.ALWAYS_ALLOW_PRINCIPAL_INVESTIGATOR_LINE_ACCESS_IND);
373 if (alwaysAllowPIAccess) {
374 Person principalInvestigator = contractsAndGrantsModuleService.getProjectDirectorForAccount(line.getAccount());
375 if (principalInvestigator != null && StringUtils.equals(principalInvestigator.getPrincipalId(), person.getPrincipalId())) {
376 return true;
377 }
378 }
379
380 return false;
381 }
382
383 /**
384 * Checks parameter overrides for edit line permission. Currently only have fiscal officer and principal investigator overrides
385 *
386 * @param document Document that we are checking permissions for
387 * @param person Person we are checking permissions for
388 * @param line AccountingLine we are checking permissions for
389 * @return boolean true if any override is turned on and the person meets the override conditions, false otherwise
390 */
391 protected boolean checkForEditLineOverrides(AccountingDocument document, AccountingLine line, Person person) {
392 // account must be not be empty for override checks
393 if (line.getAccount() == null || line.getAccountNumber() == null) {
394 return false;
395 }
396
397 // fiscal officer override
398 boolean alwaysAllowFOAccess = parameterService.getIndicatorParameter(SecConstants.ACCESS_SECURITY_NAMESPACE_CODE, SecConstants.ALL_PARAMETER_DETAIL_COMPONENT, SecConstants.SecurityParameterNames.ALWAYS_ALLOW_FISCAL_OFFICER_LINE_ACCESS_IND);
399 if (alwaysAllowFOAccess) {
400 if (StringUtils.equals(line.getAccount().getAccountFiscalOfficerSystemIdentifier(), person.getPrincipalId())) {
401 return true;
402 }
403 }
404
405 // pi override
406 boolean alwaysAllowPIAccess = parameterService.getIndicatorParameter(SecConstants.ACCESS_SECURITY_NAMESPACE_CODE, SecConstants.ALL_PARAMETER_DETAIL_COMPONENT, SecConstants.SecurityParameterNames.ALWAYS_ALLOW_PRINCIPAL_INVESTIGATOR_LINE_ACCESS_IND);
407 if (alwaysAllowPIAccess) {
408 Person principalInvestigator = contractsAndGrantsModuleService.getProjectDirectorForAccount(line.getAccount());
409 if (principalInvestigator != null && StringUtils.equals(principalInvestigator.getPrincipalId(), person.getPrincipalId())) {
410 return true;
411 }
412 }
413
414 return false;
415 }
416
417 /**
418 * Validates any security permissions setup for the user and attributes of the class against the business object values
419 *
420 * @param businessObject instance with attribute values to validate
421 * @param entryClass Class of business object to pull attribute restrictions for
422 * @param person the user who we are checking access for
423 * @param templateId type of security permissions to check
424 * @param additionalPermissionDetails any additional details that should be used for retrieving permissions
425 * @param restrictionInfo Object providing information on a restriction if one is found
426 * @return boolean true if user has access given by template to the business object, false otherwise
427 */
428 protected boolean evaluateSecurityPermissionsByTemplate(BusinessObject businessObject, Class entryClass, Person person, String templateId, AttributeSet additionalPermissionDetails, AccessSecurityRestrictionInfo restrictionInfo) {
429 boolean success = true;
430
431 if (!isAccessSecurityEnabled()) {
432 return success;
433 }
434
435 // get all configured restricted attributes for this business object through it data dictionary entry
436 FinancialSystemBusinessObjectEntry businessObjectEntry = (FinancialSystemBusinessObjectEntry) dataDictionaryService.getDataDictionary().getBusinessObjectEntry(entryClass.getName());
437
438 // get template name from id
439 KimPermissionTemplateInfo templateInfo = permissionService.getPermissionTemplate(templateId);
440 String templateName = templateInfo.getName();
441
442 if (PersistableBusinessObject.class.isAssignableFrom(businessObject.getClass())) {
443 ((PersistableBusinessObject) businessObject).refreshNonUpdateableReferences();
444 }
445 else {
446 businessObject.refresh();
447 }
448
449 for (AccessSecurityAttributeRestrictionEntry accessRestrictedAttribute : businessObjectEntry.getAccessRestrictedAttributes()) {
450 AttributeSet permissionDetails = new AttributeSet();
451 permissionDetails.put(SecKimAttributes.PROPERTY_NAME, accessRestrictedAttribute.getSecurityAttributeName());
452
453 if (additionalPermissionDetails != null) {
454 permissionDetails.putAll(additionalPermissionDetails);
455 }
456
457 List<KimPermissionInfo> permissions = permissionService.getAuthorizedPermissionsByTemplateName(person.getPrincipalId(), SecConstants.ACCESS_SECURITY_NAMESPACE_CODE, templateName, permissionDetails, null);
458 if (permissions == null || permissions.isEmpty()) {
459 continue;
460 }
461
462 // retrieve field value to check
463 Object propertyValue = ObjectUtils.getPropertyValue(businessObject, accessRestrictedAttribute.getAttribute().getName());
464 if (propertyValue != null && StringUtils.isNotEmpty(propertyValue.toString())) {
465 // retrieve other field values that might be necessary to validate main field
466 Map<String, Object> otherKeyValues = new HashMap<String, Object>();
467 for (String keyFieldName : accessRestrictedAttribute.getOtherKeyFields().keySet()) {
468 AttributeDefinition fieldDefinition = accessRestrictedAttribute.getOtherKeyFields().get(keyFieldName);
469
470 Object keyFieldValue = ObjectUtils.getPropertyValue(businessObject, fieldDefinition.getName());
471 otherKeyValues.put(keyFieldName, keyFieldValue);
472 }
473
474 success = evaluateSecurityPermissions(accessRestrictedAttribute.getAccessPermissionEvaluatorClass(), permissions, propertyValue.toString(), person, otherKeyValues);
475 if (!success) {
476 if (restrictionInfo != null) {
477 restrictionInfo.setSecurityAttributeName(accessRestrictedAttribute.getSecurityAttributeName());
478 restrictionInfo.setPropertyName(accessRestrictedAttribute.getAttribute().getName());
479 restrictionInfo.setPropertyLabel(accessRestrictedAttribute.getAttribute().getLabel());
480 restrictionInfo.setRetrictedValue((String) propertyValue);
481 }
482
483 break;
484 }
485 }
486 }
487
488 return success;
489 }
490
491 /**
492 * Constructs a new AttributeSet and adds document type name detail with value from document instance
493 *
494 * @param document AccountingDocument instance which document type will be set from
495 * @return AttributeSet containing document type name detail
496 */
497 protected AttributeSet getDocumentTypeDetail(AccountingDocument document) {
498 AttributeSet details = new AttributeSet();
499 details.put(SecKimAttributes.DOCUMENT_TYPE_NAME, document.getFinancialDocumentTypeCode());
500
501 return details;
502 }
503
504 /**
505 * Checks whether the given value is allowed based on the given permissions and user
506 *
507 * @param accessPermissionEvaluatorClass Class of type AccessPermissionEvaluator that will be used to evaluate the security
508 * restriction
509 * @param permissions List of permissions to evaluate
510 * @param value the value that will be checked
511 * @param person the user who we are checking access for
512 * @param otherKeyValues Map for other key field name/value pairs
513 * @return boolean true if access is allowed false if not
514 */
515 protected boolean evaluateSecurityPermissions(Class<? extends AccessPermissionEvaluator> accessPermissionEvaluatorClass, List<KimPermissionInfo> permissions, String value, Person person, Map<String, Object> otherKeyValues) {
516 boolean success = true;
517
518 List<AttributeSet> qualficationsToEvaluate = new ArrayList<AttributeSet>();
519 for (KimPermissionInfo permission : permissions) {
520 // find all roles that have been granted this permission
521 List<String> roleIds = permissionService.getRoleIdsForPermissionId(permission.getPermissionId());
522
523 // for all the roles that have this permission, find the users qualification in those roles (if any)
524 List<AttributeSet> qualfications = roleManagementService.getRoleQualifiersForPrincipalIncludingNested(person.getPrincipalId(), roleIds, null);
525
526 if (qualfications != null) {
527 qualficationsToEvaluate.addAll(qualfications);
528 }
529 }
530
531 // cycle through the users qualifications and evaluate against the given value
532 boolean hasAllowQualification = false;
533 boolean allowQualificationSuccess = false;
534 boolean hasDenyFailure = false;
535 boolean hasAllowOverride = false;
536 for (AttributeSet attributeSet : qualficationsToEvaluate) {
537 AccessPermissionEvaluator accessPermissionEvaluator = constructAccessPermissionEvaluator(accessPermissionEvaluatorClass, attributeSet, otherKeyValues, person);
538 boolean allowed = accessPermissionEvaluator.valueIsAllowed(value);
539
540 // all qualifications with constraint 'D' (deny) must pass
541 String constraintCode = attributeSet.get(SecKimAttributes.CONSTRAINT_CODE);
542 if (!allowed && StringUtils.contains(constraintCode, SecConstants.SecurityConstraintCodes.DENIED)) {
543 hasDenyFailure = true;
544 }
545
546 // if there are any 'A' (allow) qualifications, at least one must succeed
547 if (StringUtils.contains(constraintCode, SecConstants.SecurityConstraintCodes.ALLOWED)) {
548 hasAllowQualification = true;
549 if (allowed) {
550 allowQualificationSuccess = true;
551
552 // check for override of deny
553 String overrideDeny = attributeSet.get(SecKimAttributes.OVERRIDE_DENY);
554 if (Boolean.parseBoolean(overrideDeny)) {
555 hasAllowOverride = true;
556 }
557 }
558 }
559 }
560
561 if ((hasDenyFailure && !hasAllowOverride) || (hasAllowQualification && !allowQualificationSuccess)) {
562 success = false;
563 }
564
565 return success;
566 }
567
568 /**
569 * Constructs a new instance of the AccessPermissionEvaluator class and sets the constraint, operator, and value based on the
570 * given qualification
571 *
572 * @param accessPermissionEvaluatorClass Class to create instance of (must implement AccessPermissionEvaluator interface)
573 * @param attributeSet AttributeSet containing the qualifier values
574 * @param otherKeyValues Map for other key field name/value pairs
575 * @param person Person who permission should be evaluated for
576 * @return new instance of type AccessPermissionEvaluator
577 * @see org.kuali.kfs.sec.service.AccessPermissionEvaluator
578 */
579 protected AccessPermissionEvaluator constructAccessPermissionEvaluator(Class<? extends AccessPermissionEvaluator> accessPermissionEvaluatorClass, AttributeSet attributeSet, Map<String, Object> otherKeyValues, Person person) {
580 AccessPermissionEvaluator accessPermissionEvaluator = null;
581 try {
582 accessPermissionEvaluator = accessPermissionEvaluatorClass.newInstance();
583 }
584 catch (Exception e) {
585 String msg = "Unable to create new instance of AccessPermissionEvaluator class: " + accessPermissionEvaluatorClass.getName();
586 LOG.error(msg, e);
587 throw new RuntimeException(msg, e);
588 }
589
590 accessPermissionEvaluator.setConstraintCode(attributeSet.get(SecKimAttributes.CONSTRAINT_CODE));
591 accessPermissionEvaluator.setOperatorCode(attributeSet.get(SecKimAttributes.OPERATOR));
592 accessPermissionEvaluator.setPropertyValue(attributeSet.get(SecKimAttributes.PROPERTY_VALUE));
593 accessPermissionEvaluator.setOtherKeyFieldValueMap(otherKeyValues);
594 accessPermissionEvaluator.setPerson(person);
595
596 return accessPermissionEvaluator;
597 }
598
599 /**
600 * Helper method to check system parameter that turns access security on/off
601 *
602 * @return boolean indicating whether access security is turned on (true) or off (false)
603 */
604 protected boolean isAccessSecurityEnabled() {
605 return parameterService.getIndicatorParameter(SecConstants.ACCESS_SECURITY_NAMESPACE_CODE, SecConstants.ALL_PARAMETER_DETAIL_COMPONENT, SecConstants.SecurityParameterNames.ENABLE_ACCESS_SECURITY);
606 }
607
608 /**
609 * Sets the dataDictionaryService attribute value.
610 *
611 * @param dataDictionaryService The dataDictionaryService to set.
612 */
613 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
614 this.dataDictionaryService = dataDictionaryService;
615 }
616
617 /**
618 * Sets the parameterService attribute value.
619 *
620 * @param parameterService The parameterService to set.
621 */
622 public void setParameterService(ParameterService parameterService) {
623 this.parameterService = parameterService;
624 }
625
626 /**
627 * Sets the permissionService attribute value.
628 *
629 * @param permissionService The permissionService to set.
630 */
631 public void setPermissionService(PermissionService permissionService) {
632 this.permissionService = permissionService;
633 }
634
635 /**
636 * Sets the roleManagementService attribute value.
637 *
638 * @param roleManagementService The roleManagementService to set.
639 */
640 public void setRoleManagementService(RoleManagementService roleManagementService) {
641 this.roleManagementService = roleManagementService;
642 }
643
644 /**
645 * Sets the contractsAndGrantsModuleService attribute value.
646 *
647 * @param contractsAndGrantsModuleService The contractsAndGrantsModuleService to set.
648 */
649 public void setContractsAndGrantsModuleService(ContractsAndGrantsModuleService contractsAndGrantsModuleService) {
650 this.contractsAndGrantsModuleService = contractsAndGrantsModuleService;
651 }
652
653 /**
654 * @see org.kuali.kfs.sec.service.AccessSecurityService#getEditAccountingLineWithFieldValueTemplateId()
655 */
656 public String getEditAccountingLineWithFieldValueTemplateId() {
657 KimPermissionTemplateInfo templateInfo = permissionService.getPermissionTemplateByName(KFSConstants.CoreModuleNamespaces.ACCESS_SECURITY, SecurityTemplateNames.EDIT_ACCOUNTING_LINE_FIELD_VALUE);
658 if (ObjectUtils.isNotNull(templateInfo)) {
659 return templateInfo.getPermissionTemplateId();
660 }
661 else
662 throw new RuntimeException(SecurityTemplateNames.EDIT_ACCOUNTING_LINE_FIELD_VALUE + " parameter does not exist");
663 }
664
665
666 /**
667 * @see org.kuali.kfs.sec.service.AccessSecurityService#getEditDocumentWithFieldValueTemplateId()
668 */
669 public String getEditDocumentWithFieldValueTemplateId() {
670 KimPermissionTemplateInfo templateInfo = permissionService.getPermissionTemplateByName(KFSConstants.CoreModuleNamespaces.ACCESS_SECURITY, SecurityTemplateNames.EDIT_DOCUMENT_FIELD_VALUE);
671 if (ObjectUtils.isNotNull(templateInfo)) {
672 return templateInfo.getPermissionTemplateId();
673 }
674 else
675 throw new RuntimeException(SecurityTemplateNames.EDIT_DOCUMENT_FIELD_VALUE + " parameter does not exist");
676 }
677
678
679 /**
680 * @see org.kuali.kfs.sec.service.AccessSecurityService#getInquiryWithFieldValueTemplateId()
681 */
682 public String getInquiryWithFieldValueTemplateId() {
683 KimPermissionTemplateInfo templateInfo = permissionService.getPermissionTemplateByName(KFSConstants.CoreModuleNamespaces.ACCESS_SECURITY, SecurityTemplateNames.INQUIRY_FIELD_VALUE);
684 if (ObjectUtils.isNotNull(templateInfo)) {
685 return templateInfo.getPermissionTemplateId();
686 }
687 else
688 throw new RuntimeException(SecurityTemplateNames.INQUIRY_FIELD_VALUE + " parameter does not exist");
689 }
690
691
692 /**
693 * @see org.kuali.kfs.sec.service.AccessSecurityService#getLookupWithFieldValueTemplateId()
694 */
695 public String getLookupWithFieldValueTemplateId() {
696 KimPermissionTemplateInfo templateInfo = permissionService.getPermissionTemplateByName(KFSConstants.CoreModuleNamespaces.ACCESS_SECURITY, SecurityTemplateNames.LOOKUP_FIELD_VALUE);
697 if (ObjectUtils.isNotNull(templateInfo)) {
698 return templateInfo.getPermissionTemplateId();
699 }
700 else
701 throw new RuntimeException(SecurityTemplateNames.LOOKUP_FIELD_VALUE + " parameter does not exist");
702 }
703
704
705 /**
706 * @see org.kuali.kfs.sec.service.AccessSecurityService#getViewAccountingLineWithFieldValueTemplateId()
707 */
708 public String getViewAccountingLineWithFieldValueTemplateId() {
709 KimPermissionTemplateInfo templateInfo = permissionService.getPermissionTemplateByName(KFSConstants.CoreModuleNamespaces.ACCESS_SECURITY, SecurityTemplateNames.VIEW_ACCOUNTING_LINE_FIELD_VALUE);
710 if (ObjectUtils.isNotNull(templateInfo)) {
711 return templateInfo.getPermissionTemplateId();
712 }
713 else
714 throw new RuntimeException(SecurityTemplateNames.VIEW_ACCOUNTING_LINE_FIELD_VALUE + " parameter does not exist");
715 }
716
717
718 /**
719 * @see org.kuali.kfs.sec.service.AccessSecurityService#getViewDocumentWithFieldValueTemplateId()
720 */
721 public String getViewDocumentWithFieldValueTemplateId() {
722 KimPermissionTemplateInfo templateInfo = permissionService.getPermissionTemplateByName(KFSConstants.CoreModuleNamespaces.ACCESS_SECURITY, SecurityTemplateNames.VIEW_DOCUMENT_FIELD_VALUE);
723 if (ObjectUtils.isNotNull(templateInfo)) {
724 return templateInfo.getPermissionTemplateId();
725 }
726 else
727 throw new RuntimeException(SecurityTemplateNames.VIEW_DOCUMENT_FIELD_VALUE + " parameter does not exist");
728 }
729
730
731 /**
732 * @see org.kuali.kfs.sec.service.AccessSecurityService#getViewNotesAttachmentsWithFieldValueTemplateId()
733 */
734 public String getViewNotesAttachmentsWithFieldValueTemplateId() {
735 KimPermissionTemplateInfo templateInfo = permissionService.getPermissionTemplateByName(KFSConstants.CoreModuleNamespaces.ACCESS_SECURITY, SecurityTemplateNames.VIEW_NOTES_ATTACHMENTS_FIELD_VALUE);
736 if (ObjectUtils.isNotNull(templateInfo)) {
737 return templateInfo.getPermissionTemplateId();
738 }
739 else
740 throw new RuntimeException(SecurityTemplateNames.VIEW_NOTES_ATTACHMENTS_FIELD_VALUE + " parameter does not exist");
741 }
742
743 }