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 }