001 /**
002 * Copyright 2005-2011 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.kim.impl.role;
017
018 import org.apache.commons.collections.CollectionUtils;
019 import org.apache.commons.lang.StringUtils;
020 import org.apache.log4j.Logger;
021 import org.joda.time.DateTime;
022 import org.kuali.rice.core.api.criteria.GenericQueryResults;
023 import org.kuali.rice.core.api.criteria.QueryByCriteria;
024 import org.kuali.rice.core.api.delegation.DelegationType;
025 import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
026 import org.kuali.rice.core.api.exception.RiceIllegalStateException;
027 import org.kuali.rice.core.api.membership.MemberType;
028 import org.kuali.rice.core.api.mo.ModelObjectUtils;
029 import org.kuali.rice.kim.api.KimConstants;
030 import org.kuali.rice.kim.api.common.delegate.DelegateMember;
031 import org.kuali.rice.kim.api.common.delegate.DelegateType;
032 import org.kuali.rice.kim.api.role.DelegateMemberQueryResults;
033 import org.kuali.rice.kim.api.role.Role;
034 import org.kuali.rice.kim.api.role.RoleMember;
035 import org.kuali.rice.kim.api.role.RoleMemberQueryResults;
036 import org.kuali.rice.kim.api.role.RoleMembership;
037 import org.kuali.rice.kim.api.role.RoleMembershipQueryResults;
038 import org.kuali.rice.kim.api.role.RoleQueryResults;
039 import org.kuali.rice.kim.api.role.RoleResponsibility;
040 import org.kuali.rice.kim.api.role.RoleResponsibilityAction;
041 import org.kuali.rice.kim.api.role.RoleService;
042 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
043 import org.kuali.rice.kim.api.type.KimType;
044 import org.kuali.rice.kim.framework.common.delegate.DelegationTypeService;
045 import org.kuali.rice.kim.framework.role.RoleTypeService;
046 import org.kuali.rice.kim.framework.services.KimFrameworkServiceLocator;
047 import org.kuali.rice.kim.framework.type.KimTypeService;
048 import org.kuali.rice.kim.impl.common.attribute.KimAttributeDataBo;
049 import org.kuali.rice.kim.impl.common.delegate.DelegateMemberAttributeDataBo;
050 import org.kuali.rice.kim.impl.common.delegate.DelegateMemberBo;
051 import org.kuali.rice.kim.impl.common.delegate.DelegateTypeBo;
052 import org.kuali.rice.kim.impl.services.KimImplServiceLocator;
053 import org.kuali.rice.krad.service.KRADServiceLocator;
054 import org.springframework.util.LinkedMultiValueMap;
055 import org.springframework.util.MultiValueMap;
056
057 import javax.jws.WebParam;
058 import java.sql.Timestamp;
059 import java.util.ArrayList;
060 import java.util.Collection;
061 import java.util.Collections;
062 import java.util.Date;
063 import java.util.HashMap;
064 import java.util.HashSet;
065 import java.util.List;
066 import java.util.Map;
067 import java.util.Set;
068
069 import static org.kuali.rice.core.api.criteria.PredicateFactory.equal;
070
071 public class RoleServiceImpl extends RoleServiceBase implements RoleService {
072 private static final Logger LOG = Logger.getLogger(RoleServiceImpl.class);
073
074 private static final Map<String, RoleDaoAction> memberTypeToRoleDaoActionMap = populateMemberTypeToRoleDaoActionMap();
075
076 private static Map<String, RoleDaoAction> populateMemberTypeToRoleDaoActionMap() {
077 Map<String, RoleDaoAction> map = new HashMap<String, RoleDaoAction>();
078 map.put(MemberType.GROUP.getCode(), RoleDaoAction.ROLE_GROUPS_FOR_GROUP_IDS_AND_ROLE_IDS);
079 map.put(MemberType.PRINCIPAL.getCode(), RoleDaoAction.ROLE_PRINCIPALS_FOR_PRINCIPAL_ID_AND_ROLE_IDS);
080 map.put(MemberType.ROLE.getCode(), RoleDaoAction.ROLE_MEMBERSHIPS_FOR_ROLE_IDS_AS_MEMBERS);
081 return Collections.unmodifiableMap(map);
082 }
083
084
085 @Override
086 public Role createRole(final Role role) throws RiceIllegalArgumentException, RiceIllegalStateException {
087 incomingParamCheck(role, "role");
088
089 if (StringUtils.isNotBlank(role.getId()) && getRole(role.getId()) != null) {
090 throw new RiceIllegalStateException("the role to create already exists: " + role);
091 }
092 RoleBo bo = RoleBo.from(role);
093 return RoleBo.to(getBusinessObjectService().save(bo));
094 }
095
096 @Override
097 public Role updateRole(final Role role) throws RiceIllegalArgumentException, RiceIllegalStateException {
098 incomingParamCheck(role, "role");
099
100 RoleBo originalRole = getRoleBo(role.getId());
101 if (StringUtils.isBlank(role.getId()) || originalRole == null) {
102 throw new RiceIllegalStateException("the role does not exist: " + role);
103 }
104
105 RoleBo bo = RoleBo.from(role);
106
107 RoleBo updatedRole = getBusinessObjectService().save(bo);
108 if (originalRole.isActive()
109 && !updatedRole.isActive()) {
110 KimImplServiceLocator.getRoleInternalService().roleInactivated(updatedRole.getId());
111 }
112 return RoleBo.to(updatedRole);
113 }
114
115 /**
116 * This method tests to see if assigning a roleBo to another roleBo will create a circular reference.
117 * The Role is checked to see if it is a member (direct or nested) of the roleBo to be assigned as a member.
118 *
119 * @param newMemberId
120 * @param roleBo
121 * @return true - assignment is allowed, no circular reference will be created.
122 * false - illegal assignment, it will create a circular membership
123 */
124 protected boolean checkForCircularRoleMembership(String newMemberId, RoleBo roleBo) {
125 // get all nested roleBo members that are of type roleBo
126 Set<String> newRoleMemberIds = getRoleTypeRoleMemberIds(newMemberId);
127 return !newRoleMemberIds.contains(roleBo.getId());
128 }
129
130 protected RoleMember findRoleMember(String roleMemberId) {
131 final List<RoleMember> roleMembers = findRoleMembers(QueryByCriteria.Builder.fromPredicates(equal(KimConstants.PrimaryKeyConstants.ROLE_MEMBER_ID, roleMemberId))).getResults();
132 if (roleMembers != null && !roleMembers.isEmpty()) {
133 return roleMembers.get(0);
134 }
135 return null;
136 }
137
138 @Override
139 public RoleMemberQueryResults findRoleMembers(QueryByCriteria queryByCriteria) throws RiceIllegalStateException {
140 incomingParamCheck(queryByCriteria, "queryByCriteria");
141
142 GenericQueryResults<RoleMemberBo> results = getCriteriaLookupService().lookup(RoleMemberBo.class, queryByCriteria);
143
144 RoleMemberQueryResults.Builder builder = RoleMemberQueryResults.Builder.create();
145 builder.setMoreResultsAvailable(results.isMoreResultsAvailable());
146 builder.setTotalRowCount(results.getTotalRowCount());
147
148 final List<RoleMember.Builder> ims = new ArrayList<RoleMember.Builder>();
149 for (RoleMemberBo bo : results.getResults()) {
150 ims.add(RoleMember.Builder.create(bo));
151 }
152
153 builder.setResults(ims);
154 return builder.build();
155 }
156
157 @Override
158 public Set<String> getRoleTypeRoleMemberIds(String roleId) throws RiceIllegalStateException {
159 incomingParamCheck(roleId, "roleId");
160
161 Set<String> results = new HashSet<String>();
162 getNestedRoleTypeMemberIds(roleId, results);
163 return Collections.unmodifiableSet(results);
164 }
165
166 @Override
167 public List<String> getMemberParentRoleIds(String memberType, String memberId) throws RiceIllegalStateException {
168 incomingParamCheck(memberType, "memberType");
169 incomingParamCheck(memberId, "memberId");
170
171 List<RoleMemberBo> parentRoleMembers = getRoleDao().getRoleMembershipsForMemberId(memberType, memberId,
172 Collections.<String, String>emptyMap());
173
174 List<String> parentRoleIds = new ArrayList<String>(parentRoleMembers.size());
175 for (RoleMemberBo parentRoleMember : parentRoleMembers) {
176 parentRoleIds.add(parentRoleMember.getRoleId());
177 }
178
179 return parentRoleIds;
180 }
181
182 @Override
183 public List<RoleResponsibilityAction> getRoleMemberResponsibilityActions(String roleMemberId) throws RiceIllegalStateException {
184 incomingParamCheck(roleMemberId, "roleMemberId");
185
186 Map<String, String> criteria = new HashMap<String, String>(1);
187 criteria.put(KimConstants.PrimaryKeyConstants.ROLE_MEMBER_ID, roleMemberId);
188
189 List<RoleResponsibilityActionBo> responsibilityActionBoList = (List<RoleResponsibilityActionBo>)
190 getBusinessObjectService().findMatching(RoleResponsibilityActionBo.class, criteria);
191
192 List<RoleResponsibilityAction> roleResponsibilityActionsList = new ArrayList<RoleResponsibilityAction>();
193 for (RoleResponsibilityActionBo roleResponsibilityActionBo : responsibilityActionBoList) {
194 RoleResponsibilityAction roleResponsibility = RoleResponsibilityActionBo.to(roleResponsibilityActionBo);
195 roleResponsibilityActionsList.add(roleResponsibility);
196 }
197 return roleResponsibilityActionsList;
198 }
199
200 @Override
201 public DelegateMemberQueryResults findDelegateMembers(QueryByCriteria queryByCriteria) throws RiceIllegalStateException {
202 incomingParamCheck(queryByCriteria, "queryByCriteria");
203
204 GenericQueryResults<DelegateMemberBo> results = getCriteriaLookupService().lookup(DelegateMemberBo.class, queryByCriteria);
205
206 DelegateMemberQueryResults.Builder builder = DelegateMemberQueryResults.Builder.create();
207 builder.setMoreResultsAvailable(results.isMoreResultsAvailable());
208 builder.setTotalRowCount(results.getTotalRowCount());
209
210 final List<DelegateMember.Builder> ims = new ArrayList<DelegateMember.Builder>();
211 for (DelegateMemberBo bo : results.getResults()) {
212 ims.add(DelegateMember.Builder.create(bo));
213 }
214
215 builder.setResults(ims);
216 return builder.build();
217 }
218
219 @Override
220 public Role getRole(String roleId) throws RiceIllegalStateException {
221 incomingParamCheck(roleId, "rpleId");
222
223 RoleBo roleBo = getRoleBo(roleId);
224 if (roleBo == null) {
225 return null;
226 }
227 return RoleBo.to(roleBo);
228 }
229
230 protected Map<String, RoleBo> getRoleBoMap(Collection<String> roleIds) {
231 Map<String, RoleBo> result;
232 // check for a non-null result in the cache, return it if found
233 if (roleIds.size() == 1) {
234 String roleId = roleIds.iterator().next();
235 RoleBo bo = getRoleBo(roleId);
236 result = bo.isActive() ? Collections.singletonMap(roleId, bo) : Collections.<String, RoleBo>emptyMap();
237 } else {
238 result = new HashMap<String, RoleBo>(roleIds.size());
239 for (String roleId : roleIds) {
240 RoleBo bo = getRoleBo(roleId);
241 if (bo.isActive()) {
242 result.put(roleId, bo);
243 }
244 }
245 }
246 return result;
247 }
248
249 @Override
250 public List<Role> getRoles(List<String> roleIds) throws RiceIllegalStateException {
251 if (CollectionUtils.isEmpty(roleIds)) {
252 throw new RiceIllegalArgumentException("roleIds is null or empty");
253 }
254
255 Collection<RoleBo> roleBos = getRoleBoMap(roleIds).values();
256 List<Role> roles = new ArrayList<Role>(roleBos.size());
257 for (RoleBo bo : roleBos) {
258 roles.add(RoleBo.to(bo));
259 }
260 return Collections.unmodifiableList(roles);
261 }
262
263 @Override
264 public Role getRoleByNameAndNamespaceCode(String namespaceCode, String roleName) throws RiceIllegalStateException {
265 incomingParamCheck(namespaceCode, "namespaceCode");
266 incomingParamCheck(roleName, "roleName");
267
268 RoleBo roleBo = getRoleBoByName(namespaceCode, roleName);
269 if (roleBo != null) {
270 return RoleBo.to(roleBo);
271 }
272 return null;
273 }
274
275 @Override
276 public String getRoleIdByNameAndNamespaceCode(String namespaceCode, String roleName) throws RiceIllegalStateException {
277 incomingParamCheck(namespaceCode, "namespaceCode");
278 incomingParamCheck(roleName, "roleName");
279
280 Role role = getRoleByNameAndNamespaceCode(namespaceCode, roleName);
281 if (role != null) {
282 return role.getId();
283 } else {
284 return null;
285 }
286 }
287
288 @Override
289 public boolean isRoleActive(String roleId) throws RiceIllegalStateException {
290 incomingParamCheck(roleId, "roleId");
291
292 RoleBo roleBo = getRoleBo(roleId);
293 return roleBo != null && roleBo.isActive();
294 }
295
296 @Override
297 public List<Map<String, String>> getRoleQualifersForPrincipalByRoleIds(String principalId, List<String> roleIds,
298 Map<String, String> qualification) throws RiceIllegalStateException {
299 incomingParamCheck(principalId, "principalId");
300 incomingParamCheck(roleIds, "roleIds");
301 incomingParamCheck(qualification, "qualification");
302
303 List<Map<String, String>> results = new ArrayList<Map<String, String>>();
304
305 List<RoleMemberBo> roleMemberBoList = getStoredRoleMembersUsingExactMatchOnQualification(principalId, null,
306 roleIds, qualification);
307
308 Map<String, List<RoleMembership>> roleIdToMembershipMap = new HashMap<String, List<RoleMembership>>();
309 for (RoleMemberBo roleMemberBo : roleMemberBoList) {
310 // gather up the qualifier sets and the service they go with
311 if (MemberType.PRINCIPAL.equals(roleMemberBo.getMemberType())) {
312 RoleTypeService roleTypeService = getRoleTypeService(roleMemberBo.getRoleId());
313 if (roleTypeService != null) {
314 List<RoleMembership> las = roleIdToMembershipMap.get(roleMemberBo.getRoleId());
315 if (las == null) {
316 las = new ArrayList<RoleMembership>();
317 roleIdToMembershipMap.put(roleMemberBo.getRoleId(), las);
318 }
319 RoleMembership mi = RoleMembership.Builder.create(
320 roleMemberBo.getRoleId(),
321 roleMemberBo.getRoleMemberId(),
322 roleMemberBo.getMemberId(),
323 roleMemberBo.getMemberType(),
324 roleMemberBo.getAttributes()).build();
325
326 las.add(mi);
327 } else {
328 results.add(roleMemberBo.getAttributes());
329 }
330 }
331 }
332 for (Map.Entry<String, List<RoleMembership>> entry : roleIdToMembershipMap.entrySet()) {
333 RoleTypeService roleTypeService = getRoleTypeService(entry.getKey());
334 //it is possible that the the roleTypeService is coming from a remote application
335 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility.
336 try {
337 List<RoleMembership> matchingMembers = roleTypeService.getMatchingRoleMemberships(qualification, entry.getValue());
338 for (RoleMembership rmi : matchingMembers) {
339 results.add(rmi.getQualifier());
340 }
341 } catch (Exception ex) {
342 LOG.warn("Not able to retrieve RoleTypeService from remote system for role Id: " + entry.getKey(), ex);
343 }
344 }
345 return Collections.unmodifiableList(results);
346 }
347
348 @Override
349 public List<Map<String, String>> getRoleQualifersForPrincipalByNamespaceAndRolename(String principalId,
350 String namespaceCode, String roleName, Map<String, String> qualification)
351 throws RiceIllegalStateException {
352 incomingParamCheck(principalId, "principalId");
353 incomingParamCheck(namespaceCode, "namespaceCode");
354 incomingParamCheck(roleName, "roleName");
355 incomingParamCheck(qualification, "qualification");
356
357 String roleId = getRoleIdByNameAndNamespaceCode(namespaceCode, roleName);
358 if (roleId == null) {
359 return Collections.emptyList();
360 }
361 return getNestedRoleQualifiersForPrincipalByRoleIds(principalId, Collections.singletonList(roleId),
362 qualification);
363 }
364
365 @Override
366 public List<Map<String, String>> getNestedRoleQualifersForPrincipalByNamespaceAndRolename(String principalId,
367 String namespaceCode, String roleName, Map<String, String> qualification) throws RiceIllegalStateException {
368 incomingParamCheck(principalId, "principalId");
369 incomingParamCheck(namespaceCode, "namespaceCode");
370 incomingParamCheck(roleName, "roleName");
371 incomingParamCheck(qualification, "qualification");
372
373 String roleId = getRoleIdByNameAndNamespaceCode(namespaceCode, roleName);
374 if (roleId == null) {
375 return new ArrayList<Map<String, String>>(0);
376 }
377 return getNestedRoleQualifiersForPrincipalByRoleIds(principalId, Collections.singletonList(roleId),
378 qualification);
379 }
380
381 @Override
382 public List<Map<String, String>> getNestedRoleQualifiersForPrincipalByRoleIds(String principalId,
383 List<String> roleIds, Map<String, String> qualification) throws RiceIllegalStateException {
384 incomingParamCheck(principalId, "principalId");
385 incomingParamCheck(roleIds, "roleIds");
386 incomingParamCheck(qualification, "qualification");
387
388
389 List<Map<String, String>> results = new ArrayList<Map<String, String>>();
390
391 Map<String, RoleBo> roleBosById = getRoleBoMap(roleIds);
392
393 // get the person's groups
394 List<String> groupIds = getGroupService().getGroupIdsByPrincipalId(principalId);
395 List<RoleMemberBo> roleMemberBos = getStoredRoleMembersUsingExactMatchOnQualification(principalId, groupIds, roleIds, qualification);
396
397 Map<String, List<RoleMembership>> roleIdToMembershipMap = new HashMap<String, List<RoleMembership>>();
398 for (RoleMemberBo roleMemberBo : roleMemberBos) {
399 RoleTypeService roleTypeService = getRoleTypeService(roleMemberBo.getRoleId());
400 // gather up the qualifier sets and the service they go with
401 if (MemberType.PRINCIPAL.equals(roleMemberBo.getMemberType())
402 || MemberType.GROUP.equals(roleMemberBo.getMemberType())) {
403 if (roleTypeService != null) {
404 List<RoleMembership> las = roleIdToMembershipMap.get(roleMemberBo.getRoleId());
405 if (las == null) {
406 las = new ArrayList<RoleMembership>();
407 roleIdToMembershipMap.put(roleMemberBo.getRoleId(), las);
408 }
409 RoleMembership mi = RoleMembership.Builder.create(
410 roleMemberBo.getRoleId(),
411 roleMemberBo.getRoleMemberId(),
412 roleMemberBo.getMemberId(),
413 roleMemberBo.getMemberType(),
414 roleMemberBo.getAttributes()).build();
415
416 las.add(mi);
417 } else {
418 results.add(roleMemberBo.getAttributes());
419 }
420 } else if (MemberType.ROLE.equals(roleMemberBo.getMemberType())) {
421 // find out if the user has the role
422 // need to convert qualification using this role's service
423 Map<String, String> nestedQualification = qualification;
424 if (roleTypeService != null) {
425 RoleBo roleBo = roleBosById.get(roleMemberBo.getRoleId());
426 // pulling from here as the nested roleBo is not necessarily (and likely is not)
427 // in the roleBosById Map created earlier
428 RoleBo nestedRole = getRoleBo(roleMemberBo.getMemberId());
429 //it is possible that the the roleTypeService is coming from a remote application
430 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility.
431 try {
432 nestedQualification = roleTypeService.convertQualificationForMemberRoles(roleBo.getNamespaceCode(), roleBo.getName(), nestedRole.getNamespaceCode(), nestedRole.getName(), qualification);
433 } catch (Exception ex) {
434 LOG.warn("Not able to retrieve RoleTypeService from remote system for roleBo Id: " + roleBo.getId(), ex);
435 }
436 }
437 List<String> nestedRoleId = new ArrayList<String>(1);
438 nestedRoleId.add(roleMemberBo.getMemberId());
439 // if the user has the given role, add the qualifier the *nested role* has with the
440 // originally queries role
441 if (principalHasRole(principalId, nestedRoleId, nestedQualification, false)) {
442 results.add(roleMemberBo.getAttributes());
443 }
444 }
445 }
446 for (Map.Entry<String, List<RoleMembership>> entry : roleIdToMembershipMap.entrySet()) {
447 RoleTypeService roleTypeService = getRoleTypeService(entry.getKey());
448 //it is possible that the the roleTypeService is coming from a remote application
449 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility.
450 try {
451 List<RoleMembership> matchingMembers = roleTypeService.getMatchingRoleMemberships(qualification,
452 entry.getValue());
453 for (RoleMembership roleMembership : matchingMembers) {
454 results.add(roleMembership.getQualifier());
455 }
456 } catch (Exception ex) {
457 LOG.warn("Not able to retrieve RoleTypeService from remote system for role Id: " + entry.getKey(), ex);
458 }
459 }
460 return Collections.unmodifiableList(results);
461 }
462
463 @Override
464 public List<RoleMembership> getRoleMembers(List<String> roleIds, Map<String, String> qualification) throws RiceIllegalStateException {
465 incomingParamCheck(roleIds, "roleIds");
466 incomingParamCheck(qualification, "qualification");
467
468 Set<String> foundRoleTypeMembers = new HashSet<String>();
469 return getRoleMembers(roleIds, qualification, true, foundRoleTypeMembers);
470 }
471
472 @Override
473 public Collection<String> getRoleMemberPrincipalIds(String namespaceCode, String roleName, Map<String, String> qualification) throws RiceIllegalStateException {
474 incomingParamCheck(namespaceCode, "namespaceCode");
475 incomingParamCheck(roleName, "roleName");
476 incomingParamCheck(qualification, "qualification");
477
478 Set<String> principalIds = new HashSet<String>();
479 Set<String> foundRoleTypeMembers = new HashSet<String>();
480 List<String> roleIds = Collections.singletonList(getRoleIdByNameAndNamespaceCode(namespaceCode, roleName));
481 for (RoleMembership roleMembership : getRoleMembers(roleIds, qualification, false, foundRoleTypeMembers)) {
482 if (MemberType.GROUP.equals(roleMembership.getMemberType())) {
483 principalIds.addAll(getGroupService().getMemberPrincipalIds(roleMembership.getMemberId()));
484 } else {
485 principalIds.add(roleMembership.getMemberId());
486 }
487 }
488 return Collections.unmodifiableSet(principalIds);
489 }
490
491 @Override
492 public boolean principalHasRole(String principalId, List<String> roleIds, Map<String, String> qualification) throws RiceIllegalStateException {
493 incomingParamCheck(principalId, "principalId");
494 incomingParamCheck(roleIds, "roleIds");
495 incomingParamCheck(qualification, "qualification");
496
497 return principalHasRole(principalId, roleIds, qualification, true);
498 }
499
500 @Override
501 public List<String> getPrincipalIdSubListWithRole(List<String> principalIds,
502 String roleNamespaceCode, String roleName, Map<String, String> qualification) throws RiceIllegalStateException {
503 incomingParamCheck(principalIds, "principalIds");
504 incomingParamCheck(roleNamespaceCode, "roleNamespaceCode");
505 incomingParamCheck(roleName, "roleName");
506 incomingParamCheck(qualification, "qualification");
507
508 List<String> subList = new ArrayList<String>();
509 RoleBo role = getRoleBoByName(roleNamespaceCode, roleName);
510 for (String principalId : principalIds) {
511 if (principalHasRole(principalId, Collections.singletonList(role.getId()), qualification)) {
512 subList.add(principalId);
513 }
514 }
515 return Collections.unmodifiableList(subList);
516 }
517
518 @Override
519 public RoleQueryResults findRoles(QueryByCriteria queryByCriteria) throws RiceIllegalStateException {
520 incomingParamCheck(queryByCriteria, "queryByCriteria");
521
522 GenericQueryResults<RoleBo> results = getCriteriaLookupService().lookup(RoleBo.class, queryByCriteria);
523
524 RoleQueryResults.Builder builder = RoleQueryResults.Builder.create();
525 builder.setMoreResultsAvailable(results.isMoreResultsAvailable());
526 builder.setTotalRowCount(results.getTotalRowCount());
527
528 final List<Role.Builder> ims = new ArrayList<Role.Builder>();
529 for (RoleBo bo : results.getResults()) {
530 ims.add(Role.Builder.create(bo));
531 }
532
533 builder.setResults(ims);
534 return builder.build();
535 }
536
537 @Override
538 public List<RoleMembership> getFirstLevelRoleMembers(List<String> roleIds) throws RiceIllegalStateException {
539 incomingParamCheck(roleIds, "roleIds");
540 if (roleIds.isEmpty()) {
541 return Collections.emptyList();
542 }
543
544 List<RoleMemberBo> roleMemberBoList = getStoredRoleMembersForRoleIds(roleIds, null, null);
545 List<RoleMembership> roleMemberships = new ArrayList<RoleMembership>();
546 for (RoleMemberBo roleMemberBo : roleMemberBoList) {
547 RoleMembership roleMembeship = RoleMembership.Builder.create(
548 roleMemberBo.getRoleId(),
549 roleMemberBo.getRoleMemberId(),
550 roleMemberBo.getMemberId(),
551 roleMemberBo.getMemberType(),
552 roleMemberBo.getAttributes()).build();
553 roleMemberships.add(roleMembeship);
554 }
555 return Collections.unmodifiableList(roleMemberships);
556 }
557
558 @Override
559 public RoleMembershipQueryResults findRoleMemberships( QueryByCriteria queryByCriteria) throws RiceIllegalStateException {
560 incomingParamCheck(queryByCriteria, "queryByCriteria");
561
562 GenericQueryResults<RoleMemberBo> results = getCriteriaLookupService().lookup(RoleMemberBo.class, queryByCriteria);
563
564 RoleMembershipQueryResults.Builder builder = RoleMembershipQueryResults.Builder.create();
565 builder.setMoreResultsAvailable(results.isMoreResultsAvailable());
566 builder.setTotalRowCount(results.getTotalRowCount());
567
568 final List<RoleMembership.Builder> ims = new ArrayList<RoleMembership.Builder>();
569 for (RoleMemberBo bo : results.getResults()) {
570 RoleMembership.Builder roleMembership = RoleMembership.Builder.create(
571 bo.getRoleId(),
572 bo.getRoleMemberId(),
573 bo.getMemberId(),
574 bo.getMemberType(),
575 bo.getAttributes());
576 ims.add(roleMembership);
577 }
578
579 builder.setResults(ims);
580 return builder.build();
581 }
582
583 @Override
584 public List<DelegateMember> getDelegationMembersByDelegationId(String delegationId) throws RiceIllegalStateException {
585 incomingParamCheck(delegationId, "delegationId");
586
587 DelegateTypeBo delegateBo = getKimDelegationImpl(delegationId);
588 if (delegateBo == null) {return Collections.emptyList();}
589
590 return getDelegateMembersForDelegation(delegateBo);
591 }
592
593 @Override
594 public DelegateMember getDelegationMemberByDelegationAndMemberId(String delegationId, String memberId) throws RiceIllegalStateException {
595 incomingParamCheck(delegationId, "delegationId");
596 incomingParamCheck(memberId, "memberId");
597
598 DelegateTypeBo delegateBo = getKimDelegationImpl(delegationId);
599 DelegateMemberBo delegationMember = getKimDelegationMemberImplByDelegationAndId(delegationId, memberId);
600
601 return getDelegateCompleteInfo(delegateBo, delegationMember);
602 }
603
604 @Override
605 public DelegateMember getDelegationMemberById(String delegationMemberId) throws RiceIllegalStateException {
606 incomingParamCheck(delegationMemberId, "delegationMemberId");
607
608 DelegateMemberBo delegateMemberBo = getDelegateMemberBo(delegationMemberId);
609 if (delegateMemberBo == null) {
610 return null;
611 }
612
613 DelegateTypeBo delegateBo = getKimDelegationImpl(delegateMemberBo.getDelegationId());
614
615 return getDelegateCompleteInfo(delegateBo, delegateMemberBo);
616 }
617
618 @Override
619 public List<RoleResponsibility> getRoleResponsibilities(String roleId) throws RiceIllegalStateException {
620 incomingParamCheck(roleId, "roleId");
621
622 Map<String, String> criteria = new HashMap<String, String>(1);
623 criteria.put(KimConstants.PrimaryKeyConstants.SUB_ROLE_ID, roleId);
624 List<RoleResponsibilityBo> roleResponsibilityBos = (List<RoleResponsibilityBo>)
625 getBusinessObjectService().findMatching(RoleResponsibilityBo.class, criteria);
626 List<RoleResponsibility> roleResponsibilities = new ArrayList<RoleResponsibility>();
627
628 for (RoleResponsibilityBo roleResponsibilityImpl : roleResponsibilityBos) {
629 roleResponsibilities.add(RoleResponsibilityBo.to(roleResponsibilityImpl));
630 }
631 return Collections.unmodifiableList(roleResponsibilities);
632 }
633
634 @Override
635 public DelegateType getDelegateTypeByRoleIdAndDelegateTypeCode(String roleId, DelegationType delegationType) throws RiceIllegalStateException {
636 incomingParamCheck(roleId, "roleId");
637 incomingParamCheck(delegationType, "delegationType");
638
639 DelegateTypeBo delegateBo = getDelegationOfType(roleId, delegationType);
640 return DelegateTypeBo.to(delegateBo);
641 }
642
643 @Override
644 public DelegateType getDelegateTypeByDelegationId(String delegationId) throws RiceIllegalStateException {
645 incomingParamCheck(delegationId, "delegationId");
646
647 DelegateTypeBo delegateBo = getKimDelegationImpl(delegationId);
648 return DelegateTypeBo.to(delegateBo);
649 }
650
651 protected List<RoleMembership> getRoleMembers(List<String> roleIds, Map<String, String> qualification, boolean followDelegations, Set<String> foundRoleTypeMembers) {
652 List<RoleMembership> results = new ArrayList<RoleMembership>();
653 Set<String> allRoleIds = new HashSet<String>();
654 for (String roleId : roleIds) {
655 if (isRoleActive(roleId)) {
656 allRoleIds.add(roleId);
657 }
658 }
659 // short-circuit if no roles match
660 if (allRoleIds.isEmpty()) {
661 return Collections.emptyList();
662 }
663 Set<String> matchingRoleIds = new HashSet<String>(allRoleIds.size());
664 // for efficiency, retrieve all roles and store in a map
665 Map<String, RoleBo> roles = getRoleBoMap(allRoleIds);
666
667 List<String> copyRoleIds = new ArrayList<String>(allRoleIds);
668 List<RoleMemberBo> rms = new ArrayList<RoleMemberBo>();
669
670 for (String roleId : allRoleIds) {
671 RoleTypeService roleTypeService = getRoleTypeService(roleId);
672 if (roleTypeService != null) {
673 List<String> attributesForExactMatch = roleTypeService.getQualifiersForExactMatch();
674 if (CollectionUtils.isNotEmpty(attributesForExactMatch)) {
675 copyRoleIds.remove(roleId);
676 rms.addAll(getStoredRoleMembersForRoleIds(Collections.singletonList(roleId), null, populateQualifiersForExactMatch(qualification, attributesForExactMatch)));
677 }
678 }
679 }
680 if (CollectionUtils.isNotEmpty(copyRoleIds)) {
681 rms.addAll(getStoredRoleMembersForRoleIds(copyRoleIds, null, null));
682 }
683
684 // build a map of role ID to membership information
685 // this will be used for later qualification checks
686 Map<String, List<RoleMembership>> roleIdToMembershipMap = new HashMap<String, List<RoleMembership>>();
687 for (RoleMemberBo roleMemberBo : rms) {
688 RoleMembership mi = RoleMembership.Builder.create(
689 roleMemberBo.getRoleId(),
690 roleMemberBo.getRoleMemberId(),
691 roleMemberBo.getMemberId(),
692 roleMemberBo.getMemberType(),
693 roleMemberBo.getAttributes()).build();
694
695 // if the qualification check does not need to be made, just add the result
696 if ((qualification == null || qualification.isEmpty()) || getRoleTypeService(roleMemberBo.getRoleId()) == null) {
697 if (MemberType.ROLE.equals(roleMemberBo.getMemberType())) {
698 // if a role member type, do a non-recursive role member check
699 // to obtain the group and principal members of that role
700 // given the qualification
701 Map<String, String> nestedRoleQualification = qualification;
702 if (getRoleTypeService(roleMemberBo.getRoleId()) != null) {
703 // get the member role object
704 RoleBo memberRole = getRoleBo(mi.getMemberId());
705 nestedRoleQualification = getRoleTypeService(roleMemberBo.getRoleId())
706 .convertQualificationForMemberRoles(
707 roles.get(roleMemberBo.getRoleId()).getNamespaceCode(),
708 roles.get(roleMemberBo.getRoleId()).getName(),
709 memberRole.getNamespaceCode(),
710 memberRole.getName(),
711 qualification);
712 }
713 if (isRoleActive(roleMemberBo.getRoleId())) {
714 Collection<RoleMembership> nestedRoleMembers = getNestedRoleMembers(nestedRoleQualification, mi, foundRoleTypeMembers);
715 if (!nestedRoleMembers.isEmpty()) {
716 results.addAll(nestedRoleMembers);
717 matchingRoleIds.add(roleMemberBo.getRoleId());
718 }
719 }
720 } else { // not a role member type
721 results.add(mi);
722 matchingRoleIds.add(roleMemberBo.getRoleId());
723 }
724 matchingRoleIds.add(roleMemberBo.getRoleId());
725 } else {
726 List<RoleMembership> lrmi = roleIdToMembershipMap.get(mi.getRoleId());
727 if (lrmi == null) {
728 lrmi = new ArrayList<RoleMembership>();
729 roleIdToMembershipMap.put(mi.getRoleId(), lrmi);
730 }
731 lrmi.add(mi);
732 }
733 }
734 // if there is anything in the role to membership map, we need to check the role type services
735 // for those entries
736 if (!roleIdToMembershipMap.isEmpty()) {
737 // for each role, send in all the qualifiers for that role to the type service
738 // for evaluation, the service will return those which match
739 for (Map.Entry<String, List<RoleMembership>> entry : roleIdToMembershipMap.entrySet()) {
740 //it is possible that the the roleTypeService is coming from a remote application
741 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility.
742 try {
743 RoleTypeService roleTypeService = getRoleTypeService(entry.getKey());
744 List<RoleMembership> matchingMembers = roleTypeService.getMatchingRoleMemberships(qualification,
745 entry.getValue());
746 // loop over the matching entries, adding them to the results
747 for (RoleMembership roleMemberships : matchingMembers) {
748 if (MemberType.ROLE.equals(roleMemberships.getMemberType())) {
749 // if a role member type, do a non-recursive role member check
750 // to obtain the group and principal members of that role
751 // given the qualification
752 // get the member role object
753 RoleBo memberRole = getRoleBo(roleMemberships.getMemberId());
754 if (memberRole.isActive()) {
755 Map<String, String> nestedRoleQualification = roleTypeService.convertQualificationForMemberRoles(
756 roles.get(roleMemberships.getRoleId()).getNamespaceCode(),
757 roles.get(roleMemberships.getRoleId()).getName(),
758 memberRole.getNamespaceCode(),
759 memberRole.getName(),
760 qualification);
761 Collection<RoleMembership> nestedRoleMembers = getNestedRoleMembers(nestedRoleQualification, roleMemberships, foundRoleTypeMembers);
762 if (!nestedRoleMembers.isEmpty()) {
763 results.addAll(nestedRoleMembers);
764 matchingRoleIds.add(roleMemberships.getRoleId());
765 }
766 }
767 } else { // not a role member
768 results.add(roleMemberships);
769 matchingRoleIds.add(roleMemberships.getRoleId());
770 }
771 }
772 } catch (Exception ex) {
773 LOG.warn("Not able to retrieve RoleTypeService from remote system for role Id: " + entry.getKey(), ex);
774 }
775 }
776 }
777
778 // handle application roles
779 for ( String roleId : allRoleIds ) {
780 RoleTypeService roleTypeService = getRoleTypeService( roleId );
781 RoleBo role = roles.get( roleId );
782 // check if an application role
783 try {
784 if ( isApplicationRoleType(role.getKimTypeId(), roleTypeService) ) {
785 // for each application role, get the list of principals and groups which are in that role given the qualification (per the role type service)
786 List<RoleMembership> roleMembers = roleTypeService.getRoleMembersFromApplicationRole(role.getNamespaceCode(), role.getName(), qualification);
787 if ( !roleMembers.isEmpty() ) {
788 matchingRoleIds.add( roleId );
789 }
790 for ( RoleMembership rm : roleMembers ) {
791 RoleMembership.Builder builder = RoleMembership.Builder.create(rm);
792 builder.setRoleId(roleId);
793 builder.setRoleMemberId("*");
794 results.add(builder.build());
795 }
796 }
797 } catch (Exception ex) {
798 LOG.warn("Not able to retrieve RoleTypeService from remote system for role Id: " + roleId, ex);
799 }
800 }
801
802 if ( followDelegations && !matchingRoleIds.isEmpty() ) {
803 // we have a list of RoleMembershipInfo objects
804 // need to get delegations for distinct list of roles in that list
805 Map<String, DelegateTypeBo> delegationIdToDelegationMap = getStoredDelegationImplMapFromRoleIds(matchingRoleIds);
806 if (!delegationIdToDelegationMap.isEmpty()) {
807 List<RoleMembership.Builder> membershipsWithDelegations =
808 applyDelegationsToRoleMembers(results, delegationIdToDelegationMap.values(), qualification);
809 resolveDelegationMemberRoles(membershipsWithDelegations, qualification, foundRoleTypeMembers);
810 results = ModelObjectUtils.buildImmutableCopy(membershipsWithDelegations);
811 }
812 }
813
814 return Collections.unmodifiableList(results);
815 }
816
817 /**
818 * Checks each of the result records to determine if there are potentially applicable delegation members for that
819 * role membership. If there are, applicable delegations and members will be linked to the RoleMemberships in the
820 * given list. An updated list will be returned from this method which includes the appropriate linked delegations.
821 */
822 protected List<RoleMembership.Builder> applyDelegationsToRoleMembers(List<RoleMembership> roleMemberships,
823 Collection<DelegateTypeBo> delegations, Map<String, String> qualification) {
824 MultiValueMap<String, String> roleIdToRoleMembershipIds = new LinkedMultiValueMap<String, String>();
825 Map<String, RoleMembership.Builder> roleMembershipIdToBuilder = new HashMap<String, RoleMembership.Builder>();
826 List<RoleMembership.Builder> roleMembershipBuilders = new ArrayList<RoleMembership.Builder>();
827 // to make our algorithm less painful, let's do some indexing and load the given list of RoleMemberships into
828 // builders
829 for (RoleMembership roleMembership : roleMemberships) {
830 roleIdToRoleMembershipIds.add(roleMembership.getRoleId(), roleMembership.getRoleMemberId());
831 RoleMembership.Builder builder = RoleMembership.Builder.create(roleMembership);
832 roleMembershipBuilders.add(builder);
833 roleMembershipIdToBuilder.put(roleMembership.getRoleMemberId(), builder);
834 }
835 for (DelegateTypeBo delegation : delegations) {
836 // determine the candidate role memberships where this delegation can be mapped
837 List<String> candidateRoleMembershipIds = roleIdToRoleMembershipIds.get(delegation.getRoleId());
838 if (CollectionUtils.isNotEmpty(candidateRoleMembershipIds)) {
839 DelegationTypeService delegationTypeService = getDelegationTypeService(delegation.getDelegationId());
840 for (DelegateMemberBo delegationMember : delegation.getMembers()) {
841 // Make sure that the delegation member is active
842 if (delegationMember.isActive(DateTime.now()) && (delegationTypeService == null ||
843 delegationTypeService.doesDelegationQualifierMatchQualification(qualification, delegationMember.getQualifier()))) {
844 DelegateMember.Builder delegateMemberBuilder = DelegateMember.Builder.create(delegationMember);
845 // if the member has no role member id, check qualifications and apply to all matching role memberships on the role
846 if (StringUtils.isBlank(delegationMember.getRoleMemberId())) {
847 RoleTypeService roleTypeService = getRoleTypeService(delegation.getRoleId());
848 for (String roleMembershipId : candidateRoleMembershipIds) {
849 RoleMembership.Builder roleMembershipBuilder = roleMembershipIdToBuilder.get(roleMembershipId);
850 if (roleTypeService == null || roleTypeService.doesRoleQualifierMatchQualification(roleMembershipBuilder.getQualifier(), delegationMember.getQualifier())) {
851 linkDelegateToRoleMembership(delegation, delegateMemberBuilder, roleMembershipBuilder);
852 }
853 }
854 } else if (candidateRoleMembershipIds.contains(delegationMember.getRoleMemberId())) {
855 RoleMembership.Builder roleMembershipBuilder = roleMembershipIdToBuilder.get(delegationMember.getRoleMemberId());
856 linkDelegateToRoleMembership(delegation, delegateMemberBuilder, roleMembershipBuilder);
857 }
858 }
859 }
860 }
861 }
862 return roleMembershipBuilders;
863 }
864
865 protected void linkDelegateToRoleMembership(DelegateTypeBo delegation, DelegateMember.Builder delegateMemberBuilder,
866 RoleMembership.Builder roleMembershipBuilder) {
867 DelegateType.Builder delegateBuilder = null;
868 for(DelegateType.Builder existingDelegateBuilder : roleMembershipBuilder.getDelegates()) {
869 if (existingDelegateBuilder.getDelegationId().equals(delegation.getDelegationId())) {
870 delegateBuilder = existingDelegateBuilder;
871 }
872 }
873 if (delegateBuilder == null) {
874 delegateBuilder = DelegateType.Builder.create(delegation);
875 delegateBuilder.setMembers(new ArrayList<DelegateMember.Builder>());
876 roleMembershipBuilder.getDelegates().add(delegateBuilder);
877 }
878 delegateBuilder.getMembers().add(delegateMemberBuilder);
879
880 }
881
882 /**
883 * Once the delegations for a RoleMembershipInfo object have been determined,
884 * any "role" member types need to be resolved into groups and principals so that
885 * further KIM requests are not needed.
886 */
887 protected void resolveDelegationMemberRoles(List<RoleMembership.Builder> membershipBuilders,
888 Map<String, String> qualification, Set<String> foundRoleTypeMembers) {
889 // check delegations assigned to this role
890 for (RoleMembership.Builder roleMembership : membershipBuilders) {
891 // the applicable delegation IDs will already be set in the RoleMembership.Builder
892 // this code examines those delegations and obtains the member groups and principals
893 for (DelegateType.Builder delegation : roleMembership.getDelegates()) {
894 List<DelegateMember.Builder> newMembers = new ArrayList<DelegateMember.Builder>();
895 for (DelegateMember.Builder member : delegation.getMembers()) {
896 if (MemberType.ROLE.equals(member.getType())) {
897 // loop over delegation roles and extract the role IDs where the qualifications match
898 Collection<RoleMembership> delegateMembers = getRoleMembers(Collections.singletonList(
899 member.getMemberId()), qualification, false, foundRoleTypeMembers);
900 // loop over the role members and create the needed DelegationMember builders
901 for (RoleMembership rmi : delegateMembers) {
902 DelegateMember.Builder delegateMember = DelegateMember.Builder.create(member);
903 delegateMember.setMemberId(rmi.getMemberId());
904 delegateMember.setType(rmi.getMemberType());
905 newMembers.add(delegateMember);
906 }
907 } else {
908 newMembers.add(member);
909 }
910 }
911 delegation.setMembers(newMembers);
912 }
913 }
914 }
915
916 protected boolean principalHasRole(String principalId, List<String> roleIds, Map<String, String> qualification, boolean checkDelegations) {
917 if (StringUtils.isBlank(principalId)) {
918 return false;
919 }
920 Set<String> allRoleIds = new HashSet<String>();
921 // remove inactive roles
922 for (String roleId : roleIds) {
923 if (isRoleActive(roleId)) {
924 allRoleIds.add(roleId);
925 }
926 }
927 // short-circuit if no roles match
928 if (allRoleIds.isEmpty()) {
929 return false;
930 }
931 // for efficiency, retrieve all roles and store in a map
932 Map<String, RoleBo> roles = getRoleBoMap(allRoleIds);
933 // get all roles to which the principal is assigned
934 List<String> copyRoleIds = new ArrayList<String>(allRoleIds);
935 List<RoleMemberBo> rps = new ArrayList<RoleMemberBo>();
936
937 for (String roleId : allRoleIds) {
938 RoleTypeService roleTypeService = getRoleTypeService(roleId);
939 if (roleTypeService != null) {
940 List<String> attributesForExactMatch = roleTypeService.getQualifiersForExactMatch();
941 if (CollectionUtils.isNotEmpty(attributesForExactMatch)) {
942 copyRoleIds.remove(roleId);
943 rps.addAll(getStoredRolePrincipalsForPrincipalIdAndRoleIds(Collections.singletonList(roleId), principalId, populateQualifiersForExactMatch(qualification, attributesForExactMatch)));
944 }
945 }
946 }
947 if (CollectionUtils.isNotEmpty(copyRoleIds)) {
948 rps.addAll(getStoredRolePrincipalsForPrincipalIdAndRoleIds(copyRoleIds, principalId, null));
949 }
950
951 // if the qualification is null and the role list is not, then any role in the list will match
952 // so since the role ID list is not blank, we can return true at this point
953 if ((qualification == null || qualification.isEmpty()) && !rps.isEmpty()) {
954 return true;
955 }
956
957 // check each membership to see if the principal matches
958
959 // build a map of role ID to membership information
960 // this will be used for later qualification checks
961 Map<String, List<RoleMembership>> roleIdToMembershipMap = new HashMap<String, List<RoleMembership>>();
962 if (getRoleIdToMembershipMap(roleIdToMembershipMap, rps)) {
963 return true;
964 }
965
966 // perform the checks against the role type services
967 for (Map.Entry<String, List<RoleMembership>> entry : roleIdToMembershipMap.entrySet()) {
968 try {
969 RoleTypeService roleTypeService = getRoleTypeService(entry.getKey());
970 if (!roleTypeService.getMatchingRoleMemberships(qualification, entry.getValue()).isEmpty()) {
971 return true;
972 }
973 } catch (Exception ex) {
974 LOG.warn("Unable to find role type service with id: " + entry.getKey());
975 }
976 }
977
978 // find the groups that the principal belongs to
979 List<String> principalGroupIds = getGroupService().getGroupIdsByPrincipalId(principalId);
980 // find the role/group associations
981 if (!principalGroupIds.isEmpty()) {
982 List<RoleMemberBo> rgs = getStoredRoleGroupsUsingExactMatchOnQualification(principalGroupIds, allRoleIds, qualification);
983 roleIdToMembershipMap.clear(); // clear the role/member map for further use
984 if (getRoleIdToMembershipMap(roleIdToMembershipMap, rgs)) {
985 return true;
986 }
987
988 // perform the checks against the role type services
989 for (Map.Entry<String, List<RoleMembership>> entry : roleIdToMembershipMap.entrySet()) {
990 try {
991 RoleTypeService roleTypeService = getRoleTypeService(entry.getKey());
992 if (!roleTypeService.getMatchingRoleMemberships(qualification, entry.getValue()).isEmpty()) {
993 return true;
994 }
995 } catch (Exception ex) {
996 LOG.warn("Unable to find role type service with id: " + entry.getKey(), ex);
997 }
998 }
999 }
1000
1001 // check member roles
1002 // first, check that the qualifiers on the role membership match
1003 // then, perform a principalHasRole on the embedded role
1004 List<RoleMemberBo> roleMemberBos = getStoredRoleMembersForRoleIds(roleIds, MemberType.ROLE.getCode(), null);
1005 for (RoleMemberBo roleMemberBo : roleMemberBos) {
1006 RoleTypeService roleTypeService = getRoleTypeService(roleMemberBo.getRoleId());
1007 if (roleTypeService != null) {
1008 //it is possible that the the roleTypeService is coming from a remote application
1009 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility.
1010 try {
1011 if (roleTypeService.doesRoleQualifierMatchQualification(qualification, roleMemberBo.getAttributes())) {
1012 RoleBo memberRole = getRoleBo(roleMemberBo.getMemberId());
1013 Map<String, String> nestedRoleQualification = roleTypeService.convertQualificationForMemberRoles(
1014 roles.get(roleMemberBo.getRoleId()).getNamespaceCode(),
1015 roles.get(roleMemberBo.getRoleId()).getName(),
1016 memberRole.getNamespaceCode(),
1017 memberRole.getName(),
1018 qualification);
1019 ArrayList<String> roleIdTempList = new ArrayList<String>(1);
1020 roleIdTempList.add(roleMemberBo.getMemberId());
1021 if (principalHasRole(principalId, roleIdTempList, nestedRoleQualification, true)) {
1022 return true;
1023 }
1024 }
1025 } catch (Exception ex) {
1026 LOG.warn("Not able to retrieve RoleTypeService from remote system for role Id: " + roleMemberBo.getRoleId(), ex);
1027 //return false;
1028 }
1029 } else {
1030 // no qualifiers - role is always used - check membership
1031 ArrayList<String> roleIdTempList = new ArrayList<String>(1);
1032 roleIdTempList.add(roleMemberBo.getMemberId());
1033 // no role type service, so can't convert qualification - just pass as is
1034 if (principalHasRole(principalId, roleIdTempList, qualification, true)) {
1035 return true;
1036 }
1037 }
1038
1039 }
1040
1041
1042 // check for application roles and extract principals and groups from that - then check them against the
1043 // role type service passing in the qualification and principal - the qualifier comes from the
1044 // external system (application)
1045
1046 // loop over the allRoleIds list
1047 for (String roleId : allRoleIds) {
1048 RoleBo role = roles.get(roleId);
1049 RoleTypeService roleTypeService = getRoleTypeService(roleId);
1050 // check if an application role
1051 //it is possible that the the roleTypeService is coming from a remote application
1052 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility.
1053 try {
1054 if (isApplicationRoleType(role.getKimTypeId(), roleTypeService)) {
1055 if (roleTypeService.hasApplicationRole(principalId, principalGroupIds, role.getNamespaceCode(), role.getName(), qualification)) {
1056 return true;
1057 }
1058 }
1059 } catch (Exception ex) {
1060 LOG.warn("Not able to retrieve RoleTypeService from remote system for role Id: " + roleId, ex);
1061 //return false;
1062 }
1063 }
1064
1065 // delegations
1066 if (checkDelegations) {
1067 if (matchesOnDelegation(allRoleIds, principalId, principalGroupIds, qualification)) {
1068 return true;
1069 }
1070 }
1071
1072 // NOTE: this logic is a little different from the getRoleMembers method
1073 // If there is no primary (matching non-delegate), this method will still return true
1074 return false;
1075 }
1076
1077
1078 protected boolean isApplicationRoleType(String roleTypeId, RoleTypeService service) {
1079 return service != null && service.isApplicationRoleType();
1080 }
1081
1082 /**
1083 * Support method for principalHasRole. Checks delegations on the passed in roles for the given principal and groups. (It's assumed that the principal
1084 * belongs to the given groups.)
1085 * <p/>
1086 * Delegation checks are mostly the same as role checks except that the delegateBo itself is qualified against the original role (like a RolePrincipal
1087 * or RoleGroup.) And then, the members of that delegateBo may have additional qualifiers which are not part of the original role qualifiers.
1088 * <p/>
1089 * For example:
1090 * <p/>
1091 * 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
1092 * 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
1093 * when it is attached to the role.
1094 * <p/>
1095 * The principals then attached to that delegateBo (which is specific to the organization), may have additional qualifiers.
1096 * For Example: dollar amount range, effective dates, document types.
1097 * As a subsequent step, those qualifiers are checked against the qualification passed in from the client.
1098 */
1099 protected boolean matchesOnDelegation(Set<String> allRoleIds, String principalId, List<String> principalGroupIds, Map<String, String> qualification) {
1100 // get the list of delegations for the roles
1101 Map<String, DelegateTypeBo> delegations = getStoredDelegationImplMapFromRoleIds(allRoleIds);
1102 // loop over the delegations - determine those which need to be inspected more directly
1103 for (DelegateTypeBo delegation : delegations.values()) {
1104 // check if each one matches via the original role type service
1105 if (!delegation.isActive()) {
1106 continue;
1107 }
1108 RoleTypeService roleTypeService = getRoleTypeService(delegation.getRoleId());
1109 for (DelegateMemberBo delegateMemberBo : delegation.getMembers()) {
1110 if (!delegateMemberBo.isActive(new Timestamp(new Date().getTime()))) {
1111 continue;
1112 }
1113 // check if this delegateBo record applies to the given person
1114 if (MemberType.PRINCIPAL.equals(delegateMemberBo.getType())
1115 && !delegateMemberBo.getMemberId().equals(principalId)) {
1116 continue; // no match on principal
1117 }
1118 // or if a group
1119 if (MemberType.GROUP.equals(delegateMemberBo.getType())
1120 && !principalGroupIds.contains(delegateMemberBo.getMemberId())) {
1121 continue; // no match on group
1122 }
1123 // or if a role
1124 if (MemberType.ROLE.equals(delegateMemberBo.getType())
1125 && !principalHasRole(principalId, Collections.singletonList(delegateMemberBo.getMemberId()), qualification, false)) {
1126 continue; // no match on role
1127 }
1128 // OK, the member matches the current user, now check the qualifications
1129
1130 // NOTE: this compare is slightly different than the member enumeration
1131 // since the requested qualifier is always being used rather than
1132 // the role qualifier for the member (which is not available)
1133
1134 //it is possible that the the roleTypeService is coming from a remote application
1135 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility.
1136 try {
1137 //TODO: remove reference to Attributes here and use Attributes instead.
1138 if (roleTypeService != null && !roleTypeService.doesRoleQualifierMatchQualification(qualification, delegateMemberBo.getQualifier())) {
1139 continue; // no match - skip to next record
1140 }
1141 } catch (Exception ex) {
1142 LOG.warn("Unable to call doesRoleQualifierMatchQualification on role type service for role Id: " + delegation.getRoleId() + " / " + qualification + " / " + delegateMemberBo.getQualifier(), ex);
1143 continue;
1144 }
1145
1146 // role service matches this qualifier
1147 // now try the delegateBo service
1148 DelegationTypeService delegationTypeService = getDelegationTypeService(delegateMemberBo.getDelegationId());
1149 // QUESTION: does the qualifier map need to be merged with the main delegateBo qualification?
1150 if (delegationTypeService != null && !delegationTypeService.doesDelegationQualifierMatchQualification(qualification, delegateMemberBo.getQualifier())) {
1151 continue; // no match - skip to next record
1152 }
1153 // check if a role member ID is present on the delegateBo record
1154 // if so, check that the original role member would match the given qualifiers
1155 if (StringUtils.isNotBlank(delegateMemberBo.getRoleMemberId())) {
1156 RoleMemberBo rm = getRoleMemberBo(delegateMemberBo.getRoleMemberId());
1157 if (rm != null) {
1158 // check that the original role member's is active and that their
1159 // qualifier would have matched this request's
1160 // qualifications (that the original person would have the permission/responsibility
1161 // for an action)
1162 // this prevents a role-membership based delegateBo from surviving the inactivation/
1163 // changing of the main person's role membership
1164 if (!rm.isActive(new Timestamp(new Date().getTime()))) {
1165 continue;
1166 }
1167 Map<String, String> roleQualifier = rm.getAttributes();
1168 //it is possible that the the roleTypeService is coming from a remote application
1169 // and therefore it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility.
1170 try {
1171 if (roleTypeService != null && !roleTypeService.doesRoleQualifierMatchQualification(qualification, roleQualifier)) {
1172 continue;
1173 }
1174 } catch (Exception ex) {
1175 LOG.warn("Unable to call doesRoleQualifierMatchQualification on role type service for role Id: " + delegation.getRoleId() + " / " + qualification + " / " + roleQualifier, ex);
1176 continue;
1177 }
1178 } else {
1179 LOG.warn("Unknown role member ID cited in the delegateBo member table:");
1180 LOG.warn(" assignedToId: " + delegateMemberBo.getDelegationMemberId() + " / roleMemberId: " + delegateMemberBo.getRoleMemberId());
1181 }
1182 }
1183 // all tests passed, return true
1184 return true;
1185 }
1186 }
1187 return false;
1188 }
1189
1190 /**
1191 * Helper method used by principalHasRole to build the role ID -> list of members map.
1192 *
1193 * @return <b>true</b> if no further checks are needed because no role service is defined
1194 */
1195 protected boolean getRoleIdToMembershipMap(Map<String, List<RoleMembership>> roleIdToMembershipMap, List<RoleMemberBo> roleMembers) {
1196 for (RoleMemberBo roleMemberBo : roleMembers) {
1197 RoleMembership roleMembership = RoleMembership.Builder.create(
1198 roleMemberBo.getRoleId(),
1199 roleMemberBo.getRoleMemberId(),
1200 roleMemberBo.getMemberId(),
1201 roleMemberBo.getMemberType(),
1202 roleMemberBo.getAttributes()).build();
1203
1204 // if the role type service is null, assume that all qualifiers match
1205 if (getRoleTypeService(roleMemberBo.getRoleId()) == null) {
1206 return true;
1207 }
1208 List<RoleMembership> lrmi = roleIdToMembershipMap.get(roleMembership.getRoleId());
1209 if (lrmi == null) {
1210 lrmi = new ArrayList<RoleMembership>();
1211 roleIdToMembershipMap.put(roleMembership.getRoleId(), lrmi);
1212 }
1213 lrmi.add(roleMembership);
1214 }
1215 return false;
1216 }
1217
1218 /**
1219 * Retrieves a KimDelegationImpl object by its ID. If the delegateBo already exists in the cache, this method will return the cached
1220 * version; otherwise, it will retrieve the uncached version from the database and then cache it before returning it.
1221 */
1222 protected DelegateTypeBo getKimDelegationImpl(String delegationId) {
1223 if (StringUtils.isBlank(delegationId)) {
1224 return null;
1225 }
1226
1227 return getBusinessObjectService().findByPrimaryKey(DelegateTypeBo.class,
1228 Collections.singletonMap(KimConstants.PrimaryKeyConstants.DELEGATION_ID, delegationId));
1229 }
1230
1231 protected DelegationTypeService getDelegationTypeService(String delegationId) {
1232 DelegationTypeService service = null;
1233 DelegateTypeBo delegateBo = getKimDelegationImpl(delegationId);
1234 KimType delegationType = KimApiServiceLocator.getKimTypeInfoService().getKimType(delegateBo.getKimTypeId());
1235 if (delegationType != null) {
1236 KimTypeService tempService = KimFrameworkServiceLocator.getKimTypeService(delegationType);
1237 if (tempService != null && tempService instanceof DelegationTypeService) {
1238 service = (DelegationTypeService) tempService;
1239 } else {
1240 LOG.error("Service returned for type " + delegationType + "(" + delegationType.getName() + ") was not a DelegationTypeService. Was a " + (tempService != null ? tempService.getClass() : "(null)"));
1241 }
1242 } else { // delegateBo has no type - default to role type if possible
1243 RoleTypeService roleTypeService = getRoleTypeService(delegateBo.getRoleId());
1244 if (roleTypeService != null && roleTypeService instanceof DelegationTypeService) {
1245 service = (DelegationTypeService) roleTypeService;
1246 }
1247 }
1248 return service;
1249 }
1250
1251 protected Collection<RoleMembership> getNestedRoleMembers(Map<String, String> qualification, RoleMembership rm, Set<String> foundRoleTypeMembers) {
1252 // If this role has already been traversed, skip it
1253 if (foundRoleTypeMembers.contains(rm.getMemberId())) {
1254 return new ArrayList<RoleMembership>(); // return an empty list
1255 }
1256 foundRoleTypeMembers.add(rm.getMemberId());
1257
1258 ArrayList<String> roleIdList = new ArrayList<String>(1);
1259 roleIdList.add(rm.getMemberId());
1260
1261 // get the list of members from the nested role - ignore delegations on those sub-roles
1262 Collection<RoleMembership> currentNestedRoleMembers = getRoleMembers(roleIdList, qualification, false, foundRoleTypeMembers);
1263
1264 // add the roles whose members matched to the list for delegateBo checks later
1265 Collection<RoleMembership> returnRoleMembers = new ArrayList<RoleMembership>();
1266 for (RoleMembership roleMembership : currentNestedRoleMembers) {
1267 RoleMembership.Builder rmBuilder = RoleMembership.Builder.create(roleMembership);
1268
1269 // use the member ID of the parent role (needed for responsibility joining)
1270 rmBuilder.setRoleMemberId(rm.getRoleMemberId());
1271 // store the role ID, so we know where this member actually came from
1272 rmBuilder.setRoleId(rm.getRoleId());
1273 rmBuilder.setEmbeddedRoleId(rm.getMemberId());
1274 returnRoleMembers.add(rmBuilder.build());
1275 }
1276 return returnRoleMembers;
1277 }
1278
1279 /**
1280 * Retrieves a KimDelegationMemberImpl object by its ID and the ID of the delegation it belongs to. If the delegation member exists in the cache,
1281 * this method will return the cached one; otherwise, it will retrieve the uncached version from the database and then cache it before returning it.
1282 */
1283 protected DelegateMemberBo getKimDelegationMemberImplByDelegationAndId(String delegationId, String delegationMemberId) {
1284 if (StringUtils.isBlank(delegationId) || StringUtils.isBlank(delegationMemberId)) {
1285 return null;
1286 }
1287
1288 Map<String, String> searchCriteria = new HashMap<String, String>();
1289 searchCriteria.put(KimConstants.PrimaryKeyConstants.DELEGATION_ID, delegationId);
1290 searchCriteria.put(KimConstants.PrimaryKeyConstants.DELEGATION_MEMBER_ID, delegationMemberId);
1291 List<DelegateMemberBo> memberList =
1292 (List<DelegateMemberBo>) getBusinessObjectService().findMatching(DelegateMemberBo.class, searchCriteria);
1293 if (memberList != null && !memberList.isEmpty()) {
1294 return memberList.get(0);
1295 }
1296 return null;
1297 }
1298
1299 private List<RoleMemberBo> getStoredRoleMembersUsingExactMatchOnQualification(String principalId, List<String> groupIds, List<String> roleIds, Map<String, String> qualification) {
1300 List<String> copyRoleIds = new ArrayList<String>(roleIds);
1301 List<RoleMemberBo> roleMemberBoList = new ArrayList<RoleMemberBo>();
1302
1303 for (String roleId : roleIds) {
1304 RoleTypeService roleTypeService = getRoleTypeService(roleId);
1305 if (roleTypeService != null) {
1306 List<String> attributesForExactMatch = roleTypeService.getQualifiersForExactMatch();
1307 if (CollectionUtils.isNotEmpty(attributesForExactMatch)) {
1308 copyRoleIds.remove(roleId);
1309 roleMemberBoList.addAll(getStoredRoleMembersForRoleIdsWithFilters(Collections.singletonList(roleId), principalId, groupIds, populateQualifiersForExactMatch(qualification, attributesForExactMatch)));
1310 }
1311 }
1312 }
1313 if (CollectionUtils.isNotEmpty(copyRoleIds)) {
1314 roleMemberBoList.addAll(getStoredRoleMembersForRoleIdsWithFilters(copyRoleIds, principalId, groupIds, null));
1315 }
1316 return roleMemberBoList;
1317 }
1318
1319 private List<RoleMemberBo> getStoredRoleGroupsUsingExactMatchOnQualification(List<String> groupIds, Set<String> roleIds, Map<String, String> qualification) {
1320 List<String> copyRoleIds = new ArrayList<String>(roleIds);
1321 List<RoleMemberBo> roleMemberBos = new ArrayList<RoleMemberBo>();
1322
1323 for (String roleId : roleIds) {
1324 RoleTypeService roleTypeService = getRoleTypeService(roleId);
1325 if (roleTypeService != null) {
1326 List<String> attributesForExactMatch = roleTypeService.getQualifiersForExactMatch();
1327 if (CollectionUtils.isNotEmpty(attributesForExactMatch)) {
1328 copyRoleIds.remove(roleId);
1329 roleMemberBos.addAll(getStoredRoleGroupsForGroupIdsAndRoleIds(Collections.singletonList(roleId), groupIds, populateQualifiersForExactMatch(qualification, attributesForExactMatch)));
1330 }
1331 }
1332 }
1333 if (CollectionUtils.isNotEmpty(copyRoleIds)) {
1334 roleMemberBos.addAll(getStoredRoleGroupsForGroupIdsAndRoleIds(copyRoleIds, groupIds, null));
1335 }
1336 return roleMemberBos;
1337 }
1338
1339 private List<DelegateMember> getDelegateMembersForDelegation(DelegateTypeBo delegateBo) {
1340 if (delegateBo == null || delegateBo.getMembers() == null) {return null;}
1341 List<DelegateMember> delegateMembersReturnList = new ArrayList<DelegateMember>();
1342 for (DelegateMemberBo delegateMemberBo : delegateBo.getMembers()) {
1343 //FIXME: What is up with this!?!
1344 DelegateMember delegateMember = getDelegateCompleteInfo(delegateBo, delegateMemberBo);
1345
1346 delegateMembersReturnList.add(DelegateMemberBo.to(delegateMemberBo));
1347 }
1348 return Collections.unmodifiableList(delegateMembersReturnList);
1349 }
1350
1351 private DelegateMember getDelegateCompleteInfo(DelegateTypeBo delegateBo, DelegateMemberBo delegateMemberBo) {
1352 if (delegateBo == null || delegateMemberBo == null) {return null;}
1353
1354 DelegateMember.Builder delegateMemberBuilder = DelegateMember.Builder.create(delegateMemberBo);
1355 delegateMemberBuilder.setType(delegateMemberBo.getType());
1356 return delegateMemberBuilder.build();
1357 }
1358
1359 @Override
1360 public void assignPrincipalToRole(String principalId,
1361 String namespaceCode, String roleName, Map<String, String> qualifier) throws RiceIllegalStateException {
1362 incomingParamCheck(principalId, "principalId");
1363 incomingParamCheck(namespaceCode, "namespaceCode");
1364 incomingParamCheck(roleName, "roleName");
1365 incomingParamCheck(qualifier, "qualifier");
1366
1367 // look up the role
1368 RoleBo role = getRoleBoByName(namespaceCode, roleName);
1369 role.refreshReferenceObject("members");
1370
1371 // check that identical member does not already exist
1372 if ( doAnyMemberRecordsMatchByExactQualifier(role, principalId, memberTypeToRoleDaoActionMap.get(MemberType.PRINCIPAL.getCode()), qualifier) ||
1373 doAnyMemberRecordsMatch( role.getMembers(), principalId, MemberType.PRINCIPAL.getCode(), qualifier ) ) {
1374 return;
1375 }
1376 // create the new role member object
1377 RoleMemberBo newRoleMember = new RoleMemberBo();
1378
1379 newRoleMember.setRoleId(role.getId());
1380 newRoleMember.setMemberId(principalId);
1381 newRoleMember.setMemberType(MemberType.PRINCIPAL);
1382
1383 // build role member attribute objects from the given Map<String, String>
1384 addMemberAttributeData(newRoleMember, qualifier, role.getKimTypeId());
1385
1386 // add row to member table
1387 // When members are added to roles, clients must be notified.
1388 getResponsibilityInternalService().saveRoleMember(newRoleMember);
1389 }
1390
1391 @Override
1392 public void assignGroupToRole(String groupId, String namespaceCode,
1393 String roleName, Map<String, String> qualifier) throws RiceIllegalStateException {
1394 incomingParamCheck(groupId, "groupId");
1395 incomingParamCheck(namespaceCode, "namespaceCode");
1396 incomingParamCheck(roleName, "roleName");
1397 incomingParamCheck(qualifier, "qualifier");
1398
1399 // look up the role
1400 RoleBo role = getRoleBoByName(namespaceCode, roleName);
1401 // check that identical member does not already exist
1402 if ( doAnyMemberRecordsMatchByExactQualifier(role, groupId, memberTypeToRoleDaoActionMap.get(MemberType.GROUP.getCode()), qualifier) ||
1403 doAnyMemberRecordsMatch( role.getMembers(), groupId, MemberType.GROUP.getCode(), qualifier ) ) {
1404 return;
1405 }
1406 // create the new role member object
1407 RoleMemberBo newRoleMember = new RoleMemberBo();
1408 newRoleMember.setRoleId(role.getId());
1409 newRoleMember.setMemberId(groupId);
1410 newRoleMember.setMemberType(MemberType.GROUP);
1411
1412 // build role member attribute objects from the given Map<String, String>
1413 addMemberAttributeData(newRoleMember, qualifier, role.getKimTypeId());
1414
1415 // When members are added to roles, clients must be notified.
1416 getResponsibilityInternalService().saveRoleMember(newRoleMember);
1417 }
1418
1419 @Override
1420 public void assignRoleToRole(String roleId,
1421 String namespaceCode, String roleName, Map<String, String> qualifier) throws RiceIllegalStateException {
1422 incomingParamCheck(roleId, "roleId");
1423 incomingParamCheck(namespaceCode, "namespaceCode");
1424 incomingParamCheck(roleName, "roleName");
1425 incomingParamCheck(qualifier, "qualifier");
1426
1427 // look up the roleBo
1428 RoleBo roleBo = getRoleBoByName(namespaceCode, roleName);
1429 // check that identical member does not already exist
1430 if ( doAnyMemberRecordsMatchByExactQualifier(roleBo, roleId, memberTypeToRoleDaoActionMap.get(MemberType.ROLE.getCode()), qualifier) ||
1431 doAnyMemberRecordsMatch( roleBo.getMembers(), roleId, MemberType.ROLE.getCode(), qualifier ) ) {
1432 return;
1433 }
1434 // Check to make sure this doesn't create a circular membership
1435 if (!checkForCircularRoleMembership(roleId, roleBo)) {
1436 throw new IllegalArgumentException("Circular roleBo reference.");
1437 }
1438 // create the new roleBo member object
1439 RoleMemberBo newRoleMember = new RoleMemberBo();
1440 newRoleMember.setRoleId(roleBo.getId());
1441 newRoleMember.setMemberId(roleId);
1442 newRoleMember.setMemberType(MemberType.ROLE);
1443 // build roleBo member attribute objects from the given Map<String, String>
1444 addMemberAttributeData(newRoleMember, qualifier, roleBo.getKimTypeId());
1445
1446 // When members are added to roles, clients must be notified.
1447 getResponsibilityInternalService().saveRoleMember(newRoleMember);
1448 }
1449
1450 @Override
1451 public RoleMember createRoleMember(RoleMember roleMember) throws RiceIllegalStateException {
1452 incomingParamCheck(roleMember, "roleMember");
1453
1454 if (StringUtils.isNotBlank(roleMember.getRoleMemberId()) && getRoleMemberBo(roleMember.getRoleMemberId()) != null) {
1455 throw new RiceIllegalStateException("the roleMember to create already exists: " + roleMember);
1456 }
1457
1458 String kimTypeId = getRoleBo(roleMember.getRoleId()).getKimTypeId();
1459 List<RoleMemberAttributeDataBo> attrBos = Collections.emptyList();
1460 attrBos = KimAttributeDataBo.createFrom(RoleMemberAttributeDataBo.class, roleMember.getAttributes(), kimTypeId);
1461
1462 RoleMemberBo bo = RoleMemberBo.from(roleMember);
1463 bo.setAttributeDetails(attrBos);
1464 return RoleMemberBo.to(getResponsibilityInternalService().saveRoleMember(bo));
1465 }
1466
1467 @Override
1468 public RoleMember updateRoleMember(@WebParam(
1469 name = "roleMember") RoleMember roleMember) throws RiceIllegalArgumentException, RiceIllegalStateException {
1470 incomingParamCheck(roleMember, "roleMember");
1471
1472 if (StringUtils.isBlank(roleMember.getRoleMemberId()) || getRoleMemberBo(roleMember.getRoleMemberId()) == null) {
1473 throw new RiceIllegalStateException("the roleMember to update does not exists: " + roleMember);
1474 }
1475
1476 String kimTypeId = getRoleBo(roleMember.getRoleId()).getKimTypeId();
1477 List<RoleMemberAttributeDataBo> attrBos = Collections.emptyList();
1478 attrBos = KimAttributeDataBo.createFrom(RoleMemberAttributeDataBo.class, roleMember.getAttributes(), kimTypeId);
1479
1480 RoleMemberBo bo = RoleMemberBo.from(roleMember);
1481 bo.setAttributeDetails(attrBos);
1482 return RoleMemberBo.to(getResponsibilityInternalService().saveRoleMember(bo));
1483 }
1484
1485 @Override
1486 public RoleResponsibilityAction createRoleResponsibilityAction(RoleResponsibilityAction roleResponsibilityAction)
1487 throws RiceIllegalArgumentException, RiceIllegalStateException {
1488 incomingParamCheck(roleResponsibilityAction, "roleResponsibilityAction");
1489
1490
1491 if (StringUtils.isNotBlank(roleResponsibilityAction.getId())
1492 && getBusinessObjectService().findByPrimaryKey
1493 (RoleResponsibilityActionBo.class, Collections.singletonMap("id", roleResponsibilityAction.getId())) != null) {
1494 throw new RiceIllegalStateException("the roleResponsibilityAction to create already exists: " + roleResponsibilityAction);
1495 }
1496
1497 RoleResponsibilityActionBo bo = RoleResponsibilityActionBo.from(roleResponsibilityAction);
1498 return RoleResponsibilityActionBo.to(getBusinessObjectService().save(bo));
1499 }
1500
1501 @Override
1502 public DelegateType createDelegateType(DelegateType delegateType) throws RiceIllegalStateException {
1503 incomingParamCheck(delegateType, "delegateType");
1504
1505 if (StringUtils.isNotBlank(delegateType.getDelegationId())
1506 && getDelegateTypeByDelegationId(delegateType.getDelegationId()) != null) {
1507 throw new RiceIllegalStateException("the delegateType to create already exists: " + delegateType);
1508 }
1509
1510 DelegateTypeBo bo = DelegateTypeBo.from(delegateType);
1511 return DelegateTypeBo.to(getBusinessObjectService().save(bo));
1512 // look up the role
1513 /*RoleBo role = getRoleBo(delegationType.getRoleId());
1514 DelegateTypeBo delegation = getDelegationOfType(role.getId(), delegationType.getDelegationTypeCode());
1515 // create the new role member object
1516 DelegateMemberBo newDelegationMember = new DelegateMemberBo();
1517
1518 DelegateMemberBo origDelegationMember;
1519 if(StringUtils.isNotEmpty(delegationMemberId)){
1520 origDelegationMember = getDelegateMemberBo(delegationMemberId);
1521 } else{
1522 List<DelegateMemberBo> origDelegationMembers =
1523 this.getDelegationMemberBoListByMemberAndDelegationId(memberId, delegation.getDelegationId());
1524 origDelegationMember =
1525 (origDelegationMembers!=null && !origDelegationMembers.isEmpty()) ? origDelegationMembers.get(0) : null;
1526 }
1527 if(origDelegationMember!=null){
1528 newDelegationMember.setDelegationMemberId(origDelegationMember.getDelegationMemberId());
1529 newDelegationMember.setVersionNumber(origDelegationMember.getVersionNumber());
1530 }
1531 newDelegationMember.setMemberId(memberId);
1532 newDelegationMember.setDelegationId(delegation.getDelegationId());
1533 newDelegationMember.setRoleMemberId(roleMemberId);
1534 newDelegationMember.setTypeCode(memberTypeCode);
1535 if (activeFromDate != null) {
1536 newDelegationMember.setActiveFromDateValue(new java.sql.Timestamp(activeFromDate.getMillis()));
1537 }
1538 if (activeToDate != null) {
1539 newDelegationMember.setActiveToDateValue(new java.sql.Timestamp(activeToDate.getMillis()));
1540 }
1541
1542 // build role member attribute objects from the given Map<String, String>
1543 addDelegationMemberAttributeData( newDelegationMember, qualifications, role.getKimTypeId() );
1544
1545 List<DelegateMemberBo> delegationMembers = new ArrayList<DelegateMemberBo>();
1546 delegationMembers.add(newDelegationMember);
1547 delegation.setMembers(delegationMembers);
1548
1549 getBusinessObjectService().save(delegation);
1550 for(DelegateMemberBo delegationMember: delegation.getMembers()){
1551 deleteNullDelegationMemberAttributeData(delegationMember.getAttributes());
1552 }*/
1553 }
1554
1555 @Override
1556 public DelegateType updateDelegateType(DelegateType delegateType) throws RiceIllegalStateException {
1557 incomingParamCheck(delegateType, "delegateType");
1558
1559 if (StringUtils.isBlank(delegateType.getDelegationId())
1560 || getDelegateTypeByDelegationId(delegateType.getDelegationId()) == null) {
1561 throw new RiceIllegalStateException("the delegateType to update does not exist: " + delegateType);
1562 }
1563
1564 DelegateTypeBo bo = DelegateTypeBo.from(delegateType);
1565 return DelegateTypeBo.to(getBusinessObjectService().save(bo));
1566 }
1567
1568
1569 private void removeRoleMembers(List<RoleMemberBo> members) {
1570 if(CollectionUtils.isNotEmpty(members)) {
1571 for ( RoleMemberBo rm : members ) {
1572 getResponsibilityInternalService().removeRoleMember(rm);
1573 }
1574 }
1575 }
1576
1577 private List<RoleMemberBo> getRoleMembersByDefaultStrategy(RoleBo role, String memberId, String memberTypeCode, Map<String, String> qualifier) {
1578 List<RoleMemberBo> rms = new ArrayList<RoleMemberBo>();
1579 role.refreshReferenceObject("members");
1580 for ( RoleMemberBo rm : role.getMembers() ) {
1581 if ( doesMemberMatch( rm, memberId, memberTypeCode, qualifier ) ) {
1582 // if found, remove
1583 rms.add(rm);
1584 }
1585 }
1586 return rms;
1587 }
1588
1589 @Override
1590 public void removePrincipalFromRole(String principalId,
1591 String namespaceCode, String roleName, Map<String, String> qualifier) throws RiceIllegalStateException {
1592 if (StringUtils.isBlank(principalId)) {
1593 throw new RiceIllegalArgumentException("principalId is null");
1594 }
1595
1596 if (StringUtils.isBlank(namespaceCode)) {
1597 throw new RiceIllegalArgumentException("namespaceCode is null");
1598 }
1599
1600 if (StringUtils.isBlank(roleName)) {
1601 throw new RiceIllegalArgumentException("roleName is null");
1602 }
1603
1604 if (qualifier == null) {
1605 throw new RiceIllegalArgumentException("qualifier is null");
1606 }
1607
1608 // look up the role
1609 RoleBo role = getRoleBoByName(namespaceCode, roleName);
1610 // pull all the principal members
1611 // look for an exact qualifier match
1612 List<RoleMemberBo> rms = getRoleMembersByExactQualifierMatch(role, principalId, memberTypeToRoleDaoActionMap.get(MemberType.PRINCIPAL.getCode()), qualifier);
1613 if(CollectionUtils.isEmpty(rms)) {
1614 rms = getRoleMembersByDefaultStrategy(role, principalId, MemberType.PRINCIPAL.getCode(), qualifier);
1615 }
1616 removeRoleMembers(rms);
1617 }
1618
1619 @Override
1620 public void removeGroupFromRole(String groupId,
1621 String namespaceCode, String roleName, Map<String, String> qualifier) throws RiceIllegalStateException {
1622 if (StringUtils.isBlank(groupId)) {
1623 throw new RiceIllegalArgumentException("groupId is null");
1624 }
1625
1626 if (StringUtils.isBlank(namespaceCode)) {
1627 throw new RiceIllegalArgumentException("namespaceCode is null");
1628 }
1629
1630 if (StringUtils.isBlank(roleName)) {
1631 throw new RiceIllegalArgumentException("roleName is null");
1632 }
1633
1634 if (qualifier == null) {
1635 throw new RiceIllegalArgumentException("qualifier is null");
1636 }
1637
1638 // look up the roleBo
1639 RoleBo roleBo = getRoleBoByName(namespaceCode, roleName);
1640 // pull all the group roleBo members
1641 // look for an exact qualifier match
1642 List<RoleMemberBo> rms = getRoleMembersByExactQualifierMatch(roleBo, groupId, memberTypeToRoleDaoActionMap.get(MemberType.GROUP.getCode()), qualifier);
1643 if(CollectionUtils.isEmpty(rms)) {
1644 rms = getRoleMembersByDefaultStrategy(roleBo, groupId, MemberType.GROUP.getCode(), qualifier);
1645 }
1646 removeRoleMembers(rms);
1647 }
1648
1649 @Override
1650 public void removeRoleFromRole(String roleId,
1651 String namespaceCode, String roleName, Map<String, String> qualifier) throws RiceIllegalStateException {
1652 incomingParamCheck(roleId, "roleId");
1653 incomingParamCheck(namespaceCode, "namespaceCode");
1654 incomingParamCheck(roleName, "roleName");
1655 incomingParamCheck(qualifier, "qualifier");
1656
1657
1658 // look up the role
1659 RoleBo role = getRoleBoByName(namespaceCode, roleName);
1660 // pull all the group role members
1661 // look for an exact qualifier match
1662 List<RoleMemberBo> rms = getRoleMembersByExactQualifierMatch(role, roleId, memberTypeToRoleDaoActionMap.get(MemberType.ROLE.getCode()), qualifier);
1663 if(CollectionUtils.isEmpty(rms)) {
1664 rms = getRoleMembersByDefaultStrategy(role, roleId, MemberType.ROLE.getCode(), qualifier);
1665 }
1666 removeRoleMembers(rms);
1667 }
1668
1669 @Override
1670 public void assignPermissionToRole(String permissionId, String roleId) throws RiceIllegalStateException {
1671 incomingParamCheck(permissionId, "permissionId");
1672 incomingParamCheck(roleId, "roleId");
1673
1674 RolePermissionBo newRolePermission = new RolePermissionBo();
1675
1676 Long nextSeq = KRADServiceLocator.getSequenceAccessorService().getNextAvailableSequenceNumber(KimConstants.SequenceNames.KRIM_ROLE_PERM_ID_S, RolePermissionBo.class);
1677
1678 if (nextSeq == null) {
1679 LOG.error("Unable to get new role permission id from sequence " + KimConstants.SequenceNames.KRIM_ROLE_PERM_ID_S);
1680 throw new RuntimeException("Unable to get new role permission id from sequence " + KimConstants.SequenceNames.KRIM_ROLE_PERM_ID_S);
1681 }
1682
1683 newRolePermission.setId(nextSeq.toString());
1684 newRolePermission.setRoleId(roleId);
1685 newRolePermission.setPermissionId(permissionId);
1686 newRolePermission.setActive(true);
1687
1688 getBusinessObjectService().save(newRolePermission);
1689 }
1690
1691 protected void addMemberAttributeData(RoleMemberBo roleMember, Map<String, String> qualifier, String kimTypeId) {
1692 List<RoleMemberAttributeDataBo> attributes = new ArrayList<RoleMemberAttributeDataBo>();
1693 for (Map.Entry<String, String> entry : qualifier.entrySet()) {
1694 RoleMemberAttributeDataBo roleMemberAttrBo = new RoleMemberAttributeDataBo();
1695 roleMemberAttrBo.setAttributeValue(entry.getValue());
1696 roleMemberAttrBo.setKimTypeId(kimTypeId);
1697 roleMemberAttrBo.setAssignedToId(roleMember.getRoleMemberId());
1698 // look up the attribute ID
1699 roleMemberAttrBo.setKimAttributeId(getKimAttributeId(entry.getKey()));
1700
1701 Map<String, String> criteria = new HashMap<String, String>();
1702 criteria.put(KimConstants.PrimaryKeyConstants.KIM_ATTRIBUTE_ID, roleMemberAttrBo.getKimAttributeId());
1703 criteria.put(KimConstants.PrimaryKeyConstants.ROLE_MEMBER_ID, roleMember.getRoleMemberId());
1704 List<RoleMemberAttributeDataBo> origRoleMemberAttributes =
1705 (List<RoleMemberAttributeDataBo>) getBusinessObjectService().findMatching(RoleMemberAttributeDataBo.class, criteria);
1706 RoleMemberAttributeDataBo origRoleMemberAttribute =
1707 (origRoleMemberAttributes != null && !origRoleMemberAttributes.isEmpty()) ? origRoleMemberAttributes.get(0) : null;
1708 if (origRoleMemberAttribute != null) {
1709 roleMemberAttrBo.setId(origRoleMemberAttribute.getId());
1710 roleMemberAttrBo.setVersionNumber(origRoleMemberAttribute.getVersionNumber());
1711 }
1712 attributes.add(roleMemberAttrBo);
1713 }
1714 roleMember.setAttributeDetails(attributes);
1715 }
1716
1717 protected void addDelegationMemberAttributeData( DelegateMemberBo delegationMember, Map<String, String> qualifier, String kimTypeId ) {
1718 List<DelegateMemberAttributeDataBo> attributes = new ArrayList<DelegateMemberAttributeDataBo>();
1719 for ( Map.Entry<String, String> entry : qualifier.entrySet() ) {
1720 DelegateMemberAttributeDataBo delegateMemberAttrBo = new DelegateMemberAttributeDataBo();
1721 delegateMemberAttrBo.setAttributeValue(entry.getValue());
1722 delegateMemberAttrBo.setKimTypeId(kimTypeId);
1723 delegateMemberAttrBo.setAssignedToId(delegationMember.getDelegationMemberId());
1724 // look up the attribute ID
1725 delegateMemberAttrBo.setKimAttributeId(getKimAttributeId(entry.getKey()));
1726 Map<String, String> criteria = new HashMap<String, String>();
1727 criteria.put(KimConstants.PrimaryKeyConstants.KIM_ATTRIBUTE_ID, delegateMemberAttrBo.getKimAttributeId());
1728 criteria.put(KimConstants.PrimaryKeyConstants.DELEGATION_MEMBER_ID, delegationMember.getDelegationMemberId());
1729 List<DelegateMemberAttributeDataBo> origDelegationMemberAttributes =
1730 (List<DelegateMemberAttributeDataBo>)getBusinessObjectService().findMatching(DelegateMemberAttributeDataBo.class, criteria);
1731 DelegateMemberAttributeDataBo origDelegationMemberAttribute =
1732 (origDelegationMemberAttributes!=null && !origDelegationMemberAttributes.isEmpty()) ? origDelegationMemberAttributes.get(0) : null;
1733 if(origDelegationMemberAttribute!=null){
1734 delegateMemberAttrBo.setId(origDelegationMemberAttribute.getId());
1735 delegateMemberAttrBo.setVersionNumber(origDelegationMemberAttribute.getVersionNumber());
1736 }
1737 attributes.add( delegateMemberAttrBo );
1738 }
1739 delegationMember.setAttributes( attributes );
1740 }
1741
1742
1743
1744 // --------------------
1745 // Persistence Methods
1746 // --------------------
1747
1748 private void deleteNullMemberAttributeData(List<RoleMemberAttributeDataBo> attributes) {
1749 List<RoleMemberAttributeDataBo> attributesToDelete = new ArrayList<RoleMemberAttributeDataBo>();
1750 for(RoleMemberAttributeDataBo attribute: attributes){
1751 if(attribute.getAttributeValue()==null){
1752 attributesToDelete.add(attribute);
1753 }
1754 }
1755 getBusinessObjectService().delete(attributesToDelete);
1756 }
1757
1758 private void deleteNullDelegationMemberAttributeData(List<DelegateMemberAttributeDataBo> attributes) {
1759 List<DelegateMemberAttributeDataBo> attributesToDelete = new ArrayList<DelegateMemberAttributeDataBo>();
1760
1761 for(DelegateMemberAttributeDataBo attribute: attributes){
1762 if(attribute.getAttributeValue()==null){
1763 attributesToDelete.add(attribute);
1764 }
1765 }
1766 getBusinessObjectService().delete(attributesToDelete);
1767 }
1768
1769 private void incomingParamCheck(Object object, String name) {
1770 if (object == null) {
1771 throw new RiceIllegalArgumentException(name + " was null");
1772 } else if (object instanceof String
1773 && StringUtils.isBlank((String) object)) {
1774 throw new RiceIllegalArgumentException(name + " was blank");
1775 }
1776 }
1777 }