Search in sources :

Example 11 with RoleMembership

use of org.kuali.kfs.kim.api.role.RoleMembership in project cu-kfs by CU-CommunityApps.

the class RoleServiceImpl method resolveDelegationMemberRoles.

/**
 * Once the delegations for a RoleMembershipInfo object have been determined, any "role" member types need to be
 * resolved into groups and principals so that further KIM requests are not needed.
 */
protected void resolveDelegationMemberRoles(List<RoleMembership.Builder> membershipBuilders, Map<String, String> qualification, Set<String> foundRoleTypeMembers) {
    // check delegations assigned to this role
    for (RoleMembership.Builder roleMembership : membershipBuilders) {
        // this code examines those delegations and obtains the member groups and principals
        for (DelegateType delegation : roleMembership.getDelegates()) {
            List<DelegateMember> newMembers = new ArrayList<>();
            for (DelegateMember member : delegation.getMembers()) {
                if (MemberType.ROLE.equals(member.getType())) {
                    // loop over delegation roles and extract the role IDs where the qualifications match
                    Collection<RoleMembership> delegateMembers = getRoleMembers(Collections.singletonList(member.getMemberId()), qualification, false, foundRoleTypeMembers);
                    // loop over the role members and create the needed DelegationMember builders
                    for (RoleMembership rmi : delegateMembers) {
                        DelegateMember delegateMember = new DelegateMember();
                        KimCommonUtilsInternal.copyProperties(delegateMember, member);
                        delegateMember.setMemberId(rmi.getMemberId());
                        delegateMember.setType(rmi.getType());
                        newMembers.add(delegateMember);
                    }
                } else {
                    newMembers.add(member);
                }
            }
            delegation.setDelegationMembers(newMembers);
        }
    }
}
Also used : DelegateMember(org.kuali.kfs.kim.impl.common.delegate.DelegateMember) ArrayList(java.util.ArrayList) RoleMembership(org.kuali.kfs.kim.api.role.RoleMembership) DelegateType(org.kuali.kfs.kim.impl.common.delegate.DelegateType)

Example 12 with RoleMembership

use of org.kuali.kfs.kim.api.role.RoleMembership in project cu-kfs by CU-CommunityApps.

the class RoleServiceImpl method getNestedRoleMembers.

protected Collection<RoleMembership> getNestedRoleMembers(Map<String, String> qualification, RoleMembership rm, Set<String> foundRoleTypeMembers) {
    // If this role has already been traversed, skip it
    if (foundRoleTypeMembers.contains(rm.getMemberId())) {
        return new ArrayList<>();
    }
    foundRoleTypeMembers.add(rm.getMemberId());
    ArrayList<String> roleIdList = new ArrayList<>(1);
    roleIdList.add(rm.getMemberId());
    // get the list of members from the nested role - ignore delegations on those sub-roles
    Collection<RoleMembership> currentNestedRoleMembers = getRoleMembers(roleIdList, qualification, false, foundRoleTypeMembers);
    // add the roles whose members matched to the list for delegateType checks later
    Collection<RoleMembership> returnRoleMembers = new ArrayList<>();
    for (RoleMembership roleMembership : currentNestedRoleMembers) {
        RoleMembership.Builder rmBuilder = RoleMembership.Builder.create(roleMembership);
        // use the member ID of the parent role (needed for responsibility joining)
        rmBuilder.setId(rm.getId());
        // store the role ID, so we know where this member actually came from
        rmBuilder.setRoleId(rm.getRoleId());
        rmBuilder.setEmbeddedRoleId(rm.getMemberId());
        returnRoleMembers.add(rmBuilder.build());
    }
    return returnRoleMembers;
}
Also used : ArrayList(java.util.ArrayList) RoleMembership(org.kuali.kfs.kim.api.role.RoleMembership)

Example 13 with RoleMembership

use of org.kuali.kfs.kim.api.role.RoleMembership in project cu-kfs by CU-CommunityApps.

the class RoleServiceImpl method principalHasRole.

