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.rules.ui; 017 018import org.apache.commons.lang.StringUtils; 019import org.kuali.rice.core.api.CoreConstants; 020import org.kuali.rice.core.api.membership.MemberType; 021import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader; 022import org.kuali.rice.core.api.uif.RemotableAttributeError; 023import org.kuali.rice.core.api.util.RiceKeyConstants; 024import org.kuali.rice.kim.api.KimConstants; 025import org.kuali.rice.kim.api.type.KimType; 026import org.kuali.rice.kim.bo.ui.KimDocumentRoleMember; 027import org.kuali.rice.kim.document.IdentityManagementRoleDocument; 028import org.kuali.rice.kim.document.rule.AttributeValidationHelper; 029import org.kuali.rice.kim.framework.role.RoleTypeService; 030import org.kuali.rice.kim.framework.services.KimFrameworkServiceLocator; 031import org.kuali.rice.kim.framework.type.KimTypeService; 032import org.kuali.rice.kim.impl.services.KimImplServiceLocator; 033import org.kuali.rice.kim.rule.event.ui.AddMemberEvent; 034import org.kuali.rice.kim.rule.ui.AddMemberRule; 035import org.kuali.rice.kns.rules.DocumentRuleBase; 036import org.kuali.rice.krad.service.KRADServiceLocator; 037import org.kuali.rice.krad.service.impl.KRADModuleService; 038import org.kuali.rice.core.api.util.VersionHelper; 039import org.kuali.rice.krad.util.GlobalVariables; 040import org.kuali.rice.krad.util.ObjectUtils; 041import org.kuali.rice.ksb.api.KsbApiServiceLocator; 042import org.kuali.rice.ksb.api.bus.Endpoint; 043import org.kuali.rice.ksb.api.bus.ServiceBus; 044 045import javax.xml.namespace.QName; 046import java.util.ArrayList; 047import java.util.HashMap; 048import java.util.List; 049import java.util.Map; 050 051 052/** 053 * This is a description of what this class does - shyu don't forget to fill this in. 054 * 055 * @author Kuali Rice Team (rice.collab@kuali.org) 056 * 057 */ 058public class KimDocumentMemberRule extends DocumentRuleBase implements AddMemberRule { 059 060 private static final String ERROR_PATH = "member.memberId"; 061 062 protected AttributeValidationHelper attributeValidationHelper = new AttributeValidationHelper(); 063 064 public boolean processAddMember(AddMemberEvent addMemberEvent){ 065 KimDocumentRoleMember newMember = addMemberEvent.getMember(); 066 IdentityManagementRoleDocument document = (IdentityManagementRoleDocument)addMemberEvent.getDocument(); 067 boolean rulePassed = true; 068 069 if (newMember == null || StringUtils.isBlank(newMember.getMemberId())){ 070 GlobalVariables.getMessageMap().putError(ERROR_PATH, RiceKeyConstants.ERROR_EMPTY_ENTRY, new String[] {"Member"}); 071 return false; 072 } 073 if(!validAssignRole(newMember, document)) { 074 return false; 075 } 076 List<RemotableAttributeError> validationErrors = new ArrayList<RemotableAttributeError>(); 077 KimTypeService kimTypeService = KimFrameworkServiceLocator.getKimTypeService(document.getKimType()); 078 079 Long newMemberFromTime = newMember.getActiveFromDate() == null ? 0L : newMember.getActiveFromDate().getTime(); 080 Long newMemberToTime = newMember.getActiveToDate() == null ? Long.MAX_VALUE : newMember.getActiveToDate().getTime(); 081 082 List<RemotableAttributeError> errorsAttributesAgainstExisting = new ArrayList<RemotableAttributeError>(); 083 Map<String, String> newMemberQualifiers = attributeValidationHelper.convertQualifiersToMap(newMember.getQualifiers()); 084 085 Map<String, String> oldMemberQualifiers; 086 for (KimDocumentRoleMember member: document.getMembers()){ 087 Long memberFromTime = member.getActiveFromDate() == null ? 0L : member.getActiveFromDate().getTime(); 088 Long memberToTime = member.getActiveToDate() == null ? Long.MAX_VALUE : member.getActiveToDate().getTime(); 089 oldMemberQualifiers = attributeValidationHelper.convertQualifiersToMap(member.getQualifiers()); 090 091 if ((member.getMemberId().equals(newMember.getMemberId()) && 092 member.getMemberTypeCode().equals(newMember.getMemberTypeCode())) 093 && ((newMemberFromTime >= memberFromTime && newMemberFromTime < memberToTime) 094 || (newMemberToTime >= memberFromTime && newMemberToTime <= memberToTime))) { 095 096 errorsAttributesAgainstExisting = kimTypeService.validateAttributesAgainstExisting( 097 document.getKimType().getId(), newMemberQualifiers, oldMemberQualifiers); 098 validationErrors.addAll( 099 attributeValidationHelper.convertErrorsForMappedFields(ERROR_PATH, errorsAttributesAgainstExisting)); 100 if (!errorsAttributesAgainstExisting.isEmpty()) { 101 rulePassed = false; 102 GlobalVariables.getMessageMap().putError(ERROR_PATH, RiceKeyConstants.ERROR_DUPLICATE_ENTRY, new String[] {"Member"}); 103 break; 104 } 105 } 106 } 107 108 boolean shouldNotValidate = newMember.isRole(); 109 if ( kimTypeService != null && ObjectUtils.isNotNull( document.getKimType() ) && StringUtils.isNotBlank(document.getKimType().getServiceName()) ) { 110 VersionedService<RoleTypeService> versionedRoleTypeService = getVersionedRoleTypeService(document.getKimType()); 111 if (versionedRoleTypeService != null) { 112 boolean versionOk = VersionHelper.compareVersion(versionedRoleTypeService.getVersion(), CoreConstants.Versions.VERSION_2_1_2)!=-1? true:false; 113 if(versionOk) { 114 shouldNotValidate = versionedRoleTypeService.getService().shouldValidateQualifiersForMemberType( MemberType.fromCode(newMember.getMemberTypeCode())); 115 } else { 116 shouldNotValidate = false; 117 } 118 } 119 } 120 if (kimTypeService !=null && !shouldNotValidate) { 121 List<RemotableAttributeError> localErrors = kimTypeService.validateAttributes( document.getKimType().getId(), attributeValidationHelper.convertQualifiersToMap( newMember.getQualifiers() ) ); 122 validationErrors.addAll( attributeValidationHelper.convertErrors("member", 123 attributeValidationHelper.convertQualifiersToAttrIdxMap(newMember.getQualifiers()), localErrors) ); 124 } 125 if (!validationErrors.isEmpty()) { 126 attributeValidationHelper.moveValidationErrorsToErrorMap(validationErrors); 127 rulePassed = false; 128 } 129 130 return rulePassed; 131 } 132 133 protected boolean validAssignRole(KimDocumentRoleMember roleMember, IdentityManagementRoleDocument document){ 134 boolean rulePassed = true; 135 if(StringUtils.isNotEmpty(document.getRoleNamespace())){ 136 Map<String,String> roleDetails = new HashMap<String,String>(); 137 roleDetails.put(KimConstants.AttributeConstants.NAMESPACE_CODE, document.getRoleNamespace()); 138 roleDetails.put(KimConstants.AttributeConstants.ROLE_NAME, document.getRoleName()); 139 if (!getDocumentDictionaryService().getDocumentAuthorizer(document).isAuthorizedByTemplate( 140 document, 141 KimConstants.NAMESPACE_CODE, 142 KimConstants.PermissionTemplateNames.ASSIGN_ROLE, 143 GlobalVariables.getUserSession().getPerson().getPrincipalId(), 144 roleDetails, null)){ 145 GlobalVariables.getMessageMap().putError(ERROR_PATH, RiceKeyConstants.ERROR_ASSIGN_ROLE, 146 new String[] {document.getRoleNamespace(), document.getRoleName()}); 147 rulePassed = false; 148 } 149 } 150 return rulePassed; 151 } 152 153 private static class VersionedService<T> { 154 155 String version; 156 T service; 157 158 VersionedService(String version, T service) { 159 this.version = version; 160 this.service = service; 161 } 162 163 T getService() { 164 return this.service; 165 } 166 167 String getVersion() { 168 return this.version; 169 } 170 171 } 172 173 protected VersionedService<RoleTypeService> getVersionedRoleTypeService(KimType typeInfo) { 174 String serviceName = typeInfo.getServiceName(); 175 if (serviceName != null) { 176 String version = "2.0.0"; // default version since the base services have been available since then 177 RoleTypeService roleTypeService = null; 178 179 try { 180 181 ServiceBus serviceBus = KsbApiServiceLocator.getServiceBus(); 182 Endpoint endpoint = serviceBus.getEndpoint(QName.valueOf(serviceName)); 183 if (endpoint != null) { 184 version = endpoint.getServiceConfiguration().getServiceVersion(); 185 } 186 KimTypeService service = (KimTypeService) GlobalResourceLoader.getService(QName.valueOf(serviceName)); 187 if (service != null && service instanceof RoleTypeService) { 188 roleTypeService = (RoleTypeService) service; 189 } else { 190 roleTypeService = (RoleTypeService) KimImplServiceLocator.getService("kimNoMembersRoleTypeService"); 191 } 192 } catch (Exception ex) { 193 roleTypeService = (RoleTypeService) KimImplServiceLocator.getService("kimNoMembersRoleTypeService"); 194 } 195 196 return new VersionedService<RoleTypeService>(version, roleTypeService); 197 } 198 199 return null; 200 } 201 202 203}