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 a97c6dcb0..8086c8fc6 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 @@ -289,16 +289,55 @@ public void addSCIMGroupAttributesToSCIMDisabledHybridRoles(int tenantId, } } + /** + * @deprecated Use {@link GroupDAO#updateSCIMGroupAttributesWithUpdatedColumn(int, String, Map)} instead. + * Update SCIM group attributes. + * + * @param tenantId Tenant id. + * @param roleName Group name. + * @param attributes Attributes to be updated. + * @throws IdentitySCIMException If an error occurred while updating the attributes. + */ + @Deprecated public void updateSCIMGroupAttributes(int tenantId, String roleName, Map attributes) throws IdentitySCIMException { - Connection connection = IdentityDatabaseUtil.getDBConnection(); + doUpdateSCIMGroupAttributes(tenantId, roleName, attributes, SQLQueries.UPDATE_ATTRIBUTES_SQL); + } + + /** + * Update SCIM group attributes. + * + * @param tenantId Tenant id. + * @param roleName Group name. + * @param attributes Attributes to be updated. + * @throws IdentitySCIMException If an error occurred while updating the attributes. + */ + public void updateSCIMGroupAttributesWithUpdatedColumn(int tenantId, String roleName, + Map attributes) + throws IdentitySCIMException { + + doUpdateSCIMGroupAttributes(tenantId, roleName, attributes, SQLQueries.UPDATE_ATTRIBUTES_SQL_NEW); + } + + /** + * Do update SCIM group attributes. + * + * @param tenantId Tenant id. + * @param roleName Group name. + * @param attributes Attributes to be updated. + * @param sqlQuery SQL query to update the attributes. + * @throws IdentitySCIMException If an error occurred while updating the attributes. + */ + private void doUpdateSCIMGroupAttributes(int tenantId, String roleName, Map attributes, + String sqlQuery) throws IdentitySCIMException { + + Connection connection = IdentityDatabaseUtil.getDBConnection(true); PreparedStatement prepStmt = null; if (isExistingGroup(SCIMCommonUtils.getGroupNameWithDomain(roleName), tenantId)) { try { - prepStmt = connection.prepareStatement(SQLQueries.UPDATE_ATTRIBUTES_SQL); - + prepStmt = connection.prepareStatement(sqlQuery); prepStmt.setInt(2, tenantId); prepStmt.setString(3, roleName); @@ -308,19 +347,16 @@ public void updateSCIMGroupAttributes(int tenantId, String roleName, prepStmt.setString(4, entry.getKey()); prepStmt.setString(1, entry.getValue()); prepStmt.addBatch(); - } else { throw new IdentitySCIMException("Error when adding SCIM Attribute: " - + entry.getKey() - + " An attribute with the same name doesn't exists."); + + entry.getKey() + " An attribute with the same name doesn't exists."); } } - int[] return_count = prepStmt.executeBatch(); + int[] returnCount = prepStmt.executeBatch(); if (log.isDebugEnabled()) { - log.debug("No. of records updated for updating SCIM Group : " + return_count.length); + log.debug("No. of records updated for updating SCIM Group : " + returnCount.length); } connection.commit(); - } catch (SQLException e) { throw new IdentitySCIMException("Error updating the SCIM Group Attributes.", e); } finally { diff --git a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/DAO/SQLQueries.java b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/DAO/SQLQueries.java index d63eb6d41..614ce1013 100644 --- a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/DAO/SQLQueries.java +++ b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/DAO/SQLQueries.java @@ -41,10 +41,15 @@ public class SQLQueries { public static final String CHECK_EXISTING_ATTRIBUTE_WITH_AUDIENCE_SQL = "SELECT TENANT_ID, ROLE_NAME, ATTR_NAME FROM IDN_SCIM_GROUP WHERE IDN_SCIM_GROUP.TENANT_ID=? AND " + "IDN_SCIM_GROUP.ROLE_NAME=? AND IDN_SCIM_GROUP.ATTR_NAME=? AND IDN_SCIM_GROUP.AUDIENCE_REF_ID=?"; + + @Deprecated public static final String UPDATE_ATTRIBUTES_SQL = "UPDATE IDN_SCIM_GROUP SET UM_ATTR_VALUE=? WHERE TENANT_ID=? AND ROLE_NAME=? AND ATTR_NAME=?"; + public static final String UPDATE_ATTRIBUTES_SQL_NEW = + "UPDATE IDN_SCIM_GROUP SET ATTR_VALUE=? WHERE TENANT_ID=? AND ROLE_NAME=? AND ATTR_NAME=?"; public static final String UPDATE_GROUP_NAME_SQL = "UPDATE IDN_SCIM_GROUP SET ROLE_NAME=? WHERE TENANT_ID=? AND ROLE_NAME=?"; + public static final String DELETE_GROUP_SQL = "DELETE FROM IDN_SCIM_GROUP WHERE TENANT_ID=? AND ROLE_NAME=?"; public static final String CHECK_EXISTING_ATTRIBUTE_SQL = diff --git a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/group/SCIMGroupHandler.java b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/group/SCIMGroupHandler.java index ad316edb8..2fedb3052 100644 --- a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/group/SCIMGroupHandler.java +++ b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/group/SCIMGroupHandler.java @@ -335,4 +335,17 @@ public String[] getGroupListFromAttributeName(String attributeName, String searc GroupDAO groupDAO = new GroupDAO(); return groupDAO.getGroupNameList(attributeName, searchAttribute, this.tenantId, domainName); } + + /** + * Update SCIM attributes of the group. + * + * @param groupName The display name of the group. + * @param attributes The attributes to be updated. + * @throws IdentitySCIMException IdentitySCIMException when updating the SCIM Group information. + */ + public void updateSCIMAttributes(String groupName, Map attributes) throws IdentitySCIMException { + + GroupDAO groupDAO = new GroupDAO(); + groupDAO.updateSCIMGroupAttributesWithUpdatedColumn(tenantId, groupName, attributes); + } } diff --git a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/impl/SCIMUserManager.java b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/impl/SCIMUserManager.java index 33b7c806c..2c05a8eae 100644 --- a/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/impl/SCIMUserManager.java +++ b/components/org.wso2.carbon.identity.scim2.common/src/main/java/org/wso2/carbon/identity/scim2/common/impl/SCIMUserManager.java @@ -508,7 +508,7 @@ public User getUser(String userId, Map requiredAttributes) thro throw resolveError(e, errMsg); } } catch (BadRequestException | NotImplementedException e) { - throw new CharonException("Error in getting user information from Carbon User Store", e); + throw new CharonException("Error in getting user information from Carbon User Store", e); } return scimUser; } @@ -601,7 +601,7 @@ public void deleteUser(String userId) throws NotFoundException, CharonException, @Override @Deprecated public UsersGetResponse listUsersWithGET(Node rootNode, int startIndex, int count, String sortBy, String sortOrder, - String domainName, Map requiredAttributes) + String domainName, Map requiredAttributes) throws CharonException, NotImplementedException, BadRequestException { if (sortBy != null || sortOrder != null) { @@ -615,7 +615,7 @@ public UsersGetResponse listUsersWithGET(Node rootNode, int startIndex, int coun @Override public UsersGetResponse listUsersWithGET(Node rootNode, Integer startIndex, Integer count, String sortBy, - String sortOrder, String domainName, Map requiredAttributes) + String sortOrder, String domainName, Map requiredAttributes) throws CharonException, NotImplementedException, BadRequestException { // Validate NULL value for startIndex. @@ -689,7 +689,7 @@ private Resource getResourceByTenantId(int tenantId) throws org.wso2.carbon.user * @throws BadRequestException */ private UsersGetResponse listUsers(Map requiredAttributes, int offset, Integer limit, - String sortBy, String sortOrder, String domainName) throws CharonException, + String sortBy, String sortOrder, String domainName) throws CharonException, BadRequestException { List scimUsers = new ArrayList<>(); @@ -980,7 +980,7 @@ private Set listUsernamesAcrossAllDomains * @throws CharonException Error while retrieving users */ private List getUserDetails(Set coreUsers, - Map requiredAttributes) + Map requiredAttributes) throws CharonException, BadRequestException { List users = new ArrayList<>(); @@ -1410,7 +1410,7 @@ private int handleLimitEqualsNULL(Integer limit) { * @throws BadRequestException */ private UsersGetResponse filterUsers(Node node, Map requiredAttributes, int offset, Integer limit, - String sortBy, String sortOrder, String domainName) throws CharonException, + String sortBy, String sortOrder, String domainName) throws CharonException, BadRequestException { // Handle limit equals NULL scenario. @@ -3503,6 +3503,9 @@ private void doPatchGroup(String groupId, String currentGroupName, Map displayNameOperations = new ArrayList<>(); List memberOperations = new ArrayList<>(); String newGroupName = currentGroupName; + Date groupLastUpdatedTime = null; + String groupNameForIDNScim = SCIMCommonUtils.getGroupNameWithDomain(currentGroupName); + for (List patchOperationList : patchOperations.values()) { for (PatchOperation patchOperation : patchOperationList) { if (StringUtils.equals(SCIMConstants.GroupSchemaConstants.DISPLAY_NAME, @@ -3519,7 +3522,14 @@ private void doPatchGroup(String groupId, String currentGroupName, Map attributes = new HashMap<>(); + attributes.put(SCIMConstants.CommonSchemaConstants.LAST_MODIFIED_URI, + AttributeUtil.formatDateTime(groupLastUpdatedTime.toInstant())); + SCIMGroupHandler groupHandler = new SCIMGroupHandler(carbonUM.getTenantId()); + groupHandler.updateSCIMAttributes(groupNameForIDNScim, attributes); + } } catch (UserStoreException e) { if (e instanceof org.wso2.carbon.user.core.UserStoreException && (StringUtils .equals(UserCoreErrorConstants.ErrorMessages.ERROR_CODE_DUPLICATE_WHILE_WRITING_TO_DATABASE @@ -3676,12 +3696,10 @@ private void prepareAddedRemovedMemberLists(Set addedMembers, Set re public boolean doUpdateGroup(Group oldGroup, Group newGroup) throws CharonException, IdentitySCIMException, BadRequestException, IdentityApplicationManagementException, org.wso2.carbon.user.core.UserStoreException { + Date groupLastUpdatedTime = null; + String groupNameForIDNScim = SCIMCommonUtils.getGroupNameWithDomain(oldGroup.getDisplayName()); + setGroupDisplayName(oldGroup, newGroup); if (log.isDebugEnabled()) { log.debug("Updating group: " + oldGroup.getDisplayName()); @@ -3806,6 +3836,8 @@ public boolean doUpdateGroup(Group oldGroup, Group newGroup) throws CharonExcept // Update group name in carbon UM carbonUM.renameGroup(oldGroup.getId(), newGroupDisplayName); updated = true; + groupLastUpdatedTime = new Date(); + groupNameForIDNScim = SCIMCommonUtils.getGroupNameWithDomain(newGroupDisplayName); } // Update the group with added members and deleted members. if (isNotEmpty(addedMembers) || isNotEmpty(deletedMembers)) { @@ -3813,7 +3845,18 @@ public boolean doUpdateGroup(Group oldGroup, Group newGroup) throws CharonExcept deletedMemberIdsFromUserstore.toArray(new String[0]), addedMemberIdsFromUserstore.toArray(new String[0])); updated = true; + groupLastUpdatedTime = new Date(); + } + + // Update the last modified time of the group. + if (!carbonUM.isUniqueGroupIdEnabled() && groupLastUpdatedTime != null) { + Map attributes = new HashMap<>(); + attributes.put(SCIMConstants.CommonSchemaConstants.LAST_MODIFIED_URI, + AttributeUtil.formatDateTime(groupLastUpdatedTime.toInstant())); + SCIMGroupHandler groupHandler = new SCIMGroupHandler(carbonUM.getTenantId()); + groupHandler.updateSCIMAttributes(groupNameForIDNScim, attributes); } + return updated; }