protected boolean principalHasRole(Context context, String principalId, List<String> roleIds, Map<String, String> qualification, boolean checkDelegations) {
    /*
         * This method uses a multi-phase approach to determining if the given principal of any of the roles given
         * based on the qualification map that is passed.
         *
         * Phase 1: Check the cache to find if it's already been determined that the principal is a member of any of
         *          the roles with the given ids.
         * Phase 2: Perform exact database-level matching. This can be done for all roles if the given qualification
         *          map is null or empty since that means qualification matching does not need to be performed. It can
         *          also be done for roles who's RoleTypeService defines qualifiers for exact match.
         * Phase 3: Use RoleTypeService matching for roles which have not already been checked. Will need to determine
         *          which role memberships match the given principal then delegate to the appropriate RoleTypeService
         *          to execute matching logic.
         * Phase 4: Check nested roles.
         * Phase 5: For any cases where derived roles are used, determine if the principal is a member of those
         *          derived roles.
         * Phase 6: If checkDelegations is true, check if any delegations match
         */
    try {
        // Phase 1: first check if any of the role membership is cached, only proceed with checking the role ids
        // that aren't already cached
        List<String> roleIdsToCheck = new ArrayList<>(roleIds.size());
        for (String roleId : roleIds) {
            Boolean hasRole = getPrincipalHasRoleFromCache(principalId, roleId, qualification, checkDelegations);
            if (hasRole != null) {
                if (hasRole) {
                    return true;
                }
            } else {
                roleIdsToCheck.add(roleId);
            }
        }
        // load the roles, this will also filter out inactive roles!
        List<RoleLite> roles = loadRoles(roleIdsToCheck);
        // short-circuit if no roles match
        if (roles.isEmpty()) {
            return false;
        }
        // Phase 2: If they didn't pass any qualifications or they are using exact qualifier matching, we can go
        // straight to the database
        Set<String> rolesCheckedForExactMatch = new HashSet<>();
        for (RoleLite role : roles) {
            Map<String, String> qualificationForExactMatch = null;
            if (qualification == null || qualification.isEmpty()) {
                qualificationForExactMatch = new HashMap<>();
            } else {
                RoleTypeService roleTypeService = context.getRoleTypeService(role.getKimTypeId());
                if (roleTypeService != null) {
                    List<String> attributesForExactMatch = getQualifiersForExactMatch(role.getKimTypeId(), roleTypeService);
                    if (CollectionUtils.isNotEmpty(attributesForExactMatch)) {
                        qualificationForExactMatch = populateQualifiersForExactMatch(qualification, attributesForExactMatch);
                        if (qualificationForExactMatch.isEmpty()) {
                            // go onto the next role.
                            continue;
                        }
                    }
                }
            }
            if (qualificationForExactMatch != null) {
                rolesCheckedForExactMatch.add(role.getId());
                List<RoleMember> matchingRoleMembers = getStoredRolePrincipalsForPrincipalIdAndRoleIds(Collections.singletonList(role.getId()), principalId, qualificationForExactMatch);
                // if a role member matched our principal, we're good to go
                if (CollectionUtils.isNotEmpty(matchingRoleMembers)) {
                    return putPrincipalHasRoleInCache(true, principalId, role.getId(), qualification, checkDelegations);
                }
                // now check groups
                if (!context.getPrincipalGroupIds().isEmpty()) {
                    List<RoleMember> matchingRoleGroupMembers = getStoredRoleGroupsUsingExactMatchOnQualification(context.getPrincipalGroupIds(), role.getId(), qualification);
                    if (CollectionUtils.isNotEmpty(matchingRoleGroupMembers)) {
                        return putPrincipalHasRoleInCache(true, principalId, role.getId(), qualification, checkDelegations);
                    }
                }
            // if we drop to this point, either we didn't match or the role has nested or derived role
            // membership, we'll check that later
            }
        }
        for (RoleLite role : roles) {
            // if we didn't do an exact match, we need to do a manual match
            if (!rolesCheckedForExactMatch.contains(role.getId())) {
                List<RoleMember> matchingPrincipalRoleMembers = getRoleMembersForPrincipalId(role.getId(), principalId);
                List<RoleMember> matchingGroupRoleMembers = getRoleMembersForGroupIds(role.getId(), context.getPrincipalGroupIds());
                List<RoleMembership> roleMemberships = convertToRoleMemberships(matchingPrincipalRoleMembers, matchingGroupRoleMembers);
                for (RoleMembership roleMembership : roleMemberships) {
                    try {
                        RoleTypeService roleTypeService = context.getRoleTypeService(role.getKimTypeId());
                        if (!roleTypeService.getMatchingRoleMemberships(qualification, roleMemberships).isEmpty()) {
                            return putPrincipalHasRoleInCache(true, principalId, role.getId(), qualification, checkDelegations);
                        }
                    } catch (Exception ex) {
                        LOG.warn("Unable to find role type service with id: " + role.getKimTypeId());
                    }
                }
            }
        }
        // Phase 4: If we have nested roles, execute a recursive check on those
        // first, check that the qualifiers on the role membership match then, perform a principalHasRole on the
        // embedded role
        Map<String, RoleLite> roleIndex = new HashMap<>();
        for (RoleLite role : roles) {
            roleIndex.put(role.getId(), role);
        }
        List<RoleMember> roleMembers = getStoredRoleMembersForRoleIds(new ArrayList<>(roleIndex.keySet()), MemberType.ROLE.getCode(), null);
        for (RoleMember roleMember : roleMembers) {
            RoleLite role = roleIndex.get(roleMember.getRoleId());
            RoleTypeService roleTypeService = context.getRoleTypeService(role.getKimTypeId());
            if (roleTypeService != null) {
                // it can't be guaranteed that it is up and working, so using a try/catch to catch this possibility.
                try {
                    if (roleTypeService.doesRoleQualifierMatchQualification(qualification, roleMember.getAttributes())) {
                        RoleLite memberRole = getRoleLite(roleMember.getMemberId());
                        Map<String, String> nestedRoleQualification = roleTypeService.convertQualificationForMemberRoles(role.getNamespaceCode(), role.getName(), memberRole.getNamespaceCode(), memberRole.getName(), qualification);
                        if (principalHasRole(context, principalId, Collections.singletonList(roleMember.getMemberId()), nestedRoleQualification, true)) {
                            return putPrincipalHasRoleInCache(true, principalId, role.getId(), qualification, checkDelegations);
                        }
                    }
                } catch (Exception ex) {
                    LOG.warn("Not able to retrieve RoleTypeService from remote system for role Id: " + roleMember.getRoleId(), ex);
                }
            } else {
                // no role type service, so can't convert qualification - just pass as is
                if (principalHasRole(context, principalId, Collections.singletonList(roleMember.getMemberId()), qualification, true)) {
                    return putPrincipalHasRoleInCache(true, principalId, role.getId(), qualification, checkDelegations);
                }
            }
        }
        // external system (application)
        for (RoleLite role : roles) {
            // to catch this possibility.
            try {
                boolean isDerivedRoleType = context.isDerivedRoleType(role.getKimTypeId());
                if (isDerivedRoleType) {
                    RoleTypeService roleTypeService = context.getRoleTypeService(role.getKimTypeId());
                    if (roleTypeService.hasDerivedRole(principalId, context.getPrincipalGroupIds(), role.getNamespaceCode(), role.getName(), qualification)) {
                        if (!roleTypeService.dynamicRoleMembership(role.getNamespaceCode(), role.getName())) {
                            putPrincipalHasRoleInCache(true, principalId, role.getId(), qualification, checkDelegations);
                        }
                        return true;
                    }
                } else {
                    if (!checkDelegations) {
                        putPrincipalHasRoleInCache(false, principalId, role.getId(), qualification, false);
                    }
                }
            } catch (Exception ex) {
                LOG.warn("Not able to retrieve RoleTypeService from remote system for role Id: " + role.getId(), ex);
            }
        }
        if (checkDelegations) {
            if (matchesOnDelegation(roleIndex.keySet(), principalId, context.getPrincipalGroupIds(), qualification, context)) {
                return true;
            }
        }
    } catch (Exception e) {
        LOG.warn("Caught exception during a principalHasRole check", e);
    }
    return false;
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) RoleTypeService(org.kuali.kfs.kim.framework.role.RoleTypeService) RoleMembership(org.kuali.kfs.kim.api.role.RoleMembership) HashSet(java.util.HashSet)

