use of org.wso2.carbon.identity.scim2.common.exceptions.IdentitySCIMException in project identity-inbound-provisioning-scim2 by wso2-extensions.
the class SCIMUserManager method doGetGroup.
private Group doGetGroup(String groupName, boolean isMemberIdRequired, boolean excludeMembers) throws CharonException, org.wso2.carbon.user.core.UserStoreException, IdentitySCIMException, BadRequestException {
String userStoreDomainName = IdentityUtil.extractDomainFromName(groupName);
if (!isInternalOrApplicationGroup(userStoreDomainName) && StringUtils.isNotBlank(userStoreDomainName) && !isSCIMEnabled(userStoreDomainName)) {
throw new CharonException("Cannot retrieve group through scim to user store " + ". SCIM is not " + "enabled for user store " + userStoreDomainName);
}
// Requested attributes are handled from Charon. Therefore we can retrieve the group with meta.
org.wso2.carbon.user.core.common.Group retrievedGroup = carbonUM.getGroupByGroupName(groupName, null);
if (retrievedGroup == null) {
throw new org.wso2.carbon.user.core.UserStoreException("No group found with the name: " + groupName);
}
Group group = buildGroup(retrievedGroup);
if (!excludeMembers) {
// Add users from the user store who has the given group.
addUsersToTheGroup(group);
}
// Set roles of the group.
setGroupRoles(group);
return group;
}
use of org.wso2.carbon.identity.scim2.common.exceptions.IdentitySCIMException in project identity-inbound-provisioning-scim2 by wso2-extensions.
the class SCIMUserManager method patchGroup.
@Override
public Group patchGroup(String groupId, String currentGroupName, Map<String, List<PatchOperation>> patchOperations, Map<String, Boolean> requiredAttributes) throws NotImplementedException, BadRequestException, CharonException, NotFoundException {
if (log.isDebugEnabled()) {
log.debug("Updating group: " + currentGroupName);
}
try {
List<PatchOperation> displayNameOperations = new ArrayList<>();
List<PatchOperation> memberOperations = new ArrayList<>();
String newGroupName = currentGroupName;
for (List<PatchOperation> patchOperationList : patchOperations.values()) {
for (PatchOperation patchOperation : patchOperationList) {
if (StringUtils.equals(SCIMConstants.GroupSchemaConstants.DISPLAY_NAME, patchOperation.getAttributeName())) {
displayNameOperations.add(patchOperation);
} else if (StringUtils.equals(SCIMConstants.GroupSchemaConstants.MEMBERS, patchOperation.getAttributeName())) {
memberOperations.add(patchOperation);
}
}
}
Collections.reverse(displayNameOperations);
if (CollectionUtils.isNotEmpty(displayNameOperations)) {
newGroupName = (String) displayNameOperations.get(0).getValues();
setGroupDisplayName(currentGroupName, newGroupName);
}
Collections.sort(memberOperations);
Set<String> addedMembers = new HashSet<>();
Set<String> deletedMembers = new HashSet<>();
Set<Object> newlyAddedMemberIds = new HashSet<>();
Set<Object> deletedMemberIds = new HashSet<>();
for (PatchOperation memberOperation : memberOperations) {
if (memberOperation.getValues() instanceof Map) {
Map<String, String> memberObject = (Map<String, String>) memberOperation.getValues();
prepareAddedRemovedMemberLists(addedMembers, deletedMembers, newlyAddedMemberIds, deletedMemberIds, memberOperation, memberObject);
} else if (memberOperation.getValues() instanceof List) {
List<Map<String, String>> memberOperationValues = (List<Map<String, String>>) memberOperation.getValues();
for (Map<String, String> memberObject : memberOperationValues) {
prepareAddedRemovedMemberLists(addedMembers, deletedMembers, newlyAddedMemberIds, deletedMemberIds, memberOperation, memberObject);
}
}
}
String userStoreDomainForGroup = IdentityUtil.extractDomainFromName(newGroupName);
Set<String> temporaryMembers = new HashSet<>();
if (isNotInternalOrApplicationGroup(userStoreDomainForGroup) && (!addedMembers.isEmpty() || !deletedMembers.isEmpty())) {
for (String member : addedMembers) {
String username = UserCoreUtil.addDomainToName(UserCoreUtil.removeDomainFromName(member), userStoreDomainForGroup);
temporaryMembers.add(username);
}
addedMembers.clear();
addedMembers.addAll(temporaryMembers);
temporaryMembers.clear();
for (String member : deletedMembers) {
String username = UserCoreUtil.addDomainToName(UserCoreUtil.removeDomainFromName(member), userStoreDomainForGroup);
temporaryMembers.add(username);
}
deletedMembers.clear();
deletedMembers.addAll(temporaryMembers);
}
// Check for deleted members.
Set<String> deletedMemberIdsFromUserstore = getMemberValuesFromUserstore(deletedMembers, userStoreDomainForGroup, newGroupName);
// Check for added members.
Set<String> addedMemberIdsFromUserstore = getMemberValuesFromUserstore(addedMembers, userStoreDomainForGroup, newGroupName);
// Validate the memberIds sent in the update request against the Ids retrieved from the user store.
if (isNotEmpty(addedMembers)) {
validateUserIds(addedMemberIdsFromUserstore, newlyAddedMemberIds);
}
if (isNotEmpty(deletedMemberIds)) {
validateUserIds(deletedMemberIdsFromUserstore, deletedMemberIds);
}
/*
Set thread local property to signal the downstream SCIMUserOperationListener
about the provisioning route.
*/
SCIMCommonUtils.setThreadLocalIsManagedThroughSCIMEP(true);
/*
We do not update Identity_SCIM DB here since it is updated in SCIMUserOperationListener's methods.
Update the group with added members and deleted members.
*/
if (isNotEmpty(addedMembers) || isNotEmpty(deletedMembers)) {
carbonUM.updateUserListOfRoleWithID(newGroupName, deletedMemberIdsFromUserstore.toArray(new String[0]), addedMemberIdsFromUserstore.toArray(new String[0]));
}
} catch (UserStoreException e) {
throw resolveError(e, e.getMessage());
} catch (IdentitySCIMException e) {
throw new CharonException(e.getMessage(), e);
} catch (IdentityApplicationManagementException e) {
throw new CharonException("Error retrieving User Store name. ", e);
} catch (BadRequestException e) {
throw new CharonException("Error in updating the group", e);
}
return getGroup(groupId, requiredAttributes);
}
use of org.wso2.carbon.identity.scim2.common.exceptions.IdentitySCIMException 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;
}
use of org.wso2.carbon.identity.scim2.common.exceptions.IdentitySCIMException in project identity-inbound-provisioning-scim2 by wso2-extensions.
the class SCIMUserManager method createGroup.
@Override
public Group createGroup(Group group, Map<String, Boolean> requiredAttributes) throws CharonException, ConflictException, BadRequestException {
if (log.isDebugEnabled()) {
log.debug("Creating group: " + group.getDisplayName());
}
try {
// Modify display name if no domain is specified, in order to support multiple user store feature.
String originalName = group.getDisplayName();
String roleNameWithDomain = null;
String domainName = "";
try {
if (getUserStoreDomainFromSP() != null) {
domainName = getUserStoreDomainFromSP();
roleNameWithDomain = IdentityUtil.addDomainToName(UserCoreUtil.removeDomainFromName(originalName), domainName);
} else if (originalName.indexOf(CarbonConstants.DOMAIN_SEPARATOR) > 0) {
domainName = IdentityUtil.extractDomainFromName(originalName);
roleNameWithDomain = IdentityUtil.addDomainToName(UserCoreUtil.removeDomainFromName(originalName), domainName);
} else {
domainName = UserCoreConstants.PRIMARY_DEFAULT_DOMAIN_NAME;
roleNameWithDomain = SCIMCommonUtils.getGroupNameWithDomain(originalName);
}
} catch (IdentityApplicationManagementException e) {
throw new CharonException("Error retrieving User Store name. ", e);
}
if (!isInternalOrApplicationGroup(domainName) && StringUtils.isNotBlank(domainName) && !isSCIMEnabled(domainName)) {
CharonException charonException = new CharonException();
charonException.setDetail("Cannot create group through in userstore. SCIM is not " + "enabled for user store: " + domainName);
charonException.setStatus(HttpStatus.SC_BAD_REQUEST);
throw charonException;
}
group.setDisplayName(roleNameWithDomain);
// check if the group already exists
if (carbonUM.isExistingRole(group.getDisplayName(), false)) {
String error = "Group with name: " + group.getDisplayName() + " already exists in the system.";
throw new ConflictException(error);
}
// Set thread local property to signal the downstream SCIMUserOperationListener about the
// provisioning route.
SCIMCommonUtils.setThreadLocalIsManagedThroughSCIMEP(true);
// If members are sent when creating the group, check whether users already exist in the user store.
List<Object> userIds = group.getMembers();
List<String> userDisplayNames = group.getMembersWithDisplayName();
if (isNotEmpty(userIds)) {
List<String> members = new ArrayList<>();
for (Object userId : userIds) {
String userIdLocalClaim = SCIMCommonUtils.getSCIMtoLocalMappings().get(SCIMConstants.CommonSchemaConstants.ID_URI);
org.wso2.carbon.user.core.common.User coreUser = null;
if (StringUtils.isNotBlank(userIdLocalClaim)) {
coreUser = carbonUM.getUserWithID((String) userId, null, UserCoreConstants.DEFAULT_PROFILE);
}
if (coreUser == null) {
String error = "User: " + userId + " doesn't exist in the user store. " + "Hence, can not create the group: " + group.getDisplayName();
throw new IdentitySCIMException(error);
} else if (coreUser.getUsername().indexOf(UserCoreConstants.DOMAIN_SEPARATOR) > 0 && !StringUtils.containsIgnoreCase(coreUser.getUsername(), domainName)) {
String error = "User: " + userId + " doesn't exist in the same user store. " + "Hence, can not create the group: " + group.getDisplayName();
throw new IdentitySCIMException(error);
} else {
members.add(coreUser.getUserID());
if (isNotEmpty(userDisplayNames)) {
boolean userContains = false;
for (String user : userDisplayNames) {
user = user.indexOf(UserCoreConstants.DOMAIN_SEPARATOR) > 0 ? user.split(UserCoreConstants.DOMAIN_SEPARATOR)[1] : user;
if (isUserContains(coreUser, user)) {
userContains = true;
break;
}
}
if (!userContains) {
throw new IdentitySCIMException("Given SCIM user Id and name does not match..");
}
}
}
}
// Add other scim attributes in the identity DB since user store doesn't support some attributes.
SCIMGroupHandler scimGroupHandler = new SCIMGroupHandler(carbonUM.getTenantId());
scimGroupHandler.createSCIMAttributes(group);
carbonUM.addRoleWithID(group.getDisplayName(), members.toArray(new String[0]), null, false);
if (log.isDebugEnabled()) {
log.debug("Group: " + group.getDisplayName() + " is created through SCIM.");
}
} else {
// Add other scim attributes in the identity DB since user store doesn't support some attributes.
SCIMGroupHandler scimGroupHandler = new SCIMGroupHandler(carbonUM.getTenantId());
scimGroupHandler.createSCIMAttributes(group);
carbonUM.addRoleWithID(group.getDisplayName(), null, null, false);
if (log.isDebugEnabled()) {
log.debug("Group: " + group.getDisplayName() + " is created through SCIM.");
}
}
} catch (UserStoreException e) {
try {
SCIMGroupHandler scimGroupHandler = new SCIMGroupHandler(carbonUM.getTenantId());
scimGroupHandler.deleteGroupAttributes(group.getDisplayName());
} catch (UserStoreException | IdentitySCIMException ex) {
throw resolveError(e, "Error occurred while doing rollback operation of the SCIM " + "table entry for role: " + group.getDisplayName());
}
handleErrorsOnRoleNamePolicy(e);
throw resolveError(e, "Error occurred while adding role : " + group.getDisplayName());
} catch (IdentitySCIMException | BadRequestException e) {
String error = "One or more group members do not exist in the same user store. " + "Hence, can not create the group: " + group.getDisplayName();
if (log.isDebugEnabled()) {
log.debug(error, e);
}
throw new BadRequestException(error, ResponseCodeConstants.INVALID_VALUE);
}
return group;
}
use of org.wso2.carbon.identity.scim2.common.exceptions.IdentitySCIMException in project identity-inbound-provisioning-scim2 by wso2-extensions.
the class SCIMUserManager method setGroupDisplayName.
private void setGroupDisplayName(Group oldGroup, Group newGroup) throws IdentityApplicationManagementException, CharonException, BadRequestException, IdentitySCIMException {
String userStoreDomainFromSP = getUserStoreDomainFromSP();
String oldGroupDomain = IdentityUtil.extractDomainFromName(oldGroup.getDisplayName());
if (userStoreDomainFromSP != null && !userStoreDomainFromSP.equalsIgnoreCase(oldGroupDomain)) {
throw new CharonException("Group :" + oldGroup.getDisplayName() + "is not belong to user store " + userStoreDomainFromSP + "Hence group updating fail");
}
// If the updated group name does not contain a user store domain, it will be returned as PRIMARY.
String updatedGroupDomain = IdentityUtil.extractDomainFromName(newGroup.getDisplayName());
if (isPrimaryDomain(updatedGroupDomain) && !isPrimaryDomain(oldGroupDomain)) {
// This is the case where the updated group name did not contain a domain name but was returned as PRIMARY
// from IdentityUtil.extractDomainFromName() method.
String newGroupNameWithoutDomain = UserCoreUtil.removeDomainFromName(newGroup.getDisplayName());
newGroup.setDisplayName(IdentityUtil.addDomainToName(newGroupNameWithoutDomain, oldGroupDomain));
} else if (!oldGroupDomain.equals(updatedGroupDomain)) {
// This is the case where the updated group domain does not match the old group's domain.
throw new IdentitySCIMException("User store domain of the group is not matching with the given SCIM group Id.");
}
newGroup.setDisplayName(SCIMCommonUtils.getGroupNameWithDomain(newGroup.getDisplayName()));
oldGroup.setDisplayName(SCIMCommonUtils.getGroupNameWithDomain(oldGroup.getDisplayName()));
}
Aggregations