From 694109b50f4cbc75a2dff814e06abbbd3d408e3b Mon Sep 17 00:00:00 2001 From: Jayasanka Weerasinghe Date: Wed, 5 Feb 2020 18:45:18 +0530 Subject: [PATCH] Create API and the report to filter devices by encryption status --- .../react-app/src/index.js | 11 +- .../EncryptedDevicesTable.js | 258 ++++++++++++++++++ .../Reports/scenes/EncryptionStatus/index.js | 59 ++++ .../service/api/ReportManagementService.java | 50 ++++ .../impl/ReportManagementServiceImpl.java | 26 ++ .../report/mgt/ReportManagementService.java | 10 + .../carbon/device/mgt/core/dao/DeviceDAO.java | 23 ++ .../core/dao/impl/AbstractDeviceDAOImpl.java | 102 +++++++ .../dao/impl/device/OracleDeviceDAOImpl.java | 64 +++++ .../mgt/ReportManagementServiceImpl.java | 42 +++ 10 files changed, 640 insertions(+), 5 deletions(-) create mode 100644 components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EncryptionStatus/components/EncryptedDeviceTable/EncryptedDevicesTable.js create mode 100644 components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EncryptionStatus/index.js diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/index.js index 1823f97d2a..94b2c91c00 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/index.js +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/index.js @@ -30,6 +30,7 @@ import PolicyReport from './scenes/Home/scenes/Reports/scenes/PolicyCompliance'; import DeviceStatusReport from './scenes/Home/scenes/Reports/scenes/DeviceStatus'; import AppNotInstalledDevicesReport from './scenes/Home/scenes/Reports/scenes/AppNotInstalledDevices'; import Geo from './scenes/Home/scenes/Geo'; +import EncryptionStatus from './scenes/Home/scenes/Reports/scenes/EncryptionStatus'; const routes = [ { @@ -53,11 +54,6 @@ const routes = [ // exact: true, // }, // { - // path: '/entgra/geo', - // component: Geo, - // exact: true, - // }, - // { // path: '/entgra/devices', // component: Devices, // exact: true, @@ -137,6 +133,11 @@ const routes = [ component: AppNotInstalledDevicesReport, exact: true, }, + { + path: '/entgra/reports/encryption-status', + component: EncryptionStatus, + exact: true, + }, ], }, ]; diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EncryptionStatus/components/EncryptedDeviceTable/EncryptedDevicesTable.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EncryptionStatus/components/EncryptedDeviceTable/EncryptedDevicesTable.js new file mode 100644 index 0000000000..a18985d64b --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EncryptionStatus/components/EncryptedDeviceTable/EncryptedDevicesTable.js @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2020, Entgra (pvt) Ltd. (http://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. + */ + +import React from 'react'; +import axios from 'axios'; +import { Icon, message, notification, Radio, Table, Tag, Tooltip } from 'antd'; +import TimeAgo from 'javascript-time-ago'; +// Load locale-specific relative date/time formatting rules. +import en from 'javascript-time-ago/locale/en'; +import { withConfigContext } from '../../../../../../../../components/ConfigContext'; + +let config = null; + +const columns = [ + { + title: 'Device', + dataIndex: 'name', + }, + { + title: 'Type', + dataIndex: 'type', + key: 'type', + // eslint-disable-next-line react/display-name + render: type => { + const defaultPlatformIcons = config.defaultPlatformIcons; + let icon = defaultPlatformIcons.default.icon; + let color = defaultPlatformIcons.default.color; + let theme = defaultPlatformIcons.default.theme; + + if (defaultPlatformIcons.hasOwnProperty(type)) { + icon = defaultPlatformIcons[type].icon; + color = defaultPlatformIcons[type].color; + theme = defaultPlatformIcons[type].theme; + } + + return ( + + + + ); + }, + // todo add filtering options + }, + { + title: 'Owner', + dataIndex: 'enrolmentInfo', + key: 'owner', + render: enrolmentInfo => enrolmentInfo.owner, + // todo add filtering options + }, + { + title: 'Ownership', + dataIndex: 'enrolmentInfo', + key: 'ownership', + render: enrolmentInfo => enrolmentInfo.ownership, + // todo add filtering options + }, + { + title: 'Status', + dataIndex: 'enrolmentInfo', + key: 'status', + // eslint-disable-next-line react/display-name + render: enrolmentInfo => { + const status = enrolmentInfo.status.toLowerCase(); + let color = '#f9ca24'; + switch (status) { + case 'active': + color = '#badc58'; + break; + case 'created': + color = '#6ab04c'; + break; + case 'removed': + color = '#ff7979'; + break; + case 'inactive': + color = '#f9ca24'; + break; + case 'blocked': + color = '#636e72'; + break; + } + return {status}; + }, + // todo add filtering options + }, + { + title: 'Last Updated', + dataIndex: 'enrolmentInfo', + key: 'dateOfLastUpdate', + // eslint-disable-next-line react/display-name + render: data => { + const { dateOfLastUpdate } = data; + const timeAgoString = getTimeAgo(dateOfLastUpdate); + return ( + + {timeAgoString} + + ); + }, + // todo add filtering options + }, +]; + +const getTimeAgo = time => { + const timeAgo = new TimeAgo('en-US'); + return timeAgo.format(time); +}; + +class EncryptedDeviceTable extends React.Component { + constructor(props) { + super(props); + config = this.props.context; + TimeAgo.addLocale(en); + this.state = { + data: [], + pagination: {}, + loading: false, + isEncrypted: true, + }; + } + + componentDidMount() { + this.fetch(); + } + + // fetch data from api + fetch = (params = {}) => { + const config = this.props.context; + this.setState({ loading: true }); + // get current page + const currentPage = params.hasOwnProperty('page') ? params.page : 1; + + const extraParams = { + offset: 10 * (currentPage - 1), // calculate the offset + limit: 10, + requireDeviceInfo: true, + isEncrypted: this.state.isEncrypted, + }; + + const encodedExtraParams = Object.keys(extraParams) + .map(key => key + '=' + extraParams[key]) + .join('&'); + + // send request to the invoker + axios + .get( + window.location.origin + + config.serverConfig.invoker.uri + + config.serverConfig.invoker.deviceMgt + + '/reports/encryption-status?' + + encodedExtraParams, + ) + .then(res => { + if (res.status === 200) { + const pagination = { ...this.state.pagination }; + this.setState({ + loading: false, + data: res.data.data.devices, + pagination, + }); + } + }) + .catch(error => { + if (error.hasOwnProperty('response') && error.response.status === 401) { + // todo display a popop with error + message.error('You are not logged in'); + window.location.href = window.location.origin + '/entgra/login'; + } else { + notification.error({ + message: 'There was a problem', + duration: 0, + description: 'Error occurred while trying to load devices.', + }); + } + this.setState({ loading: false }); + }); + }; + + handleTableChange = (pagination, filters, sorter) => { + const pager = { ...this.state.pagination }; + pager.current = pagination.current; + this.setState({ + pagination: pager, + }); + this.fetch({ + results: pagination.pageSize, + page: pagination.current, + sortField: sorter.field, + sortOrder: sorter.order, + ...filters, + }); + }; + + handleModeChange = value => { + this.setState( + { + isEncrypted: value.target.value, + }, + this.fetch, + ); + }; + + render() { + const { data, pagination, loading } = this.state; + + return ( +
+ + Enabled Devices + Disabled Devices + +
+ + record.deviceIdentifier + + record.enrolmentInfo.owner + + record.enrolmentInfo.ownership + } + dataSource={data} + pagination={{ + ...pagination, + size: 'small', + // position: "top", + showTotal: (total, range) => + `showing ${range[0]}-${range[1]} of ${total} devices`, + // showQuickJumper: true + }} + loading={loading} + onChange={this.handleTableChange} + /> + + + ); + } +} + +export default withConfigContext(EncryptedDeviceTable); diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EncryptionStatus/index.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EncryptionStatus/index.js new file mode 100644 index 0000000000..cd9f568ec7 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/scenes/Home/scenes/Reports/scenes/EncryptionStatus/index.js @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020, Entgra (pvt) Ltd. (http://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. + */ + +import React from 'react'; +import { PageHeader, Breadcrumb, Icon } from 'antd'; +import { Link } from 'react-router-dom'; +import EncryptedDeviceTable from './components/EncryptedDeviceTable/EncryptedDevicesTable'; + +class EncryptionStatus extends React.Component { + routes; + + constructor(props) { + super(props); + this.routes = props.routes; + } + render() { + return ( +
+ + + + + Home + + + + Reports + + Encryption Status + +
+

Encryption Status Report

+
+ +
+
+
+ ); + } +} + +export default EncryptionStatus; 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 6a33957f27..6ce1b09403 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 @@ -371,6 +371,56 @@ public interface ReportManagementService { @QueryParam("limit") int limit); + @GET + @Path("/encryption-status") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting Details of Registered Devices filtered by encryption status", + notes = "Provides details of devices which is in provided encryption status", + tags = "Device Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:view") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the list of devices.", + response = DeviceList.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body")}), + @ApiResponse( + code = 500, + message = "Internal Server Error. " + + "\n Server error occurred while fetching the devices.", + response = ErrorResponse.class) + }) + Response getDevicesByEncryptionStatus( + @ApiParam( + name = "isEncrypted", + value = "The encryption states which used to filter the devices", + required = true) + @QueryParam("isEncrypted") + boolean isEncrypted, + @ApiParam( + name = "offset", + value = "The starting pagination index for the list of filtered devices.", + defaultValue = "0") + @QueryParam("offset") + int offset, + @ApiParam( + name = "limit", + value = "Limit of the number of deices that should be returned.", + defaultValue = "5") + @QueryParam("limit") + int limit); + @GET @Path("/devices/{device-type}/{package-name}/not-installed") @ApiOperation( 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 212c73177f..331a3bfdd2 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 @@ -238,4 +238,30 @@ public class ReportManagementServiceImpl implements ReportManagementService { return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } } + + @GET + @Path("/encryption-status") + @Override + public Response getDevicesByEncryptionStatus(@QueryParam("isEncrypted") boolean isEncrypted, + @DefaultValue("0") + @QueryParam("offset") int offset, + @DefaultValue("5") + @QueryParam("limit") int limit) { + try { + PaginationRequest request = new PaginationRequest(offset, limit); + + PaginationResult paginationResult = DeviceMgtAPIUtils + .getReportManagementService() + .getDevicesByEncryptionStatus(request, isEncrypted); + + DeviceList deviceList = new DeviceList(); + deviceList.setList((List) paginationResult.getData()); + deviceList.setCount(paginationResult.getRecordsTotal()); + return Response.status(Response.Status.OK).entity(deviceList).build(); + } catch (ReportManagementException e) { + String msg = "Error occurred while retrieving devices list with provided encryption status"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).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 a8b24bae30..6e001fd73b 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 @@ -61,6 +61,16 @@ public interface ReportManagementService { PaginationResult getDevicesExpiredByOSVersion(PaginationRequest request) throws ReportManagementException, DeviceTypeNotFoundException; + /** + * Get a paginated list of devices which is filtered by given encryption status + * + * @param request {@link PaginationRequest} + * @return {@link PaginationResult} + * @throws ReportManagementException Might occur during the business logic or building database query + */ + PaginationResult getDevicesByEncryptionStatus(PaginationRequest request, boolean isEncrypted) + throws ReportManagementException; + /** * This method is used to get devices which have not installed the app with the given package name * diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java index 072e12b61c..7f7b2f047f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java @@ -645,6 +645,29 @@ public interface DeviceDAO { int getCountOfDeviceExpiredByOSVersion(String deviceType, long osBuildDate, int tenantId) throws DeviceManagementDAOException; + /** + * Get a paginated list of devices filtered by given encryption status + * + * @param request Object with device type and OS version info + * @param tenantId Id of the current tenant. + * @param isEncrypted Encryption status to be filtered. + * @return {@link List} + * @throws DeviceManagementDAOException Thrown if error occurs while database transactions + */ + List getDevicesByEncryptionStatus(PaginationRequest request, int tenantId, boolean isEncrypted) + throws DeviceManagementDAOException; + + /** + * Count the number of devices devices in the given encryption status + * + * @param tenantId Id of the current tenant. + * @param isEncrypted Encryption status to be filtered. + * @return {@link Integer} + * @throws DeviceManagementDAOException Thrown if error occurs while database transactions + */ + int getCountOfDevicesByEncryptionStatus(int tenantId, boolean isEncrypted) + throws DeviceManagementDAOException; + /** * This method is used to get devices which have not installed the app with the given package name * diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java index b01925016f..5bcfb202e9 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/AbstractDeviceDAOImpl.java @@ -2134,6 +2134,108 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO { } } + @Override + public List getDevicesByEncryptionStatus(PaginationRequest request, int tenantId, boolean isEncrypted) + throws DeviceManagementDAOException { + try { + Connection conn = getConnection(); + String sql = "" + + "SELECT e1.owner," + + "e1.ownership," + + "e1.enrolment_id," + + "e1.device_id," + + "e1.status," + + "e1.date_of_last_update," + + "e1.date_of_enrolment," + + "d.description," + + "d.NAME AS DEVICE_NAME," + + "d.device_identification," + + "t.NAME AS DEVICE_TYPE " + + "FROM dm_device d," + + "(SELECT e.owner," + + "e.ownership," + + "e.id AS ENROLMENT_ID," + + "e.device_id," + + "e.status, " + + "e.date_of_last_update, " + + "e.date_of_enrolment " + + "FROM dm_enrolment e " + + "INNER JOIN " + + "(SELECT DEVICE_ID " + + "FROM DM_DEVICE_INFO " + + "WHERE " + + "KEY_FIELD = 'encryptionEnabled' " + + "AND VALUE_FIELD = ?) AS di " + + "ON di.DEVICE_ID = e.DEVICE_ID " + + "WHERE e.tenant_id = ?) e1, " + + "dm_device_type t " + + "WHERE d.id = e1.device_id " + + "AND t.id = d.device_type_id " + + "ORDER BY e1.date_of_last_update DESC " + + "LIMIT ? OFFSET ?"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setBoolean(1, isEncrypted); + ps.setInt(2, tenantId); + ps.setInt(3, request.getRowCount()); + ps.setInt(4, request.getStartIndex()); + + try (ResultSet rs = ps.executeQuery()) { + List devices = new ArrayList<>(); + if (rs.next()) { + Device device = DeviceManagementDAOUtil.loadDevice(rs); + devices.add(device); + } + return devices; + } + } + } catch (SQLException e) { + String msg = "Error occurred while building or executing queries to retrieve information " + + "of devices filtered by encryption status: " + isEncrypted; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + + @Override + public int getCountOfDevicesByEncryptionStatus(int tenantId, boolean isEncrypted) + throws DeviceManagementDAOException { + try { + Connection conn = getConnection(); + String sql = "" + + "SELECT " + + "COUNT(e1.DEVICE_ID) AS DEVICE_COUNT " + + "FROM dm_device d," + + "(SELECT e.id AS ENROLMENT_ID, " + + "e.device_id " + + "FROM dm_enrolment e " + + "INNER JOIN " + + "(SELECT DEVICE_ID " + + "FROM DM_DEVICE_INFO " + + "WHERE KEY_FIELD = 'encryptionEnabled' " + + "AND VALUE_FIELD = ?) AS di " + + "ON di.DEVICE_ID = e.DEVICE_ID " + + "WHERE e.tenant_id = ?) e1, " + + "dm_device_type t " + + "WHERE d.id = e1.device_id " + + "AND t.id = d.device_type_id "; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setBoolean(1, isEncrypted); + ps.setInt(2, tenantId); + + try (ResultSet rs = ps.executeQuery()) { + return rs.next() ? rs.getInt("DEVICE_COUNT") : 0; + } + } + } catch (SQLException e) { + String msg = "Error occurred while building or executing queries to retrieve the count of devices " + + "in the provided encryption status: " + isEncrypted; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + /*** * This method removes records of a given list of devices from the DM_DEVICE_DETAIL table * @param conn Connection object diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java index 033d7c80b9..37a64568b6 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java @@ -894,6 +894,70 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl { } } + @Override + public List getDevicesByEncryptionStatus(PaginationRequest request, int tenantId, boolean isEncrypted) + throws DeviceManagementDAOException { + try { + Connection conn = getConnection(); + String sql = "" + + "SELECT e1.owner, " + + "e1.ownership, " + + "e1.enrolment_id, " + + "e1.device_id, " + + "e1.status, " + + "e1.date_of_last_update, " + + "e1.date_of_enrolment, " + + "d.description, " + + "d.NAME AS DEVICE_NAME, " + + "d.device_identification, " + + "t.NAME AS DEVICE_TYPE " + + "FROM dm_device d, " + + "(SELECT e.owner, " + + "e.ownership, " + + "e.id AS ENROLMENT_ID, " + + "e.device_id, " + + "e.status, " + + "e.date_of_last_update, " + + "e.date_of_enrolment " + + "FROM dm_enrolment e " + + "INNER JOIN " + + "(SELECT DEVICE_ID " + + "FROM DM_DEVICE_INFO " + + "WHERE " + + "KEY_FIELD = 'encryptionEnabled' " + + "AND VALUE_FIELD = ?) AS di " + + "ON di.DEVICE_ID = e.DEVICE_ID " + + "WHERE e.tenant_id = ?) e1, " + + "dm_device_type t " + + "WHERE d.id = e1.device_id " + + "AND t.id = d.device_type_id " + + "ORDER BY e1.date_of_last_update DESC " + + "OFFSET ? ROWS " + + "FETCH NEXT ? ROWS ONLY"; + + try (PreparedStatement ps = conn.prepareStatement(sql)) { + ps.setBoolean(1, isEncrypted); + ps.setInt(2, tenantId); + ps.setInt(3, request.getStartIndex()); + ps.setInt(4, request.getRowCount()); + + try (ResultSet rs = ps.executeQuery()) { + List devices = new ArrayList<>(); + if (rs.next()) { + Device device = DeviceManagementDAOUtil.loadDevice(rs); + devices.add(device); + } + return devices; + } + } + } catch (SQLException e) { + String msg = "Error occurred while building or executing queries to retrieve information " + + "of devices filtered by encryption status: " + isEncrypted; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } + } + private Connection getConnection() throws SQLException { return DeviceManagementDAOFactory.getConnection(); } 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 2d8971c618..4c09790655 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 @@ -215,6 +215,48 @@ public class ReportManagementServiceImpl implements ReportManagementService { } } + @Override + public PaginationResult getDevicesByEncryptionStatus(PaginationRequest request, boolean isEncrypted) + throws ReportManagementException { + if (request == null) { + String msg = "Error. The request must be a not null value."; + log.error(msg); + throw new ReportManagementException(msg); + } + try { + int tenantId = DeviceManagementDAOUtil.getTenantId(); + PaginationResult paginationResult = new PaginationResult(); + + DeviceManagerUtil.validateDeviceListPageSize(request); + + try { + DeviceManagementDAOFactory.openConnection(); + List devices = deviceDAO.getDevicesByEncryptionStatus(request, tenantId, isEncrypted); + int deviceCount = deviceDAO.getCountOfDevicesByEncryptionStatus(tenantId, isEncrypted); + paginationResult.setData(devices); + paginationResult.setRecordsFiltered(devices.size()); + paginationResult.setRecordsTotal(deviceCount); + + 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); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while retrieving expired devices by encryption status for the tenant"; + log.error(msg, e); + throw new ReportManagementException(msg, e); + } catch (DeviceManagementException e) { + String msg = "Error occurred while validating the request"; + log.error(msg, e); + throw new ReportManagementException(msg, e); + } + } + //NOTE: This is just a temporary method for retrieving device counts public JsonObject buildCount(String start, String end, List countList) throws ParseException { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");