Example 14 with RoleMembership

use of org.kuali.kfs.kim.api.role.RoleMembership in project cu-kfs by CU-CommunityApps.

the class RoleServiceImpl method getRoleMemberPrincipalIds.

// backport redis annotations
@Cacheable(cacheNames = RoleMember.CACHE_NAME, key = "'namespaceCode=' + #p0 + '|' + 'roleName=' + #p1 + '|' + 'qualification=' +" + "T(org.kuali.kfs.core.api.cache.CacheKeyUtils).mapKey(#p2)", condition = "!T(org.kuali.kfs.kim.api.cache.KimCacheUtils).isDynamicMembshipRoleByNamespaceAndName(#p0, #p1)")
@Override
public Collection<String> getRoleMemberPrincipalIds(String namespaceCode, String roleName, Map<String, String> qualification) throws IllegalStateException {
    incomingParamCheck(namespaceCode, "namespaceCode");
    incomingParamCheck(roleName, "roleName");
    Set<String> principalIds = new HashSet<>();
    Set<String> foundRoleTypeMembers = new HashSet<>();
    List<String> roleIds = Collections.singletonList(getRoleIdByNamespaceCodeAndName(namespaceCode, roleName));
    for (RoleMembership roleMembership : getRoleMembers(roleIds, qualification, false, foundRoleTypeMembers)) {
        if (MemberType.GROUP.equals(roleMembership.getType())) {
            principalIds.addAll(getGroupService().getMemberPrincipalIds(roleMembership.getMemberId()));
        } else {
            principalIds.add(roleMembership.getMemberId());
        }
    }
    return Collections.unmodifiableSet(principalIds);
}
Also used : RoleMembership(org.kuali.kfs.kim.api.role.RoleMembership) HashSet(java.util.HashSet) Cacheable(org.springframework.cache.annotation.Cacheable)

