Search in sources :

Example 1 with SCIMCommonUtils

use of org.wso2.carbon.identity.scim2.common.utils.SCIMCommonUtils in project identity-inbound-provisioning-scim2 by wso2-extensions.

the class SCIMUserManager method getSCIMUsers.

/**
 * get the specified user from the store
 *
 * @param users                Set of users.
 * @param claimURIList         Requested claim list.
 * @param scimToLocalClaimsMap SCIM to local claims mappings.
 * @param requiredAttributes   Attributes required.
 * @return Array of SCIM User
 * @throws CharonException CharonException
 */
private Set<User> getSCIMUsers(Set<org.wso2.carbon.user.core.common.User> users, List<String> claimURIList, Map<String, String> scimToLocalClaimsMap, Map<String, Boolean> requiredAttributes) throws CharonException {
    List<User> scimUsers = new ArrayList<>();
    // obtain user claim values
    List<UniqueIDUserClaimSearchEntry> searchEntries;
    Map<String, List<String>> usersRoles = new HashMap<>();
    try {
        searchEntries = carbonUM.getUsersClaimValuesWithID(users.stream().map(org.wso2.carbon.user.core.common.User::getUserID).collect(Collectors.toList()), claimURIList, null);
        if (isGroupsAttributeRequired(requiredAttributes)) {
            if (IdentityUtil.isGroupsVsRolesSeparationImprovementsEnabled()) {
                usersRoles = searchEntries.stream().map(userClaimSearchEntry -> {
                    String userID = userClaimSearchEntry.getUser().getUserID();
                    List<String> groupsList = getGroups(userClaimSearchEntry);
                    return new AbstractMap.SimpleEntry<>(userID, groupsList);
                }).collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
            } else {
                usersRoles = carbonUM.getRoleListOfUsersWithID(users.stream().map(org.wso2.carbon.user.core.common.User::getUserID).collect(Collectors.toList()));
            }
        }
    } catch (org.wso2.carbon.user.core.UserStoreException e) {
        String errorMsg = "Error occurred while retrieving SCIM user information";
        throw resolveError(e, errorMsg);
    }
    Map<String, Group> groupMetaAttributesCache = new HashMap<>();
    for (org.wso2.carbon.user.core.common.User user : users) {
        String userStoreDomainName = user.getUserStoreDomain();
        if (isSCIMEnabled(userStoreDomainName)) {
            if (log.isDebugEnabled()) {
                log.debug("SCIM is enabled for the user-store domain : " + userStoreDomainName + ". " + "Including user : " + user.getUsername() + " in the response.");
            }
            User scimUser;
            Map<String, String> userClaimValues = new HashMap<>();
            for (UniqueIDUserClaimSearchEntry entry : searchEntries) {
                if (entry.getUser() != null && StringUtils.isNotBlank(entry.getUser().getUserID()) && entry.getUser().getUserID().equals(user.getUserID())) {
                    userClaimValues = entry.getClaims();
                }
            }
            Map<String, String> attributes;
            try {
                attributes = SCIMCommonUtils.convertLocalToSCIMDialect(userClaimValues, scimToLocalClaimsMap);
            } catch (UserStoreException e) {
                throw resolveError(e, "Error in converting local claims to SCIM dialect for user: " + user.getUsername());
            }
            try {
                if (!attributes.containsKey(SCIMConstants.CommonSchemaConstants.ID_URI)) {
                    if (log.isDebugEnabled()) {
                        log.debug(String.format("Skipping adding user %s with id %s as attribute %s is not " + "available.", user.getFullQualifiedUsername(), user.getUserID(), SCIMConstants.CommonSchemaConstants.ID_URI));
                    }
                    continue;
                }
                // skip simple type addresses claim because it is complex with sub types in the schema
                if (attributes.containsKey(SCIMConstants.UserSchemaConstants.ADDRESSES_URI)) {
                    attributes.remove(SCIMConstants.UserSchemaConstants.ADDRESSES_URI);
                }
                if (IdentityUtil.isGroupsVsRolesSeparationImprovementsEnabled()) {
                    filterAttributes(attributes, Arrays.asList(SCIMConstants.UserSchemaConstants.ROLES_URI, SCIMConstants.UserSchemaConstants.GROUP_URI));
                }
                // Location URI is not available for users who created from the mgt console also location URI is not
                // tenant aware, so need to update the location URI according to the tenant.
                String locationURI = SCIMCommonUtils.getSCIMUserURL(attributes.get(SCIMConstants.CommonSchemaConstants.ID_URI));
                attributes.put(SCIMConstants.CommonSchemaConstants.LOCATION_URI, locationURI);
                if (!attributes.containsKey(SCIMConstants.CommonSchemaConstants.RESOURCE_TYPE_URI)) {
                    attributes.put(SCIMConstants.CommonSchemaConstants.RESOURCE_TYPE_URI, SCIMConstants.USER);
                }
                // Add username with domain name
                if (mandateDomainForUsernamesAndGroupNamesInResponse()) {
                    setUserNameWithDomain(userClaimValues, attributes, user);
                } else {
                    if (isLoginIdentifiersEnabled() && StringUtils.isNotBlank(getPrimaryLoginIdentifierClaim())) {
                        String primaryLoginIdentifier = userClaimValues.get(getPrimaryLoginIdentifierClaim());
                        if (StringUtils.isNotBlank(primaryLoginIdentifier)) {
                            attributes.put(SCIMConstants.UserSchemaConstants.USER_NAME_URI, primaryLoginIdentifier);
                        } else {
                            attributes.put(SCIMConstants.UserSchemaConstants.USER_NAME_URI, user.getDomainQualifiedUsername());
                        }
                    } else {
                        attributes.put(SCIMConstants.UserSchemaConstants.USER_NAME_URI, user.getDomainQualifiedUsername());
                    }
                }
                // construct the SCIM Object from the attributes
                scimUser = (User) AttributeMapper.constructSCIMObjectFromAttributes(this, attributes, 1);
                if (isGroupsAttributeRequired(requiredAttributes)) {
                    // Get groups of user and add it as groups attribute.
                    List<String> roleList = usersRoles.get(user.getUserID());
                    List<String> groupsList = new ArrayList<>();
                    if (isNotEmpty(roleList)) {
                        groupsList = new ArrayList<>(roleList);
                    } else {
                        if (log.isDebugEnabled()) {
                            log.debug(String.format("Roles not found for user %s with id %s .", user.getFullQualifiedUsername(), user.getUserID()));
                        }
                    }
                    if (!IdentityUtil.isGroupsVsRolesSeparationImprovementsEnabled()) {
                        if (carbonUM.isRoleAndGroupSeparationEnabled()) {
                            // Remove roles, if the role and group separation feature is enabled.
                            groupsList.removeIf(SCIMCommonUtils::isHybridRole);
                        } else {
                            checkForSCIMDisabledHybridRoles(groupsList);
                        }
                    }
                    for (String group : groupsList) {
                        if (UserCoreUtil.isEveryoneRole(group, carbonUM.getRealmConfiguration()) || CarbonConstants.REGISTRY_ANONNYMOUS_ROLE_NAME.equalsIgnoreCase(group)) {
                            // Carbon specific roles do not possess SCIM info, hence skipping them.
                            continue;
                        }
                        Group groupObject = groupMetaAttributesCache.get(group);
                        if (groupObject == null && !groupMetaAttributesCache.containsKey(group)) {
                            org.wso2.carbon.user.core.common.Group userGroup = carbonUM.getGroupByGroupName(UserCoreUtil.addDomainToName(group, userStoreDomainName), null);
                            groupObject = buildGroup(userGroup);
                            groupMetaAttributesCache.put(group, groupObject);
                        }
                        if (groupObject != null && isFilteringEnhancementsEnabled()) {
                            groupObject.setDisplayName(prependDomain(group));
                        }
                        if (groupObject != null) {
                            // Can be null for non SCIM groups.
                            scimUser.setGroup(null, groupObject);
                        }
                    }
                }
                // Set the roles attribute if the the role and group separation feature is enabled.
                if (IdentityUtil.isGroupsVsRolesSeparationImprovementsEnabled()) {
                    List<String> rolesList = getRoles(searchEntries, user);
                    setRolesOfUser(rolesList, groupMetaAttributesCache, user, scimUser);
                } else if (carbonUM.isRoleAndGroupSeparationEnabled()) {
                    List<String> rolesList = carbonUM.getHybridRoleListOfUser(user.getUsername(), user.getUserStoreDomain());
                    checkForSCIMDisabledHybridRoles(rolesList);
                    setRolesOfUser(rolesList, groupMetaAttributesCache, user, scimUser);
                }
            } catch (UserStoreException e) {
                throw resolveError(e, "Error in getting user information for user: " + user.getUsername());
            } catch (CharonException | NotFoundException | IdentitySCIMException | BadRequestException e) {
                throw new CharonException("Error in getting user information for user: " + user.getUsername(), e);
            }
            if (scimUser != null) {
                scimUsers.add(scimUser);
            }
        } else {
            if (log.isDebugEnabled()) {
                log.debug("SCIM is disabled for the user-store domain : " + userStoreDomainName + ". " + "Hence user : " + user.getUsername() + " in this domain is excluded in the response.");
            }
        }
    }
    if (removeDuplicateUsersInUsersResponseEnabled) {
        TreeSet<User> scimUserSet = new TreeSet<>(Comparator.comparing(User::getUsername));
        scimUserSet.addAll(scimUsers);
        return scimUserSet;
    }
    Set<User> scimUserSet = new LinkedHashSet<>();
    scimUserSet.addAll(scimUsers);
    return scimUserSet;
}
Also used : LinkedHashSet(java.util.LinkedHashSet) Group(org.wso2.charon3.core.objects.Group) User(org.wso2.charon3.core.objects.User) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) NotFoundException(org.wso2.charon3.core.exceptions.NotFoundException) IdentitySCIMException(org.wso2.carbon.identity.scim2.common.exceptions.IdentitySCIMException) UniqueIDUserClaimSearchEntry(org.wso2.carbon.user.core.model.UniqueIDUserClaimSearchEntry) TreeSet(java.util.TreeSet) UserStoreException(org.wso2.carbon.user.api.UserStoreException) SCIMUserStoreException(org.wso2.carbon.identity.scim2.common.extenstion.SCIMUserStoreException) ArrayList(java.util.ArrayList) List(java.util.List) SCIMCommonUtils(org.wso2.carbon.identity.scim2.common.utils.SCIMCommonUtils) BadRequestException(org.wso2.charon3.core.exceptions.BadRequestException) CharonException(org.wso2.charon3.core.exceptions.CharonException)

