From e403a92db9137c843bafcc73f31cea91da746e93 Mon Sep 17 00:00:00 2001 From: Saad Sahibjan Date: Thu, 24 Jun 2021 13:10:20 +0530 Subject: [PATCH 1/8] Add PARENT_PATH column to DM_GROUP table --- .../src/main/resources/dbscripts/cdm/h2.sql | 3 ++- .../src/main/resources/dbscripts/cdm/mssql.sql | 3 ++- .../src/main/resources/dbscripts/cdm/mysql.sql | 3 ++- .../src/main/resources/dbscripts/cdm/oracle.sql | 3 ++- .../src/main/resources/dbscripts/cdm/postgresql.sql | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql index 0fb5fc7c42..4a75bb8ca6 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql @@ -23,6 +23,7 @@ CREATE TABLE IF NOT EXISTS DM_GROUP ( STATUS VARCHAR(50) DEFAULT NULL, DESCRIPTION TEXT DEFAULT NULL, OWNER VARCHAR(255) DEFAULT NULL, + PARENT_PATH VARCHAR(255) DEFAULT NULL, TENANT_ID INTEGER DEFAULT 0, PRIMARY KEY (ID) ); @@ -722,4 +723,4 @@ CREATE TABLE IF NOT EXISTS DM_GEOFENCE_EVENT_MAPPING ( DM_DEVICE_EVENT (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ); --- END OF DM_GEOFENCE_GROUP_MAPPING TABLE-- \ No newline at end of file +-- END OF DM_GEOFENCE_GROUP_MAPPING TABLE-- diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql index c70277074a..da1d79c4e2 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql @@ -32,6 +32,7 @@ IF NOT EXISTS(SELECT * STATUS VARCHAR(50) DEFAULT NULL, DESCRIPTION VARCHAR(MAX) DEFAULT NULL, OWNER VARCHAR(255) DEFAULT NULL, + PARENT_PATH VARCHAR(255) DEFAULT NULL, TENANT_ID INTEGER DEFAULT 0, PRIMARY KEY (ID) ); @@ -714,4 +715,4 @@ CREATE TABLE DM_GEOFENCE ( PRIMARY KEY (ID) ); --- END OF DM_GEOFENCE TABLE-- \ No newline at end of file +-- END OF DM_GEOFENCE TABLE-- diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql index 6ba30303b8..1739b079e7 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql @@ -27,6 +27,7 @@ CREATE TABLE IF NOT EXISTS DM_GROUP ( STATUS VARCHAR(50) DEFAULT NULL, DESCRIPTION TEXT DEFAULT NULL, OWNER VARCHAR(255) DEFAULT NULL, + PARENT_PATH VARCHAR(255) DEFAULT NULL, TENANT_ID INTEGER DEFAULT 0, PRIMARY KEY (ID) ) @@ -786,4 +787,4 @@ CREATE TABLE IF NOT EXISTS DM_GEOFENCE_EVENT_MAPPING ( DM_DEVICE_EVENT (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB; --- END OF DM_GEOFENCE_GROUP_MAPPING TABLE-- \ No newline at end of file +-- END OF DM_GEOFENCE_GROUP_MAPPING TABLE-- diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql index de19680e81..7c23e51138 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql @@ -50,6 +50,7 @@ CREATE TABLE DM_GROUP ( GROUP_NAME VARCHAR2(100) DEFAULT NULL, STATUS VARCHAR2(50) DEFAULT NULL, OWNER VARCHAR2(255) DEFAULT NULL, + PARENT_PATH VARCHAR2(255) DEFAULT NULL, TENANT_ID NUMBER(10) DEFAULT 0, CONSTRAINT PK_DM_GROUP PRIMARY KEY (ID) ) @@ -1083,4 +1084,4 @@ CREATE TABLE DM_GEOFENCE ( CONSTRAINT PK_DM_GEOFENCE PRIMARY KEY (ID) ); --- END OF DM_GEOFENCE TABLE-- \ No newline at end of file +-- END OF DM_GEOFENCE TABLE-- diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql index db431497e8..bd8eb8771a 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql @@ -21,6 +21,7 @@ CREATE TABLE IF NOT EXISTS DM_GROUP ( GROUP_NAME VARCHAR(100) DEFAULT NULL, DESCRIPTION TEXT DEFAULT NULL, OWNER VARCHAR(45) DEFAULT NULL, + PARENT_PATH VARCHAR(255) DEFAULT NULL, TENANT_ID INTEGER DEFAULT 0, PRIMARY KEY (ID) ) @@ -732,4 +733,4 @@ CREATE TABLE IF NOT EXISTS DM_GEOFENCE ( PRIMARY KEY (ID) ); --- END OF DM_GEOFENCE TABLE-- \ No newline at end of file +-- END OF DM_GEOFENCE TABLE-- From f1892f726d6a36c64cc4d96eaed274ff3363b37a Mon Sep 17 00:00:00 2001 From: Saad Sahibjan Date: Thu, 24 Jun 2021 13:15:12 +0530 Subject: [PATCH 2/8] Update device group and request beans classes to have new variable --- .../mgt/common/GroupPaginationRequest.java | 35 +++++++++++++ .../mgt/common/group/mgt/DeviceGroup.java | 50 +++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/GroupPaginationRequest.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/GroupPaginationRequest.java index d7a74f199b..9402d2ab37 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/GroupPaginationRequest.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/GroupPaginationRequest.java @@ -14,6 +14,23 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.common; @@ -28,6 +45,8 @@ public class GroupPaginationRequest { private String owner; private String groupName; private String status; + private String parentPath; + private int depth; public GroupPaginationRequest(int start, int rowCount) { this.startIndex = start; @@ -74,6 +93,22 @@ public class GroupPaginationRequest { this.groupName = groupName; } + public String getParentPath() { + return parentPath; + } + + public void setParentPath(String parentPath) { + this.parentPath = parentPath; + } + + public int getDepth() { + return depth; + } + + public void setDepth(int depth) { + this.depth = depth; + } + @Override public String toString() { return "Group Name '" + this.groupName + "' num of rows: " + this.rowCount + " start index: " + this.startIndex diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroup.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroup.java index 20ed01fb49..a3511033d5 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroup.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroup.java @@ -14,6 +14,23 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.common.group.mgt; @@ -21,6 +38,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import java.io.Serializable; +import java.util.List; import java.util.Map; /** @@ -47,6 +65,15 @@ public class DeviceGroup implements Serializable { @ApiModelProperty(name = "status", value = "The status of group that needs updating/retrieval.") private String status; + @ApiModelProperty(name = "parentGroupId", value = "Group ID of parent group") + private int parentGroupId; + + @ApiModelProperty(name = "parentPath", value = "Path of parent group") + private String parentPath; + + @ApiModelProperty(name = "childrenGroups", value = "Children groups") + private List childrenGroups; + public String getStatus() { return status; } @@ -103,4 +130,27 @@ public class DeviceGroup implements Serializable { this.groupProperties = groupProperties; } + public int getParentGroupId() { + return parentGroupId; + } + + public void setParentGroupId(int parentGroupId) { + this.parentGroupId = parentGroupId; + } + + public String getParentPath() { + return parentPath; + } + + public void setParentPath(String parentPath) { + this.parentPath = parentPath; + } + + public List getChildrenGroups() { + return childrenGroups; + } + + public void setChildrenGroups(List childrenGroups) { + this.childrenGroups = childrenGroups; + } } From e22d9fd8fc5bed372c384e0c3019e65851f24d23 Mon Sep 17 00:00:00 2001 From: Saad Sahibjan Date: Thu, 24 Jun 2021 19:57:45 +0530 Subject: [PATCH 3/8] Add and update dao layer methods related to hierarchical changes --- .../carbon/device/mgt/core/dao/GroupDAO.java | 78 +++- .../core/dao/impl/AbstractGroupDAOImpl.java | 360 +++++++++++++++++- .../dao/impl/group/GenericGroupDAOImpl.java | 150 +------- .../dao/impl/group/OracleGroupDAOImpl.java | 38 +- .../impl/group/PostgreSQLGroupDAOImpl.java | 156 ++------ .../dao/impl/group/SQLServerGroupDAOImpl.java | 38 +- .../core/dao/util/GroupManagementDAOUtil.java | 17 + 7 files changed, 542 insertions(+), 295 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/GroupDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/GroupDAO.java index 79b536feaa..9ba4e36283 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/GroupDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/GroupDAO.java @@ -14,6 +14,23 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.core.dao; @@ -74,6 +91,15 @@ public interface GroupDAO { */ void deleteAllGroupProperties(int groupId, int tenantId) throws GroupManagementDAOException; + /** + * Remove properties of device groups. + * + * @param groupIds to be deleted. + * @param tenantId of the group. + * @throws GroupManagementDAOException on error during deletion of group properties of groups + */ + void deleteAllGroupsProperties(List groupIds, int tenantId) throws GroupManagementDAOException; + /** * Retrives all properties stored against a group. * @@ -95,6 +121,15 @@ public interface GroupDAO { void updateGroup(DeviceGroup deviceGroup, int groupId, int tenantId) throws GroupManagementDAOException; + /** + * Update existing Device Groups. + * + * @param deviceGroups groups to update. + * @param tenantId of the group. + * @throws GroupManagementDAOException on error during updating of groups + */ + void updateGroups(List deviceGroups, int tenantId) throws GroupManagementDAOException; + /** * Delete an existing Device Group. * @@ -104,6 +139,24 @@ public interface GroupDAO { */ void deleteGroup(int groupId, int tenantId) throws GroupManagementDAOException; + /** + * Delete mappings of Device Groups. + * + * @param groupIds of Device Groups. + * @param tenantId of the group. + * @throws GroupManagementDAOException on error during deletion of mappings of groups + */ + void deleteGroupsMapping(List groupIds, int tenantId) throws GroupManagementDAOException; + + /** + * Delete existing Device Groups. + * + * @param groupIds of Device Groups. + * @param tenantId of the group. + * @throws GroupManagementDAOException on error during deletion of groups + */ + void deleteGroups(List groupIds, int tenantId) throws GroupManagementDAOException; + /** * Get device group by id. * @@ -114,6 +167,25 @@ public interface GroupDAO { */ DeviceGroup getGroup(int groupId, int tenantId) throws GroupManagementDAOException; + /** + * Get children groups by parent path. + * + * @param parentPath of parent group. + * @param tenantId of the group. + * @return {@link List} list of children device groups + * @throws GroupManagementDAOException on error during retrieval of children groups + */ + List getChildrenGroups(String parentPath, int tenantId) throws GroupManagementDAOException; + + /** + * Get root groups. + * + * @param tenantId of the group. + * @return {@link List} list of root device groups + * @throws GroupManagementDAOException on error during retrieval of root groups + */ + List getRootGroups(int tenantId) throws GroupManagementDAOException; + /** * Get the groups of device with device id provided * @param deviceId @@ -306,10 +378,11 @@ public interface GroupDAO { * * @param roles of the group. * @param tenantId of user's tenant. + * @param parentPath of the group. * @return count of device groups. * @throws GroupManagementDAOException */ - int getGroupsCount(String[] roles, int tenantId) throws GroupManagementDAOException; + int getGroupsCount(String[] roles, int tenantId, String parentPath) throws GroupManagementDAOException; /** * Get all device groups which owned by user. @@ -336,10 +409,11 @@ public interface GroupDAO { * * @param username of the owner. * @param tenantId of user's tenant. + * @param parentPath of the group. * @return count of device groups. * @throws GroupManagementDAOException */ - int getOwnGroupsCount(String username, int tenantId) throws GroupManagementDAOException; + int getOwnGroupsCount(String username, int tenantId, String parentPath) throws GroupManagementDAOException; /** * Get device Ids of devices which are assigned to groups. diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java index 04d4bce584..c3426e3521 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractGroupDAOImpl.java @@ -14,18 +14,34 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.core.dao.impl; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.solr.common.StringUtils; import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.GroupPaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; -import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.GroupDAO; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOFactory; @@ -49,6 +65,127 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { private static final Log log = LogFactory.getLog(AbstractGroupDAOImpl.class); + @Override + public List getGroups(GroupPaginationRequest request, int tenantId) + throws GroupManagementDAOException { + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE TENANT_ID = ?"; + if (StringUtils.isNotBlank(request.getGroupName())) { + sql += " AND UPPER(GROUP_NAME) LIKE ?"; + } + if (StringUtils.isNotBlank(request.getOwner())) { + sql += " AND UPPER(OWNER) LIKE ?"; + } + if (StringUtils.isNotBlank(request.getStatus())) { + sql += " AND STATUS = ?"; + } + if (StringUtils.isNotBlank(request.getParentPath())) { + sql += " AND PARENT_PATH LIKE ?"; + } + if (request.getRowCount() != 0) { + sql += " LIMIT ? OFFSET ?"; + } + + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + int paramIndex = 1; + stmt.setInt(paramIndex++, tenantId); + if (StringUtils.isNotBlank(request.getGroupName())) { + stmt.setString(paramIndex++, request.getGroupName() + "%"); + } + if (StringUtils.isNotBlank(request.getOwner())) { + stmt.setString(paramIndex++, request.getOwner() + "%"); + } + if (StringUtils.isNotBlank(request.getStatus())) { + stmt.setString(paramIndex++, request.getStatus().toUpperCase()); + } + if (StringUtils.isNotBlank(request.getParentPath())) { + stmt.setString(paramIndex++, request.getParentPath()); + } + if (request.getRowCount() != 0) { + stmt.setInt(paramIndex++, request.getRowCount()); + stmt.setInt(paramIndex, request.getStartIndex()); + } + List deviceGroupList = new ArrayList<>(); + try (ResultSet resultSet = stmt.executeQuery()) { + while (resultSet.next()) { + deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet)); + } + } + return deviceGroupList; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving groups in tenant: " + tenantId; + log.error(msg); + throw new GroupManagementDAOException(msg, e); + } + } + + @Override + public List getGroups(GroupPaginationRequest request, List deviceGroupIds, + int tenantId) throws GroupManagementDAOException { + int deviceGroupIdsCount = deviceGroupIds.size(); + if (deviceGroupIdsCount == 0) { + return new ArrayList<>(); + } + + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP WHERE TENANT_ID = ?"; + if (StringUtils.isNotBlank(request.getGroupName())) { + sql += " AND GROUP_NAME LIKE ?"; + } + if (StringUtils.isNotBlank(request.getOwner())) { + sql += " AND OWNER LIKE ?"; + } + if (StringUtils.isNotBlank(request.getParentPath())) { + sql += " AND PARENT_PATH LIKE ?"; + } + sql += " AND ID IN ("; + for (int i = 0; i < deviceGroupIdsCount; i++) { + sql += (deviceGroupIdsCount - 1 != i) ? "?," : "?"; + } + sql += ")"; + if (request.getRowCount() != 0) { + sql += " LIMIT ? OFFSET ?"; + } + + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + int paramIndex = 1; + stmt.setInt(paramIndex++, tenantId); + if (StringUtils.isNotBlank(request.getGroupName())) { + stmt.setString(paramIndex++, request.getGroupName() + "%"); + } + if (StringUtils.isNotBlank(request.getOwner())) { + stmt.setString(paramIndex++, request.getOwner() + "%"); + } + if (StringUtils.isNotBlank(request.getParentPath())) { + stmt.setString(paramIndex++, request.getParentPath()); + } + for (Integer deviceGroupId : deviceGroupIds) { + stmt.setInt(paramIndex++, deviceGroupId); + } + if (request.getRowCount() != 0) { + stmt.setInt(paramIndex++, request.getRowCount()); + stmt.setInt(paramIndex, request.getStartIndex()); + } + List deviceGroupList = new ArrayList<>(); + try (ResultSet resultSet = stmt.executeQuery()) { + while (resultSet.next()) { + deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet)); + } + } + return deviceGroupList; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving groups of groups IDs " + deviceGroupIds.toString() + + " in tenant: " + tenantId; + log.error(msg); + throw new GroupManagementDAOException(msg, e); + } + } + @Override public int addGroup(DeviceGroup deviceGroup, int tenantId) throws GroupManagementDAOException { PreparedStatement stmt = null; @@ -59,9 +196,11 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { Connection conn = GroupManagementDAOFactory.getConnection(); String sql; if (deviceGroup.getStatus() == null || deviceGroup.getStatus().isEmpty()) { - sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID) VALUES (?, ?, ?, ?)"; + sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID, PARENT_PATH) " + + "VALUES (?, ?, ?, ?, ?)"; } else { - sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID, STATUS) VALUES (?, ?, ?, ?, ?)"; + sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID, PARENT_PATH, STATUS) " + + "VALUES (?, ?, ?, ?, ?, ?)"; hasStatus = true; } stmt = conn.prepareStatement(sql, new String[]{"ID"}); @@ -69,8 +208,9 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { stmt.setString(2, deviceGroup.getName()); stmt.setString(3, deviceGroup.getOwner()); stmt.setInt(4, tenantId); + stmt.setString(5, deviceGroup.getParentPath()); if (hasStatus) { - stmt.setString(5, deviceGroup.getStatus()); + stmt.setString(6, deviceGroup.getStatus()); } stmt.executeUpdate(); @@ -151,10 +291,12 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { try { Connection conn = GroupManagementDAOFactory.getConnection(); String sql = - "UPDATE DM_GROUP SET DESCRIPTION = ?, GROUP_NAME = ?, OWNER = ? WHERE ID = ? AND TENANT_ID = ?"; + "UPDATE DM_GROUP SET DESCRIPTION = ?, GROUP_NAME = ?, OWNER = ?, PARENT_PATH = ? WHERE ID = ? " + + "AND TENANT_ID = ?"; if (deviceGroup.getStatus() != null && !deviceGroup.getStatus().isEmpty()) { - sql = "UPDATE DM_GROUP SET DESCRIPTION = ?, GROUP_NAME = ?, OWNER = ?, STATUS = ? WHERE ID = ? AND TENANT_ID = ?"; + sql = "UPDATE DM_GROUP SET DESCRIPTION = ?, GROUP_NAME = ?, OWNER = ?, PARENT_PATH = ?, STATUS = ? " + + "WHERE ID = ? AND TENANT_ID = ?"; hasStatus = true; } stmt = conn.prepareStatement(sql); @@ -162,11 +304,12 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { stmt.setString(paramIndex++, deviceGroup.getDescription()); stmt.setString(paramIndex++, deviceGroup.getName()); stmt.setString(paramIndex++, deviceGroup.getOwner()); + stmt.setString(paramIndex++, deviceGroup.getParentPath()); if (hasStatus) { stmt.setString(paramIndex++, deviceGroup.getStatus()); } stmt.setInt(paramIndex++, groupId); - stmt.setInt(paramIndex++, tenantId); + stmt.setInt(paramIndex, tenantId); stmt.executeUpdate(); } catch (SQLException e) { throw new GroupManagementDAOException("Error occurred while updating deviceGroup '" + @@ -176,6 +319,32 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } } + @Override + public void updateGroups(List deviceGroups, int tenantId) throws GroupManagementDAOException { + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + String sql = "UPDATE DM_GROUP SET DESCRIPTION = ?, GROUP_NAME = ?, OWNER = ?, STATUS = ?, " + + "PARENT_PATH = ? WHERE ID = ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)){ + for (DeviceGroup deviceGroup : deviceGroups) { + stmt.setString(1, deviceGroup.getDescription()); + stmt.setString(2, deviceGroup.getName()); + stmt.setString(3, deviceGroup.getOwner()); + stmt.setString(4, deviceGroup.getStatus()); + stmt.setString(5, deviceGroup.getParentPath()); + stmt.setInt(6, deviceGroup.getGroupId()); + stmt.setInt(7, tenantId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while updating groups as batch"; + log.error(msg); + throw new GroupManagementDAOException(msg, e); + } + } + @Override public void deleteGroup(int groupId, int tenantId) throws GroupManagementDAOException { Connection conn; @@ -217,6 +386,64 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } } + @Override + public void deleteGroupsMapping(List groupIds, int tenantId) throws GroupManagementDAOException { + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + String sql = "DELETE FROM DM_ROLE_GROUP_MAP WHERE GROUP_ID = ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (int groupId : groupIds) { + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + sql = "DELETE FROM DM_DEVICE_GROUP_MAP WHERE GROUP_ID = ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (int groupId : groupIds) { + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + sql = "DELETE FROM DM_DEVICE_GROUP_POLICY WHERE DEVICE_GROUP_ID = ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (int groupId : groupIds) { + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while removing mappings of groups as batches"; + log.error(msg); + throw new GroupManagementDAOException(msg, e); + } + } + + @Override + public void deleteGroups(List groupIds, int tenantId) throws GroupManagementDAOException { + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + String sql = "DELETE FROM DM_GROUP WHERE ID = ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (int groupId : groupIds) { + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + stmt.addBatch(); + } + stmt.executeBatch(); + } + } catch (SQLException e) { + String msg = "Error occurred while deleting groups as batches"; + log.error(msg); + throw new GroupManagementDAOException(msg, e); + } + } + public void deleteAllGroupProperties(int groupId, int tenantId) throws GroupManagementDAOException { PreparedStatement stmt = null; @@ -235,6 +462,25 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } } + public void deleteAllGroupsProperties(List groupIds, int tenantId) throws GroupManagementDAOException { + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + String sql = "DELETE FROM GROUP_PROPERTIES WHERE GROUP_ID = ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + for (Integer groupId : groupIds) { + stmt.setInt(1, groupId); + stmt.setInt(2, tenantId); + stmt.addBatch(); + } + stmt.executeUpdate(); + } + } catch (SQLException e) { + String msg = "Error occurred while deleting properties of groups as batches"; + log.error(msg); + throw new GroupManagementDAOException(msg, e); + } + } + public Map getAllGroupProperties(int groupId, int tenantId) throws GroupManagementDAOException { PreparedStatement stmt = null; @@ -266,7 +512,8 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { ResultSet resultSet = null; try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE ID = ? AND TENANT_ID = ?"; + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP WHERE ID = ? " + + "AND TENANT_ID = ?"; stmt = conn.prepareStatement(sql); stmt.setInt(1, groupId); stmt.setInt(2, tenantId); @@ -284,6 +531,56 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } } + @Override + public List getChildrenGroups(String parentPath, int tenantId) throws GroupManagementDAOException { + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE PARENT_PATH LIKE ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, parentPath + "%"); + stmt.setInt(2, tenantId); + List deviceGroupList = new ArrayList<>(); + try (ResultSet resultSet = stmt.executeQuery()) { + while (resultSet.next()) { + deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet)); + } + } + return deviceGroupList; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving children group having parent path '" + parentPath + + "' in tenant: " + tenantId; + log.error(msg); + throw new GroupManagementDAOException(msg, e); + } + } + + @Override + public List getRootGroups(int tenantId) throws GroupManagementDAOException { + try { + Connection conn = GroupManagementDAOFactory.getConnection(); + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE PARENT_PATH LIKE ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, "/"); + stmt.setInt(2, tenantId); + List deviceGroupList = new ArrayList<>(); + try (ResultSet resultSet = stmt.executeQuery()) { + deviceGroupList = new ArrayList<>(); + while (resultSet.next()) { + deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet)); + } + } + return deviceGroupList; + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving root groups in tenant: " + tenantId; + log.error(msg); + throw new GroupManagementDAOException(msg, e); + } + } + @Override public List getGroups(int deviceId, int tenantId) throws GroupManagementDAOException { PreparedStatement stmt = null; @@ -291,7 +588,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { List deviceGroupBuilders = new ArrayList<>(); try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT G.ID, G.GROUP_NAME, G.DESCRIPTION, G.OWNER, G.STATUS FROM DM_GROUP G " + + String sql = "SELECT G.ID, G.GROUP_NAME, G.DESCRIPTION, G.OWNER, G.STATUS, G.PARENT_PATH FROM DM_GROUP G " + "INNER JOIN DM_DEVICE_GROUP_MAP GM ON G.ID = GM.GROUP_ID " + "WHERE GM.DEVICE_ID = ? AND GM.TENANT_ID = ?"; stmt = conn.prepareStatement(sql); @@ -316,7 +613,8 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { List deviceGroupList = null; try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE TENANT_ID = ?"; stmt = conn.prepareStatement(sql); stmt.setInt(1, tenantId); resultSet = stmt.executeQuery(); @@ -389,6 +687,9 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { sql += " AND STATUS = ?"; hasStatus = true; } + if (StringUtils.isNotBlank(request.getParentPath())) { + sql += " AND PARENT_PATH = ?"; + } int paramIndex = 1; stmt = conn.prepareStatement(sql); @@ -397,10 +698,13 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { stmt.setString(paramIndex++, groupName + "%"); } if (hasOwner) { - stmt.setString(paramIndex, owner + "%"); + stmt.setString(paramIndex++, owner + "%"); } if (hasStatus) { - stmt.setString(paramIndex, request.getStatus()); + stmt.setString(paramIndex++, request.getStatus()); + } + if (StringUtils.isNotBlank(request.getParentPath())) { + stmt.setString(paramIndex, request.getParentPath()); } resultSet = stmt.executeQuery(); if (resultSet.next()) { @@ -422,7 +726,8 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { try { Connection conn = GroupManagementDAOFactory.getConnection(); String sql = - "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE GROUP_NAME = ? AND TENANT_ID = ?"; + "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE GROUP_NAME = ? AND TENANT_ID = ?"; stmt = conn.prepareStatement(sql); stmt.setString(1, groupName); stmt.setInt(2, tenantId); @@ -592,7 +897,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { List deviceGroupList = null; try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP g, " + + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP g, " + "(SELECT GROUP_ID FROM DM_ROLE_GROUP_MAP WHERE ROLE IN ("; int index = 0; @@ -658,7 +963,7 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } @Override - public int getGroupsCount(String[] roles, int tenantId) throws GroupManagementDAOException { + public int getGroupsCount(String[] roles, int tenantId, String parentPath) throws GroupManagementDAOException { int rolesCount = roles.length; if (rolesCount == 0) { return 0; @@ -672,14 +977,20 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { for (int i = 0; i < rolesCount; i++) { sql += (rolesCount - 1 != i) ? "?," : "?"; } - sql += ")) gr WHERE g.ID = gr.GROUP_ID AND TENANT_ID = ? GROUP BY g.ID"; - + sql += ")) gr WHERE g.ID = gr.GROUP_ID AND TENANT_ID = ? "; + if (StringUtils.isNotBlank(parentPath)) { + sql += " AND g.PARENT_PATH = ? "; + } + sql += "GROUP BY g.ID"; stmt = conn.prepareStatement(sql); int index = 0; while (index++ < rolesCount) { stmt.setString(index, roles[index - 1]); } - stmt.setInt(index, tenantId); + stmt.setInt(index++, tenantId); + if (StringUtils.isNotBlank(parentPath)) { + stmt.setString(index, parentPath); + } resultSet = stmt.executeQuery(); if (resultSet.next()) { return resultSet.getInt("GROUP_COUNT"); @@ -700,7 +1011,8 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { List deviceGroupList = null; try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE OWNER = ? AND TENANT_ID = ?"; + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE OWNER = ? AND TENANT_ID = ?"; stmt = conn.prepareStatement(sql); stmt.setString(1, username); stmt.setInt(2, tenantId); @@ -744,15 +1056,21 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } @Override - public int getOwnGroupsCount(String username, int tenantId) throws GroupManagementDAOException { + public int getOwnGroupsCount(String username, int tenantId, String parentPath) throws GroupManagementDAOException { PreparedStatement stmt = null; ResultSet resultSet = null; try { Connection conn = GroupManagementDAOFactory.getConnection(); String sql = "SELECT COUNT(ID) AS GROUP_COUNT FROM DM_GROUP WHERE OWNER = ? AND TENANT_ID = ?"; + if (StringUtils.isNotBlank(parentPath)) { + sql += " AND PARENT_PATH = ?"; + } stmt = conn.prepareStatement(sql); stmt.setString(1, username); stmt.setInt(2, tenantId); + if (StringUtils.isNotBlank(parentPath)) { + stmt.setString(3, parentPath); + } resultSet = stmt.executeQuery(); if (resultSet.next()) { return resultSet.getInt("GROUP_COUNT"); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/GenericGroupDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/GenericGroupDAOImpl.java index d980e9e0ab..96ca67edd0 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/GenericGroupDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/GenericGroupDAOImpl.java @@ -14,18 +14,32 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.core.dao.impl.group; import org.wso2.carbon.device.mgt.common.Device; -import org.wso2.carbon.device.mgt.common.GroupPaginationRequest; -import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.impl.AbstractGroupDAOImpl; import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; -import org.wso2.carbon.device.mgt.core.dao.util.GroupManagementDAOUtil; import java.sql.Connection; import java.sql.PreparedStatement; @@ -38,134 +52,6 @@ import java.util.List; * This class represents implementation of GroupDAO */ public class GenericGroupDAOImpl extends AbstractGroupDAOImpl { - @Override - public List getGroups(GroupPaginationRequest request, int tenantId) - throws GroupManagementDAOException { - PreparedStatement stmt = null; - ResultSet resultSet = null; - List deviceGroupList = null; - - String groupName = request.getGroupName(); - boolean hasGroupName = false; - String owner = request.getOwner(); - String status = request.getStatus(); - boolean hasOwner = false; - boolean hasStatus = false; - boolean hasLimit = request.getRowCount() != 0; - - try { - Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; - if (groupName != null && !groupName.isEmpty()) { - sql += " AND UPPER(GROUP_NAME) LIKE ?"; - hasGroupName = true; - } - if (owner != null && !owner.isEmpty()) { - sql += " AND UPPER(OWNER) LIKE ?"; - hasOwner = true; - } - if (status != null && !status.isEmpty()) { - sql += " AND STATUS = ?"; - hasStatus = true; - } - if (hasLimit) { - sql += " LIMIT ?, ?"; - } - - int paramIndex = 1; - stmt = conn.prepareStatement(sql); - stmt.setInt(paramIndex++, tenantId); - if (hasGroupName) { - stmt.setString(paramIndex++, groupName + "%"); - } - if (hasOwner) { - stmt.setString(paramIndex++, owner + "%"); - } - if (hasStatus) { - stmt.setString(paramIndex++, status.toUpperCase()); - } - if (hasLimit) { - stmt.setInt(paramIndex++, request.getStartIndex()); - stmt.setInt(paramIndex, request.getRowCount()); - } - resultSet = stmt.executeQuery(); - deviceGroupList = new ArrayList<>(); - while (resultSet.next()) { - deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet)); - } - } catch (SQLException e) { - throw new GroupManagementDAOException("Error occurred while listing all groups in tenant: " + tenantId, e); - } finally { - GroupManagementDAOUtil.cleanupResources(stmt, resultSet); - } - return deviceGroupList; - } - - @Override - public List getGroups(GroupPaginationRequest request, List deviceGroupIds, - int tenantId) throws GroupManagementDAOException { - int deviceGroupIdsCount = deviceGroupIds.size(); - if (deviceGroupIdsCount == 0) { - return new ArrayList<>(); - } - PreparedStatement stmt = null; - ResultSet resultSet = null; - List deviceGroupList = null; - - String groupName = request.getGroupName(); - boolean hasGroupName = false; - String owner = request.getOwner(); - boolean hasOwner = false; - boolean hasLimit = request.getRowCount() != 0; - - try { - Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; - if (groupName != null && !groupName.isEmpty()) { - sql += " AND GROUP_NAME LIKE ?"; - hasGroupName = true; - } - if (owner != null && !owner.isEmpty()) { - sql += " AND OWNER LIKE ?"; - hasOwner = true; - } - sql += " AND ID IN ("; - for (int i = 0; i < deviceGroupIdsCount; i++) { - sql += (deviceGroupIdsCount - 1 != i) ? "?," : "?"; - } - sql += ")"; - if (hasLimit) { - sql += " LIMIT ?, ?"; - } - - int paramIndex = 1; - stmt = conn.prepareStatement(sql); - stmt.setInt(paramIndex++, tenantId); - if (hasGroupName) { - stmt.setString(paramIndex++, groupName + "%"); - } - if (hasOwner) { - stmt.setString(paramIndex++, owner + "%"); - } - for (Integer deviceGroupId : deviceGroupIds) { - stmt.setInt(paramIndex++, deviceGroupId); - } - if (hasLimit) { - stmt.setInt(paramIndex++, request.getStartIndex()); - stmt.setInt(paramIndex, request.getRowCount()); - } - resultSet = stmt.executeQuery(); - deviceGroupList = new ArrayList<>(); - while (resultSet.next()) { - deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet)); - } - } catch (SQLException e) { - throw new GroupManagementDAOException("Error occurred while listing all groups in tenant: " + tenantId, e); - } finally { - GroupManagementDAOUtil.cleanupResources(stmt, resultSet); - } - return deviceGroupList; - } @Override public List getDevices(int groupId, int startIndex, int rowCount, int tenantId) @@ -209,4 +95,4 @@ public class GenericGroupDAOImpl extends AbstractGroupDAOImpl { } return devices; } -} \ No newline at end of file +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/OracleGroupDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/OracleGroupDAOImpl.java index 4074840e0f..e7473b6b53 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/OracleGroupDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/OracleGroupDAOImpl.java @@ -14,10 +14,28 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.core.dao.impl.group; +import org.apache.commons.lang.StringUtils; import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.GroupPaginationRequest; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; @@ -56,7 +74,8 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl { try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE TENANT_ID = ?"; if (groupName != null && !groupName.isEmpty()) { sql += " AND GROUP_NAME LIKE ?"; hasGroupName = true; @@ -69,6 +88,9 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl { sql += " AND STATUS = ?"; hasStatus = true; } + if (StringUtils.isNotBlank(request.getParentPath())) { + sql += " AND PARENT_PATH LIKE ?"; + } if (hasLimit) { sql += " OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; } @@ -85,6 +107,9 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl { if (hasStatus) { stmt.setString(paramIndex++, status.toUpperCase()); } + if (StringUtils.isNotBlank(request.getParentPath())) { + stmt.setString(paramIndex++, request.getParentPath()); + } if (hasLimit) { stmt.setInt(paramIndex++, request.getStartIndex()); stmt.setInt(paramIndex, request.getRowCount()); @@ -121,7 +146,8 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl { try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE TENANT_ID = ?"; if (groupName != null && !groupName.isEmpty()) { sql += " AND GROUP_NAME LIKE ?"; hasGroupName = true; @@ -130,6 +156,9 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl { sql += " AND OWNER LIKE ?"; hasOwner = true; } + if (StringUtils.isNotBlank(request.getParentPath())) { + sql += " AND PARENT_PATH LIKE ?"; + } sql += " AND ID IN ("; for (int i = 0; i < deviceGroupIdsCount; i++) { sql += (deviceGroupIdsCount - 1 != i) ? "?," : "?"; @@ -148,6 +177,9 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl { if (hasOwner) { stmt.setString(paramIndex++, owner + "%"); } + if (StringUtils.isNotBlank(request.getParentPath())) { + stmt.setString(paramIndex++, request.getParentPath()); + } for (Integer deviceGroupId : deviceGroupIds) { stmt.setInt(paramIndex++, deviceGroupId); } @@ -210,4 +242,4 @@ public class OracleGroupDAOImpl extends AbstractGroupDAOImpl { } return devices; } -} \ No newline at end of file +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/PostgreSQLGroupDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/PostgreSQLGroupDAOImpl.java index 4140a5c48a..a01ef5b6b8 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/PostgreSQLGroupDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/PostgreSQLGroupDAOImpl.java @@ -14,13 +14,29 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.core.dao.impl.group; import org.apache.solr.common.StringUtils; import org.wso2.carbon.device.mgt.common.Device; -import org.wso2.carbon.device.mgt.common.GroupPaginationRequest; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOFactory; @@ -50,10 +66,10 @@ public class PostgreSQLGroupDAOImpl extends AbstractGroupDAOImpl { Connection conn = GroupManagementDAOFactory.getConnection(); String sql; if(StringUtils.isEmpty(deviceGroup.getStatus())) { - sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID) " + + sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID, PARENT_PATH) " + "VALUES (?, ?, ?, ?) RETURNING ID"; } else { - sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID, STATUS) " + + sql = "INSERT INTO DM_GROUP(DESCRIPTION, GROUP_NAME, OWNER, TENANT_ID, PARENT_PATH, STATUS) " + "VALUES (?, ?, ?, ?, ?) RETURNING ID"; hasStatus = true; } @@ -62,8 +78,9 @@ public class PostgreSQLGroupDAOImpl extends AbstractGroupDAOImpl { stmt.setString(2, deviceGroup.getName()); stmt.setString(3, deviceGroup.getOwner()); stmt.setInt(4, tenantId); + stmt.setString(5, deviceGroup.getParentPath()); if(hasStatus) { - stmt.setString(5, deviceGroup.getStatus()); + stmt.setString(6, deviceGroup.getStatus()); } stmt.execute(); rs = stmt.getGeneratedKeys(); @@ -79,135 +96,6 @@ public class PostgreSQLGroupDAOImpl extends AbstractGroupDAOImpl { } } - @Override - public List getGroups(GroupPaginationRequest request, int tenantId) - throws GroupManagementDAOException { - PreparedStatement stmt = null; - ResultSet resultSet = null; - List deviceGroupList = null; - - String groupName = request.getGroupName(); - boolean hasGroupName = false; - String owner = request.getOwner(); - String status = request.getStatus(); - boolean hasOwner = false; - boolean hasStatus = false; - boolean hasLimit = request.getRowCount() != 0; - - try { - Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; - if (groupName != null && !groupName.isEmpty()) { - sql += " AND GROUP_NAME LIKE ?"; - hasGroupName = true; - } - if (owner != null && !owner.isEmpty()) { - sql += " AND OWNER LIKE ?"; - hasOwner = true; - } - if (status != null && !status.isEmpty()) { - sql += " AND STATUS = ?"; - hasStatus = true; - } - if (hasLimit) { - sql += " LIMIT ? OFFSET ?"; - } - - int paramIndex = 1; - stmt = conn.prepareStatement(sql); - stmt.setInt(paramIndex++, tenantId); - if (hasGroupName) { - stmt.setString(paramIndex++, groupName + "%"); - } - if (hasOwner) { - stmt.setString(paramIndex++, owner + "%"); - } - if (hasStatus) { - stmt.setString(paramIndex++, status.toUpperCase()); - } - if (hasLimit) { - stmt.setInt(paramIndex++, request.getRowCount()); - stmt.setInt(paramIndex, request.getStartIndex()); - } - resultSet = stmt.executeQuery(); - deviceGroupList = new ArrayList<>(); - while (resultSet.next()) { - deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet)); - } - } catch (SQLException e) { - throw new GroupManagementDAOException("Error occurred while listing all groups in tenant: " + tenantId, e); - } finally { - GroupManagementDAOUtil.cleanupResources(stmt, resultSet); - } - return deviceGroupList; - } - - @Override - public List getGroups(GroupPaginationRequest request, List deviceGroupIds, - int tenantId) throws GroupManagementDAOException { - int deviceGroupIdsCount = deviceGroupIds.size(); - if (deviceGroupIdsCount == 0) { - return new ArrayList<>(); - } - PreparedStatement stmt = null; - ResultSet resultSet = null; - List deviceGroupList = null; - - String groupName = request.getGroupName(); - boolean hasGroupName = false; - String owner = request.getOwner(); - boolean hasOwner = false; - boolean hasLimit = request.getRowCount() != 0; - - try { - Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; - if (groupName != null && !groupName.isEmpty()) { - sql += " AND GROUP_NAME LIKE ?"; - hasGroupName = true; - } - if (owner != null && !owner.isEmpty()) { - sql += " AND OWNER LIKE ?"; - hasOwner = true; - } - sql += " AND ID IN ("; - for (int i = 0; i < deviceGroupIdsCount; i++) { - sql += (deviceGroupIdsCount - 1 != i) ? "?," : "?"; - } - sql += ")"; - if (hasLimit) { - sql += " LIMIT ? OFFSET ?"; - } - - int paramIndex = 1; - stmt = conn.prepareStatement(sql); - stmt.setInt(paramIndex++, tenantId); - if (hasGroupName) { - stmt.setString(paramIndex++, groupName + "%"); - } - if (hasOwner) { - stmt.setString(paramIndex++, owner + "%"); - } - for (Integer deviceGroupId : deviceGroupIds) { - stmt.setInt(paramIndex++, deviceGroupId); - } - if (hasLimit) { - stmt.setInt(paramIndex++, request.getRowCount()); - stmt.setInt(paramIndex, request.getStartIndex()); - } - resultSet = stmt.executeQuery(); - deviceGroupList = new ArrayList<>(); - while (resultSet.next()) { - deviceGroupList.add(GroupManagementDAOUtil.loadGroup(resultSet)); - } - } catch (SQLException e) { - throw new GroupManagementDAOException("Error occurred while listing all groups in tenant: " + tenantId, e); - } finally { - GroupManagementDAOUtil.cleanupResources(stmt, resultSet); - } - return deviceGroupList; - } - @Override public List getDevices(int groupId, int startIndex, int rowCount, int tenantId) throws GroupManagementDAOException { @@ -250,4 +138,4 @@ public class PostgreSQLGroupDAOImpl extends AbstractGroupDAOImpl { } return devices; } -} \ No newline at end of file +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/SQLServerGroupDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/SQLServerGroupDAOImpl.java index 879d450349..5065628b08 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/SQLServerGroupDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/group/SQLServerGroupDAOImpl.java @@ -14,10 +14,28 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.core.dao.impl.group; +import org.apache.commons.lang.StringUtils; import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.GroupPaginationRequest; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; @@ -56,7 +74,8 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl { try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE TENANT_ID = ?"; if (groupName != null && !groupName.isEmpty()) { sql += " AND GROUP_NAME LIKE ?"; hasGroupName = true; @@ -69,6 +88,9 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl { sql += " AND STATUS = ?"; hasStatus = true; } + if (StringUtils.isNotBlank(request.getParentPath())) { + sql += " AND PARENT_PATH LIKE ?"; + } if (hasLimit) { sql += " ORDER BY ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; } @@ -85,6 +107,9 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl { if (hasStatus) { stmt.setString(paramIndex++, status.toUpperCase()); } + if (StringUtils.isNotBlank(request.getParentPath())) { + stmt.setString(paramIndex++, request.getParentPath()); + } if (hasLimit) { stmt.setInt(paramIndex++, request.getStartIndex()); stmt.setInt(paramIndex, request.getRowCount()); @@ -121,7 +146,8 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl { try { Connection conn = GroupManagementDAOFactory.getConnection(); - String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS FROM DM_GROUP WHERE TENANT_ID = ?"; + String sql = "SELECT ID, DESCRIPTION, GROUP_NAME, OWNER, STATUS, PARENT_PATH FROM DM_GROUP " + + "WHERE TENANT_ID = ?"; if (groupName != null && !groupName.isEmpty()) { sql += " AND GROUP_NAME LIKE ?"; hasGroupName = true; @@ -130,6 +156,9 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl { sql += " AND OWNER LIKE ?"; hasOwner = true; } + if (StringUtils.isNotBlank(request.getParentPath())) { + sql += " AND PARENT_PATH LIKE ?"; + } sql += " AND ID IN ("; for (int i = 0; i < deviceGroupIdsCount; i++) { sql += (deviceGroupIdsCount - 1 != i) ? "?," : "?"; @@ -148,6 +177,9 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl { if (hasOwner) { stmt.setString(paramIndex++, owner + "%"); } + if (StringUtils.isNotBlank(request.getParentPath())) { + stmt.setString(paramIndex++, request.getParentPath()); + } for (Integer deviceGroupId : deviceGroupIds) { stmt.setInt(paramIndex++, deviceGroupId); } @@ -210,4 +242,4 @@ public class SQLServerGroupDAOImpl extends AbstractGroupDAOImpl { } return devices; } -} \ No newline at end of file +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/util/GroupManagementDAOUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/util/GroupManagementDAOUtil.java index b3acd1d313..3025fb6d0a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/util/GroupManagementDAOUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/util/GroupManagementDAOUtil.java @@ -14,6 +14,22 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.core.dao.util; @@ -86,6 +102,7 @@ public final class GroupManagementDAOUtil { group.setName(resultSet.getString("GROUP_NAME")); group.setOwner(resultSet.getString("OWNER")); group.setStatus(resultSet.getString("STATUS")); + group.setParentPath(resultSet.getString("PARENT_PATH")); return group; } From 0ae6c6246aa15c577720b01ebb412c4e382e2e91 Mon Sep 17 00:00:00 2001 From: Saad Sahibjan Date: Thu, 24 Jun 2021 20:31:11 +0530 Subject: [PATCH 4/8] Add and update service layer related to hierarchical changes --- .../GroupManagementProviderService.java | 57 +++- .../GroupManagementProviderServiceImpl.java | 269 +++++++++++++++--- .../mgt/core/util/DeviceManagerUtil.java | 13 + 3 files changed, 291 insertions(+), 48 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderService.java index f729218314..c5e7417c86 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderService.java @@ -14,6 +14,23 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.core.service; @@ -60,10 +77,11 @@ public interface GroupManagementProviderService { * Delete existing device group. * * @param groupId to be deleted. + * @param isDeleteChildren to delete the children groups or not. * @return status of the delete operation. * @throws GroupManagementException */ - boolean deleteGroup(int groupId) throws GroupManagementException; + boolean deleteGroup(int groupId, boolean isDeleteChildren) throws GroupManagementException; /** * Get the device group provided the device group id. @@ -75,6 +93,17 @@ public interface GroupManagementProviderService { */ DeviceGroup getGroup(int groupId, boolean requireGroupProps) throws GroupManagementException; + /** + * Get the device group provided the device group id and depth of children groups. + * + * @param groupId of the group. + * @param requireGroupProps to include group properties. + * @param depth of children groups to retrieve. + * @return {@link DeviceGroup} group with details. + * @throws GroupManagementException on error during retrieval of group + */ + DeviceGroup getGroup(int groupId, boolean requireGroupProps, int depth) throws GroupManagementException; + /** * Get the device group provided the device group name. * @@ -85,6 +114,17 @@ public interface GroupManagementProviderService { */ DeviceGroup getGroup(String groupName, boolean requireGroupProps) throws GroupManagementException; + /** + * Get the device group provided the device group id and depth of children groups. + * + * @param groupName of the group. + * @param requireGroupProps to include group properties. + * @param depth of children groups to retrieve. + * @return {@link DeviceGroup} group with details. + * @throws GroupManagementException on error during retrieval of group + */ + DeviceGroup getGroup(String groupName, boolean requireGroupProps, int depth) throws GroupManagementException; + /** * Get all device groups in tenant. * @@ -127,6 +167,18 @@ public interface GroupManagementProviderService { PaginationResult getGroups(String username, GroupPaginationRequest paginationRequest, boolean requireGroupProps) throws GroupManagementException; + /** + * Get device groups with children groups hierarchically which belongs to specified user with pagination. + * + * @param username of the user. + * @param request to filter results + * @param requireGroupProps to include group properties + * @return {@link PaginationResult} paginated groups. + * @throws GroupManagementException on error during retrieval of groups with hierarchy + */ + PaginationResult getGroupsWithHierarchy(String username, GroupPaginationRequest request, + boolean requireGroupProps) throws GroupManagementException; + /** * Get all device group count in tenant * @@ -147,10 +199,11 @@ public interface GroupManagementProviderService { * Get device group count of user * * @param username of the user + * @param parentPath of the group * @return group count * @throws GroupManagementException */ - int getGroupCount(String username) throws GroupManagementException; + int getGroupCount(String username, String parentPath) throws GroupManagementException; /** * Manage device group sharing with user with list of roles. diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java index b28cbefe25..35f4915481 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java @@ -14,10 +14,28 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.core.service; +import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.CarbonConstants; @@ -36,14 +54,12 @@ import org.wso2.carbon.device.mgt.common.group.mgt.GroupAlreadyExistException; import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; import org.wso2.carbon.device.mgt.common.group.mgt.GroupNotExistException; import org.wso2.carbon.device.mgt.common.group.mgt.RoleDoesNotExistException; -import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; import org.wso2.carbon.device.mgt.core.dao.DeviceDAO; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.GroupDAO; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOFactory; -import org.wso2.carbon.device.mgt.core.event.config.EventOperationTaskConfiguration; import org.wso2.carbon.device.mgt.core.event.config.GroupAssignmentEventOperationExecutor; import org.wso2.carbon.device.mgt.core.geo.task.GeoFenceEventOperationManager; import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; @@ -56,10 +72,11 @@ import org.wso2.carbon.user.api.UserStoreManager; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; +import java.util.stream.Collectors; public class GroupManagementProviderServiceImpl implements GroupManagementProviderService { @@ -95,6 +112,20 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid GroupManagementDAOFactory.beginTransaction(); DeviceGroup existingGroup = this.groupDAO.getGroup(deviceGroup.getName(), tenantId); if (existingGroup == null) { + if (deviceGroup.getParentGroupId() == 0) { + deviceGroup.setParentPath("/"); + } else { + DeviceGroup immediateParentGroup = groupDAO.getGroup(deviceGroup.getParentGroupId(), tenantId); + if (immediateParentGroup == null) { + String msg = "Parent group with group ID '" + deviceGroup.getParentGroupId() + + "' does not exist. Hence creating of group '" + deviceGroup.getName() + + "' was not success"; + log.error(msg); + throw new GroupManagementException(msg); + } + String parentPath = DeviceManagerUtil.createParentPath(immediateParentGroup); + deviceGroup.setParentPath(parentPath); + } int updatedGroupID = this.groupDAO.addGroup(deviceGroup, tenantId); if (deviceGroup.getGroupProperties() != null && deviceGroup.getGroupProperties().size() > 0) { this.groupDAO.addGroupProperties(deviceGroup, updatedGroupID, tenantId); @@ -146,6 +177,20 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid GroupManagementDAOFactory.beginTransaction(); DeviceGroup existingGroup = this.groupDAO.getGroup(groupId, tenantId); if (existingGroup != null) { + if (deviceGroup.getParentGroupId() == 0) { + deviceGroup.setParentPath("/"); + } else { + DeviceGroup immediateParentGroup = groupDAO.getGroup(deviceGroup.getParentGroupId(), tenantId); + if (immediateParentGroup == null) { + String msg = "Parent group with group ID '" + deviceGroup.getParentGroupId() + + "' does not exist. Hence updating of group '" + groupId + + "' was not success"; + log.error(msg); + throw new GroupManagementException(msg); + } + String parentPath = DeviceManagerUtil.createParentPath(immediateParentGroup); + deviceGroup.setParentPath(parentPath); + } this.groupDAO.updateGroup(deviceGroup, groupId, tenantId); if (deviceGroup.getGroupProperties() != null && deviceGroup.getGroupProperties().size() > 0) { this.groupDAO.updateGroupProperties(deviceGroup, groupId, tenantId); @@ -178,7 +223,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid * {@inheritDoc} */ @Override - public boolean deleteGroup(int groupId) throws GroupManagementException { + public boolean deleteGroup(int groupId, boolean isDeleteChildren) throws GroupManagementException { if (log.isDebugEnabled()) { log.debug("Delete group: " + groupId); } @@ -189,8 +234,37 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); try { GroupManagementDAOFactory.beginTransaction(); - this.groupDAO.deleteGroup(groupId, tenantId); - this.groupDAO.deleteAllGroupProperties(groupId, tenantId); + List childrenGroups = new ArrayList<>(); + List groupIdsToDelete = new ArrayList<>(); + if (deviceGroup.getChildrenGroups() != null && !deviceGroup.getChildrenGroups().isEmpty()) { + String parentPath = DeviceManagerUtil.createParentPath(deviceGroup); + childrenGroups = groupDAO.getChildrenGroups(parentPath, tenantId); + if (isDeleteChildren) { + groupIdsToDelete = childrenGroups.stream().map(DeviceGroup::getGroupId) + .collect(Collectors.toList()); + } else { + for (DeviceGroup childrenGroup : childrenGroups) { + String newParentPath = childrenGroup.getParentPath() + .replace("/" + deviceGroup.getGroupId(), ""); + if (StringUtils.isEmpty(newParentPath)) { + newParentPath = "/"; + } + childrenGroup.setParentPath(newParentPath); + } + } + } + if (isDeleteChildren) { + groupIdsToDelete.add(groupId); + groupDAO.deleteGroupsMapping(groupIdsToDelete, tenantId); + groupDAO.deleteGroups(groupIdsToDelete, tenantId); + groupDAO.deleteAllGroupsProperties(groupIdsToDelete, tenantId); + } else { + groupDAO.deleteGroup(groupId, tenantId); + groupDAO.deleteAllGroupProperties(groupId, tenantId); + if (!childrenGroups.isEmpty()) { + groupDAO.updateGroups(childrenGroups, tenantId); + } + } GroupManagementDAOFactory.commitTransaction(); if (log.isDebugEnabled()) { log.debug("DeviceGroup " + deviceGroup.getName() + " removed."); @@ -219,6 +293,11 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid */ @Override public DeviceGroup getGroup(int groupId, boolean requireGroupProps) throws GroupManagementException { + return getGroup(groupId, requireGroupProps, 1); + } + + @Override + public DeviceGroup getGroup(int groupId, boolean requireGroupProps, int depth) throws GroupManagementException { if (log.isDebugEnabled()) { log.debug("Get group by id: " + groupId); } @@ -227,8 +306,13 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid try { GroupManagementDAOFactory.openConnection(); deviceGroup = this.groupDAO.getGroup(groupId, tenantId); - if (requireGroupProps) { - populateGroupProperties(deviceGroup, tenantId); + if (deviceGroup != null) { + String parentPath = DeviceManagerUtil.createParentPath(deviceGroup); + List childrenGroups = groupDAO.getChildrenGroups(parentPath, tenantId); + createGroupWithChildren(deviceGroup, childrenGroups, requireGroupProps, tenantId, depth, 0); + if (requireGroupProps) { + populateGroupProperties(deviceGroup, tenantId); + } } return deviceGroup; } catch (GroupManagementDAOException e) { @@ -236,11 +320,8 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid log.error(msg, e); throw new GroupManagementException(msg, e); } catch (SQLException e) { - String msg = "Error occurred while opening a connection to the data source."; - log.error(msg, e); - throw new GroupManagementException(msg, e); - } catch (Exception e) { - String msg = "Error occurred in getGroup for groupId: " + groupId; + String msg = "Error occurred while opening a connection to the data source to retrieve the group '" + + groupId + "'"; log.error(msg, e); throw new GroupManagementException(msg, e); } finally { @@ -253,6 +334,11 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid */ @Override public DeviceGroup getGroup(String groupName, boolean requireGroupProps) throws GroupManagementException { + return getGroup(groupName, requireGroupProps, 1); + } + + @Override + public DeviceGroup getGroup(String groupName, boolean requireGroupProps, int depth) throws GroupManagementException { if (groupName == null) { String msg = "Received empty groupName for getGroup"; log.error(msg); @@ -266,8 +352,13 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid try { GroupManagementDAOFactory.openConnection(); deviceGroup = this.groupDAO.getGroup(groupName, tenantId); - if (requireGroupProps) { - populateGroupProperties(deviceGroup, tenantId); + if (deviceGroup != null) { + String parentPath = DeviceManagerUtil.createParentPath(deviceGroup); + List childrenGroups = groupDAO.getChildrenGroups(parentPath, tenantId); + createGroupWithChildren(deviceGroup, childrenGroups, requireGroupProps, tenantId, depth , 0); + if (requireGroupProps) { + populateGroupProperties(deviceGroup, tenantId); + } } return deviceGroup; } catch (GroupManagementDAOException e) { @@ -275,11 +366,8 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid log.error(msg, e); throw new GroupManagementException(msg, e); } catch (SQLException e) { - String msg = "Error occurred while opening a connection to the data source."; - log.error(msg, e); - throw new GroupManagementException(msg, e); - } catch (Exception e) { - String msg = "Error occurred in getGroup with name " + groupName; + String msg = "Error occurred while opening a connection to the data source to retrieve group with name '" + + groupName + "'"; log.error(msg, e); throw new GroupManagementException(msg, e); } finally { @@ -296,12 +384,10 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid try { int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); GroupManagementDAOFactory.openConnection(); - deviceGroups = this.groupDAO.getGroups(tenantId); - if (requireGroupProps) { - if (deviceGroups != null && !deviceGroups.isEmpty()) { - for (DeviceGroup group : deviceGroups) { - populateGroupProperties(group, tenantId); - } + deviceGroups = groupDAO.getRootGroups(tenantId); + for (DeviceGroup deviceGroup : deviceGroups) { + if (requireGroupProps) { + populateGroupProperties(deviceGroup, tenantId); } } return deviceGroups; @@ -334,16 +420,15 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid log.debug("Get groups with pagination " + request.toString()); } request = DeviceManagerUtil.validateGroupListPageSize(request); - List deviceGroups; + List rootGroups; try { int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); GroupManagementDAOFactory.openConnection(); - deviceGroups = this.groupDAO.getGroups(request, tenantId); - if (requireGroupProps) { - if (deviceGroups != null && !deviceGroups.isEmpty()) { - for (DeviceGroup group : deviceGroups) { - populateGroupProperties(group, tenantId); - } + request.setParentPath("/"); + rootGroups = this.groupDAO.getGroups(request, tenantId); + for (DeviceGroup rootGroup : rootGroups) { + if (requireGroupProps) { + populateGroupProperties(rootGroup, tenantId); } } } catch (GroupManagementDAOException e) { @@ -362,11 +447,68 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid GroupManagementDAOFactory.closeConnection(); } PaginationResult groupResult = new PaginationResult(); - groupResult.setData(deviceGroups); + groupResult.setData(rootGroups); groupResult.setRecordsTotal(getGroupCount(request)); return groupResult; } + @Override + public PaginationResult getGroupsWithHierarchy(String username, GroupPaginationRequest request, + boolean requireGroupProps) throws GroupManagementException { + if (request == null) { + String msg = "Received incomplete data for retrieve groups with hierarchy"; + log.error(msg); + throw new GroupManagementException(msg); + } + if (log.isDebugEnabled()) { + log.debug("Get groups with hierarchy " + request.toString()); + } + DeviceManagerUtil.validateGroupListPageSize(request); + List rootGroups; + try { + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + request.setParentPath("/"); + if (StringUtils.isBlank(username)) { + GroupManagementDAOFactory.openConnection(); + rootGroups = groupDAO.getGroups(request, tenantId); + } else { + List allDeviceGroupIdsOfUser = getGroupIds(username); + GroupManagementDAOFactory.openConnection(); + rootGroups = this.groupDAO.getGroups(request, allDeviceGroupIdsOfUser, tenantId); + } + String parentPath; + List childrenGroups; + for (DeviceGroup rootGroup : rootGroups) { + parentPath = DeviceManagerUtil.createParentPath(rootGroup); + childrenGroups = groupDAO.getChildrenGroups(parentPath, tenantId); + createGroupWithChildren( + rootGroup, childrenGroups, requireGroupProps, tenantId, request.getDepth(), 0); + if (requireGroupProps) { + populateGroupProperties(rootGroup, tenantId); + } + } + } catch (GroupManagementDAOException e) { + String msg = "Error occurred while retrieving all groups with hierarchy"; + log.error(msg, e); + throw new GroupManagementException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while opening a connection to the data source to retrieve all groups " + + "with hierarchy"; + log.error(msg, e); + throw new GroupManagementException(msg, e); + } finally { + GroupManagementDAOFactory.closeConnection(); + } + PaginationResult groupResult = new PaginationResult(); + groupResult.setData(rootGroups); + if (StringUtils.isBlank(username)) { + groupResult.setRecordsTotal(getGroupCount(request)); + } else { + groupResult.setRecordsTotal(getGroupCount(username, request.getParentPath())); + } + return groupResult; + } + @Override public List getGroups(String username, boolean requireGroupProps) throws GroupManagementException { if (username == null || username.isEmpty()) { @@ -457,16 +599,15 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid } request = DeviceManagerUtil.validateGroupListPageSize(request); List allDeviceGroupIdsOfUser = getGroupIds(currentUser); - List allMatchingGroups; + List rootGroups; try { int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); GroupManagementDAOFactory.openConnection(); - allMatchingGroups = this.groupDAO.getGroups(request, allDeviceGroupIdsOfUser, tenantId); - if (requireGroupProps) { - if (allMatchingGroups != null && !allMatchingGroups.isEmpty()) { - for (DeviceGroup group : allMatchingGroups) { - populateGroupProperties(group, tenantId); - } + request.setParentPath("/"); + rootGroups = this.groupDAO.getGroups(request, allDeviceGroupIdsOfUser, tenantId); + for (DeviceGroup rootGroup : rootGroups) { + if (requireGroupProps) { + populateGroupProperties(rootGroup, tenantId); } } } catch (GroupManagementDAOException | SQLException e) { @@ -481,8 +622,8 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid GroupManagementDAOFactory.closeConnection(); } PaginationResult groupResult = new PaginationResult(); - groupResult.setData(allMatchingGroups); - groupResult.setRecordsTotal(getGroupCount(currentUser)); + groupResult.setData(rootGroups); + groupResult.setRecordsTotal(getGroupCount(currentUser, request.getParentPath())); return groupResult; } @@ -557,7 +698,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid * {@inheritDoc} */ @Override - public int getGroupCount(String username) throws GroupManagementException { + public int getGroupCount(String username, String parentPath) throws GroupManagementException { if (username == null || username.isEmpty()) { String msg = "Received empty user name for getGroupCount"; log.error(msg); @@ -574,8 +715,8 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid .getUserStoreManager(); String[] roleList = userStoreManager.getRoleListOfUser(username); GroupManagementDAOFactory.openConnection(); - count = groupDAO.getOwnGroupsCount(username, tenantId); - count += groupDAO.getGroupsCount(roleList, tenantId); + count = groupDAO.getOwnGroupsCount(username, tenantId, parentPath); + count += groupDAO.getGroupsCount(roleList, tenantId, parentPath); return count; } catch (UserStoreException e) { String msg = "Error occurred while retrieving role list of user '" + username + "'"; @@ -1131,4 +1272,40 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid } } } + + /** + * Recursive method to create group with children based on params to provide hierarchical grouping. + * @param parentGroup to which children group should be set. + * @param childrenGroups which are descendants of parent group. + * @param requireGroupProps to include device properties. + * @param tenantId of the group. + * @param depth of children groups set and when reaches recursive call returns to callee. + * @param counter to track the recursive calls and to stop when reaches the depth. + * @throws GroupManagementDAOException on error during population of group properties. + */ + private void createGroupWithChildren(DeviceGroup parentGroup, List childrenGroups, + boolean requireGroupProps, int tenantId, int depth, int counter) throws GroupManagementDAOException { + if (childrenGroups.isEmpty() || depth == counter) { + return; + } + List immediateChildrenGroups = new ArrayList<>(); + Iterator iterator = childrenGroups.iterator(); + while (iterator.hasNext()) { + DeviceGroup childGroup = iterator.next(); + int immediateParentID = Integer.parseInt(StringUtils.substringAfterLast( + childGroup.getParentPath(), "/")); + if (immediateParentID == parentGroup.getGroupId()) { + if (requireGroupProps) { + populateGroupProperties(childGroup, tenantId); + } + immediateChildrenGroups.add(childGroup); + iterator.remove(); + } + } + parentGroup.setChildrenGroups(immediateChildrenGroups); + counter++; + for (DeviceGroup nextParentGroup : immediateChildrenGroups) { + createGroupWithChildren(nextParentGroup, childrenGroups, requireGroupProps, tenantId, depth, counter); + } + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java index 7822754208..334c9b848c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java @@ -1162,4 +1162,17 @@ public final class DeviceManagerUtil { .getUserStoreManager(); return userStoreManager.getUserClaimValue(username, claimUri, null); } + + /** + * Create the parent path that the children groups can have + * @param deviceGroup parent group + * @return created parent path + */ + public static String createParentPath(DeviceGroup deviceGroup) { + if ("/".equals(deviceGroup.getParentPath())) { + return deviceGroup.getParentPath() + deviceGroup.getGroupId(); + } else { + return deviceGroup.getParentPath() + "/" + deviceGroup.getGroupId(); + } + } } From e18aa57fe8b37f0c3a5b6701e8108276f28ca6bc Mon Sep 17 00:00:00 2001 From: Saad Sahibjan Date: Thu, 24 Jun 2021 20:41:11 +0530 Subject: [PATCH 5/8] Add and update api layer related to hierarchical changes --- .../service/api/GroupManagementService.java | 123 +++++++++++++++++- .../admin/GroupManagementAdminService.java | 100 ++++++++++++++ .../impl/GroupManagementServiceImpl.java | 65 +++++++-- .../GroupManagementAdminServiceImpl.java | 51 ++++++++ 4 files changed, 327 insertions(+), 12 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GroupManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GroupManagementService.java index f61d212493..6ad3b14bd7 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GroupManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/GroupManagementService.java @@ -15,6 +15,22 @@ * specific language governing permissions and limitations * under the License. * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.jaxrs.service.api; @@ -45,6 +61,7 @@ import org.wso2.carbon.device.mgt.jaxrs.util.Constants; import javax.validation.Valid; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PUT; @@ -243,6 +260,87 @@ public interface GroupManagementService { @QueryParam("requireGroupProps") boolean requireGroupProps); + + @GET + @Path("/hierarchy") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = HTTPConstants.HEADER_GET, + value = "Getting the List of Hierarchical Groups", + notes = "Returns all groups enrolled with the system hierarchically.", + tags = "Device Group Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:groups:groups") + }) + } + ) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK. \n Successfully fetched the list of device hierarchical groups.", + response = DeviceGroupList.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 304, + message = "Not Modified. \n Empty body because the client has already the latest version of " + + "the requested resource."), + @ApiResponse( + code = 406, + message = "Not Acceptable.\n The requested media type is not supported."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while fetching the groups list.", + response = ErrorResponse.class) + }) + Response getGroupsWithHierarchy( + @ApiParam( + name = "name", + value = "Name of the group.") + @QueryParam("name") + String name, + @ApiParam( + name = "owner", + value = "Owner of the group.") + @QueryParam("owner") + String owner, + @ApiParam( + name = "requireGroupProps", + value = "Request group properties to include in the response", + defaultValue = "false") + @QueryParam("requireGroupProps") + boolean requireGroupProps, + @ApiParam( + name = "depth", + value = "Depth of the group hierarchy.") + @DefaultValue("3") + @QueryParam("depth") + int depth, + @ApiParam( + name = "offset", + value = "The starting pagination index for the complete list of qualified items.", + defaultValue = "0") + @DefaultValue("0") + @QueryParam("offset") + int offset, + @ApiParam( + name = "limit", + value = "Provide how many records require from the starting pagination index/offset.", + defaultValue = "5") + @DefaultValue("5") + @QueryParam("limit") + int limit); + @Path("/count") @GET @ApiOperation( @@ -412,7 +510,14 @@ public interface GroupManagementService { value = "Request group properties to include in the response", defaultValue = "false") @QueryParam("requireGroupProps") - boolean requireGroupProps); + boolean requireGroupProps, + @ApiParam( + name = "depth", + value = "Depth of the group hierarchy.", + defaultValue = "1") + @DefaultValue("1") + @QueryParam("depth") + int depth); @Path("/name/{groupName}") @GET @@ -471,7 +576,14 @@ public interface GroupManagementService { value = "Request group properties to include in the response", defaultValue = "false") @QueryParam("requireGroupProps") - boolean requireGroupProps); + boolean requireGroupProps, + @ApiParam( + name = "depth", + value = "Depth of the group hierarchy.", + defaultValue = "1") + @DefaultValue("1") + @QueryParam("depth") + int depth); @Path("/id/{groupId}") @PUT @@ -580,7 +692,12 @@ public interface GroupManagementService { name = "groupId", value = "ID of the group to be deleted.", required = true) - @PathParam("groupId") int groupId); + @PathParam("groupId") int groupId, + @ApiParam( + name = "isDeleteChildren", + value = "Is the children groups needs to be deleted.", + required = true) + @QueryParam("isDeleteChildren") boolean isDeleteChildren); @Path("/id/{groupId}/share") @POST diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/GroupManagementAdminService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/GroupManagementAdminService.java index f631b1dc51..d7b8553b20 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/GroupManagementAdminService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/GroupManagementAdminService.java @@ -15,6 +15,22 @@ * specific language governing permissions and limitations * under the License. * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.jaxrs.service.api.admin; @@ -163,6 +179,90 @@ public interface GroupManagementAdminService { @QueryParam("requireGroupProps") boolean requireGroupProps); + @GET + @Path("hierarchy") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = HTTPConstants.HEADER_GET, + value = "Getting the List of Hierarchical Groups", + notes = "Returns all groups enrolled with the system hierarchically.", + tags = "Device Group Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:admin-groups:view") + }) + } + ) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK. \n Successfully fetched the list of device groups hierarchically.", + response = DeviceGroupList.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 304, + message = "Not Modified. \n Empty body because the client has already the latest version of " + + "the requested resource."), + @ApiResponse( + code = 406, + message = "Not Acceptable.\n The requested media type is not supported."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while fetching the groups list.", + response = ErrorResponse.class) + }) + Response getGroupsWithHierarchy(@ApiParam( + name = "name", + value = "Name of the group.") + @QueryParam("name") + String name, + @ApiParam( + name = "owner", + value = "Owner of the group.") + @QueryParam("owner") + String owner, + @ApiParam( + name = "status", + value = "status of group to be retrieve.") + @QueryParam("status") + String status, + @ApiParam( + name = "requireGroupProps", + value = "Request group properties to include in the response", + defaultValue = "false") + @QueryParam("requireGroupProps") + boolean requireGroupProps, + @ApiParam( + name = "depth", + value = "Depth of the group hierarchy.") + @DefaultValue("3") + @QueryParam("depth") + int depth, + @ApiParam( + name = "offset", + value = "The starting pagination index for the complete list of qualified items.", + defaultValue = "0") + @DefaultValue("0") + @QueryParam("offset") + int offset, + @ApiParam( + name = "limit", + value = "Provide how many records require from the starting pagination index/offset.", + defaultValue = "5") + @DefaultValue("5") + @QueryParam("limit") + int limit); + @Path("/count") @GET @ApiOperation( diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GroupManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GroupManagementServiceImpl.java index 0502f37ab3..3fed8e7504 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GroupManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GroupManagementServiceImpl.java @@ -15,6 +15,22 @@ * specific language governing permissions and limitations * under the License. * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.jaxrs.service.impl; @@ -36,7 +52,6 @@ import org.wso2.carbon.device.mgt.common.group.mgt.GroupAlreadyExistException; import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; import org.wso2.carbon.device.mgt.common.group.mgt.GroupNotExistException; import org.wso2.carbon.device.mgt.common.group.mgt.RoleDoesNotExistException; -import org.wso2.carbon.device.mgt.common.policy.mgt.Policy; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService; import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceGroupList; @@ -47,10 +62,12 @@ import org.wso2.carbon.device.mgt.jaxrs.service.api.GroupManagementService; import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil; import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; import org.wso2.carbon.policy.mgt.common.PolicyAdministratorPoint; -import org.wso2.carbon.policy.mgt.common.PolicyEvaluationException; -import org.wso2.carbon.policy.mgt.common.PolicyEvaluationPoint; import org.wso2.carbon.policy.mgt.common.PolicyManagementException; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; import java.util.ArrayList; import java.util.List; @@ -89,11 +106,41 @@ public class GroupManagementServiceImpl implements GroupManagementService { } } + @GET + @Path("/hierarchy") + @Override + public Response getGroupsWithHierarchy( + @QueryParam("name") String name, + @QueryParam("owner") String owner, + @QueryParam("requireGroupProps") boolean requireGroupProps, + @DefaultValue("3") @QueryParam("depth") int depth, + @DefaultValue("0") @QueryParam("offset") int offset, + @DefaultValue("5") @QueryParam("limit") int limit) { + try { + RequestValidationUtil.validatePaginationParameters(offset, limit); + String currentUser = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + GroupPaginationRequest request = new GroupPaginationRequest(offset, limit); + request.setGroupName(name); + request.setOwner(owner); + request.setDepth(depth); + PaginationResult deviceGroupsResult = DeviceMgtAPIUtils.getGroupManagementProviderService() + .getGroupsWithHierarchy(currentUser, request, requireGroupProps); + DeviceGroupList deviceGroupList = new DeviceGroupList(); + deviceGroupList.setList(deviceGroupsResult.getData()); + deviceGroupList.setCount(deviceGroupsResult.getRecordsTotal()); + return Response.status(Response.Status.OK).entity(deviceGroupList).build(); + } catch (GroupManagementException e) { + String error = "Error occurred while retrieving groups with hierarchy."; + log.error(error, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } + } + @Override public Response getGroupCount() { try { String currentUser = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); - int count = DeviceMgtAPIUtils.getGroupManagementProviderService().getGroupCount(currentUser); + int count = DeviceMgtAPIUtils.getGroupManagementProviderService().getGroupCount(currentUser, null); return Response.status(Response.Status.OK).entity(count).build(); } catch (GroupManagementException e) { String msg = "Error occurred while retrieving group count."; @@ -125,10 +172,10 @@ public class GroupManagementServiceImpl implements GroupManagementService { } @Override - public Response getGroup(int groupId, boolean requireGroupProps) { + public Response getGroup(int groupId, boolean requireGroupProps, int depth) { try { GroupManagementProviderService service = DeviceMgtAPIUtils.getGroupManagementProviderService(); - DeviceGroup deviceGroup = service.getGroup(groupId, requireGroupProps); + DeviceGroup deviceGroup = service.getGroup(groupId, requireGroupProps, depth); if (deviceGroup != null) { return Response.status(Response.Status.OK).entity(deviceGroup).build(); } else { @@ -142,7 +189,7 @@ public class GroupManagementServiceImpl implements GroupManagementService { } @Override - public Response getGroup(String groupName, boolean requireGroupProps) { + public Response getGroup(String groupName, boolean requireGroupProps, int depth) { try { GroupManagementProviderService service = DeviceMgtAPIUtils.getGroupManagementProviderService(); DeviceGroup deviceGroup = service.getGroup(groupName, requireGroupProps); @@ -178,9 +225,9 @@ public class GroupManagementServiceImpl implements GroupManagementService { } @Override - public Response deleteGroup(int groupId) { + public Response deleteGroup(int groupId, boolean isDeleteChildren) { try { - if (DeviceMgtAPIUtils.getGroupManagementProviderService().deleteGroup(groupId)) { + if (DeviceMgtAPIUtils.getGroupManagementProviderService().deleteGroup(groupId, isDeleteChildren)) { return Response.status(Response.Status.OK).build(); } else { return Response.status(Response.Status.NOT_FOUND).entity("Group not found.").build(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/GroupManagementAdminServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/GroupManagementAdminServiceImpl.java index b742a1d8e1..a461b71b50 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/GroupManagementAdminServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/GroupManagementAdminServiceImpl.java @@ -15,6 +15,22 @@ * specific language governing permissions and limitations * under the License. * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.jaxrs.service.impl.admin; @@ -31,6 +47,10 @@ import org.wso2.carbon.device.mgt.jaxrs.service.api.admin.GroupManagementAdminSe import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil; import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.Response; import java.util.ArrayList; @@ -74,6 +94,37 @@ public class GroupManagementAdminServiceImpl implements GroupManagementAdminServ } } + @GET + @Path("/hierarchy") + @Override + public Response getGroupsWithHierarchy( + @QueryParam("name") String name, + @QueryParam("owner") String owner, + @QueryParam("status") String status, + @QueryParam("requireGroupProps") boolean requireGroupProps, + @DefaultValue("3") @QueryParam("depth") int depth, + @DefaultValue("0") @QueryParam("offset") int offset, + @DefaultValue("5") @QueryParam("limit") int limit) { + try { + RequestValidationUtil.validatePaginationParameters(offset, limit); + GroupPaginationRequest request = new GroupPaginationRequest(offset, limit); + request.setGroupName(name); + request.setOwner(owner); + request.setStatus(status); + request.setDepth(depth); + PaginationResult deviceGroupsResult = DeviceMgtAPIUtils.getGroupManagementProviderService() + .getGroupsWithHierarchy(null, request, requireGroupProps); + DeviceGroupList deviceGroupList = new DeviceGroupList(); + deviceGroupList.setList(deviceGroupsResult.getData()); + deviceGroupList.setCount(deviceGroupsResult.getRecordsTotal()); + return Response.status(Response.Status.OK).entity(deviceGroupList).build(); + } catch (GroupManagementException e) { + String error = "Error occurred while retrieving groups with hierarchy."; + log.error(error, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build(); + } + } + @Override public Response getGroupCount(String status) { try { From 24e69d5492b1be2c76c26e754769c6082f527650 Mon Sep 17 00:00:00 2001 From: Saad Sahibjan Date: Thu, 24 Jun 2021 21:06:30 +0530 Subject: [PATCH 6/8] Fix test cases related to hierarchical group changes --- .../impl/GroupManagementServiceImplTest.java | 46 +++++++++++++------ ...ManagementProviderServiceNegativeTest.java | 21 ++++++++- .../GroupManagementProviderServiceTest.java | 23 ++++++++-- .../src/test/resources/sql/h2.sql | 1 + .../src/test/resources/sql/CreateH2TestDB.sql | 3 +- 5 files changed, 73 insertions(+), 21 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GroupManagementServiceImplTest.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GroupManagementServiceImplTest.java index 20136b172d..2d430c09f6 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GroupManagementServiceImplTest.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/test/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/GroupManagementServiceImplTest.java @@ -15,11 +15,26 @@ * specific language governing permissions and limitations * under the License. * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.jaxrs.service.impl; -import org.mockito.Mock; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PowerMockIgnore; @@ -130,13 +145,14 @@ public class GroupManagementServiceImplTest { .toReturn(groupManagementProviderService); PowerMockito.stub(PowerMockito.method(PrivilegedCarbonContext.class, "getThreadLocalCarbonContext")) .toReturn(context); - Mockito.doReturn(2).when(groupManagementProviderService).getGroupCount(Mockito.anyString()); + Mockito.doReturn(2).when(groupManagementProviderService) + .getGroupCount(Mockito.anyString(), Mockito.anyString()); Response response = groupManagementService.getGroupCount(); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode(), "GetGroupCount request failed with valid parameters"); Mockito.reset(groupManagementProviderService); Mockito.doThrow(new GroupManagementException()).when(groupManagementProviderService) - .getGroupCount(Mockito.anyString()); + .getGroupCount(Mockito.anyString(), Mockito.anyString()); response = groupManagementService.getGroupCount(); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), "GetGroupCount request succeeded with in-valid parameters"); @@ -174,16 +190,16 @@ public class GroupManagementServiceImplTest { public void testGetGroup() throws GroupManagementException { PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getGroupManagementProviderService")) .toReturn(groupManagementProviderService); - Mockito.doReturn(new DeviceGroup()).when(groupManagementProviderService).getGroup(1, false); - Mockito.doReturn(null).when(groupManagementProviderService).getGroup(2, false); - Mockito.doThrow(new GroupManagementException()).when(groupManagementProviderService).getGroup(3, false); - Response response = groupManagementService.getGroup(1, false); + Mockito.doReturn(new DeviceGroup()).when(groupManagementProviderService).getGroup(1, false, 1); + Mockito.doReturn(null).when(groupManagementProviderService).getGroup(2, false, 1); + Mockito.doThrow(new GroupManagementException()).when(groupManagementProviderService).getGroup(3, false, 1); + Response response = groupManagementService.getGroup(1, false, 1); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode(), "getGroup request failed for a request with valid parameters"); - response = groupManagementService.getGroup(2, false); + response = groupManagementService.getGroup(2, false, 1); Assert.assertEquals(response.getStatus(), Response.Status.NOT_FOUND.getStatusCode(), "getGroup request returned a group for a non-existing group"); - response = groupManagementService.getGroup(3, false); + response = groupManagementService.getGroup(3, false, 1); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), "getGroup request returned a group for a in-valid request"); } @@ -216,16 +232,16 @@ public class GroupManagementServiceImplTest { public void testDeleteGroup() throws GroupManagementException { PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getGroupManagementProviderService")) .toReturn(groupManagementProviderService); - Mockito.doReturn(true).when(groupManagementProviderService).deleteGroup(1); - Mockito.doReturn(false).when(groupManagementProviderService).deleteGroup(2); - Mockito.doThrow(new GroupManagementException()).when(groupManagementProviderService).deleteGroup(3); - Response response = groupManagementService.deleteGroup(1); + Mockito.doReturn(true).when(groupManagementProviderService).deleteGroup(1, false); + Mockito.doReturn(false).when(groupManagementProviderService).deleteGroup(2, false); + Mockito.doThrow(new GroupManagementException()).when(groupManagementProviderService).deleteGroup(3, false); + Response response = groupManagementService.deleteGroup(1, false); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode(), "delete group request failed for a request with valid parameters"); - response = groupManagementService.deleteGroup(2); + response = groupManagementService.deleteGroup(2, false); Assert.assertEquals(response.getStatus(), Response.Status.NOT_FOUND.getStatusCode(), "Non-existing group was successfully deleted"); - response = groupManagementService.deleteGroup(3); + response = groupManagementService.deleteGroup(3, false); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), "Deletion succeeded with an erroneous condition."); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceNegativeTest.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceNegativeTest.java index fd34165031..ec8004e475 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceNegativeTest.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceNegativeTest.java @@ -8,6 +8,23 @@ * * http://www.apache.org/licenses/LICENSE-2.0 * + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -103,7 +120,7 @@ public class GroupManagementProviderServiceNegativeTest extends BaseDeviceManage expectedExceptions = {GroupManagementException.class}, expectedExceptionsMessageRegExp = "Error occurred " + "while retrieving group count of user.*") public void testGetGroupCountWithUserName() throws GroupManagementException { - groupManagementProviderService.getGroupCount("test"); + groupManagementProviderService.getGroupCount("test", null); } @@ -145,7 +162,7 @@ public class GroupManagementProviderServiceNegativeTest extends BaseDeviceManage expectedExceptions = {GroupManagementException.class}, expectedExceptionsMessageRegExp = "Received empty " + "user name for getGroupCount.*") public void testGetGroupCountWithUserName2() throws GroupManagementException { - groupManagementProviderService.getGroupCount(null); + groupManagementProviderService.getGroupCount(null, null); } @Test(description = "This method tests getGroups method under negative circumstances", diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceTest.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceTest.java index 4ffb675fe7..b645eac9a0 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceTest.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceTest.java @@ -14,6 +14,23 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. + * + * + * Copyright (c) 2021, Entgra (pvt) Ltd. (https://entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ package org.wso2.carbon.device.mgt.core.service; @@ -119,13 +136,13 @@ public class GroupManagementProviderServiceTest extends BaseDeviceManagementTest @Test(dependsOnMethods = ("createGroup")) public void deleteGroup() throws GroupManagementException { DeviceGroup deviceGroup = groupManagementProviderService.getGroup(TestUtils.createDeviceGroup4().getName(), false); - Assert.assertTrue(groupManagementProviderService.deleteGroup(deviceGroup.getGroupId())); + Assert.assertTrue(groupManagementProviderService.deleteGroup(deviceGroup.getGroupId(), false)); } @Test(dependsOnMethods = ("createGroup")) public void deleteGroupNotExists() throws GroupManagementException { - groupManagementProviderService.deleteGroup(8); + groupManagementProviderService.deleteGroup(8, false); } @@ -190,7 +207,7 @@ public class GroupManagementProviderServiceTest extends BaseDeviceManagementTest @Test(dependsOnMethods = ("createGroup")) public void getGroupCountByUsername(String username) throws GroupManagementException { - int x = groupManagementProviderService.getGroupCount(username); + int x = groupManagementProviderService.getGroupCount(username, null); Assert.assertNotNull(x); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/sql/h2.sql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/sql/h2.sql index a380bf5204..2fc9fb4b29 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/sql/h2.sql +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/sql/h2.sql @@ -14,6 +14,7 @@ CREATE TABLE IF NOT EXISTS DM_GROUP ( STATUS VARCHAR(50) DEFAULT NULL, DESCRIPTION TEXT DEFAULT NULL, OWNER VARCHAR(45) DEFAULT NULL, + PARENT_PATH VARCHAR(255) DEFAULT NULL, TENANT_ID INTEGER DEFAULT 0, PRIMARY KEY (ID) ); diff --git a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/test/resources/sql/CreateH2TestDB.sql b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/test/resources/sql/CreateH2TestDB.sql index e53054a6a0..bce9121e73 100644 --- a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/test/resources/sql/CreateH2TestDB.sql +++ b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/test/resources/sql/CreateH2TestDB.sql @@ -18,6 +18,7 @@ CREATE TABLE IF NOT EXISTS DM_GROUP ( DATE_OF_CREATE BIGINT DEFAULT NULL, DATE_OF_LAST_UPDATE BIGINT DEFAULT NULL, OWNER VARCHAR(45) DEFAULT NULL, + PARENT_PATH VARCHAR(255) DEFAULT NULL, TENANT_ID INTEGER DEFAULT 0, PRIMARY KEY (ID) ); @@ -607,4 +608,4 @@ DM_DEVICE.DEVICE_TYPE_ID = DM_DEVICE_TYPE.ID AND DM_DEVICE.ID = DM_DEVICE_DETAIL.DEVICE_ID ORDER BY TENANT_ID, DEVICE_ID; --- END OF DASHBOARD RELATED VIEWS -- \ No newline at end of file +-- END OF DASHBOARD RELATED VIEWS -- From ed087e2a0cfd9ac055a4b0a0da588f24c97a9739 Mon Sep 17 00:00:00 2001 From: Saad Sahibjan Date: Thu, 15 Jul 2021 21:37:36 +0530 Subject: [PATCH 7/8] Update all children groups when updating a group --- .../GroupManagementProviderServiceImpl.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java index 35f4915481..808a355cbe 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java @@ -177,6 +177,9 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid GroupManagementDAOFactory.beginTransaction(); DeviceGroup existingGroup = this.groupDAO.getGroup(groupId, tenantId); if (existingGroup != null) { + List groupsToUpdate = new ArrayList<>(); + String immediateParentID = StringUtils.substringAfterLast(existingGroup.getParentPath(), "/"); + String parentPath = ""; if (deviceGroup.getParentGroupId() == 0) { deviceGroup.setParentPath("/"); } else { @@ -188,10 +191,20 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid log.error(msg); throw new GroupManagementException(msg); } - String parentPath = DeviceManagerUtil.createParentPath(immediateParentGroup); + parentPath = DeviceManagerUtil.createParentPath(immediateParentGroup); deviceGroup.setParentPath(parentPath); } - this.groupDAO.updateGroup(deviceGroup, groupId, tenantId); + deviceGroup.setGroupId(groupId); + groupsToUpdate.add(deviceGroup); + if (StringUtils.isNotBlank(immediateParentID)) { + List childrenGroups = groupDAO.getChildrenGroups(DeviceManagerUtil.createParentPath(existingGroup), tenantId); + for (DeviceGroup childrenGroup : childrenGroups) { + childrenGroup.setParentPath(childrenGroup.getParentPath() + .replace(existingGroup.getParentPath(), parentPath)); + groupsToUpdate.add(childrenGroup); + } + } + this.groupDAO.updateGroups(groupsToUpdate, tenantId); if (deviceGroup.getGroupProperties() != null && deviceGroup.getGroupProperties().size() > 0) { this.groupDAO.updateGroupProperties(deviceGroup, groupId, tenantId); } From 489aaabc445087abcc9d972d759f68332dfe05de Mon Sep 17 00:00:00 2001 From: Saad Sahibjan Date: Fri, 16 Jul 2021 00:13:30 +0530 Subject: [PATCH 8/8] Move slash to a constant --- .../group/mgt/DeviceGroupConstants.java | 4 ++++ .../GroupManagementProviderServiceImpl.java | 21 ++++++++++--------- .../mgt/core/util/DeviceManagerUtil.java | 6 ++++-- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroupConstants.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroupConstants.java index 039219bfe8..b1a185d98f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroupConstants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/group/mgt/DeviceGroupConstants.java @@ -84,4 +84,8 @@ public class DeviceGroupConstants { public static final String[] DEFAULT_VIEW_EVENTS_PERMISSIONS = {"/permission/device-mgt/user/groups/device_events"}; } + + public static final class HierarchicalGroup { + public static final String SEPERATOR = "/"; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java index 808a355cbe..6a678c1fca 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/GroupManagementProviderServiceImpl.java @@ -113,7 +113,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid DeviceGroup existingGroup = this.groupDAO.getGroup(deviceGroup.getName(), tenantId); if (existingGroup == null) { if (deviceGroup.getParentGroupId() == 0) { - deviceGroup.setParentPath("/"); + deviceGroup.setParentPath(DeviceGroupConstants.HierarchicalGroup.SEPERATOR); } else { DeviceGroup immediateParentGroup = groupDAO.getGroup(deviceGroup.getParentGroupId(), tenantId); if (immediateParentGroup == null) { @@ -178,10 +178,10 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid DeviceGroup existingGroup = this.groupDAO.getGroup(groupId, tenantId); if (existingGroup != null) { List groupsToUpdate = new ArrayList<>(); - String immediateParentID = StringUtils.substringAfterLast(existingGroup.getParentPath(), "/"); + String immediateParentID = StringUtils.substringAfterLast(existingGroup.getParentPath(), DeviceGroupConstants.HierarchicalGroup.SEPERATOR); String parentPath = ""; if (deviceGroup.getParentGroupId() == 0) { - deviceGroup.setParentPath("/"); + deviceGroup.setParentPath(DeviceGroupConstants.HierarchicalGroup.SEPERATOR); } else { DeviceGroup immediateParentGroup = groupDAO.getGroup(deviceGroup.getParentGroupId(), tenantId); if (immediateParentGroup == null) { @@ -197,7 +197,8 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid deviceGroup.setGroupId(groupId); groupsToUpdate.add(deviceGroup); if (StringUtils.isNotBlank(immediateParentID)) { - List childrenGroups = groupDAO.getChildrenGroups(DeviceManagerUtil.createParentPath(existingGroup), tenantId); + List childrenGroups = groupDAO.getChildrenGroups( + DeviceManagerUtil.createParentPath(existingGroup), tenantId); for (DeviceGroup childrenGroup : childrenGroups) { childrenGroup.setParentPath(childrenGroup.getParentPath() .replace(existingGroup.getParentPath(), parentPath)); @@ -258,9 +259,9 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid } else { for (DeviceGroup childrenGroup : childrenGroups) { String newParentPath = childrenGroup.getParentPath() - .replace("/" + deviceGroup.getGroupId(), ""); + .replace(DeviceGroupConstants.HierarchicalGroup.SEPERATOR + deviceGroup.getGroupId(), ""); if (StringUtils.isEmpty(newParentPath)) { - newParentPath = "/"; + newParentPath = DeviceGroupConstants.HierarchicalGroup.SEPERATOR; } childrenGroup.setParentPath(newParentPath); } @@ -437,7 +438,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid try { int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); GroupManagementDAOFactory.openConnection(); - request.setParentPath("/"); + request.setParentPath(DeviceGroupConstants.HierarchicalGroup.SEPERATOR); rootGroups = this.groupDAO.getGroups(request, tenantId); for (DeviceGroup rootGroup : rootGroups) { if (requireGroupProps) { @@ -480,7 +481,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid List rootGroups; try { int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); - request.setParentPath("/"); + request.setParentPath(DeviceGroupConstants.HierarchicalGroup.SEPERATOR); if (StringUtils.isBlank(username)) { GroupManagementDAOFactory.openConnection(); rootGroups = groupDAO.getGroups(request, tenantId); @@ -616,7 +617,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid try { int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); GroupManagementDAOFactory.openConnection(); - request.setParentPath("/"); + request.setParentPath(DeviceGroupConstants.HierarchicalGroup.SEPERATOR); rootGroups = this.groupDAO.getGroups(request, allDeviceGroupIdsOfUser, tenantId); for (DeviceGroup rootGroup : rootGroups) { if (requireGroupProps) { @@ -1306,7 +1307,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid while (iterator.hasNext()) { DeviceGroup childGroup = iterator.next(); int immediateParentID = Integer.parseInt(StringUtils.substringAfterLast( - childGroup.getParentPath(), "/")); + childGroup.getParentPath(), DeviceGroupConstants.HierarchicalGroup.SEPERATOR)); if (immediateParentID == parentGroup.getGroupId()) { if (requireGroupProps) { populateGroupProperties(childGroup, tenantId); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java index 334c9b848c..36315a1315 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java @@ -70,6 +70,7 @@ import org.wso2.carbon.device.mgt.common.exceptions.DeviceNotFoundException; import org.wso2.carbon.device.mgt.common.exceptions.TransactionManagementException; import org.wso2.carbon.device.mgt.common.geo.service.GeofenceData; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; +import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroupConstants; import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; import org.wso2.carbon.device.mgt.common.exceptions.MetadataManagementException; import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementException; @@ -1169,10 +1170,11 @@ public final class DeviceManagerUtil { * @return created parent path */ public static String createParentPath(DeviceGroup deviceGroup) { - if ("/".equals(deviceGroup.getParentPath())) { + if (DeviceGroupConstants.HierarchicalGroup.SEPERATOR.equals(deviceGroup.getParentPath())) { return deviceGroup.getParentPath() + deviceGroup.getGroupId(); } else { - return deviceGroup.getParentPath() + "/" + deviceGroup.getGroupId(); + return deviceGroup.getParentPath() + DeviceGroupConstants.HierarchicalGroup.SEPERATOR + + deviceGroup.getGroupId(); } } }