001/* 002 * Copyright 2012 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 */ 016package org.kuali.ole.sec.document; 017 018import java.util.HashMap; 019import java.util.Map; 020 021import org.apache.commons.lang.StringUtils; 022import org.joda.time.DateTime; 023import org.kuali.ole.sec.SecConstants; 024import org.kuali.ole.sec.businessobject.AbstractSecurityModelDefinition; 025import org.kuali.ole.sec.businessobject.SecurityModelMember; 026import org.kuali.ole.sec.identity.SecKimAttributes; 027import org.kuali.ole.sys.context.SpringContext; 028import org.kuali.ole.sys.document.FinancialSystemMaintainable; 029import org.kuali.rice.core.api.criteria.PredicateFactory; 030import org.kuali.rice.core.api.criteria.QueryByCriteria; 031import org.kuali.rice.core.api.membership.MemberType; 032import org.kuali.rice.kim.api.KimConstants; 033import org.kuali.rice.kim.api.role.Role; 034import org.kuali.rice.kim.api.role.RoleMember; 035import org.kuali.rice.kim.api.role.RoleMemberQueryResults; 036import org.kuali.rice.kim.api.role.RoleService; 037import org.kuali.rice.kim.api.services.KimApiServiceLocator; 038import org.kuali.rice.kns.document.MaintenanceDocument; 039import org.kuali.rice.krad.bo.PersistableBusinessObject; 040 041public abstract class AbstractSecurityModuleMaintainable extends FinancialSystemMaintainable { 042 043 /** 044 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#refresh(java.lang.String, java.util.Map, 045 * org.kuali.rice.kns.document.MaintenanceDocument) 046 */ 047 @Override 048 public void refresh(String refreshCaller, Map fieldValues, MaintenanceDocument document) { 049 super.refresh(refreshCaller, fieldValues, document); 050 051 getBusinessObject().refreshNonUpdateableReferences(); 052 for (PersistableBusinessObject businessObject : newCollectionLines.values() ) { 053 businessObject.refreshNonUpdateableReferences(); 054 } 055 } 056 057 protected String getDefaultRoleTypeId() { 058 return KimApiServiceLocator.getKimTypeInfoService().findKimTypeByNameAndNamespace(KimConstants.KIM_TYPE_DEFAULT_NAMESPACE, KimConstants.KIM_TYPE_DEFAULT_NAME).getId(); 059 } 060 061 protected Map<String,String> getRoleQualifiersFromSecurityModelDefinition( AbstractSecurityModelDefinition def ) { 062 Map<String,String> membershipQualifications = new HashMap<String,String>(4); 063 membershipQualifications.put(SecKimAttributes.CONSTRAINT_CODE, def.getConstraintCode()); 064 membershipQualifications.put(SecKimAttributes.OPERATOR, def.getOperatorCode()); 065 membershipQualifications.put(SecKimAttributes.PROPERTY_VALUE, def.getAttributeValue()); 066 membershipQualifications.put(SecKimAttributes.OVERRIDE_DENY, Boolean.toString(def.isOverrideDeny())); 067 068 return membershipQualifications; 069 } 070 071 protected void updateSecurityModelRoleMember( Role modelRole, SecurityModelMember modelMember, String memberTypeCode, String memberId, Map<String,String> roleQualifiers ) { 072 RoleService roleService = KimApiServiceLocator.getRoleService(); 073 074 RoleMember existingRoleMember = getRoleMembershipForMemberType(modelRole.getId(), memberId, memberTypeCode, roleQualifiers); 075 076 if ( existingRoleMember == null ) { 077 // new role member 078 if ( memberTypeCode.equals( MemberType.PRINCIPAL.getCode() ) ) { 079 roleService.assignPrincipalToRole(memberId, modelRole.getNamespaceCode(), modelRole.getName(), roleQualifiers); 080 } else if ( memberTypeCode.equals( MemberType.GROUP.getCode() ) ) { 081 roleService.assignGroupToRole(memberId, modelRole.getNamespaceCode(), modelRole.getName(), roleQualifiers); 082 } else if ( memberTypeCode.equals( MemberType.ROLE.getCode() ) ) { 083 roleService.assignRoleToRole(memberId, modelRole.getNamespaceCode(), modelRole.getName(), roleQualifiers); 084 } else { 085 throw new RuntimeException( "Invalid role member type code: " + memberTypeCode ); 086 } 087 // now, we need to re-retrieve it in order to set the from/to dates 088 existingRoleMember = getRoleMembershipForMemberType(modelRole.getId(), memberId, memberTypeCode, roleQualifiers); 089 if ( existingRoleMember == null ) { 090 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 ); 091 } 092 } 093 RoleMember.Builder updatedRoleMember = RoleMember.Builder.create(existingRoleMember); 094 updatedRoleMember.setAttributes(new HashMap<String,String>(0)); 095 updatedRoleMember.setType(MemberType.fromCode(memberTypeCode)); 096 updatedRoleMember.setMemberId(memberId); 097 updatedRoleMember.setActiveFromDate( (modelMember.getActiveFromDate()==null)?null:new DateTime( modelMember.getActiveFromDate().getTime() ) ); 098 updatedRoleMember.setActiveToDate( (modelMember.getActiveToDate()==null)?null:new DateTime( modelMember.getActiveToDate().getTime() ) ); 099 roleService.updateRoleMember(updatedRoleMember.build()); 100 101 } 102 103 /** 104 * Finds the role membership (if exists) for the given role and member id 105 * 106 * @param roleId id of role to find member for 107 * @param memberRoleId id of member role 108 * @param membershipQualifications Qualifications to match role membership 109 * @return RoleMembership containing information on the member record, or null if the member id is not assigned to the role 110 */ 111 protected RoleMember getRoleMembershipForMemberType(String roleId, String memberId, String memberType, Map<String,String> membershipQualifications) { 112 RoleService roleService = KimApiServiceLocator.getRoleService(); 113 114 RoleMemberQueryResults results = roleService.findRoleMembers( 115 QueryByCriteria.Builder.fromPredicates( 116 PredicateFactory.equal("roleId", roleId), 117 PredicateFactory.equal("typeCode", memberType), 118 PredicateFactory.equal("memberId", memberId) ) ); 119 for (RoleMember roleMembershipInfo : results.getResults() ) { 120 // no qualifiers - then an automatic match 121 if (membershipQualifications == null || membershipQualifications.isEmpty() ) { 122 return roleMembershipInfo; 123 } 124 // otherwise, check the qualifier attributes 125 if (doQualificationsMatch(membershipQualifications, roleMembershipInfo.getAttributes())) { 126 return roleMembershipInfo; 127 } 128 } 129 130 return null; 131 } 132 133 /** 134 * Determines whether an Map<String,String> has the same keys and values as another Map<String,String> 135 * 136 * @param qualfiicationToMatch Map<String,String> to match keys and values 137 * @param qualfication Map<String,String> for matching 138 * @return boolean if second Map<String,String> has same keys and values as first 139 */ 140 protected boolean doQualificationsMatch(Map<String,String> qualificationToMatch, Map<String,String> qualification) { 141 for (String key : qualificationToMatch.keySet()) { 142 if (qualification.containsKey(key)) { 143 String matchValue = qualification.get(key); 144 String value = qualificationToMatch.get(key); 145 146 if ( !StringUtils.equals(value, matchValue) ) { 147 return false; 148 } 149 } else { 150 return false; 151 } 152 } 153 154 return true; 155 } 156 157 /** 158 * Determines whether each of the qualifying values in the given qualification (Map<String,String>) match the given corresponding values 159 * 160 * @param membershipQualifications Map<String,String> containing qualifying values to check 161 * @param constraintCode constraint code value to match 162 * @param operator operator value to match 163 * @param attributeValue attribute value to match 164 * @return boolean true if all qualifying values match the given values, false if at least one qualifying value does not match 165 */ 166 protected boolean doMembershipQualificationsMatchValues(Map<String,String> membershipQualifications, String constraintCode, String operator, String attributeValue) { 167 String constraintQualifyValue = membershipQualifications.get(SecKimAttributes.CONSTRAINT_CODE); 168 String operatorQualifyValue = membershipQualifications.get(SecKimAttributes.OPERATOR); 169 String propertyValueQualifyValue = membershipQualifications.get(SecKimAttributes.PROPERTY_VALUE); 170 171 if (!StringUtils.equals(propertyValueQualifyValue, attributeValue)) { 172 return false; 173 } 174 175 if (!StringUtils.equals(constraintQualifyValue, constraintCode)) { 176 return false; 177 } 178 179 if (!StringUtils.equals(operatorQualifyValue, operator)) { 180 return false; 181 } 182 183 return true; 184 } 185}