diff --git a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/DAO/GroupDAO.java b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/DAO/GroupDAO.java index ec9d1b171..a97c6dcb0 100644 --- a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/DAO/GroupDAO.java +++ b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/DAO/GroupDAO.java @@ -195,7 +195,6 @@ public void addSCIMGroupAttributes(int tenantId, String roleName, Map requiredAttributes) throw charonException; } group.setDisplayName(roleNameWithDomain); - //check if the group already exists + // 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); @@ -2625,8 +2626,8 @@ public Group createGroup(Group group, Map requiredAttributes) // If members are sent when creating the group, check whether users already exist in the user store. List userIds = group.getMembers(); List userDisplayNames = group.getMembersWithDisplayName(); + List members = new ArrayList<>(); if (isNotEmpty(userIds)) { - List members = new ArrayList<>(); for (Object userId : userIds) { String userIdLocalClaim = SCIMCommonUtils.getSCIMtoLocalMappings().get(SCIMConstants .CommonSchemaConstants.ID_URI); @@ -2662,21 +2663,14 @@ public Group createGroup(Group group, Map requiredAttributes) } } } - // 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."); - } + } + Map claimsInLocalDialect = + SCIMCommonUtils.convertSCIMtoLocalDialect(AttributeMapper.getClaimsMap(group)); + org.wso2.carbon.user.core.common.Group createdGroup = + carbonUM.addGroup(roleNameWithDomain, members, buildGroupMetaClaimsList(claimsInLocalDialect)); + group = buildGroup(createdGroup); + if (log.isDebugEnabled()) { + log.debug("Group: " + group.getDisplayName() + " is created through SCIM."); } } catch (UserStoreException e) { try { @@ -2699,6 +2693,26 @@ public Group createGroup(Group group, Map requiredAttributes) return group; } + /** + * Convert the claimsInLocalDialect to a list of Claims. NOTE: This method drops the RESOURCE_TYPE_CLAIM claim + * dialect being added to the returned claims list. + * + * @param claimsInLocalDialect Map of claims in local dialect. + * @return List of claims. + */ + private List buildGroupMetaClaimsList(Map claimsInLocalDialect) { + + List claimsList = new ArrayList<>(); + for (Map.Entry entry : claimsInLocalDialect.entrySet()) { + String claimUri = entry.getKey(); + if (RESOURCE_TYPE_CLAIM.equals(claimUri)) { + continue; + } + claimsList.add(new Claim(entry.getKey(), entry.getValue())); + } + return claimsList; + } + @Override public Group getGroup(String id, Map requiredAttributes) throws CharonException { @@ -2810,11 +2824,9 @@ public void deleteGroup(String groupId) throws NotFoundException, CharonExceptio SCIMCommonUtils.setThreadLocalIsManagedThroughSCIMEP(true); // Get group name by id. - SCIMGroupHandler groupHandler = new SCIMGroupHandler(carbonUM.getTenantId()); - String groupName = groupHandler.getGroupName(groupId); - + String groupName = carbonUM.getGroupNameByGroupId(groupId); if (groupName != null) { - String userStoreDomainFromSP = null; + String userStoreDomainFromSP; try { userStoreDomainFromSP = getUserStoreDomainFromSP(); } catch (IdentityApplicationManagementException e) { @@ -2825,24 +2837,19 @@ public void deleteGroup(String groupId) throws NotFoundException, CharonExceptio 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)) { + 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); + // Delete group in carbon UM. + carbonUM.deleteGroup(groupId); carbonUM.removeGroupRoleMappingByGroupName(groupName); - - //we do not update Identity_SCIM DB here since it is updated in SCIMUserOperationListener's methods. + // 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."); @@ -2851,10 +2858,7 @@ public void deleteGroup(String groupId) throws NotFoundException, CharonExceptio } } 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); } - } @Override @@ -3346,12 +3350,10 @@ private void doPatchGroup(String groupId, String currentGroupName, Map displayNameOperations = new ArrayList<>(); List memberOperations = new ArrayList<>(); String newGroupName = currentGroupName; - for (List patchOperationList : patchOperations.values()) { for (PatchOperation patchOperation : patchOperationList) { if (StringUtils.equals(SCIMConstants.GroupSchemaConstants.DISPLAY_NAME, @@ -3368,7 +3370,7 @@ private void doPatchGroup(String groupId, String currentGroupName, Map addedMembers, Set attributes = new HashMap<>(); + attributes.put(SCIMConstants.CommonSchemaConstants.ID_URI, group.getGroupID()); + // Validate whether date time attributes are in the correct format. + try { + if (StringUtils.isNotBlank(group.getCreatedDate())) { + attributes.put(SCIMConstants.CommonSchemaConstants.CREATED_URI, + AttributeUtil.formatDateTime(AttributeUtil.parseDateTime(group.getCreatedDate()))); + } + if (StringUtils.isNotBlank(group.getLastModifiedDate())) { + attributes.put(SCIMConstants.CommonSchemaConstants.LAST_MODIFIED_URI, + AttributeUtil.formatDateTime(AttributeUtil.parseDateTime(group.getLastModifiedDate()))); + } + } catch (CharonException e) { + throw new UserStoreException(String.format("Error occurred while adding the group: %s in tenant: %s. " + + "Unsupported Datetime formats provided in the request", groupWithDomain, tenantId), e); + } + if (StringUtils.isNotBlank(group.getLastModifiedDate())) { + attributes.put(SCIMConstants.CommonSchemaConstants.LOCATION_URI, group.getLocation()); + } + // Update SCIM tables for storing meta information. + GroupDAO groupDAO = new GroupDAO(); + try { + groupDAO.addSCIMGroupAttributes(tenantId, groupWithDomain, attributes); + } catch (IdentitySCIMException e) { + throw new UserStoreException(String.format("Error occurred while adding the group: %s in tenant: %s", + groupWithDomain, tenantId), e); + } + return true; + } + + @Override + public boolean deleteGroupByName(String groupName, UserStoreManager userStoreManager) throws UserStoreException { + + AbstractUserStoreManager abstractUserStoreManager = ((AbstractUserStoreManager) userStoreManager); + boolean isGroupIdEnabled = abstractUserStoreManager.isUniqueGroupIdEnabled(); + if (isGroupIdEnabled) { + if (log.isDebugEnabled()) { + log.debug(String.format("SCIMGroupResolver will not be executed for userstore: %s in " + + "tenant %s since group id support is available in the userstore manager", + abstractUserStoreManager.getRealmConfiguration().getRealmProperty(PROPERTY_DOMAIN_NAME), + abstractUserStoreManager.getTenantId())); + } + return true; + } + int tenantId = abstractUserStoreManager.getTenantId(); + String domain = abstractUserStoreManager.getRealmConfiguration() + .getUserStoreProperty(UserStoreConfigConstants.DOMAIN_NAME); + // User core methods don't append primary domain name to the group name. Hence, we need to do it manually. + String groupWithDomain = + SCIMCommonUtils.getGroupNameWithDomain(UserCoreUtil.addDomainToName(groupName, domain)); + GroupDAO groupDAO = new GroupDAO(); + try { + if (!groupDAO.isExistingGroup(groupWithDomain, tenantId)) { + log.debug(String.format("No group with name: %s found in SCIM tables for tenant: %s", groupWithDomain, + tenantId)); + return true; + } + groupDAO.removeSCIMGroup(tenantId, groupWithDomain); + } catch (IdentitySCIMException e) { + throw new UserStoreException(String.format("Error occurred while removing the group: %s in tenant: %s", + groupWithDomain, tenantId), e); + } + return true; + } + @Override public boolean resolveGroupDomainByGroupId(Group group, int tenantId) throws UserStoreException { diff --git a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/listener/SCIMUserOperationListener.java b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/listener/SCIMUserOperationListener.java index be176a31e..3311f39c6 100644 --- a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/listener/SCIMUserOperationListener.java +++ b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/listener/SCIMUserOperationListener.java @@ -615,15 +615,15 @@ private boolean postAddRole(String roleName, UserStoreManager userStoreManager) !CarbonConstants.ENABLE_LEGACY_AUTHZ_RUNTIME) { scimGroupHandler.addRoleV2MandatoryAttributes(roleNameWithDomain); } else { - scimGroupHandler.addMandatoryAttributes(roleNameWithDomain); + if (!((AbstractUserStoreManager) userStoreManager).isUniqueGroupIdEnabled()) { + scimGroupHandler.addMandatoryAttributes(roleNameWithDomain); + } } } } catch (IdentitySCIMException e) { throw new UserStoreException("Error retrieving group information from SCIM Tables.", e); } - return true; - } catch (org.wso2.carbon.user.api.UserStoreException e) { throw new UserStoreException(e); } diff --git a/pom.xml b/pom.xml index f219e1c0d..752711e4f 100644 --- a/pom.xml +++ b/pom.xml @@ -284,7 +284,7 @@ 3.3.7 6.5.3 3.2.0.wso2v1 - 4.9.18 + 4.10.1 5.25.612 4.13.1 20030203.000129