Aggregations

RoleMembership (org.kuali.kfs.kim.api.role.RoleMembership)14 ArrayList (java.util.ArrayList)12 HashMap (java.util.HashMap)6 Map (java.util.Map)4 RoleTypeService (org.kuali.kfs.kim.framework.role.RoleTypeService)4 HashSet (java.util.HashSet)3 List (java.util.List)3 DelegateType (org.kuali.kfs.kim.impl.common.delegate.DelegateType)3 LinkedMultiValueMap (org.springframework.util.LinkedMultiValueMap)3 WorkflowException (org.kuali.kfs.kew.api.exception.WorkflowException)2 DelegateMember (org.kuali.kfs.kim.impl.common.delegate.DelegateMember)2 Cacheable (org.springframework.cache.annotation.Cacheable)2 MultiValueMap (org.springframework.util.MultiValueMap)2 SecurityRequestRole (edu.cornell.kfs.ksr.businessobject.SecurityRequestRole)1 SecurityRequestRoleQualification (edu.cornell.kfs.ksr.businessobject.SecurityRequestRoleQualification)1 SecurityRequestDocument (edu.cornell.kfs.ksr.document.SecurityRequestDocument)1 ResponsibilityAction (org.kuali.kfs.kim.api.responsibility.ResponsibilityAction)1 Builder (org.kuali.kfs.kim.api.role.RoleMembership.Builder)1 DelegationTypeService (org.kuali.kfs.kim.framework.common.delegate.DelegationTypeService)1 RoleResponsibilityAction (org.kuali.kfs.kim.impl.role.RoleResponsibilityAction)1