Example 2 with SCIMCommonUtils

use of org.wso2.carbon.identity.scim2.common.utils.SCIMCommonUtils in project identity-inbound-provisioning-scim2 by wso2-extensions.

the class SCIMUserManager method getSCIMUser.

/**
 * get the specfied user from the store
 *
 * @param coreUser     User of the underlying user store.
 * @param claimURIList
 * @return
 * @throws CharonException
 */
private User getSCIMUser(org.wso2.carbon.user.core.common.User coreUser, List<String> claimURIList, Map<String, String> scimToLocalClaimsMap, Map<String, String> userClaimValues) throws CharonException {
    User scimUser = null;
    String userStoreDomainName = coreUser.getUserStoreDomain();
    if (StringUtils.isNotBlank(userStoreDomainName) && !isSCIMEnabled(userStoreDomainName)) {
        throw new CharonException("Cannot get user through SCIM to user store. SCIM is not enabled for user store: " + userStoreDomainName);
    }
    try {
        // TODO: If we can get the updated user claim values from the add user method, we don't need to do
        // this call. Please check the status of the issue: https://github.com/wso2/product-is/issues/7160
        userClaimValues = carbonUM.getUserClaimValuesWithID(coreUser.getUserID(), claimURIList.toArray(new String[0]), null);
        Map<String, String> attributes = SCIMCommonUtils.convertLocalToSCIMDialect(userClaimValues, scimToLocalClaimsMap);
        if (!attributes.containsKey(SCIMConstants.CommonSchemaConstants.ID_URI)) {
            return scimUser;
        }
        // Skip simple type addresses claim because it is complex with sub types in the schema.
        attributes.remove(SCIMConstants.UserSchemaConstants.ADDRESSES_URI);
        List<String> groupsList = null;
        List<String> rolesList = null;
        if (IdentityUtil.isGroupsVsRolesSeparationImprovementsEnabled()) {
            // Get user groups from attributes.
            groupsList = getMultiValuedAttributeList(userStoreDomainName, attributes, SCIMConstants.UserSchemaConstants.GROUP_URI);
            // Add userstore domain to the group names.
            groupsList = addDomainToNames(userStoreDomainName, groupsList);
            // Get user roles from attributes.
            rolesList = getMultiValuedAttributeList(userStoreDomainName, attributes, SCIMConstants.UserSchemaConstants.ROLES_URI + "." + SCIMConstants.DEFAULT);
            checkForSCIMDisabledHybridRoles(rolesList);
            // Skip groups and roles claims because they are handled separately.
            filterAttributes(attributes, Arrays.asList(SCIMConstants.UserSchemaConstants.ROLES_URI, SCIMConstants.UserSchemaConstants.GROUP_URI));
        } else {
            // Set groups.
            groupsList = new ArrayList<>(carbonUM.getRoleListOfUserWithID(coreUser.getUserID()));
            if (carbonUM.isRoleAndGroupSeparationEnabled()) {
                // Remove roles, if the role and group separation feature is enabled.
                groupsList.removeIf(SCIMCommonUtils::isHybridRole);
                // Set roles.
                rolesList = carbonUM.getHybridRoleListOfUser(coreUser.getUsername(), coreUser.getUserStoreDomain());
                checkForSCIMDisabledHybridRoles(rolesList);
            } else {
                checkForSCIMDisabledHybridRoles(groupsList);
            }
        }
        // If primary login identifire is enabled, set the username value of scim response to that value.
        if (isLoginIdentifiersEnabled() && StringUtils.isNotBlank(getPrimaryLoginIdentifierClaim())) {
            String primaryLoginIdentifier = userClaimValues.get(getPrimaryLoginIdentifierClaim());
            attributes.put(SCIMConstants.UserSchemaConstants.USER_NAME_URI, primaryLoginIdentifier);
        } else {
            // Add username with domain name.
            attributes.put(SCIMConstants.UserSchemaConstants.USER_NAME_URI, coreUser.getUsername());
        }
        // Location URI is not available for users who created from the mgt console also location URI is not
        // tenant aware, so need to update the location URI according to the tenant.
        String locationURI = SCIMCommonUtils.getSCIMUserURL(attributes.get(SCIMConstants.CommonSchemaConstants.ID_URI));
        attributes.put(SCIMConstants.CommonSchemaConstants.LOCATION_URI, locationURI);
        if (!attributes.containsKey(SCIMConstants.CommonSchemaConstants.RESOURCE_TYPE_URI)) {
            attributes.put(SCIMConstants.CommonSchemaConstants.RESOURCE_TYPE_URI, SCIMConstants.USER);
        }
        Map<String, Group> groupMetaAttributesCache = new HashMap<>();
        // Construct the SCIM Object from the attributes.
        scimUser = (User) AttributeMapper.constructSCIMObjectFromAttributes(this, attributes, 1);
        // Add username with domain name.
        if (mandateDomainForUsernamesAndGroupNamesInResponse()) {
            // If primary login identifire is enabled, set the username value of scim response to that value.
            if (isLoginIdentifiersEnabled() && StringUtils.isNotBlank(getPrimaryLoginIdentifierClaim())) {
                String primaryLoginIdentifier = userClaimValues.get(getPrimaryLoginIdentifierClaim());
                scimUser.setUserName(prependDomain(primaryLoginIdentifier));
            } else {
                scimUser.setUserName(prependDomain(coreUser.getDomainQualifiedUsername()));
            }
        } else {
            if (isLoginIdentifiersEnabled() && StringUtils.isNotBlank(getPrimaryLoginIdentifierClaim())) {
                String primaryLoginIdentifier = userClaimValues.get(getPrimaryLoginIdentifierClaim());
                scimUser.setUserName(primaryLoginIdentifier);
            } else {
                scimUser.setUserName(coreUser.getDomainQualifiedUsername());
            }
        }
        // Add groups of user.
        for (String groupName : groupsList) {
            if (UserCoreUtil.isEveryoneRole(groupName, carbonUM.getRealmConfiguration()) || CarbonConstants.REGISTRY_ANONNYMOUS_ROLE_NAME.equalsIgnoreCase(groupName)) {
                // Carbon specific roles do not possess SCIM info, hence skipping them.
                continue;
            }
            Group groupObject = groupMetaAttributesCache.get(groupName);
            if (groupObject == null && !groupMetaAttributesCache.containsKey(groupName)) {
                org.wso2.carbon.user.core.common.Group userGroup = carbonUM.getGroupByGroupName(UserCoreUtil.addDomainToName(groupName, userStoreDomainName), null);
                groupObject = buildGroup(userGroup);
                groupMetaAttributesCache.put(groupName, groupObject);
            }
            if (groupObject != null && isFilteringEnhancementsEnabled()) {
                groupObject.setDisplayName(prependDomain(groupName));
            }
            if (groupObject != null) {
                // can be null for non SCIM groups
                scimUser.setGroup(null, groupObject);
            }
        }
        // Set the roles attribute if the the role and group separation feature is enabled.
        if (carbonUM.isRoleAndGroupSeparationEnabled()) {
            setRolesOfUser(rolesList, groupMetaAttributesCache, coreUser, scimUser);
        }
    } catch (UserStoreException e) {
        throw resolveError(e, "Error in getting user information for user: " + coreUser.getDomainQualifiedUsername());
    } catch (CharonException | NotFoundException | IdentitySCIMException | BadRequestException e) {
        throw new CharonException("Error in getting user information for user: " + coreUser.getDomainQualifiedUsername(), e);
    }
    return scimUser;
}
Also used : Group(org.wso2.charon3.core.objects.Group) User(org.wso2.charon3.core.objects.User) HashMap(java.util.HashMap) NotFoundException(org.wso2.charon3.core.exceptions.NotFoundException) IdentitySCIMException(org.wso2.carbon.identity.scim2.common.exceptions.IdentitySCIMException) SCIMCommonUtils(org.wso2.carbon.identity.scim2.common.utils.SCIMCommonUtils) UserStoreException(org.wso2.carbon.user.api.UserStoreException) SCIMUserStoreException(org.wso2.carbon.identity.scim2.common.extenstion.SCIMUserStoreException) BadRequestException(org.wso2.charon3.core.exceptions.BadRequestException) CharonException(org.wso2.charon3.core.exceptions.CharonException)

