/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.sec.document; import java.util.HashMap; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.joda.time.DateTime; import org.kuali.kfs.sec.SecConstants; import org.kuali.kfs.sec.businessobject.AbstractSecurityModelDefinition; import org.kuali.kfs.sec.businessobject.SecurityModelMember; import org.kuali.kfs.sec.identity.SecKimAttributes; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.document.FinancialSystemMaintainable; import org.kuali.rice.core.api.criteria.PredicateFactory; import org.kuali.rice.core.api.criteria.QueryByCriteria; import org.kuali.rice.core.api.membership.MemberType; import org.kuali.rice.kim.api.KimConstants; import org.kuali.rice.kim.api.role.Role; import org.kuali.rice.kim.api.role.RoleMember; import org.kuali.rice.kim.api.role.RoleMemberQueryResults; import org.kuali.rice.kim.api.role.RoleService; import org.kuali.rice.kim.api.services.KimApiServiceLocator; import org.kuali.rice.kns.document.MaintenanceDocument; import org.kuali.rice.krad.bo.PersistableBusinessObject; public abstract class AbstractSecurityModuleMaintainable extends FinancialSystemMaintainable { /** * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#refresh(java.lang.String, java.util.Map, * org.kuali.rice.kns.document.MaintenanceDocument) */ @Override public void refresh(String refreshCaller, Map fieldValues, MaintenanceDocument document) { super.refresh(refreshCaller, fieldValues, document); getBusinessObject().refreshNonUpdateableReferences(); for (PersistableBusinessObject businessObject : newCollectionLines.values() ) { businessObject.refreshNonUpdateableReferences(); } } protected String getDefaultRoleTypeId() { return KimApiServiceLocator.getKimTypeInfoService().findKimTypeByNameAndNamespace(KimConstants.KIM_TYPE_DEFAULT_NAMESPACE, KimConstants.KIM_TYPE_DEFAULT_NAME).getId(); } protected Map<String,String> getRoleQualifiersFromSecurityModelDefinition( AbstractSecurityModelDefinition def ) { Map<String,String> membershipQualifications = new HashMap<String,String>(4); membershipQualifications.put(SecKimAttributes.CONSTRAINT_CODE, def.getConstraintCode()); membershipQualifications.put(SecKimAttributes.OPERATOR, def.getOperatorCode()); membershipQualifications.put(SecKimAttributes.PROPERTY_VALUE, def.getAttributeValue()); membershipQualifications.put(SecKimAttributes.OVERRIDE_DENY, Boolean.toString(def.isOverrideDeny())); return membershipQualifications; } protected void updateSecurityModelRoleMember( Role modelRole, SecurityModelMember modelMember, String memberTypeCode, String memberId, Map<String,String> roleQualifiers ) { RoleService roleService = KimApiServiceLocator.getRoleService(); RoleMember existingRoleMember = getRoleMembershipForMemberType(modelRole.getId(), memberId, memberTypeCode, roleQualifiers); if ( existingRoleMember == null ) { // new role member if ( memberTypeCode.equals( MemberType.PRINCIPAL.getCode() ) ) { roleService.assignPrincipalToRole(memberId, modelRole.getNamespaceCode(), modelRole.getName(), roleQualifiers); } else if ( memberTypeCode.equals( MemberType.GROUP.getCode() ) ) { roleService.assignGroupToRole(memberId, modelRole.getNamespaceCode(), modelRole.getName(), roleQualifiers); } else if ( memberTypeCode.equals( MemberType.ROLE.getCode() ) ) { roleService.assignRoleToRole(memberId, modelRole.getNamespaceCode(), modelRole.getName(), roleQualifiers); } else { throw new RuntimeException( "Invalid role member type code: " + memberTypeCode ); } // now, we need to re-retrieve it in order to set the from/to dates existingRoleMember = getRoleMembershipForMemberType(modelRole.getId(), memberId, memberTypeCode, roleQualifiers); if ( existingRoleMember == null ) { throw new RuntimeException( "Role member was not saved properly. Retrieval of role member after save failed for role: " + modelRole.getId() + " and Member Type/ID: " + memberTypeCode + "/" + memberId ); } } RoleMember.Builder updatedRoleMember = RoleMember.Builder.create(existingRoleMember); updatedRoleMember.setAttributes(new HashMap<String,String>(0)); updatedRoleMember.setType(MemberType.fromCode(memberTypeCode)); updatedRoleMember.setMemberId(memberId); updatedRoleMember.setActiveFromDate( (modelMember.getActiveFromDate()==null)?null:new DateTime( modelMember.getActiveFromDate().getTime() ) ); updatedRoleMember.setActiveToDate( (modelMember.getActiveToDate()==null)?null:new DateTime( modelMember.getActiveToDate().getTime() ) ); roleService.updateRoleMember(updatedRoleMember.build()); } /** * Finds the role membership (if exists) for the given role and member id * * @param roleId id of role to find member for * @param memberRoleId id of member role * @param membershipQualifications Qualifications to match role membership * @return RoleMembership containing information on the member record, or null if the member id is not assigned to the role */ protected RoleMember getRoleMembershipForMemberType(String roleId, String memberId, String memberType, Map<String,String> membershipQualifications) { RoleService roleService = KimApiServiceLocator.getRoleService(); RoleMemberQueryResults results = roleService.findRoleMembers( QueryByCriteria.Builder.fromPredicates( PredicateFactory.equal("roleId", roleId), PredicateFactory.equal("typeCode", memberType), PredicateFactory.equal("memberId", memberId) ) ); for (RoleMember roleMembershipInfo : results.getResults() ) { // no qualifiers - then an automatic match if (membershipQualifications == null || membershipQualifications.isEmpty() ) { return roleMembershipInfo; } // otherwise, check the qualifier attributes if (doQualificationsMatch(membershipQualifications, roleMembershipInfo.getAttributes())) { return roleMembershipInfo; } } return null; } /** * Determines whether an Map<String,String> has the same keys and values as another Map<String,String> * * @param qualfiicationToMatch Map<String,String> to match keys and values * @param qualfication Map<String,String> for matching * @return boolean if second Map<String,String> has same keys and values as first */ protected boolean doQualificationsMatch(Map<String,String> qualificationToMatch, Map<String,String> qualification) { for (String key : qualificationToMatch.keySet()) { if (qualification.containsKey(key)) { String matchValue = qualification.get(key); String value = qualificationToMatch.get(key); if ( !StringUtils.equals(value, matchValue) ) { return false; } } else { return false; } } return true; } /** * Determines whether each of the qualifying values in the given qualification (Map<String,String>) match the given corresponding values * * @param membershipQualifications Map<String,String> containing qualifying values to check * @param constraintCode constraint code value to match * @param operator operator value to match * @param attributeValue attribute value to match * @return boolean true if all qualifying values match the given values, false if at least one qualifying value does not match */ protected boolean doMembershipQualificationsMatchValues(Map<String,String> membershipQualifications, String constraintCode, String operator, String attributeValue) { String constraintQualifyValue = membershipQualifications.get(SecKimAttributes.CONSTRAINT_CODE); String operatorQualifyValue = membershipQualifications.get(SecKimAttributes.OPERATOR); String propertyValueQualifyValue = membershipQualifications.get(SecKimAttributes.PROPERTY_VALUE); if (!StringUtils.equals(propertyValueQualifyValue, attributeValue)) { return false; } if (!StringUtils.equals(constraintQualifyValue, constraintCode)) { return false; } if (!StringUtils.equals(operatorQualifyValue, operator)) { return false; } return true; } }