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