001 /** 002 * Copyright 2005-2014 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 */ 016 package org.kuali.rice.kim.impl.role; 017 018 import static org.kuali.rice.core.api.criteria.PredicateFactory.equal; 019 020 import java.sql.Timestamp; 021 import java.util.ArrayList; 022 import java.util.Collection; 023 import java.util.Collections; 024 import java.util.Date; 025 import java.util.HashMap; 026 import java.util.HashSet; 027 import java.util.Iterator; 028 import java.util.List; 029 import java.util.Map; 030 import java.util.Set; 031 032 import javax.jws.WebParam; 033 import javax.sql.DataSource; 034 import javax.xml.namespace.QName; 035 036 import org.apache.commons.collections.CollectionUtils; 037 import org.apache.commons.lang.StringUtils; 038 import org.apache.commons.lang.exception.ExceptionUtils; 039 import org.apache.log4j.Logger; 040 import org.joda.time.DateTime; 041 import org.kuali.rice.core.api.CoreConstants; 042 import org.kuali.rice.core.api.cache.CacheKeyUtils; 043 import org.kuali.rice.core.api.criteria.QueryByCriteria; 044 import org.kuali.rice.core.api.criteria.QueryResults; 045 import org.kuali.rice.core.api.delegation.DelegationType; 046 import org.kuali.rice.core.api.exception.RiceIllegalArgumentException; 047 import org.kuali.rice.core.api.exception.RiceIllegalStateException; 048 import org.kuali.rice.core.api.membership.MemberType; 049 import org.kuali.rice.core.api.mo.ModelObjectUtils; 050 import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader; 051 import org.kuali.rice.core.api.util.VersionHelper; 052 import org.kuali.rice.kim.api.KimConstants; 053 import org.kuali.rice.kim.api.common.delegate.DelegateMember; 054 import org.kuali.rice.kim.api.common.delegate.DelegateType; 055 import org.kuali.rice.kim.api.identity.principal.Principal; 056 import org.kuali.rice.kim.api.role.DelegateMemberQueryResults; 057 import org.kuali.rice.kim.api.role.Role; 058 import org.kuali.rice.kim.api.role.RoleMember; 059 import org.kuali.rice.kim.api.role.RoleMemberQueryResults; 060 import org.kuali.rice.kim.api.role.RoleMembership; 061 import org.kuali.rice.kim.api.role.RoleMembershipQueryResults; 062 import org.kuali.rice.kim.api.role.RoleQueryResults; 063 import org.kuali.rice.kim.api.role.RoleResponsibility; 064 import org.kuali.rice.kim.api.role.RoleResponsibilityAction; 065 import org.kuali.rice.kim.api.role.RoleService; 066 import org.kuali.rice.kim.api.services.KimApiServiceLocator; 067 import org.kuali.rice.kim.api.type.KimType; 068 import org.kuali.rice.kim.api.type.KimTypeUtils; 069 import org.kuali.rice.kim.framework.common.delegate.DelegationTypeService; 070 import org.kuali.rice.kim.framework.role.RoleTypeService; 071 import org.kuali.rice.kim.framework.services.KimFrameworkServiceLocator; 072 import org.kuali.rice.kim.framework.type.KimTypeService; 073 import org.kuali.rice.kim.impl.common.attribute.AttributeTransform; 074 import org.kuali.rice.kim.impl.common.attribute.KimAttributeDataBo; 075 import org.kuali.rice.kim.impl.common.delegate.DelegateMemberAttributeDataBo; 076 import org.kuali.rice.kim.impl.common.delegate.DelegateMemberBo; 077 import org.kuali.rice.kim.impl.common.delegate.DelegateTypeBo; 078 import org.kuali.rice.kim.impl.services.KimImplServiceLocator; 079 import org.kuali.rice.kim.impl.type.KimTypeBo; 080 import org.kuali.rice.krad.data.platform.MaxValueIncrementerFactory; 081 import org.kuali.rice.ksb.api.KsbApiServiceLocator; 082 import org.kuali.rice.ksb.api.bus.Endpoint; 083 import org.kuali.rice.ksb.api.bus.ServiceBus; 084 import org.springframework.cache.Cache; 085 import org.springframework.cache.CacheManager; 086 import org.springframework.cache.support.NoOpCacheManager; 087 import org.springframework.util.LinkedMultiValueMap; 088 import org.springframework.util.MultiValueMap; 089 090 public class RoleServiceImpl extends RoleServiceBase implements RoleService { 091 private static final Logger LOG = Logger.getLogger(RoleServiceImpl.class); 092 093 private static final Map<String, RoleDaoAction> memberTypeToRoleDaoActionMap = populateMemberTypeToRoleDaoActionMap(); 094 095 private static Map<String, RoleDaoAction> populateMemberTypeToRoleDaoActionMap() { 096 Map<String, RoleDaoAction> map = new HashMap<String, RoleDaoAction>(); 097 map.put(MemberType.GROUP.getCode(), RoleDaoAction.ROLE_GROUPS_FOR_GROUP_IDS_AND_ROLE_IDS); 098 map.put(MemberType.PRINCIPAL.getCode(), RoleDaoAction.ROLE_PRINCIPALS_FOR_PRINCIPAL_ID_AND_ROLE_IDS); 099 map.put(MemberType.ROLE.getCode(), RoleDaoAction.ROLE_MEMBERSHIPS_FOR_ROLE_IDS_AS_MEMBERS); 100 return Collections.unmodifiableMap(map); 101 } 102 103 private RoleService proxiedRoleService; 104 private CacheManager cacheManager; 105 106 public RoleServiceImpl() { 107 this.cacheManager = new NoOpCacheManager(); 108 } 109 110 @Override 111 public Role createRole(final Role role) throws RiceIllegalArgumentException, RiceIllegalStateException { 112 incomingParamCheck(role, "role"); 113 114 if (StringUtils.isNotBlank(role.getId()) && getRole(role.getId()) != null) { 115 throw new RiceIllegalStateException("the role to create already exists: " + role); 116 } 117 RoleBo bo = RoleBo.from(role); 118 return RoleBo.to(getDataObjectService().save(bo)); 119 } 120 121 @Override 122 public Role updateRole(final Role role) throws RiceIllegalArgumentException, RiceIllegalStateException { 123 incomingParamCheck(role, "role"); 124 125 RoleBoLite originalRole = getRoleBoLite(role.getId()); 126 if (StringUtils.isBlank(role.getId()) || originalRole == null) { 127 throw new RiceIllegalStateException("the role does not exist: " + role); 128 } 129 130 RoleBo bo = RoleBo.from(role); 131 132 RoleBo updatedRole = getDataObjectService().save(bo); 133 if (originalRole.isActive() 134 && !updatedRole.isActive()) { 135 KimImplServiceLocator.getRoleInternalService().roleInactivated(updatedRole.getId()); 136 } 137 return RoleBo.to(updatedRole); 138 } 139 140 /** 141 * This method tests to see if assigning a roleBo to another roleBo will create a circular reference. 142 * The Role is checked to see if it is a member (direct or nested) of the roleBo to be assigned as a member. 143 * 144 * @param newMemberId 145 * @param roleBo 146 * @return true - assignment is allowed, no circular reference will be created. 147 * false - illegal assignment, it will create a circular membership 148 */ 149 protected boolean checkForCircularRoleMembership(String newMemberId, RoleBo roleBo) { 150 // get all nested roleBo members that are of type roleBo 151 Set<String> newRoleMemberIds = getRoleTypeRoleMemberIds(newMemberId); 152 return !newRoleMemberIds.contains(roleBo.getId()); 153 } 154 155 protected RoleMember findRoleMember(String roleMemberId) { 156 final List<RoleMember> roleMembers = findRoleMembers(QueryByCriteria.Builder.fromPredicates(equal(KimConstants.PrimaryKeyConstants.ID, roleMemberId))).getResults(); 157 if (roleMembers != null && !roleMembers.isEmpty()) { 158 return roleMembers.get(0); 159 } 160 return null; 161 } 162 163 @Override 164 public RoleMemberQueryResults findRoleMembers(QueryByCriteria queryByCriteria) throws RiceIllegalStateException { 165 incomingParamCheck(queryByCriteria, "queryByCriteria"); 166 167 QueryResults<RoleMemberBo> results = getDataObjectService().findMatching(RoleMemberBo.class, 168 AttributeTransform.getInstance().apply(queryByCriteria)); 169 170 RoleMemberQueryResults.Builder builder = RoleMemberQueryResults.Builder.create(); 171 builder.setMoreResultsAvailable(results.isMoreResultsAvailable()); 172 builder.setTotalRowCount(results.getTotalRowCount()); 173 174 final List<RoleMember.Builder> ims = new ArrayList<RoleMember.Builder>(); 175 for (RoleMemberBo bo : results.getResults()) { 176 ims.add(RoleMember.Builder.create(bo)); 177 } 178 179 builder.setResults(ims); 180 return builder.build(); 181 182 } 183 184 185 186 @Override 187 public Set<String> getRoleTypeRoleMemberIds(String roleId) throws RiceIllegalArgumentException { 188 incomingParamCheck(roleId, "roleId"); 189 190 Set<String> results = new HashSet<String>(); 191 getNestedRoleTypeMemberIds(roleId, results); 192 return Collections.unmodifiableSet(results); 193 } 194 195 @Override 196 public List<String> getMemberParentRoleIds(String memberType, String memberId) throws RiceIllegalStateException { 197 incomingParamCheck(memberType, "memberType"); 198 incomingParamCheck(memberId, "memberId"); 199 200 List<RoleMemberBo> parentRoleMembers = getRoleMembershipsForMemberId(memberType, memberId, 201 Collections.<String, String>emptyMap()); 202 203 List<String> parentRoleIds = new ArrayList<String>(parentRoleMembers.size()); 204 for (RoleMemberBo parentRoleMember : parentRoleMembers) { 205 parentRoleIds.add(parentRoleMember.getRoleId()); 206 } 207 208 return parentRoleIds; 209 } 210 211 @Override 212 public List<RoleResponsibilityAction> getRoleMemberResponsibilityActions(String roleMemberId) throws RiceIllegalStateException { 213 incomingParamCheck(roleMemberId, "roleMemberId"); 214 215 QueryResults<RoleResponsibilityActionBo> responsibilityActionBoList = getDataObjectService().findMatching(RoleResponsibilityActionBo.class, QueryByCriteria.Builder.forAttribute(KimConstants.PrimaryKeyConstants.ROLE_MEMBER_ID, roleMemberId).build()); 216 217 List<RoleResponsibilityAction> roleResponsibilityActionsList = new ArrayList<RoleResponsibilityAction>(); 218 for (RoleResponsibilityActionBo roleResponsibilityActionBo : responsibilityActionBoList.getResults()) { 219 RoleResponsibilityAction roleResponsibility = RoleResponsibilityActionBo.to(roleResponsibilityActionBo); 220 roleResponsibilityActionsList.add(roleResponsibility); 221 } 222 return roleResponsibilityActionsList; 223 } 224 225 @Override 226 public DelegateMemberQueryResults findDelegateMembers(QueryByCriteria queryByCriteria) throws RiceIllegalStateException { 227 incomingParamCheck(queryByCriteria, "queryByCriteria"); 228 229 QueryResults<DelegateMemberBo> results = getDataObjectService().findMatching(DelegateMemberBo.class, 230 AttributeTransform.getInstance().apply(queryByCriteria)); 231 232 DelegateMemberQueryResults.Builder builder = DelegateMemberQueryResults.Builder.create(); 233 builder.setMoreResultsAvailable(results.isMoreResultsAvailable()); 234 builder.setTotalRowCount(results.getTotalRowCount()); 235 236 final List<DelegateMember.Builder> ims = new ArrayList<DelegateMember.Builder>(); 237 for (DelegateMemberBo bo : results.getResults()) { 238 ims.add(DelegateMember.Builder.create(bo)); 239 } 240 241 builder.setResults(ims); 242 return builder.build(); 243 } 244 245 @Override 246 public Role getRole(String roleId) throws RiceIllegalStateException { 247 incomingParamCheck(roleId, "roleId"); 248 return loadRole(roleId); 249 } 250 251 /** 252 * Loads the role with the given id, leveraging the cache where possible and querying the database 253 * if role not already in the cache. If the role is not in the cache, then it will be placed in 254 * the cache once it is loaded. 255 */ 256 protected Role loadRole(String roleId) { 257 Role role = getRoleFromCache(roleId); 258 if (role == null) { 259 RoleBoLite roleBo = getRoleBoLite(roleId); 260 if (roleBo != null) { 261 role = RoleBoLite.to(roleBo); 262 putRoleInCache(role); 263 } 264 } 265 return role; 266 } 267 268 protected Role getRoleFromCache(String id) { 269 Cache cache = cacheManager.getCache(Role.Cache.NAME); 270 Cache.ValueWrapper cachedValue = cache.get("id=" + id); 271 if (cachedValue != null) { 272 return (Role)cachedValue.get(); 273 } 274 return null; 275 } 276 277 protected Role getRoleFromCache(String namespaceCode, String name) { 278 Cache cache = cacheManager.getCache(Role.Cache.NAME); 279 Cache.ValueWrapper cachedValue = cache.get("namespaceCode=" + namespaceCode + "|name=" + name); 280 if (cachedValue != null) { 281 return (Role)cachedValue.get(); 282 } 283 return null; 284 } 285 286 protected void putRoleInCache(Role role) { 287 if (role != null) { 288 Cache cache = cacheManager.getCache(Role.Cache.NAME); 289 String idKey = "id=" + role.getId(); 290 String nameKey = "namespaceCode=" + role.getNamespaceCode() + "|name=" + role.getName(); 291 cache.put(idKey, role); 292 cache.put(nameKey, role); 293 } 294 } 295 296 protected Map<String, RoleBoLite> getRoleBoLiteMap(Collection<String> roleIds) { 297 Map<String, RoleBoLite> result; 298 // check for a non-null result in the cache, return it if found 299 if (roleIds.size() == 1) { 300 String roleId = roleIds.iterator().next(); 301 RoleBoLite bo = getRoleBoLite(roleId); 302 if (bo == null) { 303 return Collections.<String, RoleBoLite>emptyMap(); 304 } 305 result = bo.isActive() ? Collections.singletonMap(roleId, bo) : Collections.<String, RoleBoLite>emptyMap(); 306 } else { 307 result = new HashMap<String, RoleBoLite>(roleIds.size()); 308 for (String roleId : roleIds) { 309 RoleBoLite bo = getRoleBoLite(roleId); 310 if (bo != null && bo.isActive()) { 311 result.put(roleId, bo); 312 } 313 } 314 } 315 return result; 316 } 317 318 @Override 319 public List<Role> getRoles(List<String> roleIds) throws RiceIllegalStateException { 320 if (CollectionUtils.isEmpty(roleIds)) { 321 throw new RiceIllegalArgumentException("roleIds is null or empty"); 322 } 323 return Collections.unmodifiableList(loadRoles(roleIds)); 324 } 325 326 /** 327 * Loads the roles with the given ids, leveraging the cache where possible and querying the database 328 * for role ids not already in the cache. If the role is not in the cache, then it will be placed in 329 * the cache once it is loaded. 330 */ 331 protected List<Role> loadRoles(List<String> roleIds) { 332 List<String> remainingRoleIds = new ArrayList<String>(); 333 Map<String, Role> roleMap = new HashMap<String, Role>(roleIds.size()); 334 for (String roleId : roleIds) { 335 Role role = getRoleFromCache(roleId); 336 if (role != null) { 337 roleMap.put(roleId, role); 338 } else { 339 remainingRoleIds.add(roleId); 340 } 341 } 342 if (!remainingRoleIds.isEmpty()) { 343 Map<String, RoleBoLite> roleBoMap = getRoleBoLiteMap(remainingRoleIds); 344 for (String roleId : roleBoMap.keySet()) { 345 RoleBoLite roleBo = roleBoMap.get(roleId); 346 if (roleBo != null) { 347 Role role = RoleBoLite.to(roleBo); 348 roleMap.put(roleId, role); 349 putRoleInCache(role); 350 } 351 } 352 } 353 List<Role> roles = new ArrayList<Role>(roleMap.values()); 354 return roles; 355 } 356 357 @Override 358 public Role getRoleByNamespaceCodeAndName(String namespaceCode, String roleName) throws RiceIllegalStateException { 359 incomingParamCheck(namespaceCode, "namespaceCode"); 360 incomingParamCheck(roleName, "roleName"); 361 return loadRoleByName(namespaceCode, roleName); 362 } 363 364 /** 365 * Loads the role with the given name, leveraging the cache where possible and querying the database 366 * if role not already in the cache. If the role is not in the cache, then it will be placed in 367 * the cache once it is loaded. 368 */ 369 protected Role loadRoleByName(String namespaceCode, String roleName) { 370 Role role = getRoleFromCache(namespaceCode, roleName); 371 if (role == null) { 372 RoleBoLite roleBo = getRoleBoLiteByName(namespaceCode, roleName); 373 if (roleBo != null) { 374 role = getRoleFromCache(roleBo.getId()); 375 if (role == null) { 376 role = RoleBoLite.to(roleBo); 377 } 378 putRoleInCache(role); 379 } 380 } 381 return role; 382 } 383 384 @Override 385 public String getRoleIdByNamespaceCodeAndName(String namespaceCode, String roleName) throws RiceIllegalStateException { 386 incomingParamCheck(namespaceCode, "namespaceCode"); 387 incomingParamCheck(roleName, "roleName"); 388 389 Role role = getRoleByNamespaceCodeAndName(namespaceCode, roleName); 390 if (role != null) { 391 return role.getId(); 392 } else { 393 return null; 394 } 395 } 396 397 @Override 398 public boolean isRoleActive(String roleId) throws RiceIllegalStateException { 399 incomingParamCheck(roleId, "roleId"); 400 Role role = getRole(roleId); 401 return role != null && role.isActive(); 402 } 403 404 @Override 405 public List<Map<String, String>> getRoleQualifersForPrincipalByRoleIds(String principalId, List<String> roleIds, 406 Map<String, String> qualification) throws RiceIllegalStateException { 407 incomingParamCheck(principalId, "principalId"); 408 incomingParamCheck(roleIds, "roleIds"); 409 410 List<Map<String, String>> results = new ArrayList<Map<String, String>>(); 411 412 List<RoleMemberBo> roleMemberBoList = getStoredRoleMembersUsingExactMatchOnQualification(principalId, null, 413 roleIds, qualification); 414 415 Map<String, List<RoleMembership>> roleIdToMembershipMap = new HashMap<String, List<RoleMembership>>(); 416 for (RoleMemberBo roleMemberBo : roleMemberBoList) { 417 // gather up the qualifier sets and the service they go with 418 if (MemberType.PRINCIPAL.equals(roleMemberBo.getType())) { 419 RoleTypeService roleTypeService = getRoleTypeService(roleMemberBo.getRoleId()); 420 if (roleTypeService != null) { 421 List<RoleMembership> las = roleIdToMembershipMap.get(roleMemberBo.getRoleId()); 422 if (las == null) { 423 las = new ArrayList<RoleMembership>(); 424 roleIdToMembershipMap.put(roleMemberBo.getRoleId(), las); 425 } 426 RoleMembership mi = RoleMembership.Builder.create( 427 roleMemberBo.getRoleId(), 428 roleMemberBo.getId(), 429 roleMemberBo.getMemberId(), 430 roleMemberBo.getType(), 431 roleMemberBo.getAttributes()).build(); 432 433 las.add(mi); 434 } else { 435 results.add(roleMemberBo.getAttributes()); 436 } 437 } 438 } 439 for (Map.Entry<String, List<RoleMembership>> entry : roleIdToMembershipMap.entrySet()) { 440 RoleTypeService roleTypeService = getRoleTypeService(entry.getKey()); 441 //it is possible that the the roleTypeService is coming from a remote application 442 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility. 443 try { 444 List<RoleMembership> matchingMembers = roleTypeService.getMatchingRoleMemberships(qualification, entry.getValue()); 445 for (RoleMembership rmi : matchingMembers) { 446 results.add(rmi.getQualifier()); 447 } 448 } catch (Exception ex) { 449 LOG.warn("Not able to retrieve RoleTypeService from remote system for role Id: " + entry.getKey(), ex); 450 } 451 } 452 return Collections.unmodifiableList(results); 453 } 454 455 @Override 456 public List<Map<String, String>> getRoleQualifersForPrincipalByNamespaceAndRolename(String principalId, 457 String namespaceCode, String roleName, Map<String, String> qualification) 458 throws RiceIllegalStateException { 459 incomingParamCheck(principalId, "principalId"); 460 incomingParamCheck(namespaceCode, "namespaceCode"); 461 incomingParamCheck(roleName, "roleName"); 462 463 String roleId = getRoleIdByNamespaceCodeAndName(namespaceCode, roleName); 464 if (roleId == null) { 465 return Collections.emptyList(); 466 } 467 return getNestedRoleQualifiersForPrincipalByRoleIds(principalId, Collections.singletonList(roleId), 468 qualification); 469 } 470 471 @Override 472 public List<Map<String, String>> getNestedRoleQualifersForPrincipalByNamespaceAndRolename(String principalId, 473 String namespaceCode, String roleName, Map<String, String> qualification) throws RiceIllegalStateException { 474 incomingParamCheck(principalId, "principalId"); 475 incomingParamCheck(namespaceCode, "namespaceCode"); 476 incomingParamCheck(roleName, "roleName"); 477 478 String roleId = getRoleIdByNamespaceCodeAndName(namespaceCode, roleName); 479 if (roleId == null) { 480 return new ArrayList<Map<String, String>>(0); 481 } 482 return getNestedRoleQualifiersForPrincipalByRoleIds(principalId, Collections.singletonList(roleId), 483 qualification); 484 } 485 486 @Override 487 public List<Map<String, String>> getNestedRoleQualifiersForPrincipalByRoleIds(String principalId, 488 List<String> roleIds, Map<String, String> qualification) throws RiceIllegalStateException { 489 incomingParamCheck(principalId, "principalId"); 490 incomingParamCheck(roleIds, "roleIds"); 491 492 493 List<Map<String, String>> results = new ArrayList<Map<String, String>>(); 494 495 Map<String, RoleBoLite> roleBosById = getRoleBoLiteMap(roleIds); 496 497 // get the person's groups 498 List<String> groupIds = getGroupService().getGroupIdsByPrincipalId(principalId); 499 List<RoleMemberBo> roleMemberBos = getStoredRoleMembersUsingExactMatchOnQualification(principalId, groupIds, roleIds, qualification); 500 501 Map<String, List<RoleMembership>> roleIdToMembershipMap = new HashMap<String, List<RoleMembership>>(); 502 for (RoleMemberBo roleMemberBo : roleMemberBos) { 503 RoleTypeService roleTypeService = getRoleTypeService(roleMemberBo.getRoleId()); 504 // gather up the qualifier sets and the service they go with 505 if (MemberType.PRINCIPAL.equals(roleMemberBo.getType()) 506 || MemberType.GROUP.equals(roleMemberBo.getType())) { 507 if (roleTypeService != null) { 508 List<RoleMembership> las = roleIdToMembershipMap.get(roleMemberBo.getRoleId()); 509 if (las == null) { 510 las = new ArrayList<RoleMembership>(); 511 roleIdToMembershipMap.put(roleMemberBo.getRoleId(), las); 512 } 513 RoleMembership mi = RoleMembership.Builder.create( 514 roleMemberBo.getRoleId(), 515 roleMemberBo.getId(), 516 roleMemberBo.getMemberId(), 517 roleMemberBo.getType(), 518 roleMemberBo.getAttributes()).build(); 519 520 las.add(mi); 521 } else { 522 results.add(roleMemberBo.getAttributes()); 523 } 524 } else if (MemberType.ROLE.equals(roleMemberBo.getType())) { 525 // find out if the user has the role 526 // need to convert qualification using this role's service 527 Map<String, String> nestedQualification = qualification; 528 if (roleTypeService != null) { 529 RoleBoLite roleBo = roleBosById.get(roleMemberBo.getRoleId()); 530 // pulling from here as the nested roleBo is not necessarily (and likely is not) 531 // in the roleBosById Map created earlier 532 RoleBoLite nestedRole = getRoleBoLite(roleMemberBo.getMemberId()); 533 //it is possible that the the roleTypeService is coming from a remote application 534 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility. 535 try { 536 nestedQualification = getNestedQualification(nestedRole, 537 roleBo.getNamespaceCode(), roleBo.getName(), nestedRole.getNamespaceCode(), 538 nestedRole.getName(), qualification, roleMemberBo.getAttributes()); 539 } catch (Exception ex) { 540 LOG.warn("Not able to retrieve RoleTypeService from remote system for roleBo Id: " + roleBo.getId(), ex); 541 } 542 } 543 List<String> nestedRoleId = new ArrayList<String>(1); 544 nestedRoleId.add(roleMemberBo.getMemberId()); 545 // if the user has the given role, add the qualifier the *nested role* has with the 546 // originally queries role 547 if (this.getProxiedRoleService().principalHasRole(principalId, nestedRoleId, nestedQualification, false)) { 548 results.add(roleMemberBo.getAttributes()); 549 } 550 } 551 } 552 for (Map.Entry<String, List<RoleMembership>> entry : roleIdToMembershipMap.entrySet()) { 553 RoleTypeService roleTypeService = getRoleTypeService(entry.getKey()); 554 //it is possible that the the roleTypeService is coming from a remote 555 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility. 556 try { 557 List<RoleMembership> matchingMembers = roleTypeService.getMatchingRoleMemberships(qualification, 558 entry.getValue()); 559 for (RoleMembership roleMembership : matchingMembers) { 560 results.add(roleMembership.getQualifier()); 561 } 562 } catch (Exception ex) { 563 LOG.warn("Not able to retrieve RoleTypeService from remote system for role Id: " + entry.getKey(), ex); 564 } 565 } 566 return Collections.unmodifiableList(results); 567 } 568 569 @Override 570 public List<RoleMembership> getRoleMembers(List<String> roleIds, Map<String, String> qualification) throws RiceIllegalStateException { 571 incomingParamCheck(roleIds, "roleIds"); 572 573 Set<String> foundRoleTypeMembers = new HashSet<String>(); 574 List<RoleMembership> roleMembers = getRoleMembers(roleIds, qualification, true, foundRoleTypeMembers); 575 576 return Collections.unmodifiableList(roleMembers); 577 } 578 579 @Override 580 public Collection<String> getRoleMemberPrincipalIds(String namespaceCode, String roleName, Map<String, String> qualification) throws RiceIllegalStateException { 581 incomingParamCheck(namespaceCode, "namespaceCode"); 582 incomingParamCheck(roleName, "roleName"); 583 584 Set<String> principalIds = new HashSet<String>(); 585 Set<String> foundRoleTypeMembers = new HashSet<String>(); 586 List<String> roleIds = Collections.singletonList(getRoleIdByNamespaceCodeAndName(namespaceCode, roleName)); 587 for (RoleMembership roleMembership : getRoleMembers(roleIds, qualification, false, foundRoleTypeMembers)) { 588 if (MemberType.GROUP.equals(roleMembership.getType())) { 589 principalIds.addAll(getGroupService().getMemberPrincipalIds(roleMembership.getMemberId())); 590 } else { 591 principalIds.add(roleMembership.getMemberId()); 592 } 593 } 594 595 return Collections.unmodifiableSet(principalIds); 596 } 597 598 @Override 599 public boolean principalHasRole(String principalId, List<String> roleIds, Map<String, String> qualification) throws RiceIllegalStateException { 600 601 if ( LOG.isDebugEnabled() ) { 602 logPrincipalHasRoleCheck(principalId, roleIds, qualification); 603 } 604 605 boolean hasRole = this.getProxiedRoleService().principalHasRole(principalId, roleIds, qualification, true); 606 607 if ( LOG.isDebugEnabled() ) { 608 LOG.debug( "Result: " + hasRole ); 609 } 610 611 return hasRole; 612 } 613 614 @Override 615 public List<String> getPrincipalIdSubListWithRole(List<String> principalIds, 616 String roleNamespaceCode, String roleName, Map<String, String> qualification) throws RiceIllegalStateException { 617 incomingParamCheck(principalIds, "principalIds"); 618 incomingParamCheck(roleNamespaceCode, "roleNamespaceCode"); 619 incomingParamCheck(roleName, "roleName"); 620 621 List<String> subList = new ArrayList<String>(); 622 RoleBoLite role = getRoleBoLiteByName(roleNamespaceCode, roleName); 623 for (String principalId : principalIds) { 624 if (this.getProxiedRoleService().principalHasRole(principalId, Collections.singletonList(role.getId()), qualification)) { 625 subList.add(principalId); 626 } 627 } 628 return Collections.unmodifiableList(subList); 629 } 630 631 @Override 632 public RoleQueryResults findRoles(QueryByCriteria queryByCriteria) throws RiceIllegalStateException { 633 incomingParamCheck(queryByCriteria, "queryByCriteria"); 634 635 QueryResults<RoleBoLite> results = getDataObjectService().findMatching(RoleBoLite.class, queryByCriteria); 636 637 RoleQueryResults.Builder builder = RoleQueryResults.Builder.create(); 638 builder.setMoreResultsAvailable(results.isMoreResultsAvailable()); 639 builder.setTotalRowCount(results.getTotalRowCount()); 640 641 final List<Role.Builder> ims = new ArrayList<Role.Builder>(); 642 for (RoleBoLite bo : results.getResults()) { 643 ims.add(Role.Builder.create(bo)); 644 } 645 646 builder.setResults(ims); 647 return builder.build(); 648 } 649 650 @Override 651 public List<RoleMembership> getFirstLevelRoleMembers(List<String> roleIds) throws RiceIllegalStateException { 652 incomingParamCheck(roleIds, "roleIds"); 653 if (roleIds.isEmpty()) { 654 return Collections.emptyList(); 655 } 656 657 List<RoleMemberBo> roleMemberBoList = getStoredRoleMembersForRoleIds(roleIds, null, null); 658 List<RoleMembership> roleMemberships = new ArrayList<RoleMembership>(); 659 for (RoleMemberBo roleMemberBo : roleMemberBoList) { 660 RoleMembership roleMembeship = RoleMembership.Builder.create( 661 roleMemberBo.getRoleId(), 662 roleMemberBo.getId(), 663 roleMemberBo.getMemberId(), 664 roleMemberBo.getType(), 665 roleMemberBo.getAttributes()).build(); 666 roleMemberships.add(roleMembeship); 667 } 668 return Collections.unmodifiableList(roleMemberships); 669 } 670 671 @Override 672 public RoleMembershipQueryResults findRoleMemberships( QueryByCriteria queryByCriteria) throws RiceIllegalStateException { 673 incomingParamCheck(queryByCriteria, "queryByCriteria"); 674 675 QueryResults<RoleMemberBo> results = getDataObjectService().findMatching(RoleMemberBo.class, 676 AttributeTransform.getInstance().apply(queryByCriteria)); 677 678 RoleMembershipQueryResults.Builder builder = RoleMembershipQueryResults.Builder.create(); 679 builder.setMoreResultsAvailable(results.isMoreResultsAvailable()); 680 builder.setTotalRowCount(results.getTotalRowCount()); 681 682 final List<RoleMembership.Builder> ims = new ArrayList<RoleMembership.Builder>(); 683 for (RoleMemberBo bo : results.getResults()) { 684 RoleMembership.Builder roleMembership = RoleMembership.Builder.create( 685 bo.getRoleId(), 686 bo.getId(), 687 bo.getMemberId(), 688 bo.getType(), 689 bo.getAttributes()); 690 ims.add(roleMembership); 691 } 692 693 builder.setResults(ims); 694 return builder.build(); 695 } 696 697 @Override 698 public List<DelegateMember> getDelegationMembersByDelegationId(String delegationId) throws RiceIllegalStateException { 699 incomingParamCheck(delegationId, "delegationId"); 700 701 DelegateTypeBo delegateBo = getKimDelegationImpl(delegationId); 702 if (delegateBo == null) {return Collections.emptyList();} 703 704 return getDelegateMembersForDelegation(delegateBo); 705 } 706 707 @Override 708 public DelegateMember getDelegationMemberByDelegationAndMemberId(String delegationId, String memberId) throws RiceIllegalStateException { 709 incomingParamCheck(delegationId, "delegationId"); 710 incomingParamCheck(memberId, "memberId"); 711 712 DelegateTypeBo delegateBo = getKimDelegationImpl(delegationId); 713 DelegateMemberBo delegationMember = getKimDelegationMemberImplByDelegationAndId(delegationId, memberId); 714 715 return getDelegateCompleteInfo(delegateBo, delegationMember); 716 } 717 718 @Override 719 public DelegateMember getDelegationMemberById(String delegationMemberId) throws RiceIllegalStateException { 720 incomingParamCheck(delegationMemberId, "delegationMemberId"); 721 722 DelegateMemberBo delegateMemberBo = getDelegateMemberBo(delegationMemberId); 723 if (delegateMemberBo == null) { 724 return null; 725 } 726 727 DelegateTypeBo delegateBo = getKimDelegationImpl(delegateMemberBo.getDelegationId()); 728 729 return getDelegateCompleteInfo(delegateBo, delegateMemberBo); 730 } 731 732 @Override 733 public List<RoleResponsibility> getRoleResponsibilities(String roleId) throws RiceIllegalStateException { 734 incomingParamCheck(roleId, "roleId"); 735 736 List<RoleResponsibilityBo> roleResponsibilityBos = 737 getDataObjectService().findMatching(RoleResponsibilityBo.class, QueryByCriteria.Builder.forAttribute(KimConstants.PrimaryKeyConstants.SUB_ROLE_ID, roleId).build()).getResults(); 738 List<RoleResponsibility> roleResponsibilities = new ArrayList<RoleResponsibility>(); 739 740 for (RoleResponsibilityBo roleResponsibilityImpl : roleResponsibilityBos) { 741 roleResponsibilities.add(RoleResponsibilityBo.to(roleResponsibilityImpl)); 742 } 743 return Collections.unmodifiableList(roleResponsibilities); 744 } 745 746 @Override 747 public DelegateType getDelegateTypeByRoleIdAndDelegateTypeCode(String roleId, DelegationType delegationType) throws RiceIllegalStateException { 748 incomingParamCheck(roleId, "roleId"); 749 incomingParamCheck(delegationType, "delegationType"); 750 751 DelegateTypeBo delegateBo = getDelegationOfType(roleId, delegationType); 752 return DelegateTypeBo.to(delegateBo); 753 } 754 755 @Override 756 public DelegateType getDelegateTypeByDelegationId(String delegationId) throws RiceIllegalStateException { 757 incomingParamCheck(delegationId, "delegationId"); 758 759 DelegateTypeBo delegateBo = getKimDelegationImpl(delegationId); 760 return DelegateTypeBo.to(delegateBo); 761 } 762 763 protected List<RoleMembership> getRoleMembers(List<String> roleIds, Map<String, String> qualification, boolean followDelegations, Set<String> foundRoleTypeMembers) { 764 List<RoleMembership> results = new ArrayList<RoleMembership>(); 765 Set<String> allRoleIds = new HashSet<String>(); 766 for (String roleId : roleIds) { 767 if (this.getProxiedRoleService().isRoleActive(roleId)) { 768 allRoleIds.add(roleId); 769 } 770 } 771 // short-circuit if no roles match 772 if (allRoleIds.isEmpty()) { 773 return Collections.emptyList(); 774 } 775 Set<String> matchingRoleIds = new HashSet<String>(allRoleIds.size()); 776 // for efficiency, retrieve all roles and store in a map 777 Map<String, RoleBoLite> roles = getRoleBoLiteMap(allRoleIds); 778 779 List<String> copyRoleIds = new ArrayList<String>(allRoleIds); 780 List<RoleMemberBo> rms = new ArrayList<RoleMemberBo>(); 781 782 for (String roleId : allRoleIds) { 783 RoleTypeService roleTypeService = getRoleTypeService(roleId); 784 if (roleTypeService != null) { 785 List<String> attributesForExactMatch = roleTypeService.getQualifiersForExactMatch(); 786 if (CollectionUtils.isNotEmpty(attributesForExactMatch)) { 787 copyRoleIds.remove(roleId); 788 rms.addAll(getStoredRoleMembersForRoleIds(Collections.singletonList(roleId), null, populateQualifiersForExactMatch(qualification, attributesForExactMatch))); 789 } 790 } 791 } 792 if (CollectionUtils.isNotEmpty(copyRoleIds)) { 793 rms.addAll(getStoredRoleMembersForRoleIds(copyRoleIds, null, null)); 794 } 795 796 // build a map of role ID to membership information 797 // this will be used for later qualification checks 798 Map<String, List<RoleMembership>> roleIdToMembershipMap = new HashMap<String, List<RoleMembership>>(); 799 for (RoleMemberBo roleMemberBo : rms) { 800 RoleMembership mi = RoleMembership.Builder.create( 801 roleMemberBo.getRoleId(), 802 roleMemberBo.getId(), 803 roleMemberBo.getMemberId(), 804 roleMemberBo.getType(), 805 roleMemberBo.getAttributes()).build(); 806 807 // if the qualification check does not need to be made, just add the result 808 if ((qualification == null || qualification.isEmpty())) { 809 if (MemberType.ROLE.equals(roleMemberBo.getType())) { 810 // if a role member type, do a non-recursive role member check 811 // to obtain the group and principal members of that role 812 // given the qualification 813 Map<String, String> nestedRoleQualification = qualification; 814 RoleTypeService roleTypeService = getRoleTypeService(roleMemberBo.getRoleId()); 815 if (roleTypeService != null) { 816 // get the member role object 817 RoleBoLite memberRole = getRoleBoLite(mi.getMemberId()); 818 nestedRoleQualification = getNestedQualification(memberRole, roles.get( 819 roleMemberBo.getRoleId()).getNamespaceCode(), roles.get(roleMemberBo.getRoleId()) 820 .getName(), memberRole.getNamespaceCode(), memberRole.getName(), qualification, roleMemberBo.getAttributes()); 821 } 822 if (this.getProxiedRoleService().isRoleActive(roleMemberBo.getRoleId())) { 823 Collection<RoleMembership> nestedRoleMembers = getNestedRoleMembers(nestedRoleQualification, mi, foundRoleTypeMembers); 824 if (!nestedRoleMembers.isEmpty()) { 825 results.addAll(nestedRoleMembers); 826 matchingRoleIds.add(roleMemberBo.getRoleId()); 827 } 828 } 829 } else { // not a role member type 830 results.add(mi); 831 matchingRoleIds.add(roleMemberBo.getRoleId()); 832 } 833 matchingRoleIds.add(roleMemberBo.getRoleId()); 834 } else { 835 List<RoleMembership> lrmi = roleIdToMembershipMap.get(mi.getRoleId()); 836 if (lrmi == null) { 837 lrmi = new ArrayList<RoleMembership>(); 838 roleIdToMembershipMap.put(mi.getRoleId(), lrmi); 839 } 840 lrmi.add(mi); 841 } 842 } 843 // if there is anything in the role to membership map, we need to check the role type services 844 // for those entries 845 if (!roleIdToMembershipMap.isEmpty()) { 846 // for each role, send in all the qualifiers for that role to the type service 847 // for evaluation, the service will return those which match 848 for (Map.Entry<String, List<RoleMembership>> entry : roleIdToMembershipMap.entrySet()) { 849 //it is possible that the the roleTypeService is coming from a remote application 850 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility. 851 try { 852 RoleTypeService roleTypeService = getRoleTypeService(entry.getKey()); 853 List<RoleMembership> matchingMembers = roleTypeService.getMatchingRoleMemberships(qualification, 854 entry.getValue()); 855 // loop over the matching entries, adding them to the results 856 for (RoleMembership roleMemberships : matchingMembers) { 857 if (MemberType.ROLE.equals(roleMemberships.getType())) { 858 // if a role member type, do a non-recursive role member check 859 // to obtain the group and principal members of that role 860 // given the qualification 861 // get the member role object 862 RoleBoLite memberRole = getRoleBoLite(roleMemberships.getMemberId()); 863 if (memberRole.isActive()) { 864 Map<String, String> nestedRoleQualification = getNestedQualification(memberRole, 865 roles.get(roleMemberships.getRoleId()).getNamespaceCode(), roles.get( 866 roleMemberships.getRoleId()).getName(), memberRole.getNamespaceCode(), 867 memberRole.getName(), qualification, roleMemberships.getQualifier()); 868 Collection<RoleMembership> nestedRoleMembers = getNestedRoleMembers(nestedRoleQualification, roleMemberships, foundRoleTypeMembers); 869 if (!nestedRoleMembers.isEmpty()) { 870 results.addAll(nestedRoleMembers); 871 matchingRoleIds.add(roleMemberships.getRoleId()); 872 } 873 } 874 } else { // not a role member 875 results.add(roleMemberships); 876 matchingRoleIds.add(roleMemberships.getRoleId()); 877 } 878 } 879 } catch (Exception ex) { 880 LOG.warn("Not able to retrieve RoleTypeService from remote system for role Id: " + entry.getKey(), ex); 881 } 882 } 883 } 884 885 // handle derived roles 886 for ( String roleId : allRoleIds ) { 887 RoleTypeService roleTypeService = getRoleTypeService( roleId ); 888 RoleBoLite role = roles.get( roleId ); 889 // check if a derived role 890 try { 891 if ( isDerivedRoleType(roleTypeService) ) { 892 // for each derived role, get the list of principals and groups which are in that role given the qualification (per the role type service) 893 List<RoleMembership> roleMembers = roleTypeService.getRoleMembersFromDerivedRole(role.getNamespaceCode(), role.getName(), qualification); 894 if ( !roleMembers.isEmpty() ) { 895 matchingRoleIds.add( roleId ); 896 } 897 for ( RoleMembership rm : roleMembers ) { 898 RoleMembership.Builder builder = RoleMembership.Builder.create(rm); 899 builder.setRoleId(roleId); 900 builder.setId("*"); 901 results.add(builder.build()); 902 } 903 } 904 } catch (Exception ex) { 905 LOG.warn("Not able to retrieve RoleTypeService from remote system for role Id: " + roleId, ex); 906 } 907 } 908 909 if ( followDelegations && !matchingRoleIds.isEmpty() ) { 910 // we have a list of RoleMembershipInfo objects 911 // need to get delegations for distinct list of roles in that list 912 Map<String, DelegateTypeBo> delegationIdToDelegationMap = getStoredDelegationImplMapFromRoleIds(matchingRoleIds); 913 if (!delegationIdToDelegationMap.isEmpty()) { 914 List<RoleMembership.Builder> membershipsWithDelegations = 915 applyDelegationsToRoleMembers(results, delegationIdToDelegationMap.values(), qualification); 916 resolveDelegationMemberRoles(membershipsWithDelegations, qualification, foundRoleTypeMembers); 917 results = ModelObjectUtils.buildImmutableCopy(membershipsWithDelegations); 918 } 919 } 920 921 // sort the results if a single role type service can be identified for 922 // all the matching role members 923 if ( results.size() > 1 ) { 924 // if a single role: easy case 925 if ( matchingRoleIds.size() == 1 ) { 926 String roleId = matchingRoleIds.iterator().next(); 927 RoleTypeService roleTypeService = getRoleTypeService( roleId ); 928 //it is possible that the the roleTypeService is coming from a remote application 929 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility. 930 try { 931 if ( roleTypeService != null ) { 932 results = roleTypeService.sortRoleMembers( results ); 933 } 934 } catch (Exception ex) { 935 LOG.warn("Not able to retrieve RoleTypeService from remote system for role Id: " + roleId, ex); 936 } 937 } else if ( matchingRoleIds.size() > 1 ) { 938 // if more than one, check if there is only a single role type service 939 String prevServiceName = null; 940 boolean multipleServices = false; 941 for ( String roleId : matchingRoleIds ) { 942 String serviceName = KimApiServiceLocator.getKimTypeInfoService().getKimType(getRole(roleId).getKimTypeId()).getServiceName(); 943 if ( prevServiceName != null && !StringUtils.equals( prevServiceName, serviceName ) ) { 944 multipleServices = true; 945 break; 946 } 947 prevServiceName = serviceName; 948 } 949 if ( !multipleServices ) { 950 String roleId = matchingRoleIds.iterator().next(); 951 //it is possible that the the roleTypeService is coming from a remote application 952 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility. 953 try { 954 RoleTypeService kimRoleTypeService = getRoleTypeService( roleId ); 955 if ( kimRoleTypeService != null ) { 956 results = kimRoleTypeService.sortRoleMembers( results ); 957 } 958 } catch (Exception ex) { 959 LOG.warn("Not able to retrieve RoleTypeService from remote system for role Id: " + roleId, ex); 960 } 961 } else { 962 LOG.warn( "Did not sort role members - multiple role type services found. Role Ids: " + matchingRoleIds ); 963 } 964 } 965 } 966 return Collections.unmodifiableList(results); 967 } 968 969 /** 970 * Checks each of the result records to determine if there are potentially applicable delegation members for that 971 * role membership. If there are, applicable delegations and members will be linked to the RoleMemberships in the 972 * given list. An updated list will be returned from this method which includes the appropriate linked delegations. 973 */ 974 protected List<RoleMembership.Builder> applyDelegationsToRoleMembers(List<RoleMembership> roleMemberships, 975 Collection<DelegateTypeBo> delegations, Map<String, String> qualification) { 976 MultiValueMap<String, String> roleIdToRoleMembershipIds = new LinkedMultiValueMap<String, String>(); 977 Map<String, RoleMembership.Builder> roleMembershipIdToBuilder = new HashMap<String, RoleMembership.Builder>(); 978 List<RoleMembership.Builder> roleMembershipBuilders = new ArrayList<RoleMembership.Builder>(); 979 // to make our algorithm less painful, let's do some indexing and load the given list of RoleMemberships into 980 // builders 981 for (RoleMembership roleMembership : roleMemberships) { 982 roleIdToRoleMembershipIds.add(roleMembership.getRoleId(), roleMembership.getId()); 983 RoleMembership.Builder builder = RoleMembership.Builder.create(roleMembership); 984 roleMembershipBuilders.add(builder); 985 roleMembershipIdToBuilder.put(roleMembership.getId(), builder); 986 } 987 for (DelegateTypeBo delegation : delegations) { 988 // determine the candidate role memberships where this delegation can be mapped 989 List<String> candidateRoleMembershipIds = roleIdToRoleMembershipIds.get(delegation.getRoleId()); 990 if (CollectionUtils.isNotEmpty(candidateRoleMembershipIds)) { 991 DelegationTypeService delegationTypeService = getDelegationTypeService(delegation.getDelegationId()); 992 for (DelegateMemberBo delegationMember : delegation.getMembers()) { 993 // Make sure that the delegation member is active 994 if (delegationMember.isActive(DateTime.now()) && (delegationTypeService == null || 995 delegationTypeService.doesDelegationQualifierMatchQualification(qualification, delegationMember.getQualifier()))) { 996 DelegateMember.Builder delegateMemberBuilder = DelegateMember.Builder.create(delegationMember); 997 // if the member has no role member id, check qualifications and apply to all matching role memberships on the role 998 if (StringUtils.isBlank(delegationMember.getRoleMemberId())) { 999 RoleTypeService roleTypeService = getRoleTypeService(delegation.getRoleId()); 1000 for (String roleMembershipId : candidateRoleMembershipIds) { 1001 RoleMembership.Builder roleMembershipBuilder = roleMembershipIdToBuilder.get(roleMembershipId); 1002 if (roleTypeService == null || roleTypeService.doesRoleQualifierMatchQualification(roleMembershipBuilder.getQualifier(), delegationMember.getQualifier())) { 1003 linkDelegateToRoleMembership(delegation, delegateMemberBuilder, roleMembershipBuilder); 1004 } 1005 } 1006 } else if (candidateRoleMembershipIds.contains(delegationMember.getRoleMemberId())) { 1007 RoleMembership.Builder roleMembershipBuilder = roleMembershipIdToBuilder.get(delegationMember.getRoleMemberId()); 1008 linkDelegateToRoleMembership(delegation, delegateMemberBuilder, roleMembershipBuilder); 1009 } 1010 } 1011 } 1012 } 1013 } 1014 return roleMembershipBuilders; 1015 } 1016 1017 protected void linkDelegateToRoleMembership(DelegateTypeBo delegation, DelegateMember.Builder delegateMemberBuilder, 1018 RoleMembership.Builder roleMembershipBuilder) { 1019 DelegateType.Builder delegateBuilder = null; 1020 for(DelegateType.Builder existingDelegateBuilder : roleMembershipBuilder.getDelegates()) { 1021 if (existingDelegateBuilder.getDelegationId().equals(delegation.getDelegationId())) { 1022 delegateBuilder = existingDelegateBuilder; 1023 } 1024 } 1025 if (delegateBuilder == null) { 1026 delegateBuilder = DelegateType.Builder.create(delegation); 1027 delegateBuilder.setMembers(new ArrayList<DelegateMember.Builder>()); 1028 roleMembershipBuilder.getDelegates().add(delegateBuilder); 1029 } 1030 delegateBuilder.getMembers().add(delegateMemberBuilder); 1031 1032 } 1033 1034 /** 1035 * Once the delegations for a RoleMembershipInfo object have been determined, 1036 * any "role" member types need to be resolved into groups and principals so that 1037 * further KIM requests are not needed. 1038 */ 1039 protected void resolveDelegationMemberRoles(List<RoleMembership.Builder> membershipBuilders, 1040 Map<String, String> qualification, Set<String> foundRoleTypeMembers) { 1041 // check delegations assigned to this role 1042 for (RoleMembership.Builder roleMembership : membershipBuilders) { 1043 // the applicable delegation IDs will already be set in the RoleMembership.Builder 1044 // this code examines those delegations and obtains the member groups and principals 1045 for (DelegateType.Builder delegation : roleMembership.getDelegates()) { 1046 List<DelegateMember.Builder> newMembers = new ArrayList<DelegateMember.Builder>(); 1047 for (DelegateMember.Builder member : delegation.getMembers()) { 1048 if (MemberType.ROLE.equals(member.getType())) { 1049 // loop over delegation roles and extract the role IDs where the qualifications match 1050 Collection<RoleMembership> delegateMembers = getRoleMembers(Collections.singletonList( 1051 member.getMemberId()), qualification, false, foundRoleTypeMembers); 1052 // loop over the role members and create the needed DelegationMember builders 1053 for (RoleMembership rmi : delegateMembers) { 1054 DelegateMember.Builder delegateMember = DelegateMember.Builder.create(member); 1055 delegateMember.setMemberId(rmi.getMemberId()); 1056 delegateMember.setType(rmi.getType()); 1057 newMembers.add(delegateMember); 1058 } 1059 } else { 1060 newMembers.add(member); 1061 } 1062 } 1063 delegation.setMembers(newMembers); 1064 } 1065 } 1066 } 1067 1068 @Override 1069 public boolean principalHasRole(String principalId, List<String> roleIds, Map<String, String> qualification, boolean checkDelegations) { 1070 1071 incomingParamCheck(principalId, "principalId"); 1072 incomingParamCheck(roleIds, "roleIds"); 1073 return principalHasRole(new Context(principalId), principalId, roleIds, qualification, checkDelegations); 1074 } 1075 1076 /** 1077 * An internal helper class which is used to keep context for an invocation of principalHasRole. 1078 */ 1079 private final class Context { 1080 1081 private String principalId; 1082 private List<String> principalGroupIds; 1083 private Map<String, RoleTypeService> roleTypeServiceCache; 1084 private Map<String, Boolean> isDerivedRoleTypeCache; 1085 1086 Context(String principalId) { 1087 this.principalId = principalId; 1088 this.roleTypeServiceCache = new HashMap<String, RoleTypeService>(); 1089 this.isDerivedRoleTypeCache = new HashMap<String, Boolean>(); 1090 } 1091 1092 String getPrincipalId() { 1093 return principalId; 1094 } 1095 1096 List<String> getPrincipalGroupIds() { 1097 if (principalGroupIds == null) { 1098 principalGroupIds = getGroupService().getGroupIdsByPrincipalId(principalId); 1099 } 1100 return principalGroupIds; 1101 } 1102 1103 RoleTypeService getRoleTypeService(String kimTypeId) { 1104 if (roleTypeServiceCache.containsKey(kimTypeId)) { 1105 return roleTypeServiceCache.get(kimTypeId); 1106 } 1107 RoleTypeService roleTypeService = null; 1108 if (kimTypeId != null) { 1109 KimType roleType = KimApiServiceLocator.getKimTypeInfoService().getKimType(kimTypeId); 1110 if (roleType != null && StringUtils.isNotBlank(roleType.getServiceName())) { 1111 roleTypeService = getRoleTypeServiceByName(roleType.getServiceName()); 1112 } 1113 } 1114 if (roleTypeService == null) { 1115 roleTypeService = KimImplServiceLocator.getDefaultRoleTypeService(); 1116 } 1117 roleTypeServiceCache.put(kimTypeId, roleTypeService); 1118 return roleTypeService; 1119 } 1120 1121 boolean isDerivedRoleType(String kimTypeId) { 1122 Boolean isDerived = isDerivedRoleTypeCache.get(kimTypeId); 1123 if (isDerived == null) { 1124 isDerived = Boolean.valueOf(RoleServiceImpl.this.isDerivedRoleType(getRoleTypeService(kimTypeId))); 1125 isDerivedRoleTypeCache.put(kimTypeId, isDerived); 1126 } 1127 return isDerived.booleanValue(); 1128 } 1129 1130 } 1131 1132 1133 protected boolean principalHasRole(Context context, String principalId, List<String> roleIds, Map<String, String> qualification, boolean checkDelegations) { 1134 1135 /** 1136 * This method uses a multi-phase approach to determining if the given principal of any of the roles given based 1137 * on the qualification map that is pased. 1138 * 1139 * Phase 1: Check the cache to find if it's already been determined that the principal is a member of any of 1140 * the roles with the given ids. 1141 * Phase 2: Perform exact database-level matching. This can be done for all roles if the given qualification map 1142 * is null or empty since that means qualification matching does not need to be performed. It can also 1143 * be done for roles who's RoleTypeService defines qualifiers for exact match. 1144 * Phase 3: Use RoleTypeService matching for roles which have not already been checked. Will need to determine 1145 * which role memberships match the given principal then delegate to the appropriate RoleTypeService 1146 * to execute matching logic. 1147 * Phase 4: Check nested roles. 1148 * Phase 5: For any cases where derived roles are used, determine if the principal is a member of those 1149 * derived roles. 1150 * Phase 6: If checkDelegations is true, check if any delegations match 1151 */ 1152 try { 1153 // Phase 1: first check if any of the role membership is cached, only proceed with checking the role ids that 1154 // aren't already cached 1155 1156 List<String> roleIdsToCheck = new ArrayList<String>(roleIds.size()); 1157 for (String roleId : roleIds) { 1158 Boolean hasRole = getPrincipalHasRoleFromCache(principalId, roleId, qualification, checkDelegations); 1159 if (hasRole != null) { 1160 if (hasRole.booleanValue()) { 1161 return true; 1162 } 1163 } else { 1164 roleIdsToCheck.add(roleId); 1165 } 1166 } 1167 1168 // load the roles, this will also filter out inactive roles! 1169 List<Role> roles = loadRoles(roleIdsToCheck); 1170 // short-circuit if no roles match 1171 if (roles.isEmpty()) { 1172 return false; 1173 } 1174 1175 // Phase 2: If they didn't pass any qualifications or they are using exact qualifier matching, we can go 1176 // straight to the database 1177 1178 Set<String> rolesCheckedForExactMatch = new HashSet<String>(); 1179 for (Role role : roles) { 1180 Map<String, String> qualificationForExactMatch = null; 1181 if (qualification == null || qualification.isEmpty()) { 1182 qualificationForExactMatch = new HashMap<String, String>(); 1183 } else { 1184 RoleTypeService roleTypeService = context.getRoleTypeService(role.getKimTypeId()); 1185 if (roleTypeService != null) { 1186 List<String> attributesForExactMatch = getQualifiersForExactMatch(role.getKimTypeId(), roleTypeService); 1187 if (CollectionUtils.isNotEmpty(attributesForExactMatch)) { 1188 qualificationForExactMatch = populateQualifiersForExactMatch(qualification, attributesForExactMatch); 1189 if (qualificationForExactMatch.isEmpty()) { 1190 // None of the attributes passed into principalHasRole matched attribute qualifiers on 1191 // the roleTypeService. In this case we want to skip the remaining processing and 1192 // go onto the next role. 1193 continue; 1194 } 1195 } 1196 } 1197 } 1198 if (qualificationForExactMatch != null) { 1199 rolesCheckedForExactMatch.add(role.getId()); 1200 List<RoleMemberBo> matchingRoleMembers = getStoredRolePrincipalsForPrincipalIdAndRoleIds( 1201 Collections.singletonList(role.getId()), principalId, qualificationForExactMatch); 1202 // if a role member matched our principal, we're good to go 1203 if (CollectionUtils.isNotEmpty(matchingRoleMembers)) { 1204 return putPrincipalHasRoleInCache(true, principalId, role.getId(), qualification, checkDelegations); 1205 } 1206 // now check groups 1207 if (!context.getPrincipalGroupIds().isEmpty()) { 1208 List<RoleMemberBo> matchingRoleGroupMembers = 1209 getStoredRoleGroupsUsingExactMatchOnQualification(context.getPrincipalGroupIds(), role.getId(), qualification); 1210 if (CollectionUtils.isNotEmpty(matchingRoleGroupMembers)) { 1211 return putPrincipalHasRoleInCache(true, principalId, role.getId(), qualification, checkDelegations); 1212 } 1213 } 1214 // if we drop to this point, either we didn't match or the role has nested or derived role membership, 1215 // we'll check that later 1216 } 1217 } 1218 1219 // Phase 3: If we couldn't do an exact match, we need to work with the RoleTypeService in order to 1220 // perform matching 1221 1222 for (Role role : roles) { 1223 // if we didn't do an exact match, we need to do a manual match 1224 if (!rolesCheckedForExactMatch.contains(role.getId())) { 1225 List<RoleMemberBo> matchingPrincipalRoleMembers = getRoleMembersForPrincipalId(Collections.singletonList(role.getId()), principalId); 1226 List<RoleMemberBo> matchingGroupRoleMembers = getRoleMembersForGroupIds(role.getId(), context.getPrincipalGroupIds()); 1227 List<RoleMembership> roleMemberships = convertToRoleMemberships(matchingPrincipalRoleMembers, matchingGroupRoleMembers); 1228 try { 1229 RoleTypeService roleTypeService = context.getRoleTypeService(role.getKimTypeId()); 1230 if (!roleTypeService.getMatchingRoleMemberships(qualification, roleMemberships).isEmpty()) { 1231 return putPrincipalHasRoleInCache(true, principalId, role.getId(), qualification, checkDelegations); 1232 } 1233 } catch (Exception ex) { 1234 LOG.warn("Unable to find role type service with id: " + role.getKimTypeId()); 1235 } 1236 } 1237 } 1238 1239 // Phase 4: If we have nested roles, execute a recursive check on those 1240 1241 // first, check that the qualifiers on the role membership match 1242 // then, perform a principalHasRole on the embedded role 1243 Map<String, Role> roleIndex = new HashMap<String, Role>(); 1244 for (Role role :roles) { 1245 roleIndex.put(role.getId(), role); 1246 } 1247 List<RoleMemberBo> roleMemberBos = getStoredRoleMembersForRoleIds(new ArrayList<String>(roleIndex.keySet()), 1248 MemberType.ROLE.getCode(), null); 1249 for (RoleMemberBo roleMemberBo : roleMemberBos) { 1250 Role role = roleIndex.get(roleMemberBo.getRoleId()); 1251 RoleTypeService roleTypeService = context.getRoleTypeService(role.getKimTypeId()); 1252 if (roleTypeService != null) { 1253 //it is possible that the the roleTypeService is coming from a remote application 1254 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility. 1255 try { 1256 if (roleTypeService.doesRoleQualifierMatchQualification(qualification, 1257 roleMemberBo.getAttributes())) { 1258 RoleBoLite memberRole = getRoleBoLite(roleMemberBo.getMemberId()); 1259 Map<String, String> nestedRoleQualification = 1260 getNestedQualification(memberRole, role.getNamespaceCode(), 1261 role.getName(), memberRole.getNamespaceCode(), memberRole.getName(), 1262 qualification, roleMemberBo.getAttributes()); 1263 if (principalHasRole(context, principalId, 1264 Collections.singletonList(roleMemberBo.getMemberId()), nestedRoleQualification, true)) { 1265 return putPrincipalHasRoleInCache(true, principalId, role.getId(), qualification, checkDelegations); 1266 } 1267 } 1268 } catch (Exception ex) { 1269 LOG.warn("Not able to retrieve RoleTypeService from remote system for role Id: " + roleMemberBo 1270 .getRoleId(), ex); 1271 } 1272 } else { 1273 // no qualifiers - role is always used - check membership 1274 // no role type service, so can't convert qualification - just pass as is 1275 if (principalHasRole(context, principalId, Collections.singletonList(roleMemberBo.getMemberId()), 1276 qualification, true)) { 1277 return putPrincipalHasRoleInCache(true, principalId, role.getId(), qualification, checkDelegations); 1278 } 1279 } 1280 1281 } 1282 1283 // Phase 5: derived roles 1284 1285 // check for derived roles and extract principals and groups from that - then check them against the 1286 // role type service passing in the qualification and principal - the qualifier comes from the 1287 // external system (application) 1288 for (Role role : roles) { 1289 // check if an derived role 1290 //it is possible that the the roleTypeService is coming from a remote application 1291 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility. 1292 try { 1293 boolean isDerivedRoleType = context.isDerivedRoleType(role.getKimTypeId()); 1294 if (isDerivedRoleType) { 1295 RoleTypeService roleTypeService = context.getRoleTypeService(role.getKimTypeId()); 1296 if (roleTypeService.hasDerivedRole(principalId, 1297 context.getPrincipalGroupIds(), role.getNamespaceCode(), role.getName(), qualification)) { 1298 if (!roleTypeService.dynamicRoleMembership(role.getNamespaceCode(), role.getName())) { 1299 putPrincipalHasRoleInCache(true, principalId, role.getId(), qualification, checkDelegations); 1300 } 1301 return true; 1302 } 1303 } else { 1304 if(!checkDelegations) { 1305 putPrincipalHasRoleInCache(false, principalId, role.getId(), qualification, checkDelegations); 1306 } 1307 } 1308 } catch (Exception ex) { 1309 LOG.warn("Not able to retrieve RoleTypeService from remote system for role Id: " + role.getId(), ex); 1310 } 1311 } 1312 1313 // Phase 6: delegations 1314 1315 if (checkDelegations) { 1316 if (matchesOnDelegation(roleIndex.keySet(), principalId, context.getPrincipalGroupIds(), qualification, context)) { 1317 return true; 1318 } 1319 } 1320 } catch (Exception e) { 1321 LOG.warn("Caught exception during a principalHasRole check", e); 1322 } 1323 return false; 1324 } 1325 1326 protected Boolean getPrincipalHasRoleFromCache(String principalId, String roleId, Map<String, String> qualification, boolean checkDelegations) { 1327 String key = buildPrincipalHasRoleCacheKey(principalId, roleId, qualification, checkDelegations); 1328 Cache.ValueWrapper value = cacheManager.getCache(Role.Cache.NAME).get(key); 1329 return value == null ? null : (Boolean)value.get(); 1330 } 1331 1332 protected boolean putPrincipalHasRoleInCache(boolean principalHasRole, String principalId, String roleId, 1333 Map<String, String> qualification, boolean checkDelegations) { 1334 String key = buildPrincipalHasRoleCacheKey(principalId, roleId, qualification, checkDelegations); 1335 cacheManager.getCache(Role.Cache.NAME).put(key, Boolean.valueOf(principalHasRole)); 1336 return principalHasRole; 1337 } 1338 1339 private String buildPrincipalHasRoleCacheKey(String principalId, String roleId, Map<String, String> qualification, boolean checkDelegations) { 1340 return new StringBuilder("{principalHasRole}") 1341 .append("principalId=").append(principalId).append("|") 1342 .append("roleId=").append(roleId).append("|") 1343 .append("qualification=").append(CacheKeyUtils.mapKey(qualification)).append("|") 1344 .append("checkDelegations=").append(checkDelegations).toString(); 1345 } 1346 1347 protected List<String> getQualifiersForExactMatch(String kimTypeId, RoleTypeService roleTypeService) { 1348 String cacheKey = "{getQualifiersForExactMatch}kimTypeId=" + kimTypeId; 1349 Cache cache = cacheManager.getCache(Role.Cache.NAME); 1350 Cache.ValueWrapper value = cache.get(cacheKey); 1351 List<String> qualifiers = new ArrayList<String>(); 1352 if (value == null) { 1353 try { 1354 qualifiers = roleTypeService.getQualifiersForExactMatch(); 1355 cache.put(cacheKey, qualifiers); 1356 } catch (Exception e) { 1357 LOG.warn("Caught exception when attempting to invoke a role type service", e); 1358 } 1359 } else { 1360 qualifiers = (List<String>)value.get(); 1361 } 1362 return qualifiers; 1363 } 1364 1365 public boolean isDerivedRoleType(RoleTypeService service) { 1366 return service != null && service.isDerivedRoleType(); 1367 } 1368 1369 private boolean dynamicRoleMembership(RoleTypeService service, Role role) { 1370 return service != null && role !=null && service.dynamicRoleMembership(role.getNamespaceCode(), role.getName()); 1371 } 1372 1373 @Override 1374 public boolean isDerivedRole(String roleId) { 1375 incomingParamCheck(roleId, "roleId"); 1376 RoleTypeService service = getRoleTypeService(roleId); 1377 return isDerivedRoleType(service); 1378 } 1379 1380 @Override 1381 public boolean isDynamicRoleMembership(String roleId) { 1382 incomingParamCheck(roleId, "roleId"); 1383 RoleTypeService service = getRoleTypeService(roleId); 1384 try { 1385 return dynamicRoleMembership(service, getRole(roleId)); 1386 } catch (Exception e) { 1387 LOG.warn("Caught exception while invoking a role type service for role " + roleId, e); 1388 // Returning true so the role won't be cached 1389 return true; 1390 } 1391 } 1392 1393 /** 1394 * Support method for principalHasRole. Checks delegations on the passed in roles for the given principal and groups. (It's assumed that the principal 1395 * belongs to the given groups.) 1396 * <p/> 1397 * Delegation checks are mostly the same as role checks except that the delegateBo itself is qualified against the original role (like a RolePrincipal 1398 * or RoleGroup.) And then, the members of that delegateBo may have additional qualifiers which are not part of the original role qualifiers. 1399 * <p/> 1400 * For example: 1401 * <p/> 1402 * A role could be qualified by organization. So, there is a person in the organization with primary authority for that org. But, then they delegate authority 1403 * for that organization (not their authority - the delegateBo is attached to the org.) So, in this case the delegateBo has a qualifier of the organization 1404 * when it is attached to the role. 1405 * <p/> 1406 * The principals then attached to that delegateBo (which is specific to the organization), may have additional qualifiers. 1407 * For Example: dollar amount range, effective dates, document types. 1408 * As a subsequent step, those qualifiers are checked against the qualification passed in from the client. 1409 */ 1410 protected boolean matchesOnDelegation(Set<String> allRoleIds, String principalId, List<String> principalGroupIds, Map<String, String> qualification, Context context) { 1411 // get the list of delegations for the roles 1412 Map<String, DelegateTypeBo> delegations = getStoredDelegationImplMapFromRoleIds(allRoleIds); 1413 1414 // If there are no delegations then we should cache that the principal 1415 // doesn't have the given roles if those roles do not have dynamic 1416 // membership 1417 if(delegations.isEmpty()) { 1418 for(String roleId : allRoleIds) { 1419 Role role = loadRole(roleId); 1420 RoleTypeService roleTypeService = context.getRoleTypeService(role.getKimTypeId()); 1421 if(!context.isDerivedRoleType(role.getKimTypeId()) || roleTypeService == null || !roleTypeService.dynamicRoleMembership(role.getNamespaceCode(), role.getName())) { 1422 putPrincipalHasRoleInCache(false, principalId, roleId, qualification, true); 1423 } 1424 } 1425 return false; 1426 } 1427 1428 // Build a map from a role ID to the delegations for that role ID 1429 Map<String, List<DelegateTypeBo>> roleToDelegations = new HashMap<String, List<DelegateTypeBo>>(); 1430 for(DelegateTypeBo delegation : delegations.values()) { 1431 List<DelegateTypeBo> roleDelegations = roleToDelegations.get(delegation.getRoleId()); 1432 if(roleDelegations == null) { 1433 roleDelegations = new ArrayList<DelegateTypeBo>(); 1434 roleToDelegations.put(delegation.getRoleId(), roleDelegations); 1435 } 1436 roleDelegations.add(delegation); 1437 } 1438 // Iterate through each role and check its delegations to determine if 1439 // the principal has one of the roles 1440 for(String roleId : roleToDelegations.keySet()) { 1441 boolean matchesOnRoleDelegation = false; 1442 Role role = getRole(roleId); 1443 RoleTypeService roleTypeService = context.getRoleTypeService(role.getKimTypeId()); 1444 // Iterate through each delegation for this role and determine if 1445 // the principal has the role through this delegation 1446 for(DelegateTypeBo delegation : roleToDelegations.get(roleId)) { 1447 // If the delegation isn't active skip it 1448 if (!delegation.isActive()) { 1449 continue; 1450 } 1451 // Now iterate through all of the members of the delegation to 1452 // determine if any of them apply to this principal 1453 for (DelegateMemberBo delegateMemberBo : delegation.getMembers()) { 1454 // If the membership isn't active skip the rest of the checks 1455 if (!delegateMemberBo.isActive(new Timestamp(new Date().getTime()))) { 1456 continue; 1457 } 1458 // If the membership is a principal type then check the 1459 // delegate's member ID against the principal ID 1460 if (MemberType.PRINCIPAL.equals(delegateMemberBo.getType()) 1461 && !delegateMemberBo.getMemberId().equals(principalId)) { 1462 continue; // no match on principal 1463 } 1464 // If the membership is a group type then check to see if 1465 // the group's ID is contained in the list of groups the 1466 // principal belongs to 1467 if (MemberType.GROUP.equals(delegateMemberBo.getType()) 1468 && !principalGroupIds.contains(delegateMemberBo.getMemberId())) { 1469 continue; // No match on group 1470 } 1471 // If the membership is a role type then we need to recurse 1472 // into the principalHasRole method to check if this 1473 // principal is a member of that role 1474 if (MemberType.ROLE.equals(delegateMemberBo.getType()) 1475 && !principalHasRole(principalId, Collections.singletonList(delegateMemberBo.getMemberId()), qualification, false)) { 1476 continue; // No match on role 1477 } 1478 1479 // OK, the member matches the current user, now check the qualifications 1480 1481 // NOTE: this compare is slightly different than the member enumeration 1482 // since the requested qualifier is always being used rather than 1483 // the role qualifier for the member (which is not available) 1484 1485 //it is possible that the the roleTypeService is coming from a remote application 1486 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility. 1487 try { 1488 if (roleTypeService != null && !roleTypeService.doesRoleQualifierMatchQualification(qualification, delegateMemberBo.getQualifier())) { 1489 continue; // no match - skip to next record 1490 } 1491 } catch (Exception ex) { 1492 LOG.warn("Unable to call doesRoleQualifierMatchQualification on role type service for role Id: " + delegation.getRoleId() + " / " + qualification + " / " + delegateMemberBo.getQualifier(), ex); 1493 continue; 1494 } 1495 1496 // role service matches this qualifier 1497 // now try the delegateBo service 1498 DelegationTypeService delegationTypeService = getDelegationTypeService(delegateMemberBo.getDelegationId()); 1499 // QUESTION: does the qualifier map need to be merged with the main delegateBo qualification? 1500 if (delegationTypeService != null && !delegationTypeService.doesDelegationQualifierMatchQualification(qualification, delegateMemberBo.getQualifier())) { 1501 continue; // no match - skip to next record 1502 } 1503 // check if a role member ID is present on the delegateBo record 1504 // if so, check that the original role member would match the given qualifiers 1505 if (StringUtils.isNotBlank(delegateMemberBo.getRoleMemberId())) { 1506 RoleMemberBo rm = getRoleMemberBo(delegateMemberBo.getRoleMemberId()); 1507 if (rm != null) { 1508 // check that the original role member's is active and that their 1509 // qualifier would have matched this request's 1510 // qualifications (that the original person would have the permission/responsibility 1511 // for an action) 1512 // this prevents a role-membership based delegateBo from surviving the inactivation/ 1513 // changing of the main person's role membership 1514 if (!rm.isActive(new Timestamp(new Date().getTime()))) { 1515 continue; 1516 } 1517 Map<String, String> roleQualifier = rm.getAttributes(); 1518 //it is possible that the the roleTypeService is coming from a remote application 1519 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility. 1520 try { 1521 if (roleTypeService != null && !roleTypeService.doesRoleQualifierMatchQualification(qualification, roleQualifier)) { 1522 continue; 1523 } 1524 } catch (Exception ex) { 1525 LOG.warn("Unable to call doesRoleQualifierMatchQualification on role type service for role Id: " + delegation.getRoleId() + " / " + qualification + " / " + roleQualifier, ex); 1526 continue; 1527 } 1528 } else { 1529 LOG.warn("Unknown role member ID cited in the delegateBo member table:"); 1530 LOG.warn(" assignedToId: " + delegateMemberBo.getDelegationMemberId() + " / roleMemberId: " + delegateMemberBo.getRoleMemberId()); 1531 } 1532 } 1533 // If we've made it here then all of the tests pass so the 1534 // principal must belong to this delegation so set the flag 1535 // to true and break out of this loop 1536 matchesOnRoleDelegation = true; 1537 break; 1538 } 1539 1540 // If we've found a match for one of the delegations break out 1541 // of this loop 1542 if(matchesOnRoleDelegation) { 1543 break; 1544 } 1545 } 1546 // If the role is not derived nor dynamic then cache the result of 1547 // this since the principal has the role through one of these 1548 // delegations 1549 if(!context.isDerivedRoleType(role.getKimTypeId()) || roleTypeService == null || !roleTypeService.dynamicRoleMembership(role.getNamespaceCode(), role.getName())) { 1550 putPrincipalHasRoleInCache(matchesOnRoleDelegation, principalId, roleId, qualification, true); 1551 } 1552 // If we've found a matching delegation skip processing the rest of 1553 // the roles 1554 if(matchesOnRoleDelegation) { 1555 return matchesOnRoleDelegation; 1556 } 1557 } 1558 // If we get here we didn't find a matching delegation so return false 1559 return false; 1560 } 1561 1562 protected List<RoleMembership> convertToRoleMemberships(List<RoleMemberBo>... roleMemberLists) { 1563 List<RoleMembership> roleMemberships = new ArrayList<RoleMembership>(); 1564 for (List<RoleMemberBo> roleMembers : roleMemberLists) { 1565 for (RoleMemberBo roleMember : roleMembers) { 1566 RoleMembership roleMembership = RoleMembership.Builder.create( 1567 roleMember.getRoleId(), 1568 roleMember.getId(), 1569 roleMember.getMemberId(), 1570 roleMember.getType(), 1571 roleMember.getAttributes()).build(); 1572 roleMemberships.add(roleMembership); 1573 } 1574 } 1575 return roleMemberships; 1576 } 1577 1578 /** 1579 * Helper method used by principalHasRole to build the role ID -> list of members map. 1580 * 1581 * @return <b>true</b> if no further checks are needed because no role service is defined 1582 */ 1583 protected boolean getRoleIdToMembershipMap(Map<String, List<RoleMembership>> roleIdToMembershipMap, List<RoleMemberBo> roleMembers) { 1584 for (RoleMemberBo roleMemberBo : roleMembers) { 1585 RoleMembership roleMembership = RoleMembership.Builder.create( 1586 roleMemberBo.getRoleId(), 1587 roleMemberBo.getId(), 1588 roleMemberBo.getMemberId(), 1589 roleMemberBo.getType(), 1590 roleMemberBo.getAttributes()).build(); 1591 1592 // if the role type service is null, assume that all qualifiers match 1593 if (getRoleTypeService(roleMemberBo.getRoleId()) == null) { 1594 return true; 1595 } 1596 List<RoleMembership> lrmi = roleIdToMembershipMap.get(roleMembership.getRoleId()); 1597 if (lrmi == null) { 1598 lrmi = new ArrayList<RoleMembership>(); 1599 roleIdToMembershipMap.put(roleMembership.getRoleId(), lrmi); 1600 } 1601 lrmi.add(roleMembership); 1602 } 1603 return false; 1604 } 1605 1606 /** 1607 * Retrieves a KimDelegationImpl object by its ID. If the delegateBo already exists in the cache, this method will return the cached 1608 * version; otherwise, it will retrieve the uncached version from the database and then cache it before returning it. 1609 */ 1610 protected DelegateTypeBo getKimDelegationImpl(String delegationId) { 1611 if (StringUtils.isBlank(delegationId)) { 1612 return null; 1613 } 1614 1615 return getDataObjectService().find(DelegateTypeBo.class,delegationId); 1616 } 1617 1618 protected DelegationTypeService getDelegationTypeService(String delegationId) { 1619 DelegationTypeService service = null; 1620 DelegateTypeBo delegateBo = getKimDelegationImpl(delegationId); 1621 KimType delegationType = KimApiServiceLocator.getKimTypeInfoService().getKimType(delegateBo.getKimTypeId()); 1622 if (delegationType != null) { 1623 KimTypeService tempService = KimFrameworkServiceLocator.getKimTypeService(delegationType); 1624 if (tempService != null && tempService instanceof DelegationTypeService) { 1625 service = (DelegationTypeService) tempService; 1626 } else { 1627 LOG.error("Service returned for type " + delegationType + "(" + delegationType.getName() + ") was not a DelegationTypeService. Was a " + (tempService != null ? tempService.getClass() : "(null)")); 1628 } 1629 } else { // delegateBo has no type - default to role type if possible 1630 RoleTypeService roleTypeService = getRoleTypeService(delegateBo.getRoleId()); 1631 if (roleTypeService != null && roleTypeService instanceof DelegationTypeService) { 1632 service = (DelegationTypeService) roleTypeService; 1633 } 1634 } 1635 return service; 1636 } 1637 1638 protected Collection<RoleMembership> getNestedRoleMembers(Map<String, String> qualification, RoleMembership rm, Set<String> foundRoleTypeMembers) { 1639 // If this role has already been traversed, skip it 1640 if (foundRoleTypeMembers.contains(rm.getMemberId())) { 1641 return new ArrayList<RoleMembership>(); // return an empty list 1642 } 1643 foundRoleTypeMembers.add(rm.getMemberId()); 1644 1645 ArrayList<String> roleIdList = new ArrayList<String>(1); 1646 roleIdList.add(rm.getMemberId()); 1647 1648 // get the list of members from the nested role - ignore delegations on those sub-roles 1649 Collection<RoleMembership> currentNestedRoleMembers = getRoleMembers(roleIdList, qualification, false, foundRoleTypeMembers); 1650 1651 // add the roles whose members matched to the list for delegateBo checks later 1652 Collection<RoleMembership> returnRoleMembers = new ArrayList<RoleMembership>(); 1653 for (RoleMembership roleMembership : currentNestedRoleMembers) { 1654 RoleMembership.Builder rmBuilder = RoleMembership.Builder.create(roleMembership); 1655 1656 // use the member ID of the parent role (needed for responsibility joining) 1657 rmBuilder.setId(rm.getId()); 1658 // store the role ID, so we know where this member actually came from 1659 rmBuilder.setRoleId(rm.getRoleId()); 1660 rmBuilder.setEmbeddedRoleId(rm.getMemberId()); 1661 returnRoleMembers.add(rmBuilder.build()); 1662 } 1663 return returnRoleMembers; 1664 } 1665 1666 /** 1667 * Retrieves a KimDelegationMemberImpl object by its ID and the ID of the delegation it belongs to. If the delegation member exists in the cache, 1668 * this method will return the cached one; otherwise, it will retrieve the uncached version from the database and then cache it before returning it. 1669 */ 1670 protected DelegateMemberBo getKimDelegationMemberImplByDelegationAndId(String delegationId, String delegationMemberId) { 1671 if (StringUtils.isBlank(delegationId) || StringUtils.isBlank(delegationMemberId)) { 1672 return null; 1673 } 1674 1675 Map<String, String> searchCriteria = new HashMap<String, String>(2); 1676 searchCriteria.put(KimConstants.PrimaryKeyConstants.DELEGATION_ID, delegationId); 1677 searchCriteria.put(KimConstants.PrimaryKeyConstants.DELEGATION_MEMBER_ID, delegationMemberId); 1678 QueryResults<DelegateMemberBo> memberList = getDataObjectService().findMatching(DelegateMemberBo.class, QueryByCriteria.Builder.andAttributes(searchCriteria).build()); 1679 if (!memberList.getResults().isEmpty()) { 1680 return memberList.getResults().get(0); 1681 } 1682 return null; 1683 } 1684 1685 private List<RoleMemberBo> getStoredRoleMembersUsingExactMatchOnQualification(String principalId, List<String> groupIds, List<String> roleIds, Map<String, String> qualification) { 1686 List<String> copyRoleIds = new ArrayList<String>(roleIds); 1687 List<RoleMemberBo> roleMemberBoList = new ArrayList<RoleMemberBo>(); 1688 1689 for (String roleId : roleIds) { 1690 RoleTypeService roleTypeService = getRoleTypeService(roleId); 1691 if (roleTypeService != null) { 1692 List<String> attributesForExactMatch = null; 1693 try { 1694 attributesForExactMatch = roleTypeService.getQualifiersForExactMatch(); 1695 } catch (Exception e) { 1696 LOG.warn("Caught exception when attempting to invoke a role type service for role " + roleId, e); 1697 } 1698 if (CollectionUtils.isNotEmpty(attributesForExactMatch)) { 1699 copyRoleIds.remove(roleId); 1700 roleMemberBoList.addAll(getStoredRoleMembersForRoleIdsWithFilters(Collections.singletonList(roleId), principalId, groupIds, populateQualifiersForExactMatch(qualification, attributesForExactMatch))); 1701 } 1702 } 1703 } 1704 if (CollectionUtils.isNotEmpty(copyRoleIds)) { 1705 roleMemberBoList.addAll(getStoredRoleMembersForRoleIdsWithFilters(copyRoleIds, principalId, groupIds, null)); 1706 } 1707 return roleMemberBoList; 1708 } 1709 1710 private List<RoleMemberBo> getStoredRoleGroupsUsingExactMatchOnQualification(List<String> groupIds, String roleId, Map<String, String> qualification) { 1711 Set<String> roleIds = new HashSet<String>(); 1712 if (roleId != null) { 1713 roleIds.add(roleId); 1714 } 1715 return getStoredRoleGroupsUsingExactMatchOnQualification(groupIds, roleIds, qualification); 1716 } 1717 1718 private List<RoleMemberBo> getStoredRoleGroupsUsingExactMatchOnQualification(List<String> groupIds, Set<String> roleIds, Map<String, String> qualification) { 1719 List<String> copyRoleIds = new ArrayList<String>(roleIds); 1720 List<RoleMemberBo> roleMemberBos = new ArrayList<RoleMemberBo>(); 1721 1722 for (String roleId : roleIds) { 1723 RoleTypeService roleTypeService = getRoleTypeService(roleId); 1724 if (roleTypeService != null) { 1725 List<String> attributesForExactMatch = null; 1726 try { 1727 attributesForExactMatch = roleTypeService.getQualifiersForExactMatch(); 1728 } catch (Exception e) { 1729 LOG.warn("Caught exception when attempting to invoke a role type service for role " + roleId, e); 1730 } 1731 if (CollectionUtils.isNotEmpty(attributesForExactMatch)) { 1732 copyRoleIds.remove(roleId); 1733 roleMemberBos.addAll(getStoredRoleGroupsForGroupIdsAndRoleIds(Collections.singletonList(roleId), groupIds, populateQualifiersForExactMatch(qualification, attributesForExactMatch))); 1734 } 1735 } 1736 } 1737 if (CollectionUtils.isNotEmpty(copyRoleIds)) { 1738 roleMemberBos.addAll(getStoredRoleGroupsForGroupIdsAndRoleIds(copyRoleIds, groupIds, null)); 1739 } 1740 return roleMemberBos; 1741 } 1742 1743 private List<DelegateMember> getDelegateMembersForDelegation(DelegateTypeBo delegateBo) { 1744 if (delegateBo == null || delegateBo.getMembers() == null) {return null;} 1745 List<DelegateMember> delegateMembersReturnList = new ArrayList<DelegateMember>(); 1746 for (DelegateMemberBo delegateMemberBo : delegateBo.getMembers()) { 1747 //FIXME: What is up with this!?! 1748 DelegateMember delegateMember = getDelegateCompleteInfo(delegateBo, delegateMemberBo); 1749 1750 delegateMembersReturnList.add(DelegateMemberBo.to(delegateMemberBo)); 1751 } 1752 return Collections.unmodifiableList(delegateMembersReturnList); 1753 } 1754 1755 private DelegateMember getDelegateCompleteInfo(DelegateTypeBo delegateBo, DelegateMemberBo delegateMemberBo) { 1756 if (delegateBo == null || delegateMemberBo == null) {return null;} 1757 1758 DelegateMember.Builder delegateMemberBuilder = DelegateMember.Builder.create(delegateMemberBo); 1759 delegateMemberBuilder.setType(delegateMemberBo.getType()); 1760 return delegateMemberBuilder.build(); 1761 } 1762 1763 @Override 1764 public RoleMember assignPrincipalToRole(String principalId, 1765 String namespaceCode, String roleName, Map<String, String> qualifier) 1766 throws RiceIllegalArgumentException { 1767 incomingParamCheck(principalId, "principalId"); 1768 incomingParamCheck(namespaceCode, "namespaceCode"); 1769 incomingParamCheck(roleName, "roleName"); 1770 incomingParamCheck(qualifier, "qualifier"); 1771 1772 // look up the role 1773 RoleBoLite role = getRoleBoLiteByName(namespaceCode, roleName); 1774 1775 // check that identical member does not already exist 1776 List<RoleMember> membersMatchByExactQualifiers = doAnyMemberRecordsMatchByExactQualifier(role, principalId, memberTypeToRoleDaoActionMap.get(MemberType.PRINCIPAL.getCode()), qualifier); 1777 if (CollectionUtils.isNotEmpty(membersMatchByExactQualifiers)) { 1778 return membersMatchByExactQualifiers.get(0); 1779 } 1780 List<String> roleIds = new ArrayList<String>(); 1781 roleIds.add(role.getId()); 1782 List<RoleMemberBo> roleMembers = getRoleDao().getRoleMembersForRoleIds(roleIds, MemberType.PRINCIPAL.getCode(), 1783 qualifier); 1784 RoleMember anyMemberMatch = doAnyMemberRecordsMatch( roleMembers, principalId, MemberType.PRINCIPAL.getCode(), qualifier ); 1785 if (null != anyMemberMatch) { 1786 return anyMemberMatch; 1787 } 1788 1789 // create the new role member object 1790 RoleMemberBo newRoleMember = new RoleMemberBo(); 1791 1792 newRoleMember.setRoleId(role.getId()); 1793 newRoleMember.setMemberId(principalId); 1794 newRoleMember.setType(MemberType.PRINCIPAL); 1795 1796 // build role member attribute objects from the given Map<String, String> 1797 addMemberAttributeData(newRoleMember, qualifier, role.getKimTypeId()); 1798 1799 // add row to member table 1800 // When members are added to roles, clients must be notified. 1801 return RoleMemberBo.to(getResponsibilityInternalService().saveRoleMember(newRoleMember)); 1802 } 1803 1804 @Override 1805 public RoleMember assignGroupToRole(String groupId, String namespaceCode, 1806 String roleName, Map<String, String> qualifier) throws RiceIllegalStateException { 1807 incomingParamCheck(groupId, "groupId"); 1808 incomingParamCheck(namespaceCode, "namespaceCode"); 1809 incomingParamCheck(roleName, "roleName"); 1810 incomingParamCheck(qualifier, "qualifier"); 1811 1812 // look up the role 1813 RoleBo role = getRoleBoByName(namespaceCode, roleName); 1814 1815 // check that identical member does not already exist 1816 List<RoleMember> membersMatchByExactQualifiers = doAnyMemberRecordsMatchByExactQualifier(role, groupId, memberTypeToRoleDaoActionMap.get(MemberType.GROUP.getCode()), qualifier); 1817 if (CollectionUtils.isNotEmpty(membersMatchByExactQualifiers)) { 1818 return membersMatchByExactQualifiers.get(0); 1819 } 1820 RoleMember anyMemberMatch = doAnyMemberRecordsMatch( role.getMembers(), groupId, MemberType.GROUP.getCode(), qualifier ); 1821 if (null != anyMemberMatch) { 1822 return anyMemberMatch; 1823 } 1824 1825 // create the new role member object 1826 RoleMemberBo newRoleMember = new RoleMemberBo(); 1827 newRoleMember.setRoleId(role.getId()); 1828 newRoleMember.setMemberId(groupId); 1829 newRoleMember.setType(MemberType.GROUP); 1830 1831 // build role member attribute objects from the given Map<String, String> 1832 addMemberAttributeData(newRoleMember, qualifier, role.getKimTypeId()); 1833 1834 // When members are added to roles, clients must be notified. 1835 return RoleMemberBo.to(getResponsibilityInternalService().saveRoleMember(newRoleMember)); 1836 } 1837 1838 @Override 1839 public RoleMember assignRoleToRole(String roleId, 1840 String namespaceCode, String roleName, Map<String, String> qualifier) 1841 throws RiceIllegalStateException { 1842 incomingParamCheck(roleId, "roleId"); 1843 incomingParamCheck(namespaceCode, "namespaceCode"); 1844 incomingParamCheck(roleName, "roleName"); 1845 incomingParamCheck(qualifier, "qualifier"); 1846 1847 // look up the roleBo 1848 RoleBo roleBo = getRoleBoByName(namespaceCode, roleName); 1849 1850 // check that identical member does not already exist 1851 List<RoleMember> membersMatchByExactQualifiers = doAnyMemberRecordsMatchByExactQualifier(roleBo, roleId, memberTypeToRoleDaoActionMap.get(MemberType.ROLE.getCode()), qualifier); 1852 if (CollectionUtils.isNotEmpty(membersMatchByExactQualifiers)) { 1853 return membersMatchByExactQualifiers.get(0); 1854 } 1855 RoleMember anyMemberMatch = doAnyMemberRecordsMatch( roleBo.getMembers(), roleId, MemberType.ROLE.getCode(), qualifier); 1856 if (null != anyMemberMatch) { 1857 return anyMemberMatch; 1858 } 1859 1860 1861 // Check to make sure this doesn't create a circular membership 1862 if (!checkForCircularRoleMembership(roleId, roleBo)) { 1863 throw new IllegalArgumentException("Circular roleBo reference."); 1864 } 1865 // create the new roleBo member object 1866 RoleMemberBo newRoleMember = new RoleMemberBo(); 1867 newRoleMember.setRoleId(roleBo.getId()); 1868 newRoleMember.setMemberId(roleId); 1869 newRoleMember.setType(MemberType.ROLE); 1870 // build roleBo member attribute objects from the given Map<String, String> 1871 addMemberAttributeData(newRoleMember, qualifier, roleBo.getKimTypeId()); 1872 1873 // When members are added to roles, clients must be notified. 1874 return RoleMemberBo.to(getResponsibilityInternalService().saveRoleMember(newRoleMember)); 1875 } 1876 1877 @Override 1878 public RoleMember createRoleMember(RoleMember roleMember) throws RiceIllegalStateException { 1879 incomingParamCheck(roleMember, "roleMember"); 1880 1881 if (StringUtils.isNotBlank(roleMember.getId()) && getRoleMemberBo(roleMember.getId()) != null) { 1882 throw new RiceIllegalStateException("the roleMember to create already exists: " + roleMember); 1883 } 1884 1885 String kimTypeId = getRoleBoLite(roleMember.getRoleId()).getKimTypeId(); 1886 List<RoleMemberAttributeDataBo> attrBos = Collections.emptyList(); 1887 attrBos = KimAttributeDataBo.createFrom(RoleMemberAttributeDataBo.class, roleMember.getAttributes(), kimTypeId); 1888 1889 RoleMemberBo bo = RoleMemberBo.from(roleMember); 1890 bo.setAttributeDetails(attrBos); 1891 return RoleMemberBo.to(getResponsibilityInternalService().saveRoleMember(bo)); 1892 } 1893 1894 @Override 1895 public RoleMember updateRoleMember(@WebParam( 1896 name = "roleMember") RoleMember roleMember) throws RiceIllegalArgumentException, RiceIllegalStateException { 1897 incomingParamCheck(roleMember, "roleMember"); 1898 1899 RoleMemberBo roleMemberBo = null; 1900 if (StringUtils.isNotBlank(roleMember.getId())) { 1901 roleMemberBo = getRoleMemberBo(roleMember.getId()); 1902 } 1903 if (StringUtils.isBlank(roleMember.getId()) || roleMemberBo == null) { 1904 throw new RiceIllegalStateException("the roleMember to update does not exists: " + roleMember); 1905 } 1906 1907 //RoleMemberBo bo = RoleMemberBo.from(roleMember); 1908 //List<RoleMemberAttributeDataBo> updateAttrBos = new ArrayList<RoleMemberAttributeDataBo>(); 1909 1910 // Copy the main data 1911 roleMemberBo.setMemberId(roleMember.getMemberId()); 1912 roleMemberBo.setTypeCode(roleMember.getType().getCode()); 1913 roleMemberBo.setActiveFromDateValue(roleMember.getActiveFromDate() == null ? null : new Timestamp(roleMember.getActiveFromDate().getMillis())); 1914 roleMemberBo.setActiveToDateValue(roleMember.getActiveToDate() == null ? null : new Timestamp(roleMember.getActiveToDate().getMillis())); 1915 1916 Iterator<RoleResponsibilityActionBo> actions = roleMemberBo.getRoleRspActions().iterator(); 1917 List<RoleResponsibilityAction> newActionList = new ArrayList( roleMember.getRoleRspActions() ); 1918 // loop over the existing actions 1919 while ( actions.hasNext() ) { 1920 RoleResponsibilityActionBo action = actions.next(); 1921 // look for a match in the new list 1922 boolean matched = false; 1923 Iterator<RoleResponsibilityAction> newActions = newActionList.iterator(); 1924 while ( newActions.hasNext() ) { 1925 RoleResponsibilityAction newAction = newActions.next(); 1926 if (newAction.getId().equals(action.getId())) { 1927 matched = true; 1928 action.setActionPolicyCode( newAction.getActionPolicyCode() ); 1929 action.setActionTypeCode( newAction.getActionTypeCode() ); 1930 action.setPriorityNumber( newAction.getPriorityNumber() ); 1931 action.setForceAction( newAction.isForceAction() ); 1932 newActions.remove(); // processed this one - we don't want to see it again 1933 break; 1934 } 1935 } 1936 if ( !matched ) { 1937 // nothing in the new list matched - this means this action was deleted 1938 actions.remove(); 1939 } 1940 } 1941 // now - anything left in the new attribute list needs to be added 1942 for ( RoleResponsibilityAction rra : newActionList ) { 1943 roleMemberBo.getRoleRspActions().add(RoleResponsibilityActionBo.from(rra)); 1944 } 1945 1946 String kimTypeId = getRoleBoLite(roleMember.getRoleId()).getKimTypeId(); 1947 List<RoleMemberAttributeDataBo> newAttributeBos = KimAttributeDataBo.createFrom(RoleMemberAttributeDataBo.class, roleMember.getAttributes(), kimTypeId); 1948 Iterator<RoleMemberAttributeDataBo> attributes = roleMemberBo.getAttributeDetails().iterator(); 1949 // loop over the existing attributes 1950 while ( attributes.hasNext() ) { 1951 RoleMemberAttributeDataBo attr = attributes.next(); 1952 // look for a match in the new list 1953 boolean matched = false; 1954 Iterator<RoleMemberAttributeDataBo> newAttributes = newAttributeBos.iterator(); 1955 while ( newAttributes.hasNext() ) { 1956 RoleMemberAttributeDataBo newAttr = newAttributes.next(); 1957 if (newAttr.getKimTypeId().equals(attr.getKimTypeId()) 1958 && newAttr.getKimAttributeId().equals(attr.getKimAttributeId())) { 1959 matched = true; 1960 attr.setAttributeValue( newAttr.getAttributeValue() ); 1961 newAttributes.remove(); // processed this one - we don't want to see it again 1962 break; 1963 } 1964 } 1965 if ( !matched ) { 1966 // nothing in the new list matched - this means this attribute was deleted 1967 attributes.remove(); 1968 } 1969 } 1970 // now - anything left in the new attribute list needs to be added 1971 roleMemberBo.getAttributeDetails().addAll(newAttributeBos); 1972 1973 // FIXME : this code does not delete removed attributes 1974 // while ( newAttributes.hasNext() ) { 1975 // RoleMemberAttributeDataBo newAttr = newAttributes.next(); 1976 // boolean matched = false; 1977 // for (RoleMemberAttributeDataBo roleMemberAttrDataBo : roleMemberBo.getAttributeDetails()) { 1978 // if (newAttr.getKimTypeId().equals(roleMemberAttrDataBo.getKimTypeId()) 1979 // && newAttr.getKimAttributeId().equals(roleMemberAttrDataBo.getKimAttributeId())) { 1980 // roleMemberAttrDataBo.setAttributeValue( newAttr.getAttributeValue() ); 1981 // matched = true; 1982 // newAttributes.remove(); 1983 // break; 1984 // } 1985 // } 1986 // if (!matched) { 1987 // newAttr.setAssignedToId(roleMemberBo.getId()); 1988 // roleMemberBo.getAttributeDetails().add(newAttr); 1989 // newAttributes.remove(); 1990 // } 1991 // } 1992 1993 return RoleMemberBo.to(getResponsibilityInternalService().saveRoleMember(roleMemberBo)); 1994 } 1995 1996 @Override 1997 public DelegateMember updateDelegateMember(@WebParam( 1998 name = "delegateMember") DelegateMember delegateMember) throws RiceIllegalArgumentException, RiceIllegalStateException { 1999 2000 //check delegateMember not empty 2001 incomingParamCheck(delegateMember, "delegateMember"); 2002 2003 //check delegate exists 2004 String delegationId = delegateMember.getDelegationId(); 2005 incomingParamCheck(delegationId,"delegationId"); 2006 2007 DelegateTypeBo delegate = getKimDelegationImpl(delegationId); 2008 DelegateMemberBo delegateMemberBo = null; 2009 2010 if (StringUtils.isNotEmpty(delegateMember.getDelegationMemberId())) { 2011 delegateMemberBo = getDelegateMemberBo(delegateMember.getDelegationMemberId()); 2012 } 2013 if(delegateMemberBo==null) { 2014 throw new RiceIllegalStateException("the delegate does not exist: " + delegationId); 2015 } 2016 2017 // copy the main data 2018 delegateMemberBo.setActiveFromDateValue(delegateMember.getActiveFromDate() == null ? null : new Timestamp(delegateMember.getActiveFromDate().getMillis())); 2019 delegateMemberBo.setActiveToDateValue(delegateMember.getActiveToDate() == null ? null : new Timestamp(delegateMember.getActiveToDate().getMillis())); 2020 delegateMemberBo.setMemberId(delegateMember.getMemberId()); 2021 delegateMemberBo.setRoleMemberId(delegateMember.getRoleMemberId()); 2022 delegateMemberBo.setTypeCode(delegateMember.getType().getCode()); 2023 2024 String kimTypeId = delegate.getKimTypeId(); 2025 List<DelegateMemberAttributeDataBo> newAttributeBos = KimAttributeDataBo.createFrom(DelegateMemberAttributeDataBo.class, delegateMember.getAttributes(), kimTypeId); 2026 Iterator<DelegateMemberAttributeDataBo> attributes = delegateMemberBo.getAttributeDetails().iterator(); 2027 // loop over the existing attributes 2028 while ( attributes.hasNext() ) { 2029 DelegateMemberAttributeDataBo attr = attributes.next(); 2030 // look for a match in the new list 2031 boolean matched = false; 2032 Iterator<DelegateMemberAttributeDataBo> newAttributes = newAttributeBos.iterator(); 2033 while ( newAttributes.hasNext() ) { 2034 DelegateMemberAttributeDataBo newAttr = newAttributes.next(); 2035 if (newAttr.getKimTypeId().equals(attr.getKimTypeId()) 2036 && newAttr.getKimAttributeId().equals(attr.getKimAttributeId())) { 2037 matched = true; 2038 attr.setAttributeValue( newAttr.getAttributeValue() ); 2039 newAttributes.remove(); // processed this one - we don't want to see it again 2040 break; 2041 } 2042 } 2043 if ( !matched ) { 2044 // nothing in the new list matched - this means this attribute was deleted 2045 attributes.remove(); 2046 } 2047 } 2048 // now - anything left in the new attribute list needs to be added 2049 delegateMemberBo.getAttributeDetails().addAll(newAttributeBos); 2050 2051 return DelegateMemberBo.to(getResponsibilityInternalService().saveDelegateMember(delegateMemberBo)); 2052 } 2053 2054 @Override 2055 public DelegateMember createDelegateMember(@WebParam( 2056 name = "delegateMember") DelegateMember delegateMember) throws RiceIllegalArgumentException, RiceIllegalStateException { 2057 //ensure object not empty 2058 incomingParamCheck(delegateMember, "delegateMember"); 2059 2060 //check key is null 2061 if(delegateMember.getDelegationMemberId()!=null ) { 2062 throw new RiceIllegalStateException("the delegate member already exists: " + delegateMember.getDelegationMemberId()); 2063 } 2064 2065 //check delegate exists 2066 String delegationId = delegateMember.getDelegationId(); 2067 incomingParamCheck(delegationId,"delegationId"); 2068 DelegateTypeBo delegate = getKimDelegationImpl(delegationId); 2069 if(delegate==null) { 2070 throw new RiceIllegalStateException("the delegate does not exist: " + delegationId); 2071 } 2072 2073 //check member exists 2074 String memberId = delegateMember.getMemberId(); 2075 incomingParamCheck(memberId,"memberId"); 2076 Principal kPrincipal = KimApiServiceLocator.getIdentityService().getPrincipal(memberId); 2077 if(kPrincipal==null){ 2078 throw new RiceIllegalStateException("the user does not exist: " + memberId); 2079 } 2080 2081 //create member delegate 2082 String kimTypeId = getRoleBoLite(delegate.getRoleId()).getKimTypeId(); 2083 List<DelegateMemberAttributeDataBo> attrBos = Collections.emptyList(); 2084 attrBos = KimAttributeDataBo.createFrom(DelegateMemberAttributeDataBo.class, delegateMember.getAttributes(), kimTypeId); 2085 DelegateMemberBo bo = DelegateMemberBo.from(delegateMember); 2086 bo.setAttributeDetails(attrBos); 2087 return DelegateMemberBo.to(getResponsibilityInternalService().saveDelegateMember(bo)); 2088 } 2089 2090 @Override 2091 public void removeDelegateMembers(@WebParam( 2092 name = "delegateMembers") List<DelegateMember> delegateMembers) throws RiceIllegalArgumentException, RiceIllegalStateException { 2093 incomingParamCheck(delegateMembers, "delegateMembers"); 2094 for (DelegateMember delegateMember : delegateMembers) { 2095 DelegateMember.Builder delegateMemberInfo = DelegateMember.Builder.create(); 2096 delegateMemberInfo.setDelegationMemberId(delegateMember.getDelegationMemberId()); 2097 delegateMemberInfo.setAttributes(delegateMember.getAttributes()); 2098 delegateMemberInfo.setDelegationId(delegateMember.getDelegationId()); 2099 delegateMemberInfo.setMemberId(delegateMember.getMemberId()); 2100 delegateMemberInfo.setRoleMemberId(delegateMember.getRoleMemberId()); 2101 delegateMemberInfo.setType(delegateMember.getType()); 2102 delegateMemberInfo.setActiveFromDate(delegateMember.getActiveFromDate()); 2103 delegateMemberInfo.setActiveToDate(DateTime.now()); 2104 updateDelegateMember(delegateMemberInfo.build()); 2105 } 2106 } 2107 2108 @Override 2109 public RoleResponsibilityAction createRoleResponsibilityAction(RoleResponsibilityAction roleResponsibilityAction) 2110 throws RiceIllegalArgumentException, RiceIllegalStateException { 2111 incomingParamCheck(roleResponsibilityAction, "roleResponsibilityAction"); 2112 2113 2114 if (StringUtils.isNotBlank(roleResponsibilityAction.getId()) 2115 && getRoleResponsibilityActionBo(roleResponsibilityAction.getId()) != null) { 2116 throw new RiceIllegalStateException("the roleResponsibilityAction to create already exists: " + roleResponsibilityAction); 2117 } 2118 2119 RoleResponsibilityActionBo bo = RoleResponsibilityActionBo.from(roleResponsibilityAction); 2120 return RoleResponsibilityActionBo.to(getDataObjectService().save(bo)); 2121 } 2122 2123 /** 2124 * Queues ActionRequest refresh/regeneration for RoleResponsbilityAction change 2125 * @param bo the changed or deleted RoleResponsibilityActionBo 2126 */ 2127 protected void updateActionRequestsForRoleResponsibilityActionChange(RoleResponsibilityActionBo bo) { 2128 RoleResponsibilityBo rr = bo.getRoleResponsibility(); 2129 if (rr != null) { 2130 getResponsibilityInternalService().updateActionRequestsForResponsibilityChange(Collections.singleton(rr.getResponsibilityId())); 2131 } 2132 } 2133 2134 @Override 2135 public RoleResponsibilityAction updateRoleResponsibilityAction(RoleResponsibilityAction roleResponsibilityAction) 2136 throws RiceIllegalArgumentException, RiceIllegalStateException { 2137 incomingParamCheck(roleResponsibilityAction, "roleResponsibilityAction"); 2138 2139 if (StringUtils.isBlank(roleResponsibilityAction.getId()) || getRoleResponsibilityActionBo(roleResponsibilityAction.getId()) == null) { 2140 throw new RiceIllegalStateException("the roleResponsibilityAction to create does not exist: " + roleResponsibilityAction); 2141 } 2142 2143 RoleResponsibilityActionBo bo = RoleResponsibilityActionBo.from(roleResponsibilityAction); 2144 roleResponsibilityAction = RoleResponsibilityActionBo.to(getDataObjectService().save(bo)); 2145 2146 // update action requests 2147 updateActionRequestsForRoleResponsibilityActionChange(bo); 2148 2149 return roleResponsibilityAction; 2150 } 2151 2152 @Override 2153 public void deleteRoleResponsibilityAction(String roleResponsibilityActionId) 2154 throws RiceIllegalArgumentException, RiceIllegalStateException { 2155 incomingParamCheck(roleResponsibilityActionId, "roleResponsibilityActionId"); 2156 2157 RoleResponsibilityActionBo bo = getRoleResponsibilityActionBo(roleResponsibilityActionId); 2158 if (StringUtils.isBlank(roleResponsibilityActionId) || bo == null) { 2159 throw new RiceIllegalStateException("the roleResponsibilityAction to delete does not exist: " + roleResponsibilityActionId); 2160 } 2161 2162 getDataObjectService().delete(bo); 2163 2164 // update action requests 2165 updateActionRequestsForRoleResponsibilityActionChange(bo); 2166 } 2167 2168 @Override 2169 public DelegateType createDelegateType(DelegateType delegateType) throws RiceIllegalArgumentException, RiceIllegalStateException { 2170 incomingParamCheck(delegateType, "delegateType"); 2171 2172 if (StringUtils.isNotBlank(delegateType.getDelegationId()) 2173 && getDelegateTypeByDelegationId(delegateType.getDelegationId()) != null) { 2174 throw new RiceIllegalStateException("the delegateType to create already exists: " + delegateType); 2175 } 2176 2177 DelegateTypeBo bo = DelegateTypeBo.from(delegateType); 2178 return DelegateTypeBo.to(getDataObjectService().save(bo)); 2179 } 2180 2181 @Override 2182 public DelegateType updateDelegateType(DelegateType delegateType) throws RiceIllegalArgumentException, RiceIllegalStateException { 2183 incomingParamCheck(delegateType, "delegateType"); 2184 2185 if (StringUtils.isBlank(delegateType.getDelegationId()) 2186 || getDelegateTypeByDelegationId(delegateType.getDelegationId()) == null) { 2187 throw new RiceIllegalStateException("the delegateType to update does not exist: " + delegateType); 2188 } 2189 2190 DelegateTypeBo bo = DelegateTypeBo.from(delegateType); 2191 return DelegateTypeBo.to(getDataObjectService().save(bo)); 2192 } 2193 2194 2195 private void removeRoleMembers(List<RoleMemberBo> members) { 2196 if(CollectionUtils.isNotEmpty(members)) { 2197 for ( RoleMemberBo rm : members ) { 2198 getResponsibilityInternalService().removeRoleMember(rm); 2199 } 2200 } 2201 } 2202 2203 2204 private List<RoleMemberBo> getRoleMembersByDefaultStrategy(String roleId, String memberId, String memberTypeCode, Map<String, String> qualifier) { 2205 List<RoleMemberBo> rms = new ArrayList<RoleMemberBo>(); 2206 List<RoleMemberBo> roleMem = getRoleMembershipsForMemberId(memberTypeCode,memberId,qualifier); 2207 for ( RoleMemberBo rm : roleMem ) { 2208 if ( rm.getRoleId().equals(roleId) ) { 2209 // if found, remove 2210 rms.add(rm); 2211 } 2212 } 2213 return rms; 2214 } 2215 2216 @Override 2217 public void removePrincipalFromRole(String principalId, 2218 String namespaceCode, String roleName, Map<String, String> qualifier) throws RiceIllegalArgumentException { 2219 if (StringUtils.isBlank(principalId)) { 2220 throw new RiceIllegalArgumentException("principalId is null"); 2221 } 2222 2223 if (StringUtils.isBlank(namespaceCode)) { 2224 throw new RiceIllegalArgumentException("namespaceCode is null"); 2225 } 2226 2227 if (StringUtils.isBlank(roleName)) { 2228 throw new RiceIllegalArgumentException("roleName is null"); 2229 } 2230 2231 if (qualifier == null) { 2232 throw new RiceIllegalArgumentException("qualifier is null"); 2233 } 2234 // look up the role 2235 RoleBoLite role = getRoleBoLiteByName(namespaceCode, roleName); 2236 // pull all the principal members 2237 // look for an exact qualifier match 2238 List<RoleMemberBo> rms = getRoleMembersByExactQualifierMatch(role, principalId, memberTypeToRoleDaoActionMap.get(MemberType.PRINCIPAL.getCode()), qualifier); 2239 if(CollectionUtils.isEmpty(rms)) { 2240 rms = getRoleMembersByDefaultStrategy(role.getId(), principalId, MemberType.PRINCIPAL.getCode(), qualifier); 2241 } 2242 removeRoleMembers(rms); 2243 } 2244 2245 @Override 2246 public void removeGroupFromRole(String groupId, 2247 String namespaceCode, String roleName, Map<String, String> qualifier) throws RiceIllegalArgumentException { 2248 if (StringUtils.isBlank(groupId)) { 2249 throw new RiceIllegalArgumentException("groupId is null"); 2250 } 2251 2252 if (StringUtils.isBlank(namespaceCode)) { 2253 throw new RiceIllegalArgumentException("namespaceCode is null"); 2254 } 2255 2256 if (StringUtils.isBlank(roleName)) { 2257 throw new RiceIllegalArgumentException("roleName is null"); 2258 } 2259 2260 if (qualifier == null) { 2261 throw new RiceIllegalArgumentException("qualifier is null"); 2262 } 2263 2264 // look up the roleBo 2265 RoleBoLite roleBo = getRoleBoLiteByName(namespaceCode, roleName); 2266 // pull all the group roleBo members 2267 // look for an exact qualifier match 2268 List<RoleMemberBo> rms = getRoleMembersByExactQualifierMatch(roleBo, groupId, memberTypeToRoleDaoActionMap.get(MemberType.GROUP.getCode()), qualifier); 2269 if(CollectionUtils.isEmpty(rms)) { 2270 rms = getRoleMembersByDefaultStrategy(roleBo.getId(), groupId, MemberType.GROUP.getCode(), qualifier); 2271 } 2272 removeRoleMembers(rms); 2273 } 2274 2275 @Override 2276 public void removeRoleFromRole(String roleId, 2277 String namespaceCode, String roleName, Map<String, String> qualifier) throws RiceIllegalArgumentException { 2278 incomingParamCheck(roleId, "roleId"); 2279 incomingParamCheck(namespaceCode, "namespaceCode"); 2280 incomingParamCheck(roleName, "roleName"); 2281 incomingParamCheck(qualifier, "qualifier"); 2282 2283 2284 // look up the role 2285 RoleBoLite role = getRoleBoLiteByName(namespaceCode, roleName); 2286 // pull all the group role members 2287 // look for an exact qualifier match 2288 List<RoleMemberBo> rms = getRoleMembersByExactQualifierMatch(role, roleId, memberTypeToRoleDaoActionMap.get(MemberType.ROLE.getCode()), qualifier); 2289 if(CollectionUtils.isEmpty(rms)) { 2290 rms = getRoleMembersByDefaultStrategy(role.getId(), roleId, MemberType.ROLE.getCode(), qualifier); 2291 } 2292 removeRoleMembers(rms); 2293 } 2294 2295 @Override 2296 public void assignPermissionToRole(String permissionId, String roleId) throws RiceIllegalArgumentException { 2297 incomingParamCheck(permissionId, "permissionId"); 2298 incomingParamCheck(roleId, "roleId"); 2299 2300 RolePermissionBo newRolePermission = new RolePermissionBo(); 2301 2302 Long nextSeq = new Long(MaxValueIncrementerFactory.getIncrementer(getDataSource(), 2303 KimConstants.SequenceNames.KRIM_ROLE_PERM_ID_S).nextLongValue()); 2304 2305 newRolePermission.setId(nextSeq.toString()); 2306 newRolePermission.setRoleId(roleId); 2307 newRolePermission.setPermissionId(permissionId); 2308 newRolePermission.setActive(true); 2309 2310 getDataObjectService().save(newRolePermission); 2311 } 2312 2313 @Override 2314 public void revokePermissionFromRole(String permissionId, String roleId) throws RiceIllegalArgumentException { 2315 incomingParamCheck(permissionId, "permissionId"); 2316 incomingParamCheck(roleId, "roleId"); 2317 2318 Map<String, Object> params = new HashMap<String, Object>(); 2319 params.put("roleId", roleId); 2320 params.put("permissionId", permissionId); 2321 params.put("active", Boolean.TRUE); 2322 QueryResults<RolePermissionBo> rolePermissionBos = getDataObjectService().findMatching(RolePermissionBo.class, QueryByCriteria.Builder.andAttributes(params).build()); 2323 List<RolePermissionBo> rolePermsToSave = new ArrayList<RolePermissionBo>(); 2324 for (RolePermissionBo rolePerm : rolePermissionBos.getResults()) { 2325 rolePerm.setActive(false); 2326 rolePermsToSave.add(rolePerm); 2327 } 2328 2329 getDataObjectService().save(rolePermsToSave); 2330 } 2331 2332 protected void addMemberAttributeData(RoleMemberBo roleMember, Map<String, String> qualifier, String kimTypeId) { 2333 List<RoleMemberAttributeDataBo> attributes = new ArrayList<RoleMemberAttributeDataBo>(); 2334 for (Map.Entry<String, String> entry : qualifier.entrySet()) { 2335 RoleMemberAttributeDataBo roleMemberAttrBo = new RoleMemberAttributeDataBo(); 2336 roleMemberAttrBo.setAttributeValue(entry.getValue()); 2337 roleMemberAttrBo.setKimTypeId(kimTypeId); 2338 roleMemberAttrBo.setAssignedToId(roleMember.getId()); 2339 // look up the attribute ID 2340 roleMemberAttrBo.setKimAttributeId(getKimAttributeId(kimTypeId, entry.getKey())); 2341 2342 Map<String, String> criteria = new HashMap<String, String>(); 2343 criteria.put(KimConstants.PrimaryKeyConstants.KIM_ATTRIBUTE_ID, roleMemberAttrBo.getKimAttributeId()); 2344 //criteria.put(KimConstants.PrimaryKeyConstants.ROLE_MEMBER_ID, roleMember.getId()); 2345 criteria.put("assignedToId", roleMember.getId()); 2346 QueryResults<RoleMemberAttributeDataBo> origRoleMemberAttributes = 2347 getDataObjectService().findMatching(RoleMemberAttributeDataBo.class, QueryByCriteria.Builder.andAttributes(criteria).build()); 2348 RoleMemberAttributeDataBo origRoleMemberAttribute = 2349 (!origRoleMemberAttributes.getResults().isEmpty()) ? origRoleMemberAttributes.getResults().get(0) : null; 2350 if (origRoleMemberAttribute != null) { 2351 roleMemberAttrBo.setId(origRoleMemberAttribute.getId()); 2352 roleMemberAttrBo.setVersionNumber(origRoleMemberAttribute.getVersionNumber()); 2353 } 2354 attributes.add(roleMemberAttrBo); 2355 } 2356 roleMember.setAttributeDetails(attributes); 2357 } 2358 2359 protected void addDelegationMemberAttributeData( DelegateMemberBo delegationMember, Map<String, String> qualifier, String kimTypeId ) { 2360 List<DelegateMemberAttributeDataBo> attributes = new ArrayList<DelegateMemberAttributeDataBo>(); 2361 for ( Map.Entry<String, String> entry : qualifier.entrySet() ) { 2362 DelegateMemberAttributeDataBo delegateMemberAttrBo = new DelegateMemberAttributeDataBo(); 2363 delegateMemberAttrBo.setAttributeValue(entry.getValue()); 2364 delegateMemberAttrBo.setKimTypeId(kimTypeId); 2365 delegateMemberAttrBo.setAssignedToId(delegationMember.getDelegationMemberId()); 2366 // look up the attribute ID 2367 delegateMemberAttrBo.setKimAttributeId(getKimAttributeId(kimTypeId, entry.getKey())); 2368 Map<String, String> criteria = new HashMap<String, String>(); 2369 criteria.put(KimConstants.PrimaryKeyConstants.KIM_ATTRIBUTE_ID, delegateMemberAttrBo.getKimAttributeId()); 2370 criteria.put(KimConstants.PrimaryKeyConstants.DELEGATION_MEMBER_ID, delegationMember.getDelegationMemberId()); 2371 QueryResults<DelegateMemberAttributeDataBo> origDelegationMemberAttributes = 2372 getDataObjectService().findMatching(DelegateMemberAttributeDataBo.class, QueryByCriteria.Builder.andAttributes(criteria).build()); 2373 DelegateMemberAttributeDataBo origDelegationMemberAttribute = 2374 (!origDelegationMemberAttributes.getResults().isEmpty()) ? origDelegationMemberAttributes.getResults().get(0) : null; 2375 if(origDelegationMemberAttribute!=null){ 2376 delegateMemberAttrBo.setId(origDelegationMemberAttribute.getId()); 2377 delegateMemberAttrBo.setVersionNumber(origDelegationMemberAttribute.getVersionNumber()); 2378 } 2379 attributes.add( delegateMemberAttrBo ); 2380 } 2381 delegationMember.setAttributeDetails( attributes ); 2382 } 2383 2384 2385 2386 // -------------------- 2387 // Persistence Methods 2388 // -------------------- 2389 2390 private void deleteNullMemberAttributeData(List<RoleMemberAttributeDataBo> attributes) { 2391 List<RoleMemberAttributeDataBo> attributesToDelete = new ArrayList<RoleMemberAttributeDataBo>(); 2392 for(RoleMemberAttributeDataBo attribute: attributes){ 2393 if(attribute.getAttributeValue()==null){ 2394 attributesToDelete.add(attribute); 2395 } 2396 } 2397 getDataObjectService().delete(attributesToDelete); 2398 } 2399 2400 private void deleteNullDelegationMemberAttributeData(List<DelegateMemberAttributeDataBo> attributes) { 2401 List<DelegateMemberAttributeDataBo> attributesToDelete = new ArrayList<DelegateMemberAttributeDataBo>(); 2402 2403 for(DelegateMemberAttributeDataBo attribute: attributes){ 2404 if(attribute.getAttributeValue()==null){ 2405 attributesToDelete.add(attribute); 2406 } 2407 } 2408 getDataObjectService().delete(attributesToDelete); 2409 } 2410 2411 protected void logPrincipalHasRoleCheck(String principalId, List<String> roleIds, Map<String, String> roleQualifiers ) { 2412 StringBuilder sb = new StringBuilder(); 2413 sb.append( '\n' ); 2414 sb.append( "Has Role : " ).append( roleIds ).append( '\n' ); 2415 if ( roleIds != null ) { 2416 for ( String roleId : roleIds ) { 2417 Role role = getRole( roleId ); 2418 if ( role != null ) { 2419 sb.append( " Name : " ).append( role.getNamespaceCode() ).append( '/').append( role.getName() ); 2420 sb.append( " (" ).append( roleId ).append( ')' ); 2421 sb.append( '\n' ); 2422 } 2423 } 2424 } 2425 sb.append( " Principal : " ).append( principalId ); 2426 if ( principalId != null ) { 2427 Principal principal = KimApiServiceLocator.getIdentityService().getPrincipal(principalId); 2428 if ( principal != null ) { 2429 sb.append( " (" ).append( principal.getPrincipalName() ).append( ')' ); 2430 } 2431 } 2432 sb.append( '\n' ); 2433 sb.append( " Details :\n" ); 2434 if ( roleQualifiers != null ) { 2435 sb.append( roleQualifiers ); 2436 } else { 2437 sb.append( " [null]\n" ); 2438 } 2439 if (LOG.isTraceEnabled()) { 2440 LOG.trace( sb.append(ExceptionUtils.getStackTrace(new Throwable()))); 2441 } else { 2442 LOG.debug(sb.toString()); 2443 } 2444 } 2445 2446 private void incomingParamCheck(Object object, String name) { 2447 if (object == null) { 2448 throw new RiceIllegalArgumentException(name + " was null"); 2449 } else if (object instanceof String 2450 && StringUtils.isBlank((String) object)) { 2451 throw new RiceIllegalArgumentException(name + " was blank"); 2452 } 2453 } 2454 2455 /** 2456 * This gets the proxied version of the role service which will go through 2457 * Spring's caching mechanism for method calls rather than skipping it when 2458 * methods are called directly. 2459 * 2460 * @return The proxied role service 2461 */ 2462 protected RoleService getProxiedRoleService() { 2463 if(this.proxiedRoleService == null) { 2464 this.proxiedRoleService = KimApiServiceLocator.getRoleService(); 2465 } 2466 return this.proxiedRoleService; 2467 } 2468 2469 /** 2470 * Sets the cache manager which this service implementation can for internal caching. 2471 * Calling this setter is optional, though the value passed to it must not be null. 2472 * 2473 * @param cacheManager the cache manager to use for internal caching, must not be null 2474 * @throws IllegalArgumentException if a null cache manager is passed 2475 */ 2476 public void setCacheManager(CacheManager cacheManager) { 2477 if (cacheManager == null) { 2478 throw new IllegalArgumentException("cacheManager must not be null"); 2479 } 2480 this.cacheManager = cacheManager; 2481 } 2482 2483 protected DataSource getDataSource() { 2484 return KimImplServiceLocator.getDataSource(); 2485 } 2486 2487 private static class VersionedService<T> { 2488 2489 String version; 2490 T service; 2491 2492 VersionedService(String version, T service) { 2493 this.version = version; 2494 this.service = service; 2495 } 2496 2497 T getService() { 2498 return this.service; 2499 } 2500 2501 String getVersion() { 2502 return this.version; 2503 } 2504 2505 } 2506 2507 protected VersionedService<RoleTypeService> getVersionedRoleTypeService(KimType typeInfo) { 2508 QName serviceName = KimTypeUtils.resolveKimTypeServiceName(typeInfo.getServiceName()); 2509 if (serviceName != null) { 2510 // default version since the base services have been available since then 2511 String version = CoreConstants.Versions.VERSION_2_0_0; 2512 RoleTypeService roleTypeService = null; 2513 2514 try { 2515 2516 ServiceBus serviceBus = KsbApiServiceLocator.getServiceBus(); 2517 Endpoint endpoint = serviceBus.getEndpoint(serviceName); 2518 if (endpoint != null) { 2519 version = endpoint.getServiceConfiguration().getServiceVersion(); 2520 } 2521 KimTypeService service = GlobalResourceLoader.getService(serviceName); 2522 if (service != null && service instanceof RoleTypeService) { 2523 roleTypeService = (RoleTypeService) service; 2524 } else { 2525 roleTypeService = (RoleTypeService) KimImplServiceLocator.getService("kimNoMembersRoleTypeService"); 2526 } 2527 } catch (Exception ex) { 2528 roleTypeService = (RoleTypeService) KimImplServiceLocator.getService("kimNoMembersRoleTypeService"); 2529 } 2530 2531 return new VersionedService<RoleTypeService>(version, roleTypeService); 2532 } 2533 2534 return null; 2535 } 2536 2537 private Map<String, String> getNestedQualification(RoleBoLite memberRole, String namespaceCode, String roleName, 2538 String memberNamespaceCode, String memberName, Map<String, String> qualification, 2539 Map<String, String> memberQualification) { 2540 VersionedService<RoleTypeService> versionedRoleTypeService = getVersionedRoleTypeService(KimTypeBo.to(memberRole.getKimRoleType())); 2541 // if null service - just return the original qualification (pre 2.3.4 - ignoring memberQualifications) 2542 if ( versionedRoleTypeService == null ) { 2543 return qualification; 2544 } 2545 boolean versionOk = VersionHelper.compareVersion(versionedRoleTypeService.getVersion(), 2546 CoreConstants.Versions.VERSION_2_3_4) != -1; 2547 if (versionOk) { 2548 return versionedRoleTypeService.getService().convertQualificationForMemberRolesAndMemberAttributes(namespaceCode, roleName, 2549 memberNamespaceCode, memberName, qualification, memberQualification); 2550 } else { 2551 return versionedRoleTypeService.getService().convertQualificationForMemberRoles(namespaceCode, roleName, 2552 memberNamespaceCode, memberName, qualification); 2553 } 2554 2555 } 2556 2557 }