Example 3 with SCIMCommonUtils

use of org.wso2.carbon.identity.scim2.common.utils.SCIMCommonUtils in project identity-inbound-provisioning-scim2 by wso2-extensions.

the class SCIMUserManager method filterGroupsBySingleAttribute.

/**
 * Filter groups with a single attribute.
 *
 * @param node               Expression node
 * @param startIndex         Starting index
 * @param count              Number of results required
 * @param sortBy             SortBy
 * @param sortOrder          Sorting order
 * @param domainName         Domain to be filtered
 * @param requiredAttributes Required attributes
 * @return Filtered groups
 * @throws CharonException Error in Filtering
 */
private List<Object> filterGroupsBySingleAttribute(ExpressionNode node, int startIndex, int count, String sortBy, String sortOrder, String domainName, Map<String, Boolean> requiredAttributes) throws CharonException, BadRequestException {
    String attributeName = node.getAttributeValue();
    String filterOperation = node.getOperation();
    String attributeValue = node.getValue();
    if (log.isDebugEnabled()) {
        log.debug("Filtering groups with filter: " + attributeName + " + " + filterOperation + " + " + attributeValue);
    }
    // Check whether the filter operation is supported for filtering in groups.
    if (isFilteringNotSupported(filterOperation)) {
        String errorMessage = "Filter operation: " + filterOperation + " is not supported for groups filtering.";
        throw new CharonException(errorMessage);
    }
    // Resolve the domain name in request according to 'FilterUsersAndGroupsOnlyFromPrimaryDomain' or
    // EnableFilteringEnhancements' properties in identity.xml or domain name embedded in the filter attribute
    // value.
    domainName = resolveDomain(domainName, node);
    List<Object> filteredGroups = new ArrayList<>();
    // 0th index is to store total number of results.
    filteredGroups.add(0);
    try {
        List<String> groupsList = new ArrayList<>(getGroupList(node, domainName));
        // Remove roles, if the role and group separation feature is enabled.
        if (carbonUM.isRoleAndGroupSeparationEnabled()) {
            groupsList.removeIf(SCIMCommonUtils::isHybridRole);
        }
        if (groupsList != null) {
            for (String groupName : groupsList) {
                if (groupName != null && carbonUM.isExistingRole(groupName, false)) {
                    // Skip internal roles.
                    if (CarbonConstants.REGISTRY_ANONNYMOUS_ROLE_NAME.equals(groupName) || UserCoreUtil.isEveryoneRole(groupName, carbonUM.getRealmConfiguration())) {
                        continue;
                    }
                    Group group = getRoleWithDefaultAttributes(groupName, requiredAttributes);
                    if (group != null && group.getId() != null) {
                        filteredGroups.add(group);
                    }
                } else {
                    // Returning null will send a resource not found error to client by Charon.
                    filteredGroups.clear();
                    filteredGroups.add(0);
                    return filteredGroups;
                }
            }
        }
    } catch (org.wso2.carbon.user.core.UserStoreException e) {
        String errorMsg = "Error in filtering groups by attribute name : " + attributeName + ", " + "attribute value : " + attributeValue + " and filter operation : " + filterOperation;
        throw resolveError(e, errorMsg);
    } catch (org.wso2.carbon.user.api.UserStoreException e) {
        throw resolveError(e, "Error in filtering group with filter: " + attributeName + " + " + filterOperation + " + " + attributeValue);
    }
    // Set the totalResults value in index 0.
    filteredGroups.set(0, filteredGroups.size() - 1);
    return filteredGroups;
}
Also used : Group(org.wso2.charon3.core.objects.Group) UserStoreException(org.wso2.carbon.user.api.UserStoreException) ArrayList(java.util.ArrayList) SCIMCommonUtils(org.wso2.carbon.identity.scim2.common.utils.SCIMCommonUtils) CharonException(org.wso2.charon3.core.exceptions.CharonException)

Aggregations

SCIMCommonUtils (org.wso2.carbon.identity.scim2.common.utils.SCIMCommonUtils)3 UserStoreException (org.wso2.carbon.user.api.UserStoreException)3 CharonException (org.wso2.charon3.core.exceptions.CharonException)3 Group (org.wso2.charon3.core.objects.Group)3 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 IdentitySCIMException (org.wso2.carbon.identity.scim2.common.exceptions.IdentitySCIMException)2 SCIMUserStoreException (org.wso2.carbon.identity.scim2.common.extenstion.SCIMUserStoreException)2 BadRequestException (org.wso2.charon3.core.exceptions.BadRequestException)2 NotFoundException (org.wso2.charon3.core.exceptions.NotFoundException)2 User (org.wso2.charon3.core.objects.User)2 LinkedHashSet (java.util.LinkedHashSet)1 List (java.util.List)1 TreeSet (java.util.TreeSet)1 UniqueIDUserClaimSearchEntry (org.wso2.carbon.user.core.model.UniqueIDUserClaimSearchEntry)1