Overrides
We needed to overide the PersonServiceImpl class which, since it is a KIM module and essential to implementing searching using LDAP made sense to include it in the Rice LDAP Connector module. In order to differentiate our implementation we created a new package edu.uconn.kuali.rice.kim.identity with the UConnPersonServiceImp class and include a "bean" definition in the KIMLdapSprings.xml file (see Wiring it All Together).
Mappers
The mapping implementation for Rice v2 change significantly as each "entity" category mapper now returns a list of "Builder" objects see (Rice 2.0 release notes).
The PrincipalMapper class out of the box does not implement the method (protected boolean isPersonActive(DirContextOperations context) )to determine if the person in question is "active" (has an affiliation with the university). Instead of this implementing this method we created a new isPersonActive method (see below) which compares the values of the LDAP eduPersonAffiliation attribute with affiliation mappings rice config parameter (STAFF=staff,FCLTY=faculty,STDNT=student,AFLT=affiliate)
protected boolean isPersonActive(String[] affiliattions) { if (affiliattions != null) { String[] mappings = getConstants().getAffiliationMappings().split(","); for (String affiliationName : affiliattions) { for (String affilMap : mappings) { if (contains(affilMap, affiliationName)) { return true; } } } } return false; }
Wiring it All Together
KIMLdapSpringBeans.xml
Replaced the existing connection information with connection pooling, TLS , and ldap attribute mapping elements from our Rice-1.0.5 LDAP implementation.
<?xml version="1.0" encoding="UTF-8"?> <!-- Copyright 2005-2014 The Kuali Foundation Licensed under the Educational Community License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.opensource.org/licenses/ecl2.php Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <!-- Modified for UConn specific LDAP implementation --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> <bean id="rice.kim.ldap.import.parameterService" class="org.kuali.rice.core.framework.resourceloader.GlobalResourceLoaderServiceFactoryBean" p:serviceName="parameterService"/> <!-- connection pooling --> <bean id="contextSource" class="org.springframework.ldap.pool.factory.PoolingContextSource"> <property name="contextSource" ref="contextSourceTarget" /> <property name="dirContextValidator" ref="dirContextValidator" /> <property name="testOnBorrow" value="true" /> <property name="testWhileIdle" value="true" /> <property name="timeBetweenEvictionRunsMillis" value="120000"/> <property name="minEvictableIdleTimeMillis" value="300000"/> <property name="numTestsPerEvictionRun" value="4"/> </bean> <!-- using TLS --> <bean id="contextSourceTarget" class="org.springframework.ldap.core.support.LdapContextSource"> <property name="url" value="${rice.ldap.url}" /> <property name="base" value="${rice.ldap.base}" /> <property name="authenticationSource" ref="authenticationSource" /> <property name="authenticationStrategy"> <bean class="org.springframework.ldap.core.support.DefaultTlsDirContextAuthenticationStrategy"> <property name="shutdownTlsGracefully" value="true"></property> </bean> </property> <property name="pooled" value="false"/> </bean> <bean id="dirContextValidator" class="org.springframework.ldap.pool.validation.DefaultDirContextValidator" > </bean> <bean id="contextSourceWrt" class="org.springframework.ldap.core.support.LdapContextSource"> <property name="url" value="${rice.ldap.wrt.url}" /> <property name="base" value="${rice.ldap.base}" /> <property name="authenticationSource" ref="authenticationSource" /> <property name="authenticationStrategy"> <bean class="org.springframework.ldap.core.support.DefaultTlsDirContextAuthenticationStrategy"> <property name="shutdownTlsGracefully" value="true"></property> </bean> </property> <property name="pooled" value="false"/> </bean> <bean id="kimPlatformAwareDao" abstract="true" class="org.kuali.rice.kns.dao.impl.PlatformAwareDaoBaseOjb"> <property name="jcdAlias" value="kimDataSource" /> <property name="dbPlatform" ref="dbPlatform" /> </bean> <bean id="authenticationSource" class="org.springframework.ldap.authentication.DefaultValuesAuthenticationSourceDecorator"> <property name="target" ref="springSecurityAuthenticationSource" /> <property name="defaultUser" value="${rice.ldap.username}" /> <property name="defaultPassword" value="${rice.ldap.password}" /> </bean> <bean id="springSecurityAuthenticationSource" class="org.springframework.security.ldap.authentication.SpringSecurityAuthenticationSource" /> <bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate"> <constructor-arg ref="contextSource" /> </bean> <bean id="ldapTemplateWrt" class="org.springframework.ldap.core.LdapTemplate"> <constructor-arg ref="contextSourceWrt" /> </bean> <!-- ///////////////////////////////////////////////////// --> <!--// Utility beans // --> <!-- ///////////////////////////////////////////////////// --> <bean id="orgDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${datasource.driver.name}" /> <property name="url" value="${kfs.datasource.url}" /> <property name="maxActive" value="${datasource.pool.maxActive}" /> <property name="minIdle" value="${datasource.minIdle}" /> <property name="initialSize" value="${datasource.initialSize}" /> <property name="validationQuery" value="${datasource.pool.validationQuery}" /> <property name="username" value="${kfs.datasource.username}" /> <property name="password" value="${kfs.datasource.password}" /> <property name="accessToUnderlyingConnectionAllowed" value="true" /> </bean> <!-- ///////////////////////////////////////////////////// --> <!--// end Utility beans // --> <!-- ///////////////////////////////////////////////////// --> <bean id="ldapUtilDao" class="org.kuali.rice.kim.ldap.dao.impl.UConnLdapUtilDaoImpl"> <property name="ldapTemplate" ref="ldapTemplateWrt" /> <property name="constants" ref="kimConstants" /> </bean> <bean id="uconnLdapOrgDao" class="org.kuali.rice.kim.ldap.dao.impl.UConnLdapOrgDaoImpl" > <property name="datasource" ref="orgDataSource" /> <property name="constants" ref="kimConstants" /> </bean> <!-- //////////////////////////////////////////////////////////////// --> <!-- // Start of Mappings // --> <!-- //////////////////////////////////////////////////////////////// --> <bean id="ContextMapper-EntityAddress" parent="ContextMapper-EntityAddress-parentBean" /> <bean id="ContextMapper-EntityAddress-parentBean" abstract="true" class="org.kuali.rice.kim.ldap.EntityAddressMapper" > <property name="constants" ref="kimConstants" /> </bean> <!-- UConn specific affiliations mapping <bean id="ContextMapper-EntityAffiliation" parent="ContextMapper-uconnEntityAffiliation-parentBean" /> <bean id="ContextMapper-uconnEntityAffiliation-parentBean" abstract="true" class="org.kuali.rice.kim.ldap.UconnEntityAffiliationMapper" > <property name="constants" ref="kimConstants" /> <property name="entityAffiliationMappper" ref="ContextMapper-defaultEntityAffiliation"/> </bean> <bean id="ContextMapper-defaultEntityAffiliation" parent="ContextMapper-uconnEntityAffiliation-parentBean" /> <bean id="ContextMapper-entityAffiliation-parentBean" abstract="true" class="org.kuali.rice.kim.ldap.EntityAffiliationMapper" > <property name="constants" ref="kimConstants" /> </bean> end UConn specific affiliations mapping --> <bean id="ContextMapper-EntityAffiliation" parent="ContextMapper-EntityAffiliation-parentBean" /> <bean id="ContextMapper-EntityAffiliation-parentBean" abstract="true" class="org.kuali.rice.kim.ldap.EntityAffiliationMapper" > <property name="constants" ref="kimConstants" /> </bean> <bean id="ContextMapper-EntityDefault" parent="ContextMapper-EntityDefault-parentBean" /> <bean id="ContextMapper-EntityDefault-parentBean" abstract="true" class="org.kuali.rice.kim.ldap.EntityDefaultMapper" > <property name="constants" ref="kimConstants" /> <property name="affiliationMapper" ref="ContextMapper-EntityAffiliation" /> <property name="defaultNameMapper" ref="ContextMapper-EntityName" /> <property name="employmentMapper" ref="ContextMapper-EntityEmployment" /> <property name="entityTypeContactInfoDefaultMapper" ref="ContextMapper-EntityTypeContactInfoDefault" /> </bean> <bean id="ContextMapper-EntityEmail" parent="ContextMapper-EntityEmail-parentBean" /> <bean id="ContextMapper-EntityEmail-parentBean" abstract="true" class="org.kuali.rice.kim.ldap.EntityEmailMapper" > <property name="constants" ref="kimConstants" /> </bean> <bean id="ContextMapper-EntityEmployment" parent="ContextMapper-EntityEmployment-parentBean" /> <bean id="ContextMapper-EntityEmployment-parentBean" abstract="true" class="org.kuali.rice.kim.ldap.EntityEmploymentMapper" > <property name="constants" ref="kimConstants" /> <property name="uconnLdapOrgDao" ref="uconnLdapOrgDao" /> <property name="ldapUtilDao" ref="ldapUtilDao" /> </bean> <bean id="ContextMapper-EntityTypeContactInfoDefault" parent="ContextMapper-EntityTypeContactInfoDefault-parentBean" /> <bean id="ContextMapper-EntityTypeContactInfoDefault-parentBean" abstract="true" class="org.kuali.rice.kim.ldap.EntityTypeContactInfoDefaultMapper" > <property name="constants" ref="kimConstants" /> <property name="addressMapper" ref="ContextMapper-EntityAddress" /> <property name="phoneMapper" ref="ContextMapper-EntityPhone" /> <property name="emailMapper" ref="ContextMapper-EntityEmail" /> </bean> <bean id="ContextMapper-EntityTypeContactInfo" parent="ContextMapper-EntityTypeContactInfo-parentBean" /> <bean id="ContextMapper-EntityTypeContactInfo-parentBean" abstract="true" class="org.kuali.rice.kim.ldap.EntityTypeContactInfoMapper" > <property name="constants" ref="kimConstants" /> <property name="addressMapper" ref="ContextMapper-EntityAddress" /> <property name="phoneMapper" ref="ContextMapper-EntityPhone" /> <property name="emailMapper" ref="ContextMapper-EntityEmail" /> </bean> <bean id="ContextMapper-Entity" parent="ContextMapper-Entity-parentBean" /> <bean id="ContextMapper-Entity-parentBean" abstract="true" class="org.kuali.rice.kim.ldap.EntityMapper" > <property name="constants" ref="kimConstants" /> <property name="affiliationMapper" ref="ContextMapper-EntityAffiliation" /> <property name="defaultNameMapper" ref="ContextMapper-EntityName" /> <property name="employmentMapper" ref="ContextMapper-EntityEmployment" /> <property name="entityTypeContactInfoMapper" ref="ContextMapper-EntityTypeContactInfo" /> </bean> <bean id="ContextMapper-EntityName" parent="ContextMapper-EntityName-parentBean" /> <bean id="ContextMapper-EntityName-parentBean" abstract="true" class="org.kuali.rice.kim.ldap.EntityNameMapper" > <property name="constants" ref="kimConstants" /> </bean> <bean id="ContextMapper-EntityNamePrincipalName" parent="ContextMapper-EntityNamePrincipalName-parentBean" /> <bean id="ContextMapper-EntityNamePrincipalName-parentBean" abstract="true" class="org.kuali.rice.kim.ldap.EntityNamePrincipalNameMapper" > <property name="constants" ref="kimConstants" /> <property name="defaultNameMapper" ref="ContextMapper-EntityName" /> </bean> <bean id="ContextMapper-EntityPhone" parent="ContextMapper-EntityPhone-parentBean" /> <bean id="ContextMapper-EntityPhone-parentBean" abstract="true" class="org.kuali.rice.kim.ldap.EntityPhoneMapper" > <property name="constants" ref="kimConstants" /> </bean> <bean id="ContextMapper-EntityPrivacyPreferences" parent="ContextMapper-EntityPrivacyPreferences-parentBean" /> <bean id="ContextMapper-EntityPrivacyPreferences-parentBean" abstract="true" class="org.kuali.rice.kim.ldap.EntityPrivacyPreferencesMapper" > <property name="constants" ref="kimConstants" /> </bean> <bean id="ContextMapper-Principal" parent="ContextMapper-Principal-parentBean" /> <bean id="ContextMapper-Principal-parentBean" abstract="true" class="org.kuali.rice.kim.ldap.PrincipalMapper" > <property name="constants" ref="kimConstants" /> <property name="parameterService" ref="rice.kim.ldap.import.parameterService" /> </bean> <!-- //////////////////////////////////////////////////////////////// --> <!-- // End of Mappings // --> <!-- //////////////////////////////////////////////////////////////// --> <!-- //////////////////////////////////////////////////////////////// --> <!-- // ldap attribute constants // --> <!-- //////////////////////////////////////////////////////////////// --> <bean id="kimConstants" class="org.kuali.rice.kim.util.ConstantsImpl"> <!-- for both KimPrincipal and KimEntity --> <property name="kimLdapIdProperty" value="${rice.ldapattr.entityId}" /> <!-- for KimPrincipalInfo --> <property name="kimLdapNameProperty" value="${rice.ldapattr.principalName}" /> <property name="principalAlwayActive" value="${rice.ldap.principalAlwaysActive}" /> <!-- for KimEntityNameInfo --> <property name="snLdapProperty" value="${rice.ldapattr.lastName}" /> <property name="middleNameLdapProperty" value="${rice.ldapattr.middleName}" /> <property name="givenNameLdapProperty" value="${rice.ldapattr.firstName}" /> <property name="cnLdapProperty" value="${rice.ldapattr.fullName}" /> <property name="titleLdapProperty" value="${rice.ldapattr.title}" /> <property name="entityTitleLength" value="${rice.kim.entityTitleLength}" /> <property name="uconnPublishedLdap" value="${rice.ldapattr.uconnPublished}" /> <property name="uconnPublishEmail" value="${rice.ldapattr.uconnPublished.email}" /> <!-- other person mappings --> <property name="dateOfBirth" value="${rice.ldapattr.date.of.birth}" /> <!-- for KimEntityEmailInfo --> <property name="mailLdapProperty" value="${rice.ldapattr.email}" /> <!-- for KimEntityPhoneInfo --> <property name="phoneLdapProperty" value="${rice.ldapattr.phoneNumber}" /> <property name="phonePatternKim" value="${rice.pattern.phoneNumberKimFormat}" /> <property name="phonePatternLdap" value="${rice.pattern.phoneNumberLdapRegex}" /> <!-- for KimEntityEmploymentInformationInfo --> <property name="employeeIdProperty" value="${rice.ldapattr.employeeId}" /> <property name="empolyeePayrollIdProperty" value="${rice.ldapattr.payrollId}" /> <property name="departmentCodeLdapProperty" value="${rice.ldapattr.deptNumber}" /> <property name="departmentNameLdapProperty" value="${rice.ldapattr.deptName}" /> <property name="employeeTypeProperty" value="${rice.ldapattr.employeeType}" /> <property name="employeeStatusProperty" value="${rice.ldapattr.employeeStatus}" /> <property name="employeeTypeMappings" value="${rice.ldap.employeeTypeMappings}" /> <property name="employeeStatusMappings" value="${rice.ldap.employeeStatusMappings}" /> <property name="employeeStatusId" value="${rice.kim.employee.status.id}" /> <property name="kualiDeptCodeLdapProperty" value="${rice.ldap.kuali.dept.cd}" /> <property name="unitCodeLdapProperty" value="${rice.ldapattr.unitNumber}" /> <!-- for KimEntityAddressInfo --> <property name="streetLdapProperty" value="${rice.ldapattr.street}" /> <property name="buildingLdapProperty" value="${rice.ldapattr.building}" /> <property name="postalAddrLdapProperty" value="${rice.ldapattr.postalAddr}" /> <property name="cityLdapProperty" value="${rice.ldapattr.city}" /> <property name="stateLdapProperty" value="${rice.ldapattr.state}" /> <property name="zipCodeLdapProperty" value="${rice.ldapattr.zipCode}" /> <property name="countryLdapProperty" value="${rice.ldapattr.country}" /> <property name="defaultCountryCode" value="${rice.ldap.defaultCountryCode}" /> <property name="defaultZipCode" value="${rice.ldap.defaultZipCode}" /> <property name="cityZipMappings" value="${rice.ldap.cityZipMappings}" /> <property name="defaultStateCode" value="${rice.ldap.defaultStateCode}" /> <!-- for KimEntityAffiliationInfo --> <property name="campusCodeLdapProperty" value="${rice.ldapattr.campus}" /> <property name="campusLdapProperty" value="${rice.ldapattr.campus}" /> <property name="primaryAffiliationLdapProperty" value="${rice.ldapattr.primaryAffiliation}" /> <property name="affiliationLdapProperty" value="${rice.ldapattr.affiliation}" /> <property name="campusMappings" value="${rice.ldap.campusMappings}" /> <property name="affiliationMappings" value="${rice.ldap.affiliationMappings}" /> <property name="employeeAffiliationCodes" value="Staff,Student,Faculty,Employee" /> <property name="defaultCampusCode" value="${rice.ldap.defaultCampusCode}" /> <!-- for KimEntityEntityTypeDefaultInfo and KimEntityEntityTypeInfo --> <property name="kimToLdapFieldMappings" value="${kim.to.ldap.field.mappings}" /> <property name="kimToLdapValueMappings" value="${kim.to.ldap.value.mappings}" /> <property name="parameterNamespaceCode" value="KR-SYS" /> <property name="parameterDetailTypeCode" value="Config" /> <property name="personEntityTypeCode" value="PERSON" /> <property name="kimToLdapUnmappedMappings" value="employeeStatus=, employeeType=" /> <property name="externalIdTypeCode" value="${rice.kim.externalIdTypeCode}" /> <property name="externalIdProperty" value="externalIdentifiers.externalId" /> <property name="externalIdTypeProperty" value="externalIdentifiers.externalIdentifierTypeCode" /> <property name="uconnLdpSearchMappings" value="${uconn.ldap.search.mappings}" /> <property name="updatibleAttributes" value="${uconn.ldap.updtabl.attributes}" /> </bean> <!-- //////////////////////////////////////////////////////////////// --> <!-- // end ldap attribute constants // --> <!-- //////////////////////////////////////////////////////////////// --> <bean id="ldapPrincipalDao" class="org.kuali.rice.kim.dao.impl.LdapPrincipalDaoImpl"> <property name="ldapTemplate" ref="ldapTemplate" /> <property name="parameterService" ref="rice.kim.ldap.import.parameterService" /> <property name="kimConstants" ref="kimConstants" /> <property name="contextMappers"> <map> <entry key="Principal" value-ref="ContextMapper-Principal" /> <entry key="EntityAddress" value-ref="ContextMapper-EntityAddress" /> <entry key="EntityAffiliation" value-ref="ContextMapper-EntityAffiliation" /> <entry key="EntityDefault" value-ref="ContextMapper-EntityDefault" /> <entry key="EntityEmail" value-ref="ContextMapper-EntityEmail" /> <entry key="EntityEmploymentInformation" value-ref="ContextMapper-EntityEmployment" /> <entry key="EntityTypeContactInfo" value-ref="ContextMapper-EntityTypeContactInfo" /> <entry key="EntityTypeContactInfoDefault" value-ref="ContextMapper-EntityTypeContactInfoDefault" /> <entry key="Entity" value-ref="ContextMapper-Entity" /> <entry key="EntityName" value-ref="ContextMapper-EntityName" /> <entry key="EntityNamePrincipalName" value-ref="ContextMapper-EntityNamePrincipalName" /> <entry key="EntityPhone" value-ref="ContextMapper-EntityPhone" /> <entry key="EntityPrivacyPreferences" value-ref="ContextMapper-EntityPrivacyPreferences" /> </map> </property> </bean> <!-- UConn specfic --> <bean id="uconnRiceLdapService" class="org.kuali.rice.kim.ldap.service.impl.UConnRiceLdapServiceImpl"> <property name="constants" ref="kimConstants" /> <property name="principalDao" ref="ldapPrincipalDao" /> <property name="ldapUtilDao" ref="ldapUtilDao" /> </bean> <!-- end UConn specfic --> <!-- override person service to accomodate ldap search --> <bean id="personService" class="edu.uconn.kuali.rice.kim.identity.UConnPersonServiceImp"> <property name="personEntityTypeCodes"> <list> <value>PERSON</value> <value>SYSTEM</value> </list> </property> </bean> <bean id="kimIdentityDelegateService" class="org.kuali.rice.kim.service.impl.LdapIdentityDelegateServiceImpl" > <property name="dataObjectService" ref="dataObjectService" /> <property name="principalDao" ref="ldapPrincipalDao" /> </bean> <bean id="kimUiDocumentService" class="org.kuali.rice.kim.service.impl.LdapUiDocumentServiceImpl" /> </beans>