diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/ReportManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/ReportManagementService.java index aa5424abd3..3f1f88a6c6 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/ReportManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/ReportManagementService.java @@ -35,7 +35,6 @@ import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceList; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.util.Constants; -import javax.validation.constraints.Size; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; @@ -493,4 +492,73 @@ public interface ReportManagementService { defaultValue = "5") @QueryParam("limit") int limit); + + @Path("/{device-type}/ungrouped-devices") + @GET + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting devices list that is only assigned to the querying groups.", + notes = "Devices are automatically assigned to default groups during the device " + + "enrollment. This API filters the list of devices that are only assigned to " + + "querying groups by a user.", + tags = "Device Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:view") + }) + } + ) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK.", + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource." + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource has been modified the last time." + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "Not Found. \n The requested device type is not found", + response = ErrorResponse.class), + @ApiResponse( + code = 204, + message = "No content\n There is no device without groups assigned.") + }) + Response getUngroupedDevices( + @ApiParam( + name = "device-type", + value = "The device type name, such as ios, android, windows etc", + required = true) + @PathParam("device-type") + String deviceType, + @ApiParam( + name = "groupNames", + value = "The group names available") + @QueryParam("groupNames") + List groupNames, + @ApiParam( + name = "offset", + value = "The starting pagination index for the complete list of grouped " + + "devices", + defaultValue = "0") + @QueryParam("offset") + int offset, + @ApiParam( + name = "limit", + value = "Provide how many device details you require from the starting pagination index/offset.", + defaultValue = "10") + @QueryParam("limit") + int limit); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/ReportManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/ReportManagementServiceImpl.java index 4ecf7b7bd6..2d49998af7 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/ReportManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/ReportManagementServiceImpl.java @@ -35,7 +35,6 @@ import org.wso2.carbon.device.mgt.jaxrs.service.api.ReportManagementService; import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil; import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; -import javax.validation.constraints.Size; import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; @@ -268,4 +267,41 @@ public class ReportManagementServiceImpl implements ReportManagementService { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } } + + @GET + @Path("/{device-type}/ungrouped-devices") + public Response getUngroupedDevices( + @PathParam("device-type") String deviceType, + @QueryParam("groupNames") List groupNames, + @DefaultValue("0") + @QueryParam("offset") int offset, + @DefaultValue("10") + @QueryParam("limit") int limit) { + try { + RequestValidationUtil.validatePaginationParameters(offset, limit); + PaginationRequest request = new PaginationRequest(offset, limit); + DeviceList deviceList = new DeviceList(); + request.setDeviceType(deviceType); + PaginationResult paginationResult = + DeviceMgtAPIUtils.getReportManagementService().getDeviceNotAssignedToGroups(request, groupNames); + + if (paginationResult.getData().isEmpty()) { + String msg = "There is no " + deviceType + "device without groups"; + return Response.status(Response.Status.NO_CONTENT).entity(msg).build(); + } else { + deviceList.setList((List) paginationResult.getData()); + return Response.status(Response.Status.OK).entity(deviceList).build(); + } + } catch (ReportManagementException e) { + String msg = "Error occurred while retrieving device list that are not assigned to " + + "groups"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } catch (DeviceTypeNotFoundException e) { + String msg = "Error occurred while retrieving devices list. Device type: " + deviceType + + "is not valid"; + log.error(msg, e); + return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); + } + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/report/mgt/ReportManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/report/mgt/ReportManagementService.java index ef5806d798..18a83bc9b3 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/report/mgt/ReportManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/report/mgt/ReportManagementService.java @@ -84,4 +84,19 @@ public interface ReportManagementService { */ PaginationResult getAppNotInstalledDevices(PaginationRequest request, String packageName, String version) throws ReportManagementException, DeviceTypeNotFoundException; + + /** + * This method is used to get devices which have not assigned to groups. + * + * @param paginationRequest Request object with offset and limit + * @param groupNames default group names that should be omitted when checking the device + * whether they have been assigned to groups + * @return {@link PaginationResult} + * @throws ReportManagementException Might occur when opening a connection to the data source. + * @throws DeviceTypeNotFoundException Might occur when required device type is not found. + */ + + PaginationResult getDeviceNotAssignedToGroups(PaginationRequest paginationRequest, + List groupNames) + throws ReportManagementException, DeviceTypeNotFoundException; } 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 9c2264b3f0..1951d23478 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 @@ -20,6 +20,8 @@ package org.wso2.carbon.device.mgt.core.dao; 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.exceptions.ReportManagementException; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; import java.util.List; @@ -326,4 +328,19 @@ public interface GroupDAO { */ int getOwnGroupsCount(String username, int tenantId) throws GroupManagementDAOException; + /** + * Get device Ids of devices which are assigned to groups. + * + * @param paginationRequest Request object with offset and limit. + * @param groupNames default group names that should be omitted when checking the device + * whether they have been assigned to groups + * @throws GroupManagementDAOException Might occur while retrieving information of group + * unassigned devices + * @return details of devices that are unassigned to groups. + */ + + List getGroupUnassignedDevices(PaginationRequest paginationRequest, + List groupNames) + throws GroupManagementDAOException; + } 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 e5805d14d3..1060e30c3d 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 @@ -18,9 +18,12 @@ package org.wso2.carbon.device.mgt.core.dao.impl; +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.GroupDAO; import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOException; @@ -36,12 +39,15 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.StringJoiner; /** * This class represents implementation of GroupDAO */ public abstract class AbstractGroupDAOImpl implements GroupDAO { + private static final Log log = LogFactory.getLog(AbstractGroupDAOImpl.class); + @Override public int addGroup(DeviceGroup deviceGroup, int tenantId) throws GroupManagementDAOException { PreparedStatement stmt = null; @@ -809,4 +815,52 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO { } return devices; } + + @Override + public List getGroupUnassignedDevices(PaginationRequest paginationRequest, + List groupNames) + throws GroupManagementDAOException { + List groupUnassignedDeviceList; + try { + Connection connection = GroupManagementDAOFactory.getConnection(); + StringJoiner sql = new StringJoiner(",", + "SELECT DEVICE.ID AS DEVICE_ID, " + + "DEVICE.NAME AS DEVICE_NAME, " + + "DEVICE_TYPE.NAME AS DEVICE_TYPE, " + + "DEVICE.DESCRIPTION, " + + "DEVICE.DEVICE_IDENTIFICATION, " + + "ENROLMENT.ID AS ENROLMENT_ID, " + + "ENROLMENT.OWNER, " + + "ENROLMENT.OWNERSHIP, " + + "ENROLMENT.DATE_OF_ENROLMENT, " + + "ENROLMENT.DATE_OF_LAST_UPDATE, " + + "ENROLMENT.STATUS " + + "FROM DM_DEVICE AS DEVICE, DM_DEVICE_TYPE AS DEVICE_TYPE, DM_ENROLMENT " + + "AS ENROLMENT " + + "WHERE DEVICE.ID NOT IN " + + "(SELECT DEVICE_ID " + + "FROM DM_DEVICE_GROUP_MAP " + + "WHERE GROUP_ID IN (SELECT ID FROM DM_GROUP WHERE GROUP_NAME NOT IN (", + ")) GROUP BY DEVICE_ID)"); + + groupNames.stream().map(e -> "?").forEach(sql::add); + try (PreparedStatement stmt = connection.prepareStatement(String.valueOf(sql))) { + int index = 1; + for (String groupName : groupNames) { + stmt.setString(index++, groupName); + } + try (ResultSet resultSet = stmt.executeQuery()) { + groupUnassignedDeviceList = new ArrayList<>(); + while (resultSet.next()) { + groupUnassignedDeviceList.add(DeviceManagementDAOUtil.loadDevice(resultSet)); + } + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving information of group unassigned devices"; + log.error(msg, e); + throw new GroupManagementDAOException(msg,e); + } + return groupUnassignedDeviceList; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/ReportManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/ReportManagementServiceImpl.java index 620997f091..533b1cb1bc 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/ReportManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/report/mgt/ReportManagementServiceImpl.java @@ -33,6 +33,9 @@ import org.wso2.carbon.device.mgt.common.report.mgt.ReportManagementService; 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.dao.util.DeviceManagementDAOUtil; import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; @@ -54,9 +57,11 @@ public class ReportManagementServiceImpl implements ReportManagementService { private static final Log log = LogFactory.getLog(ReportManagementServiceImpl.class); private DeviceDAO deviceDAO; + private GroupDAO groupDAO; public ReportManagementServiceImpl() { this.deviceDAO = DeviceManagementDAOFactory.getDeviceDAO(); + this.groupDAO = GroupManagementDAOFactory.getGroupDAO(); } @Override @@ -379,4 +384,49 @@ public class ReportManagementServiceImpl implements ReportManagementService { throw new ReportManagementException(msg, e); } } + + @Override + public PaginationResult getDeviceNotAssignedToGroups(PaginationRequest paginationRequest , + List groupNames) + throws ReportManagementException, DeviceTypeNotFoundException { + PaginationResult paginationResult = new PaginationResult(); + try { + int tenantId = DeviceManagementDAOUtil.getTenantId(); + DeviceManagerUtil.validateDeviceListPageSize(paginationRequest); + String deviceType = paginationRequest.getDeviceType(); + DeviceType deviceTypeObj = DeviceManagerUtil.getDeviceType(deviceType, tenantId); + if (deviceTypeObj == null) { + String msg = "Error, device of type: " + deviceType + " does not exist"; + log.error(msg); + throw new DeviceTypeNotFoundException(msg); + } + try { + GroupManagementDAOFactory.openConnection(); + List devices = groupDAO.getGroupUnassignedDevices(paginationRequest , + groupNames); + paginationResult.setData(devices); + return paginationResult; + } catch (SQLException e) { + String msg = "Error occurred while opening a connection to the data source"; + log.error(msg, e); + throw new ReportManagementException(msg, e); + } catch (GroupManagementDAOException e) { + String msg = "Error occurred while retrieving the devices that are not assigned " + + "to queried groups"; + log.error(msg, e); + throw new ReportManagementException(msg, e); + } finally { + GroupManagementDAOFactory.closeConnection(); + } + } catch (DeviceManagementException e) { + String msg = "Error occurred while validating device list page size or loading " + + "device types"; + log.error(msg, e); + throw new ReportManagementException(msg, e); + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while retrieving Tenant ID"; + log.error(msg, e); + throw new ReportManagementException(msg, e); + } + } }