From ad8d89c43d9cf5117acef7e3eb5c53d0b64f4dba Mon Sep 17 00:00:00 2001 From: pramilaniroshan Date: Mon, 21 Aug 2023 12:11:48 +0530 Subject: [PATCH] Add Devices filtering by a Custom Property feature to API and dao layer --- .../service/api/DeviceManagementService.java | 7 ++ .../impl/DeviceManagementServiceImpl.java | 23 +++-- .../impl/DeviceManagementServiceImplTest.java | 34 ++++---- .../device/mgt/common/PaginationRequest.java | 13 +++ .../dao/impl/device/GenericDeviceDAOImpl.java | 85 +++++++++++++++++-- .../impl/device/SQLServerDeviceDAOImpl.java | 85 +++++++++++++++++-- 6 files changed, 207 insertions(+), 40 deletions(-) diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/api/DeviceManagementService.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/api/DeviceManagementService.java index 53f7fd9360..e39bd1d36a 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/api/DeviceManagementService.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/api/DeviceManagementService.java @@ -65,6 +65,7 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.sql.Timestamp; import java.util.List; +import java.util.Map; /** * Device related REST-API. This can be used to manipulated device related details. @@ -283,6 +284,12 @@ public interface DeviceManagementService { required = false) @QueryParam("serialNumber") String serialNumber, + @ApiParam( + name = "customProperty", + value = "CustomProperty from device as a JSON encoded string.", + required = false) + @QueryParam("customProperty") + String customProperty, @ApiParam( name = "status", value = "Provide the device status details, such as active or inactive.", diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImpl.java index b5851dff0c..962d7068b4 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImpl.java @@ -18,6 +18,7 @@ package io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.Gson; import io.entgra.device.mgt.core.application.mgt.common.ApplicationInstallResponse; import io.entgra.device.mgt.core.application.mgt.common.SubscriptionType; @@ -29,7 +30,6 @@ import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.json.JSONObject; import io.entgra.device.mgt.core.apimgt.keymgt.extension.DCRResponse; import io.entgra.device.mgt.core.apimgt.keymgt.extension.TokenRequest; import io.entgra.device.mgt.core.apimgt.keymgt.extension.TokenResponse; @@ -64,7 +64,6 @@ import io.entgra.device.mgt.core.device.mgt.common.type.mgt.DeviceStatus; import io.entgra.device.mgt.core.device.mgt.core.app.mgt.ApplicationManagementProviderService; import io.entgra.device.mgt.core.device.mgt.core.config.DeviceConfigurationManager; import io.entgra.device.mgt.core.device.mgt.core.config.DeviceManagementConfig; -import io.entgra.device.mgt.core.device.mgt.core.dao.TrackerManagementDAOException; import io.entgra.device.mgt.core.device.mgt.core.device.details.mgt.DeviceDetailsMgtException; import io.entgra.device.mgt.core.device.mgt.core.device.details.mgt.DeviceInformationManager; import io.entgra.device.mgt.core.device.mgt.core.dto.DeviceType; @@ -75,10 +74,7 @@ import io.entgra.device.mgt.core.device.mgt.core.search.mgt.SearchManagerService import io.entgra.device.mgt.core.device.mgt.core.search.mgt.SearchMgtException; import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService; import io.entgra.device.mgt.core.device.mgt.core.service.GroupManagementProviderService; -import io.entgra.device.mgt.core.device.mgt.core.traccar.api.service.DeviceAPIClientService; -import io.entgra.device.mgt.core.device.mgt.core.traccar.common.TraccarHandlerConstants; import io.entgra.device.mgt.core.device.mgt.core.util.DeviceManagerUtil; -import io.entgra.device.mgt.core.device.mgt.core.util.HttpReportingUtil; import io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans.*; import io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.api.DeviceManagementService; import io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.impl.util.InputValidationException; @@ -105,6 +101,7 @@ import java.util.Date; import java.util.List; import java.util.Properties; import java.util.concurrent.ExecutionException; +import java.util.Map; @Path("/devices") public class DeviceManagementServiceImpl implements DeviceManagementService { @@ -142,6 +139,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { @QueryParam("role") String role, @QueryParam("ownership") String ownership, @QueryParam("serialNumber") String serialNumber, + @QueryParam("customProperty") String customProperty, @QueryParam("status") List status, @QueryParam("groupId") int groupId, @QueryParam("since") String since, @@ -155,6 +153,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); } // RequestValidationUtil.validateSelectionCriteria(type, user, roleName, ownership, status); + final ObjectMapper objectMapper = new ObjectMapper(); RequestValidationUtil.validatePaginationParameters(offset, limit); DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService(); DeviceAccessAuthorizationService deviceAccessAuthorizationService = @@ -166,6 +165,20 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { if (name != null && !name.isEmpty()) { request.setDeviceName(name); } + if (customProperty != null && !customProperty.isEmpty()) { + try { + Map customProperties = objectMapper.readValue(customProperty, Map.class); + // Extract and set custom properties + for (Map.Entry entry : customProperties.entrySet()) { + String propertyName = entry.getKey(); + String propertyValue = entry.getValue(); + // Add custom property to the paginationRequest object + request.addCustomProperty(propertyName, propertyValue); + } + }catch (Exception e){ + log.error("Error Adding custom property to the paginationRequest object"); + } + } if (type != null && !type.isEmpty()) { request.setDeviceType(type); } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/test/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImplTest.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/test/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImplTest.java index 3a24db49f5..2ef62073bd 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/test/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImplTest.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/test/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/service/impl/DeviceManagementServiceImplTest.java @@ -157,7 +157,7 @@ public class DeviceManagementServiceImplTest { .toReturn(this.deviceAccessAuthorizationService); Response response = this.deviceManagementService .getDevices(TEST_DEVICE_NAME, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, - null, DEFAULT_STATUS_LIST, 1, null, null, false, + null, null, DEFAULT_STATUS_LIST, 1, null, null, false, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode()); } @@ -177,22 +177,22 @@ public class DeviceManagementServiceImplTest { Response response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, - null, DEFAULT_STATUS_LIST, 1, null, null, false, + null,null, DEFAULT_STATUS_LIST, 1, null, null, false, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); response = this.deviceManagementService .getDevices(TEST_DEVICE_NAME, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, null, DEFAULT_OWNERSHIP, - null, DEFAULT_STATUS_LIST, 1, null, null, false, + null, null, DEFAULT_STATUS_LIST, 1, null, null, false, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); response = this.deviceManagementService .getDevices(TEST_DEVICE_NAME, TEST_DEVICE_TYPE, null, null, null, DEFAULT_OWNERSHIP, - null, DEFAULT_STATUS_LIST, 1, null, null, false, + null, null, DEFAULT_STATUS_LIST, 1, null, null, false, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); response = this.deviceManagementService .getDevices(TEST_DEVICE_NAME, TEST_DEVICE_TYPE, null, null, null, DEFAULT_OWNERSHIP, - null, DEFAULT_STATUS_LIST, 1, null, null, true, + null, null, DEFAULT_STATUS_LIST, 1, null, null, true, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); } @@ -306,7 +306,7 @@ public class DeviceManagementServiceImplTest { .toReturn(this.deviceManagementProviderService); Mockito.when(deviceAccessAuthorizationService.isDeviceAdminUser()).thenReturn(true); deviceManagementService.getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, - DEFAULT_ROLE, DEFAULT_OWNERSHIP, null, DEFAULT_STATUS_LIST, 1, + DEFAULT_ROLE, DEFAULT_OWNERSHIP, null,null, DEFAULT_STATUS_LIST, 1, null, null, false, 10, 5); } @@ -326,11 +326,11 @@ public class DeviceManagementServiceImplTest { Response response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP - , null, DEFAULT_STATUS_LIST, 1, null, null, false, 10, 5); + , null, null, DEFAULT_STATUS_LIST, 1, null, null, false, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, null, DEFAULT_USERNAME, DEFAULT_ROLE, DEFAULT_OWNERSHIP - , null, DEFAULT_STATUS_LIST, 1, null, null, false, 10, 5); + , null, null, DEFAULT_STATUS_LIST, 1, null, null, false, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); } @@ -352,7 +352,7 @@ public class DeviceManagementServiceImplTest { Response response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, "newuser", null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, - null, DEFAULT_STATUS_LIST, 0, null, null, false, + null, null, DEFAULT_STATUS_LIST, 0, null, null, false, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.UNAUTHORIZED.getStatusCode()); Mockito.reset(this.deviceAccessAuthorizationService); @@ -374,17 +374,17 @@ public class DeviceManagementServiceImplTest { Response response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, - null, DEFAULT_STATUS_LIST, 0, null, ifModifiedSince, false, + null, null, DEFAULT_STATUS_LIST, 0, null, ifModifiedSince, false, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.NOT_MODIFIED.getStatusCode()); response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, - null, DEFAULT_STATUS_LIST, 0, null, ifModifiedSince, true, + null, null, DEFAULT_STATUS_LIST, 0, null, ifModifiedSince, true, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.NOT_MODIFIED.getStatusCode()); response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, - null, DEFAULT_STATUS_LIST, 0, null, "ErrorModifiedSince", + null, null, DEFAULT_STATUS_LIST, 0, null, "ErrorModifiedSince", false, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode()); } @@ -405,17 +405,17 @@ public class DeviceManagementServiceImplTest { Response response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, - null, DEFAULT_STATUS_LIST, 0, since, null, false, + null, null,DEFAULT_STATUS_LIST, 0, since, null, false, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, - null, DEFAULT_STATUS_LIST, 0, since, null, true, + null, null,DEFAULT_STATUS_LIST, 0, since, null, true, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, - null, DEFAULT_STATUS_LIST, 0, "ErrorSince", null, false, + null, null,DEFAULT_STATUS_LIST, 0, "ErrorSince", null, false, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode()); } @@ -438,7 +438,7 @@ public class DeviceManagementServiceImplTest { Response response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, - null, DEFAULT_STATUS_LIST, 1, null, null, false, + null, null, DEFAULT_STATUS_LIST, 1, null, null, false, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); Mockito.reset(this.deviceManagementProviderService); @@ -461,7 +461,7 @@ public class DeviceManagementServiceImplTest { Response response = this.deviceManagementService .getDevices(null, TEST_DEVICE_TYPE, DEFAULT_USERNAME, null, DEFAULT_ROLE, DEFAULT_OWNERSHIP, - null, DEFAULT_STATUS_LIST, 1, null, null, false, + null, null, DEFAULT_STATUS_LIST, 1, null, null, false, 10, 5); Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); Mockito.reset(this.deviceAccessAuthorizationService); diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/PaginationRequest.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/PaginationRequest.java index d9c2c62d47..c0783fe18f 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/PaginationRequest.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/PaginationRequest.java @@ -41,6 +41,7 @@ public class PaginationRequest { private Date since; private String filter; private String serialNumber; + private Map customProperty = new HashMap<>(); private Map property = new HashMap<>(); private List statusList = new ArrayList<>(); private OperationLogFilters operationLogFilters = new OperationLogFilters(); @@ -115,6 +116,18 @@ public class PaginationRequest { return ownership; } + public Map getCustomProperty() { + return customProperty; + } + + public void setCustomProperty(Map customProperty) { + this.customProperty = customProperty; + } + + public void addCustomProperty(String key, String value) { + customProperty.put(key, value); + } + public void setOwnership(String ownership) { this.ownership = ownership; } diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java index b3c6b8f18a..bb7318adde 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java @@ -41,6 +41,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.StringJoiner; +import java.util.Map; /** * This class holds the generic implementation of DeviceDAO which can be used to support ANSI db syntax. @@ -92,15 +93,31 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { "d.DEVICE_IDENTIFICATION, " + "t.NAME AS DEVICE_TYPE "; - if (serial != null) { - sql = sql + "FROM DM_DEVICE d, DM_DEVICE_TYPE t, DM_DEVICE_INFO i " + - "WHERE DEVICE_TYPE_ID = t.ID " + - "AND d.ID= i.DEVICE_ID " + - "AND i.KEY_FIELD = 'serial' " + - "AND i.VALUE_FIELD LIKE ? " + - "AND d.TENANT_ID = ? "; - isSerialProvided = true; - } else { + //Filter by serial number or any Custom Property in DM_DEVICE_INFO + if (serial != null || !request.getCustomProperty().isEmpty()) { + sql = sql + "FROM DM_DEVICE d INNER JOIN DM_DEVICE_TYPE t ON d.DEVICE_TYPE_ID = t.ID WHERE "; + if (serial != null) { + sql += "EXISTS ( SELECT VALUE_FIELD FROM DM_DEVICE_INFO di WHERE di.DEVICE_ID = d.ID "; + sql += "AND di.KEY_FIELD = 'serial' AND di.VALUE_FIELD LIKE ? ) "; + isSerialProvided = true; + } + if (!request.getCustomProperty().isEmpty()) { + if (serial != null) { + sql += "AND "; + } + int conditionCount = 0; + for (Map.Entry entry : request.getCustomProperty().entrySet()) { + if (conditionCount > 0) { + sql += "AND "; + } + sql += "EXISTS ( SELECT VALUE_FIELD FROM DM_DEVICE_INFO di WHERE di.DEVICE_ID = d.ID "; + sql += "AND di.KEY_FIELD = '"+entry.getKey()+"' AND di.VALUE_FIELD LIKE ? ) "; + conditionCount++; + } + } + sql += "AND d.TENANT_ID = ? "; + } + else { sql = sql + "FROM DM_DEVICE d, DM_DEVICE_TYPE t WHERE DEVICE_TYPE_ID = t.ID AND d.TENANT_ID = ? "; } //Add query for last updated timestamp @@ -143,6 +160,11 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { if (isSerialProvided) { stmt.setString(paramIdx++, "%" + serial + "%"); } + if (!request.getCustomProperty().isEmpty()) { + for (Map.Entry entry : request.getCustomProperty().entrySet()) { + stmt.setString(paramIdx++, "%" + entry.getValue() + "%"); + } + } stmt.setInt(paramIdx++, tenantId); if (isSinceProvided) { stmt.setTimestamp(paramIdx++, new Timestamp(since.getTime())); @@ -624,6 +646,8 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { boolean isStatusProvided = false; Date since = request.getSince(); boolean isSinceProvided = false; + String serial = request.getSerialNumber(); + boolean isSerialProvided = false; try { Connection conn = getConnection(); @@ -692,6 +716,24 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { sql += buildStatusQuery(statusList); isStatusProvided = true; } + //Filter Group with serial number or any Custom Property in DM_DEVICE_INFO + if (serial != null || !request.getCustomProperty().isEmpty()) { + if (serial != null) { + sql += "AND EXISTS (SELECT VALUE_FIELD FROM DM_DEVICE_INFO di WHERE di.DEVICE_ID = d1.DEVICE_ID "; + sql += "AND di.KEY_FIELD = 'serial' AND di.VALUE_FIELD LIKE ?)"; + isSerialProvided = true; + } + if (!request.getCustomProperty().isEmpty()) { + for (Map.Entry entry : request.getCustomProperty().entrySet()) { + sql += "AND EXISTS (" + + "SELECT VALUE_FIELD " + + "FROM DM_DEVICE_INFO di2 " + + "WHERE di2.DEVICE_ID = d1.DEVICE_ID " + + "AND di2.KEY_FIELD = '" + entry.getKey() + "' " + + "AND di2.VALUE_FIELD LIKE ?)"; + } + } + } sql = sql + " LIMIT ?,?"; try (PreparedStatement stmt = conn.prepareStatement(sql)) { @@ -721,6 +763,14 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { stmt.setString(paramIdx++, status); } } + if (isSerialProvided) { + stmt.setString(paramIdx++, "%" + serial + "%"); + } + if (!request.getCustomProperty().isEmpty()) { + for (Map.Entry entry : request.getCustomProperty().entrySet()) { + stmt.setString(paramIdx++, "%" + entry.getValue() + "%"); + } + } stmt.setInt(paramIdx++, request.getStartIndex()); stmt.setInt(paramIdx, request.getRowCount()); @@ -1250,6 +1300,17 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { query += buildStatusQuery(status); isStatusProvided = true; } + // Loop through custom properties and add conditions + if (!request.getCustomProperty().isEmpty()) { + for (Map.Entry entry : request.getCustomProperty().entrySet()) { + query += " AND EXISTS (" + + "SELECT VALUE_FIELD " + + "FROM DM_DEVICE_INFO di2 " + + "WHERE di2.DEVICE_ID = DM_DEVICE.ID " + + "AND di2.KEY_FIELD = '" + entry.getKey() + "' " + + "AND di2.VALUE_FIELD LIKE ?)"; + } + } query = query + " LIMIT ?,?"; @@ -1277,6 +1338,12 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { ps.setString(index++, deviceStatus); } } + // Set custom property values in the loop + if (!request.getCustomProperty().isEmpty()) { + for (Map.Entry entry : request.getCustomProperty().entrySet()) { + ps.setString(index++, "%" + entry.getValue() + "%"); + } + } ps.setInt(index++, offsetValue); ps.setInt(index, limitValue); diff --git a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java index 3a7f0f95b9..604fd3f268 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java @@ -43,6 +43,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.StringJoiner; +import java.util.Map; /** * This class holds the generic implementation of DeviceDAO which can be used to support ANSI db syntax. @@ -94,15 +95,31 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl { "d.DEVICE_IDENTIFICATION, " + "t.NAME AS DEVICE_TYPE "; - if (serial != null) { - sql = sql + "FROM DM_DEVICE d, DM_DEVICE_TYPE t, DM_DEVICE_INFO i " + - "WHERE DEVICE_TYPE_ID = t.ID " + - "AND d.ID= i.DEVICE_ID " + - "AND i.KEY_FIELD = 'serial' " + - "AND i.VALUE_FIELD LIKE ? " + - "AND d.TENANT_ID = ? "; - isSerialProvided = true; - } else { + //Filter by serial number or any Custom Property in DM_DEVICE_INFO + if (serial != null || !request.getCustomProperty().isEmpty()) { + sql = sql + "FROM DM_DEVICE d INNER JOIN DM_DEVICE_TYPE t ON d.DEVICE_TYPE_ID = t.ID WHERE "; + if (serial != null) { + sql += "EXISTS ( SELECT VALUE_FIELD FROM DM_DEVICE_INFO di WHERE di.DEVICE_ID = d.ID "; + sql += "AND di.KEY_FIELD = 'serial' AND di.VALUE_FIELD LIKE ? ) "; + isSerialProvided = true; + } + if (!request.getCustomProperty().isEmpty()) { + if (serial != null) { + sql += "AND "; + } + int conditionCount = 0; + for (Map.Entry entry : request.getCustomProperty().entrySet()) { + if (conditionCount > 0) { + sql += "AND "; + } + sql += "EXISTS ( SELECT VALUE_FIELD FROM DM_DEVICE_INFO di WHERE di.DEVICE_ID = d.ID "; + sql += "AND di.KEY_FIELD = '"+entry.getKey()+"' AND di.VALUE_FIELD LIKE ? ) "; + conditionCount++; + } + } + sql += "AND d.TENANT_ID = ? "; + } + else { sql = sql + "FROM DM_DEVICE d, DM_DEVICE_TYPE t WHERE DEVICE_TYPE_ID = t.ID AND d.TENANT_ID = ? "; } //Add query for last updated timestamp @@ -145,6 +162,11 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl { if (isSerialProvided) { stmt.setString(paramIdx++, "%" + serial + "%"); } + if (!request.getCustomProperty().isEmpty()) { + for (Map.Entry entry : request.getCustomProperty().entrySet()) { + stmt.setString(paramIdx++, "%" + entry.getValue() + "%"); + } + } stmt.setInt(paramIdx++, tenantId); if (isSinceProvided) { stmt.setTimestamp(paramIdx++, new Timestamp(since.getTime())); @@ -455,6 +477,8 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl { boolean isStatusProvided = false; Date since = request.getSince(); boolean isSinceProvided = false; + String serial = request.getSerialNumber(); + boolean isSerialProvided = false; try { conn = getConnection(); @@ -522,6 +546,24 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl { sql += buildStatusQuery(statusList); isStatusProvided = true; } + //Filter Group with serial number or any Custom Property in DM_DEVICE_INFO + if (serial != null || !request.getCustomProperty().isEmpty()) { + if (serial != null) { + sql += "AND EXISTS (SELECT VALUE_FIELD FROM DM_DEVICE_INFO di WHERE di.DEVICE_ID = d1.DEVICE_ID "; + sql += "AND di.KEY_FIELD = 'serial' AND di.VALUE_FIELD LIKE ?)"; + isSerialProvided = true; + } + if (!request.getCustomProperty().isEmpty()) { + for (Map.Entry entry : request.getCustomProperty().entrySet()) { + sql += "AND EXISTS (" + + "SELECT VALUE_FIELD " + + "FROM DM_DEVICE_INFO di2 " + + "WHERE di2.DEVICE_ID = d1.DEVICE_ID " + + "AND di2.KEY_FIELD = '" + entry.getKey() + "' " + + "AND di2.VALUE_FIELD LIKE ?)"; + } + } + } sql = sql + " ORDER BY ENROLMENT_ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; try (PreparedStatement stmt = conn.prepareStatement(sql)) { @@ -551,6 +593,14 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl { stmt.setString(paramIdx++, status); } } + if (isSerialProvided) { + stmt.setString(paramIdx++, "%" + serial + "%"); + } + if (!request.getCustomProperty().isEmpty()) { + for (Map.Entry entry : request.getCustomProperty().entrySet()) { + stmt.setString(paramIdx++, "%" + entry.getValue() + "%"); + } + } stmt.setInt(paramIdx++, request.getStartIndex()); stmt.setInt(paramIdx, request.getRowCount()); @@ -883,6 +933,17 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl { query += buildStatusQuery(status); isStatusProvided = true; } + // Loop through custom properties and add conditions + if (!request.getCustomProperty().isEmpty()) { + for (Map.Entry entry : request.getCustomProperty().entrySet()) { + query += " AND EXISTS (" + + "SELECT VALUE_FIELD " + + "FROM DM_DEVICE_INFO di2 " + + "WHERE di2.DEVICE_ID = DM_DEVICE.ID " + + "AND di2.KEY_FIELD = '" + entry.getKey() + "' " + + "AND di2.VALUE_FIELD LIKE ?)"; + } + } query = query + " ORDER BY DM_DEVICE.ID OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; @@ -907,6 +968,12 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl { ps.setString(index++, deviceStatus); } } + // Set custom property values in the loop + if (!request.getCustomProperty().isEmpty()) { + for (Map.Entry entry : request.getCustomProperty().entrySet()) { + ps.setString(index++, "%" + entry.getValue() + "%"); + } + } ps.setInt(index++, offsetValue); ps.setInt(index, limitValue);