View Javadoc
1   /*
2    * Copyright 2012 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.ole.sec.document;
17  
18  import java.util.HashMap;
19  import java.util.Map;
20  
21  import org.apache.commons.lang.StringUtils;
22  import org.joda.time.DateTime;
23  import org.kuali.ole.sec.SecConstants;
24  import org.kuali.ole.sec.businessobject.AbstractSecurityModelDefinition;
25  import org.kuali.ole.sec.businessobject.SecurityModelMember;
26  import org.kuali.ole.sec.identity.SecKimAttributes;
27  import org.kuali.ole.sys.context.SpringContext;
28  import org.kuali.ole.sys.document.FinancialSystemMaintainable;
29  import org.kuali.rice.core.api.criteria.PredicateFactory;
30  import org.kuali.rice.core.api.criteria.QueryByCriteria;
31  import org.kuali.rice.core.api.membership.MemberType;
32  import org.kuali.rice.kim.api.KimConstants;
33  import org.kuali.rice.kim.api.role.Role;
34  import org.kuali.rice.kim.api.role.RoleMember;
35  import org.kuali.rice.kim.api.role.RoleMemberQueryResults;
36  import org.kuali.rice.kim.api.role.RoleService;
37  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
38  import org.kuali.rice.kns.document.MaintenanceDocument;
39  import org.kuali.rice.krad.bo.PersistableBusinessObject;
40  
41  public abstract class AbstractSecurityModuleMaintainable extends FinancialSystemMaintainable {
42  
43      /**
44       * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#refresh(java.lang.String, java.util.Map,
45       *      org.kuali.rice.kns.document.MaintenanceDocument)
46       */
47      @Override
48      public void refresh(String refreshCaller, Map fieldValues, MaintenanceDocument document) {
49          super.refresh(refreshCaller, fieldValues, document);
50  
51          getBusinessObject().refreshNonUpdateableReferences();
52          for (PersistableBusinessObject businessObject : newCollectionLines.values() ) {
53              businessObject.refreshNonUpdateableReferences();
54          }
55      }
56  
57      protected String getDefaultRoleTypeId() {
58          return KimApiServiceLocator.getKimTypeInfoService().findKimTypeByNameAndNamespace(KimConstants.KIM_TYPE_DEFAULT_NAMESPACE, KimConstants.KIM_TYPE_DEFAULT_NAME).getId();
59      }
60      
61      protected Map<String,String> getRoleQualifiersFromSecurityModelDefinition( AbstractSecurityModelDefinition def ) {
62          Map<String,String> membershipQualifications = new HashMap<String,String>(4);
63          membershipQualifications.put(SecKimAttributes.CONSTRAINT_CODE, def.getConstraintCode());
64          membershipQualifications.put(SecKimAttributes.OPERATOR, def.getOperatorCode());
65          membershipQualifications.put(SecKimAttributes.PROPERTY_VALUE, def.getAttributeValue());
66          membershipQualifications.put(SecKimAttributes.OVERRIDE_DENY, Boolean.toString(def.isOverrideDeny()));
67          
68          return membershipQualifications;
69      }
70      
71      protected void updateSecurityModelRoleMember( Role modelRole, SecurityModelMember modelMember, String memberTypeCode, String memberId, Map<String,String> roleQualifiers ) {
72          RoleService roleService = KimApiServiceLocator.getRoleService();
73  
74          RoleMember existingRoleMember = getRoleMembershipForMemberType(modelRole.getId(), memberId, memberTypeCode, roleQualifiers);
75          
76          if ( existingRoleMember == null ) {
77              // new role member
78              if ( memberTypeCode.equals( MemberType.PRINCIPAL.getCode() ) ) {
79                  roleService.assignPrincipalToRole(memberId, modelRole.getNamespaceCode(), modelRole.getName(), roleQualifiers);
80              } else if ( memberTypeCode.equals( MemberType.GROUP.getCode() ) ) {
81                  roleService.assignGroupToRole(memberId, modelRole.getNamespaceCode(), modelRole.getName(), roleQualifiers);
82              } else if ( memberTypeCode.equals( MemberType.ROLE.getCode() ) ) {
83                  roleService.assignRoleToRole(memberId, modelRole.getNamespaceCode(), modelRole.getName(), roleQualifiers);
84              } else {
85                  throw new RuntimeException( "Invalid role member type code: " + memberTypeCode );
86              }
87              // now, we need to re-retrieve it in order to set the from/to dates
88              existingRoleMember = getRoleMembershipForMemberType(modelRole.getId(), memberId, memberTypeCode, roleQualifiers);
89              if ( existingRoleMember == null ) {
90                  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 );
91              }
92          } 
93          RoleMember.Builder updatedRoleMember = RoleMember.Builder.create(existingRoleMember);
94          updatedRoleMember.setAttributes(new HashMap<String,String>(0));
95          updatedRoleMember.setType(MemberType.fromCode(memberTypeCode));
96          updatedRoleMember.setMemberId(memberId);
97          updatedRoleMember.setActiveFromDate( (modelMember.getActiveFromDate()==null)?null:new DateTime( modelMember.getActiveFromDate().getTime() ) );
98          updatedRoleMember.setActiveToDate( (modelMember.getActiveToDate()==null)?null:new DateTime( modelMember.getActiveToDate().getTime() ) );
99          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 }