001/**
002 * Copyright 2005-2016 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.rice.kim.service.impl;
017
018import java.util.ArrayList;
019import java.util.Collections;
020import java.util.List;
021
022import org.apache.commons.lang.StringUtils;
023import org.kuali.rice.core.api.membership.MemberType;
024import org.kuali.rice.kim.api.KimConstants;
025import org.kuali.rice.kim.api.group.Group;
026import org.kuali.rice.kim.api.identity.affiliation.EntityAffiliation;
027import org.kuali.rice.kim.api.identity.email.EntityEmail;
028import org.kuali.rice.kim.api.identity.employment.EntityEmployment;
029import org.kuali.rice.kim.api.identity.entity.Entity;
030import org.kuali.rice.kim.api.identity.name.EntityName;
031import org.kuali.rice.kim.api.identity.phone.EntityPhone;
032import org.kuali.rice.kim.api.identity.principal.Principal;
033import org.kuali.rice.kim.api.identity.type.EntityTypeContactInfo;
034import org.kuali.rice.kim.api.role.Role;
035import org.kuali.rice.kim.bo.ui.PersonDocumentAffiliation;
036import org.kuali.rice.kim.bo.ui.PersonDocumentEmail;
037import org.kuali.rice.kim.bo.ui.PersonDocumentEmploymentInfo;
038import org.kuali.rice.kim.bo.ui.PersonDocumentName;
039import org.kuali.rice.kim.bo.ui.PersonDocumentPhone;
040import org.kuali.rice.kim.document.IdentityManagementPersonDocument;
041import org.kuali.rice.kim.impl.common.delegate.DelegateTypeBo;
042import org.kuali.rice.kim.impl.group.GroupBo;
043import org.kuali.rice.kim.impl.group.GroupMemberBo;
044import org.kuali.rice.kim.impl.identity.entity.EntityBo;
045import org.kuali.rice.kim.impl.identity.principal.PrincipalBo;
046import org.kuali.rice.kim.impl.role.RoleBo;
047import org.kuali.rice.kim.impl.role.RoleMemberAttributeDataBo;
048import org.kuali.rice.kim.impl.role.RoleMemberBo;
049import org.kuali.rice.kim.impl.role.RoleResponsibilityActionBo;
050import org.kuali.rice.kim.impl.services.KimImplServiceLocator;
051import org.kuali.rice.krad.document.Document;
052import org.kuali.rice.krad.util.KRADUtils;
053
054/**
055 * Customized version of the UiDocumentServiceImpl to support LDAP communcation
056 *
057 * @author Leo Przybylski (przybyls@arizona.edu)
058 */
059public class LdapUiDocumentServiceImpl extends org.kuali.rice.kim.service.impl.UiDocumentServiceImpl {
060
061        /**
062         *
063         * @see org.kuali.rice.kim.service.UiDocumentService#loadEntityToPersonDoc(IdentityManagementPersonDocument, String)
064         */
065        @Override
066        public void loadEntityToPersonDoc(IdentityManagementPersonDocument identityManagementPersonDocument, String principalId) {
067                Principal principal = this.getIdentityService().getPrincipal(principalId);
068        if(principal==null) {
069                throw new RuntimeException("Principal does not exist for principal id:"+principalId);
070        }
071
072        identityManagementPersonDocument.setPrincipalId(principal.getPrincipalId());
073        identityManagementPersonDocument.setPrincipalName(principal.getPrincipalName());
074        //identityManagementPersonDocument.setPassword(principal.getPassword());
075        identityManagementPersonDocument.setActive(principal.isActive());
076        Entity kimEntity = this.getIdentityService().getEntity(principal.getEntityId());
077                identityManagementPersonDocument.setEntityId(kimEntity.getId());
078                if ( KRADUtils.isNotNull( kimEntity.getPrivacyPreferences() ) ) {
079                        identityManagementPersonDocument.setPrivacy(loadPrivacyReferences(kimEntity.getPrivacyPreferences()));
080                }
081                //identityManagementPersonDocument.setActive(kimEntity.isActive());
082                identityManagementPersonDocument.setAffiliations(loadAffiliations(kimEntity.getAffiliations(),kimEntity.getEmploymentInformation()));
083                identityManagementPersonDocument.setNames(loadNames( identityManagementPersonDocument, principalId, kimEntity.getNames(), identityManagementPersonDocument.getPrivacy().isSuppressName() ));
084                EntityTypeContactInfo entityType = null;
085                for (EntityTypeContactInfo type : kimEntity.getEntityTypeContactInfos()) {
086                        if (KimConstants.EntityTypes.PERSON.equals(type.getEntityTypeCode())) {
087                                entityType = EntityTypeContactInfo.Builder.create(type).build();
088                        }
089                }
090
091                if(entityType!=null){
092                        identityManagementPersonDocument.setEmails(loadEmails(identityManagementPersonDocument, principalId, entityType.getEmailAddresses(), identityManagementPersonDocument.getPrivacy().isSuppressEmail()));
093                        identityManagementPersonDocument.setPhones(loadPhones(identityManagementPersonDocument, principalId, entityType.getPhoneNumbers(), identityManagementPersonDocument.getPrivacy().isSuppressPhone()));
094                        identityManagementPersonDocument.setAddrs(loadAddresses(identityManagementPersonDocument, principalId, entityType.getAddresses(), identityManagementPersonDocument.getPrivacy().isSuppressAddress()));
095                }
096
097                List<Group> groups = getGroupService().getGroups(getGroupService().getDirectGroupIdsByPrincipalId(
098                identityManagementPersonDocument.getPrincipalId()));
099                loadGroupToPersonDoc(identityManagementPersonDocument, groups);
100                loadRoleToPersonDoc(identityManagementPersonDocument);
101                loadDelegationsToPersonDoc(identityManagementPersonDocument);
102        }
103
104        protected String getInitiatorPrincipalId(Document document){
105                try{
106                        return document.getDocumentHeader().getWorkflowDocument().getInitiatorPrincipalId();
107                } catch(Exception ex){
108                        return null;
109                }
110        }
111
112        /**
113         * @see org.kuali.rice.kim.service.UiDocumentService#saveEntityPerson(IdentityManagementPersonDocument)
114         */
115    @Override
116        public void saveEntityPerson(IdentityManagementPersonDocument identityManagementPersonDocument) {
117                boolean inactivatingPrincipal = false;
118
119                List <GroupMemberBo>  groupPrincipals = populateGroupMembers(identityManagementPersonDocument);
120                List <RoleMemberBo>  rolePrincipals = populateRoleMembers(identityManagementPersonDocument);
121                List <DelegateTypeBo> personDelegations = populateDelegations(identityManagementPersonDocument);
122                List <Object> bos = new ArrayList<Object>();
123                List <RoleResponsibilityActionBo> roleRspActions = populateRoleRspActions(identityManagementPersonDocument);
124                List <RoleMemberAttributeDataBo> blankRoleMemberAttrs = getBlankRoleMemberAttrs(rolePrincipals);
125                //if(ObjectUtils.isNotNull(kimEntity.getPrivacyPreferences()))
126                //      bos.add(kimEntity.getPrivacyPreferences());
127                bos.addAll(groupPrincipals);
128                bos.addAll(rolePrincipals);
129                bos.addAll(roleRspActions);
130                bos.addAll(personDelegations);
131                // boservice.save(bos) does not handle deleteawarelist
132                for ( Object bo : bos ) {
133                        getDataObjectService().save(bo);
134                }
135
136                for ( RoleMemberAttributeDataBo blankRoleMemberAttr : blankRoleMemberAttrs ) {
137                        getDataObjectService().delete(blankRoleMemberAttr);
138                }
139                if ( inactivatingPrincipal ) {
140                        //when a person is inactivated, inactivate their group, role, and delegation memberships
141                        KimImplServiceLocator.getRoleInternalService().principalInactivated(identityManagementPersonDocument.getPrincipalId());
142                }
143        }
144
145    @Override
146        protected boolean setupPrincipal(IdentityManagementPersonDocument identityManagementPersonDocument,EntityBo kimEntity, List<PrincipalBo> origPrincipals) {
147        boolean inactivatingPrincipal = false;
148                List<PrincipalBo> principals = new ArrayList<PrincipalBo>();
149                Principal.Builder principal = Principal.Builder.create(identityManagementPersonDocument.getPrincipalName());
150                principal.setPrincipalId(identityManagementPersonDocument.getPrincipalId());
151                //principal.setPassword(identityManagementPersonDocument.getPassword());
152                principal.setActive(identityManagementPersonDocument.isActive());
153                principal.setEntityId(identityManagementPersonDocument.getEntityId());
154                if(KRADUtils.isNotNull(origPrincipals)){
155                        for (PrincipalBo prncpl : origPrincipals) {
156                                if (prncpl.getPrincipalId()!=null && StringUtils.equals(prncpl.getPrincipalId(), principal.getPrincipalId())) {
157                                        principal.setVersionNumber(prncpl.getVersionNumber());
158                    principal.setObjectId(prncpl.getObjectId());
159                                        // check if inactivating the principal
160                                        if ( prncpl.isActive() && !principal.isActive() ) {
161                                                inactivatingPrincipal = true;
162                                        }
163                                }
164                        }
165                }
166                principals.add(PrincipalBo.from(principal.build()));
167
168                kimEntity.setPrincipals(principals);
169                return inactivatingPrincipal;
170        }
171
172        @Override
173        protected List<PersonDocumentAffiliation> loadAffiliations(List <EntityAffiliation> affiliations, List<EntityEmployment> empInfos) {
174                List<PersonDocumentAffiliation> docAffiliations = new ArrayList<PersonDocumentAffiliation>();
175                if(KRADUtils.isNotNull(affiliations)){
176                        for (EntityAffiliation affiliation: affiliations) {
177                                if(affiliation.isActive()){
178                                        PersonDocumentAffiliation docAffiliation = new PersonDocumentAffiliation();
179                                        docAffiliation.setAffiliationTypeCode(affiliation.getAffiliationType().getCode());
180                                        docAffiliation.setCampusCode(affiliation.getCampusCode());
181                                        docAffiliation.setActive(affiliation.isActive());
182                                        docAffiliation.setDflt(affiliation.isDefaultValue());
183                                        docAffiliation.setEntityAffiliationId(affiliation.getId());
184                                        docAffiliation.refreshReferenceObject("affiliationType");
185                                        // EntityAffiliationImpl does not define empinfos as collection
186                                        docAffiliations.add(docAffiliation);
187                                        docAffiliation.setEdit(true);
188                                        // employment informations
189                                        List<PersonDocumentEmploymentInfo> docEmploymentInformations = new ArrayList<PersonDocumentEmploymentInfo>();
190                                        if(KRADUtils.isNotNull(empInfos)){
191                                                for (EntityEmployment empInfo: empInfos) {
192                                                        if (empInfo.isActive()
193                                    && StringUtils.equals(docAffiliation.getEntityAffiliationId(),
194                                                          (empInfo.getEntityAffiliation() != null ? empInfo.getEntityAffiliation().getId() : null))) {
195                                                                PersonDocumentEmploymentInfo docEmpInfo = new PersonDocumentEmploymentInfo();
196                                                                docEmpInfo.setEntityEmploymentId(empInfo.getEmployeeId());
197                                                                docEmpInfo.setEmployeeId(empInfo.getEmployeeId());
198                                                                docEmpInfo.setEmploymentRecordId(empInfo.getEmploymentRecordId());
199                                                                docEmpInfo.setBaseSalaryAmount(empInfo.getBaseSalaryAmount());
200                                                                docEmpInfo.setPrimaryDepartmentCode(empInfo.getPrimaryDepartmentCode());
201                                                                docEmpInfo.setEmploymentStatusCode(empInfo.getEmployeeStatus() != null ? empInfo.getEmployeeStatus().getCode() : null);
202                                                                docEmpInfo.setEmploymentTypeCode(empInfo.getEmployeeType() != null ? empInfo.getEmployeeType().getCode() : null);
203                                                                docEmpInfo.setActive(empInfo.isActive());
204                                                                docEmpInfo.setPrimary(empInfo.isPrimary());
205                                                                docEmpInfo.setEntityAffiliationId(empInfo.getEntityAffiliation() != null ? empInfo.getEntityAffiliation().getId() : null);
206                                                                // there is no version number on KimEntityEmploymentInformationInfo
207                                                                //docEmpInfo.setVersionNumber(empInfo.getVersionNumber());
208                                                                docEmpInfo.setEdit(true);
209                                                                docEmpInfo.refreshReferenceObject("employmentType");
210                                                                docEmploymentInformations.add(docEmpInfo);
211                                                        }
212                                                }
213                                        }
214                                        docAffiliation.setEmpInfos(docEmploymentInformations);
215                                }
216                        }
217                }
218                return docAffiliations;
219
220        }
221
222
223    @Override
224        protected List<PersonDocumentName> loadNames( IdentityManagementPersonDocument personDoc, String principalId, List <EntityName> names, boolean suppressDisplay ) {
225                List<PersonDocumentName> docNames = new ArrayList<PersonDocumentName>();
226                if(KRADUtils.isNotNull(names)){
227                        for (EntityName name: names) {
228                                if(name.isActive()){
229                                        PersonDocumentName docName = new PersonDocumentName();
230                    if (name.getNameType() != null) {
231                                            docName.setNameCode(name.getNameType().getCode());
232                    }
233
234                                        //We do not need to check the privacy setting here - The UI should care of it
235                                        docName.setFirstName(name.getFirstNameUnmasked());
236                                        docName.setLastName(name.getLastNameUnmasked());
237                                        docName.setMiddleName(name.getMiddleNameUnmasked());
238                                        docName.setNamePrefix(name.getNamePrefixUnmasked());
239                                        docName.setNameSuffix(name.getNameSuffixUnmasked());
240
241                                        docName.setActive(name.isActive());
242                                        docName.setDflt(name.isDefaultValue());
243                                        docName.setEdit(true);
244                                        docName.setEntityNameId(name.getId());
245                                        docNames.add(docName);
246                                }
247                        }
248                }
249                return docNames;
250        }
251
252    @Override
253        protected List<PersonDocumentEmail> loadEmails(IdentityManagementPersonDocument identityManagementPersonDocument, String principalId, List<EntityEmail> entityEmails, boolean suppressDisplay ) {
254                List<PersonDocumentEmail> emails = new ArrayList<PersonDocumentEmail>();
255                if(KRADUtils.isNotNull(entityEmails)){
256                        for (EntityEmail email: entityEmails) {
257                                if(email.isActive()){
258                                        PersonDocumentEmail docEmail = new PersonDocumentEmail();
259                                        //docEmail.setEntityId(email.getEntityId());
260                                        docEmail.setEntityTypeCode(email.getEntityTypeCode());
261                    if (email.getEmailType() != null) {
262                                            docEmail.setEmailTypeCode(email.getEmailType().getCode());
263                    }
264                                        // EmailType not on info object.
265                                        //docEmail.setEmailType(((KimEntityEmailImpl)email).getEmailType());
266                                        //We do not need to check the privacy setting here - The UI should care of it
267                                        docEmail.setEmailAddress(email.getEmailAddressUnmasked());
268
269                                        docEmail.setActive(email.isActive());
270                                        docEmail.setDflt(email.isDefaultValue());
271                                        docEmail.setEntityEmailId(email.getId());
272                                        docEmail.setEdit(true);
273                                        emails.add(docEmail);
274                                }
275                        }
276                }
277                return emails;
278        }
279
280    @Override
281        protected List<PersonDocumentPhone> loadPhones(IdentityManagementPersonDocument identityManagementPersonDocument, String principalId, List<EntityPhone> entityPhones, boolean suppressDisplay ) {
282                List<PersonDocumentPhone> docPhones = new ArrayList<PersonDocumentPhone>();
283                if(KRADUtils.isNotNull(entityPhones)){
284                        for (EntityPhone phone: entityPhones) {
285                                if(phone.isActive()){
286                                        PersonDocumentPhone docPhone = new PersonDocumentPhone();
287                    if (phone.getPhoneType() != null) {
288                                            docPhone.setPhoneTypeCode(phone.getPhoneType().getCode());
289                    }
290                                        //docPhone.setPhoneType(((KimEntityPhoneImpl)phone).getPhoneType());
291                                        docPhone.setEntityTypeCode(phone.getEntityTypeCode());
292                                        //We do not need to check the privacy setting here - The UI should care of it
293                                        docPhone.setPhoneNumber(phone.getPhoneNumberUnmasked());
294                                        docPhone.setCountryCode(phone.getCountryCodeUnmasked());
295                                        docPhone.setExtensionNumber(phone.getExtensionNumberUnmasked());
296
297                                        docPhone.setActive(phone.isActive());
298                                        docPhone.setDflt(phone.isDefaultValue());
299                                        docPhone.setEntityPhoneId(phone.getId());
300                                        docPhone.setEdit(true);
301                                        docPhones.add(docPhone);
302                                }
303                        }
304                }
305                return docPhones;
306
307        }
308
309    public Object getMember(String memberTypeCode, String memberId){
310        Class<? extends Object> roleMemberTypeClass = null;
311        if(MemberType.PRINCIPAL.getCode().equals(memberTypeCode)){
312                roleMemberTypeClass = PrincipalBo.class;
313                        Principal principalInfo = getIdentityService().getPrincipal(memberId);
314                        if (principalInfo != null) {
315
316                        }
317        } else if(MemberType.GROUP.getCode().equals(memberTypeCode)){
318                roleMemberTypeClass = GroupBo.class;
319                Group groupInfo = null;
320                        groupInfo = getGroupService().getGroup(memberId);
321                        if (groupInfo != null) {
322
323                        }
324        } else if(MemberType.ROLE.getCode().equals(memberTypeCode)){
325                roleMemberTypeClass = RoleBo.class;
326                        Role role = getRoleService().getRole(memberId);
327                        if (role != null) {
328
329                        }
330        }
331        return getDataObjectService().find(roleMemberTypeClass, memberId);
332    }
333
334    /**
335     * Overridden to only check permission - users should not be able to edit themselves.
336     *
337     * @see org.kuali.rice.kim.service.impl.UiDocumentServiceImpl#canModifyEntity(java.lang.String, java.lang.String)
338     */
339    @Override
340        public boolean canModifyEntity( String currentUserPrincipalId, String toModifyPrincipalId ){
341                return (StringUtils.isNotBlank(currentUserPrincipalId) && StringUtils.isNotBlank(toModifyPrincipalId) &&
342                                currentUserPrincipalId.equals(toModifyPrincipalId)) ||
343                                getPermissionService().isAuthorized(
344                                                currentUserPrincipalId,
345                                                KimConstants.NAMESPACE_CODE,
346                                                KimConstants.PermissionNames.MODIFY_ENTITY,
347                                                Collections.singletonMap(KimConstants.AttributeConstants.PRINCIPAL_ID, currentUserPrincipalId));
348        }
349
350//    @Override
351//      protected List<RoleMemberBo> updateRoleMembers(IdentityManagementRoleDocument identityManagementRoleDocument, List<RoleMemberBo> origRoleMembers){
352//        List<RoleMemberBo> roleMembers = new ArrayList<RoleMemberBo>();
353//        RoleMemberBo newRoleMember;
354//        RoleMemberBo origRoleMemberImplTemp;
355//        List<RoleMemberAttributeDataBo> origAttributes;
356//        boolean activatingInactive = false;
357//        String newRoleMemberIdAssigned = "";
358//
359//        identityManagementRoleDocument.setKimType(KimApiServiceLocator.getKimTypeInfoService().getKimType(identityManagementRoleDocument.getRoleTypeId()));
360//        KimTypeService kimTypeService = KimFrameworkServiceLocator.getKimTypeService(identityManagementRoleDocument.getKimType());
361//
362//        if(CollectionUtils.isNotEmpty(identityManagementRoleDocument.getMembers())){
363//            for(KimDocumentRoleMember documentRoleMember: identityManagementRoleDocument.getMembers()){
364//                origRoleMemberImplTemp = null;
365//
366//                newRoleMember = new RoleMemberBo();
367//                KimCommonUtilsInternal.copyProperties(newRoleMember, documentRoleMember);
368//                newRoleMember.setRoleId(identityManagementRoleDocument.getRoleId());
369//                if(KRADUtils.isNotNull(origRoleMembers)){
370//                    for(RoleMemberBo origRoleMemberImpl: origRoleMembers){
371//                        if((origRoleMemberImpl.getRoleId()!=null && StringUtils.equals(origRoleMemberImpl.getRoleId(), newRoleMember.getRoleId())) &&
372//                            (origRoleMemberImpl.getMemberId()!=null && StringUtils.equals(origRoleMemberImpl.getMemberId(), newRoleMember.getMemberId())) &&
373//                            (origRoleMemberImpl.getType()!=null && org.apache.commons.lang.ObjectUtils.equals(origRoleMemberImpl.getType(), newRoleMember.getType())) &&
374//                            !origRoleMemberImpl.isActive(new Timestamp(System.currentTimeMillis())) &&
375//                            !kimTypeService.validateUniqueAttributes(identityManagementRoleDocument.getKimType().getId(),
376//                                    documentRoleMember.getQualifierAsMap(), origRoleMemberImpl.getAttributes()).isEmpty()) {
377//
378//                            //TODO: verify if you want to add  && newRoleMember.isActive() condition to if...
379//
380//                            newRoleMemberIdAssigned = newRoleMember.getId();
381//                            newRoleMember.setId(origRoleMemberImpl.getId());
382//                            activatingInactive = true;
383//                        }
384//                        if(origRoleMemberImpl.getId()!=null && StringUtils.equals(origRoleMemberImpl.getId(), newRoleMember.getId())){
385//                            newRoleMember.setVersionNumber(origRoleMemberImpl.getVersionNumber());
386//                            origRoleMemberImplTemp = origRoleMemberImpl;
387//                        }
388//                    }
389//                }
390//                origAttributes = (origRoleMemberImplTemp==null || origRoleMemberImplTemp.getAttributes()==null)?
391//                                    new ArrayList<RoleMemberAttributeDataBo>():origRoleMemberImplTemp.getAttributeDetails();
392//                newRoleMember.setActiveFromDateValue(documentRoleMember.getActiveFromDate());
393//                newRoleMember.setActiveToDateValue(documentRoleMember.getActiveToDate());
394//                newRoleMember.setAttributeDetails(getRoleMemberAttributeData(documentRoleMember.getQualifiers(), origAttributes, activatingInactive, newRoleMemberIdAssigned));
395//                newRoleMember.setRoleRspActions(getRoleMemberResponsibilityActions(documentRoleMember, origRoleMemberImplTemp, activatingInactive, newRoleMemberIdAssigned));
396//                roleMembers.add(newRoleMember);
397//                activatingInactive = false;
398//            }
399//        }
400//        return roleMembers;
401//    }
402}