use of org.wso2.carbon.identity.scim2.common.listener.SCIMUserOperationListener in project identity-inbound-provisioning-scim2 by wso2-extensions.
the class SCIMUserManager method deleteGroup.
@Override
public void deleteGroup(String groupId) throws NotFoundException, CharonException {
if (log.isDebugEnabled()) {
log.debug("Deleting group: " + groupId);
}
try {
// Set thread local property to signal the downstream SCIMUserOperationListener
// about the provisioning route.
SCIMCommonUtils.setThreadLocalIsManagedThroughSCIMEP(true);
// Get group name by id.
SCIMGroupHandler groupHandler = new SCIMGroupHandler(carbonUM.getTenantId());
String groupName = groupHandler.getGroupName(groupId);
if (groupName != null) {
String userStoreDomainFromSP = null;
try {
userStoreDomainFromSP = getUserStoreDomainFromSP();
} catch (IdentityApplicationManagementException e) {
throw new CharonException("Error retrieving User Store name. ", e);
}
if (userStoreDomainFromSP != null && !(userStoreDomainFromSP.equalsIgnoreCase(IdentityUtil.extractDomainFromName(groupName)))) {
throw new CharonException("Group :" + groupName + "is not belong to user store " + userStoreDomainFromSP + "Hence group updating fail");
}
String userStoreDomainName = IdentityUtil.extractDomainFromName(groupName);
if (!isInternalOrApplicationGroup(userStoreDomainName) && StringUtils.isNotBlank(userStoreDomainName) && !isSCIMEnabled(userStoreDomainName)) {
throw new CharonException("Cannot delete group: " + groupName + " through scim from user store: " + userStoreDomainName + ". SCIM is not enabled for user store: " + userStoreDomainName);
}
// delete group in carbon UM
carbonUM.deleteRole(groupName);
// we do not update Identity_SCIM DB here since it is updated in SCIMUserOperationListener's methods.
if (log.isDebugEnabled()) {
log.debug("Group: " + groupName + " is deleted through SCIM.");
}
} else {
if (log.isDebugEnabled()) {
log.debug("Group with SCIM id: " + groupId + " doesn't exist in the system.");
}
throw new NotFoundException();
}
} catch (UserStoreException e) {
throw resolveError(e, "Error occurred while deleting group " + groupId);
} catch (IdentitySCIMException e) {
throw new CharonException("Error occurred while deleting group " + groupId, e);
}
}
use of org.wso2.carbon.identity.scim2.common.listener.SCIMUserOperationListener in project identity-inbound-provisioning-scim2 by wso2-extensions.
the class SCIMUserManager method deleteUser.
@Override
public void deleteUser(String userId) throws NotFoundException, CharonException, BadRequestException {
if (log.isDebugEnabled()) {
log.debug("Deleting user: " + userId);
}
// get the user name of the user with this id
org.wso2.carbon.user.core.common.User coreUser = null;
String userName = null;
try {
// Set thread local property to signal the downstream SCIMUserOperationListener
// about the provisioning route.
SCIMCommonUtils.setThreadLocalIsManagedThroughSCIMEP(true);
String userIdLocalClaim = SCIMCommonUtils.getSCIMtoLocalMappings().get(SCIMConstants.CommonSchemaConstants.ID_URI);
if (StringUtils.isNotBlank(userIdLocalClaim)) {
// We cannot use getUserWithID because it throws exception when the user cannot be found.
// (Generic user store exception). If we can send a specific user not found exception in user core level
// we can use that method.
List<org.wso2.carbon.user.core.common.User> coreUsers = carbonUM.getUserListWithID(userIdLocalClaim, userId, UserCoreConstants.DEFAULT_PROFILE);
if (coreUsers.size() > 0) {
coreUser = coreUsers.get(0);
}
}
String userStoreDomainFromSP = null;
try {
userStoreDomainFromSP = getUserStoreDomainFromSP();
} catch (IdentityApplicationManagementException e) {
throw new CharonException("Error retrieving User Store name. ", e);
}
if (coreUser == null) {
// Resource with given id not found
if (log.isDebugEnabled()) {
log.debug("User with id: " + userId + " not found.");
}
throw new NotFoundException();
} else if (userStoreDomainFromSP != null && !(userStoreDomainFromSP.equalsIgnoreCase(coreUser.getUserStoreDomain()))) {
throw new CharonException("User :" + coreUser.getUsername() + "is not belong to user store " + userStoreDomainFromSP + "Hence user updating fail");
} else {
// We assume (since id is unique per user) only one user exists for a given id.
userName = coreUser.getUsername();
String userStoreDomainName = coreUser.getUserStoreDomain();
// Check if SCIM is enabled for the user store.
if (!isSCIMEnabled(userStoreDomainName)) {
throw new CharonException("Cannot delete user: " + userName + " through SCIM from user store: " + userStoreDomainName + ". SCIM is not enabled for user store: " + userStoreDomainName);
}
carbonUM.deleteUserWithID(coreUser.getUserID());
if (log.isDebugEnabled()) {
log.debug("User: " + userName + " is deleted through SCIM.");
}
}
} catch (UserStoreClientException e) {
String errorMessage;
if (isNotifyUserstoreStatusEnabled()) {
errorMessage = String.format("Error occurred while deleting user with ID: %s. %s", userId, e.getMessage());
} else {
errorMessage = "Error occurred while deleting user with ID: " + userId;
}
throw new BadRequestException(errorMessage, ResponseCodeConstants.INVALID_VALUE);
} catch (org.wso2.carbon.user.core.UserStoreException e) {
String errorMessage;
if (isNotifyUserstoreStatusEnabled()) {
errorMessage = String.format("Error occurred while deleting user with ID: %s. %s", userId, e.getMessage());
} else {
errorMessage = "Error occurred while deleting user with ID: " + userId;
}
/*
There are scenarios where the client exceptions are wrapped in the super class.Therefore checking for
possible client exception.
*/
Throwable ex = ExceptionUtils.getRootCause(e);
if (ex instanceof UserStoreClientException) {
throw new BadRequestException(errorMessage, ResponseCodeConstants.INVALID_VALUE);
}
throw resolveError(e, errorMessage);
}
}
use of org.wso2.carbon.identity.scim2.common.listener.SCIMUserOperationListener in project identity-inbound-provisioning-scim2 by wso2-extensions.
the class SCIMUserManager method updateUser.
/**
* Update the SCIM user.
*
* @param user {@link User} object.
* @param requiredAttributes A map of required attributes in SCIM schema.
* @param allSimpleMultiValuedAttributes A List of simple multi-valued attributes in SCIM schema.
* @return The updated user.
* @throws CharonException Exception occurred in charon level.
* @throws BadRequestException Exception occurred due to a bad request.
*/
public User updateUser(User user, Map<String, Boolean> requiredAttributes, List<String> allSimpleMultiValuedAttributes) throws CharonException, BadRequestException {
try {
if (log.isDebugEnabled()) {
log.debug("Updating user: " + user.getUserName());
}
/* Set thread local property to signal the downstream SCIMUserOperationListener
about the provisioning route. */
SCIMCommonUtils.setThreadLocalIsManagedThroughSCIMEP(true);
// Get user claim values.
Map<String, String> claims = AttributeMapper.getClaimsMap(user);
// Get claims mapped with simple multi-valued attributes.
Map<String, String> allSimpleMultiValuedClaims = new HashMap<>();
for (String simpleMultiValuedAttribute : allSimpleMultiValuedAttributes) {
allSimpleMultiValuedClaims.put(simpleMultiValuedAttribute, StringUtils.EMPTY);
}
Map<String, String> allSimpleMultiValuedClaimsList = SCIMCommonUtils.convertSCIMtoLocalDialect(allSimpleMultiValuedClaims);
// Check if username of the updating user existing in the userstore.
try {
String userStoreDomainFromSP = getUserStoreDomainFromSP();
SCIMResourceTypeSchema schema = SCIMResourceSchemaManager.getInstance().getUserResourceSchema();
User oldUser = this.getUser(user.getId(), ResourceManagerUtil.getAllAttributeURIs(schema));
if (userStoreDomainFromSP != null) {
if (!userStoreDomainFromSP.equalsIgnoreCase(IdentityUtil.extractDomainFromName(oldUser.getUserName()))) {
String errorMessage = String.format("User : %s does not belong to userstore %s. Hence user updating failed", oldUser.getUserName(), userStoreDomainFromSP);
throw new CharonException(errorMessage);
}
if (!UserCoreConstants.PRIMARY_DEFAULT_DOMAIN_NAME.equalsIgnoreCase(userStoreDomainFromSP)) {
user.setUserName(IdentityUtil.addDomainToName(UserCoreUtil.removeDomainFromName(user.getUserName()), userStoreDomainFromSP));
}
}
/* If primary login identifier configuration is enabled, username value can be another claim and it
could be modifiable. */
if (!(isLoginIdentifiersEnabled() && StringUtils.isNotBlank(getPrimaryLoginIdentifierClaim()))) {
// This is handled here as the IS is still not capable of updating the username via SCIM.
if (!StringUtils.equals(user.getUserName(), oldUser.getUserName())) {
if (log.isDebugEnabled()) {
log.debug("Failing the request as attempting to modify username. Old username: " + oldUser.getUserName() + ", new username: " + user.getUserName());
}
throw new BadRequestException("Attribute userName cannot be modified.", ResponseCodeConstants.MUTABILITY);
}
}
} catch (IdentityApplicationManagementException e) {
throw new CharonException("Error retrieving Userstore name. ", e);
}
if (!validateUserExistence(user)) {
throw new CharonException("User name is immutable in carbon user store.");
}
/*
Skip groups attribute since we map groups attribute to actual groups in ldap.
and do not update it as an attribute in user schema.
*/
claims.remove(SCIMConstants.UserSchemaConstants.GROUP_URI);
/*
Skip roles list since we map SCIM groups to local roles internally. It shouldn't be allowed to
manipulate SCIM groups from user endpoint as this attribute has a mutability of "readOnly". Group
changes must be applied via Group Resource.
*/
if (claims.containsKey(SCIMConstants.UserSchemaConstants.ROLES_URI + "." + SCIMConstants.DEFAULT)) {
claims.remove(SCIMConstants.UserSchemaConstants.ROLES_URI);
}
claims.remove(SCIMConstants.UserSchemaConstants.USER_NAME_URI);
/*
Since we are already populating last_modified claim value from SCIMUserOperationListener, we need to
remove this claim value which is coming from charon-level.
*/
claims.remove(SCIMConstants.CommonSchemaConstants.LAST_MODIFIED_URI);
// Location is a meta attribute of user object.
claims.remove(SCIMConstants.CommonSchemaConstants.LOCATION_URI);
// Resource-Type is a meta attribute of user object.
claims.remove(SCIMConstants.CommonSchemaConstants.RESOURCE_TYPE_URI);
Map<String, String> scimToLocalClaimsMap = SCIMCommonUtils.getSCIMtoLocalMappings();
List<String> requiredClaims = getOnlyRequiredClaims(scimToLocalClaimsMap.keySet(), requiredAttributes);
List<String> requiredClaimsInLocalDialect;
if (MapUtils.isNotEmpty(scimToLocalClaimsMap)) {
scimToLocalClaimsMap.keySet().retainAll(requiredClaims);
requiredClaimsInLocalDialect = new ArrayList<>(scimToLocalClaimsMap.values());
} else {
if (log.isDebugEnabled()) {
log.debug("SCIM to Local Claim mappings list is empty.");
}
requiredClaimsInLocalDialect = new ArrayList<>();
}
// Get existing user claims.
Map<String, String> oldClaimList = carbonUM.getUserClaimValuesWithID(user.getId(), requiredClaimsInLocalDialect.toArray(new String[0]), null);
oldClaimList.remove(LOCATION_CLAIM);
oldClaimList.remove(LAST_MODIFIED_CLAIM);
oldClaimList.remove(RESOURCE_TYPE_CLAIM);
// Get user claims mapped from SCIM dialect to WSO2 dialect.
Map<String, String> claimValuesInLocalDialect = SCIMCommonUtils.convertSCIMtoLocalDialect(claims);
// If the primary login identifier claim is enabled, pass that as a claim for userstoremanger.
if (isLoginIdentifiersEnabled() && StringUtils.isNotBlank(getPrimaryLoginIdentifierClaim())) {
claimValuesInLocalDialect.put(getPrimaryLoginIdentifierClaim(), UserCoreUtil.removeDomainFromName(user.getUsername()));
}
// If password is updated, set it separately.
if (user.getPassword() != null) {
carbonUM.updateCredentialByAdminWithID(user.getId(), user.getPassword());
}
updateUserClaims(user, oldClaimList, claimValuesInLocalDialect, allSimpleMultiValuedClaimsList);
if (log.isDebugEnabled()) {
log.debug("User: " + user.getUserName() + " updated through SCIM.");
}
return getUser(user.getId(), requiredAttributes);
} catch (UserStoreException e) {
handleErrorsOnUserNameAndPasswordPolicy(e);
throw resolveError(e, "Error while updating attributes of user: " + user.getUserName());
} catch (BadRequestException e) {
/*
This is needed as most BadRequests are thrown to charon as
CharonExceptions but if there are any bad requests handled
due to MUTABILITY at this level we need to properly notify
the end party.
*/
reThrowMutabilityBadRequests(e);
throw new CharonException("Error occurred while trying to update the user: " + user.getUserName(), e);
} catch (CharonException e) {
throw new CharonException("Error occurred while trying to update the user: " + user.getUserName(), e);
}
}
Aggregations