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