From fccae9b8c09049b152ec210b2851c517fb97395a Mon Sep 17 00:00:00 2001 From: Pramila Niroshan Date: Fri, 15 Sep 2023 04:02:34 +0000 Subject: [PATCH] Add Devices filtering by a Custom Property feature to API and dao layer (#208) ## Purpose * Related ticket https://roadmap.entgra.net/issues/10262 ## Description This modifed API accept any custom property key value pair as a encoded JSON String for filtering devices /devicescustomProperty=%7B%22FIRMWARE_APP_VERSION%22%3A%22122%22%2C%22FIRMWARE_VERSION%22%3A%22123%22%7D ## Add Custom property to mdm-ui-config.xml ``` FIRMWARE_VERSION label_firmware_version deviceDetailsMap FIRMWARE_APP_VERSION label_app_version deviceDetailsMap FIRMWARE_SYSTEM_VERSION label_firmware_system_version deviceDetailsMap ``` DefinedValue = Key_value in DM_DEVECE_INFO table DisplayValue = UI display text for filtering Type = Dont change Co-authored-by: pramilaniroshan Reviewed-on: https://repository.entgra.net/community/device-mgt-core/pulls/208 Co-authored-by: Pramila Niroshan Co-committed-by: Pramila Niroshan --- .../service/api/DeviceManagementService.java | 7 ++ .../impl/DeviceManagementServiceImpl.java | 26 ++++- .../impl/DeviceManagementServiceImplTest.java | 34 +++---- .../device/mgt/common/PaginationRequest.java | 13 +++ .../dao/impl/device/GenericDeviceDAOImpl.java | 97 +++++++++++++++++-- .../dao/impl/device/OracleDeviceDAOImpl.java | 97 +++++++++++++++++-- .../impl/device/PostgreSQLDeviceDAOImpl.java | 97 +++++++++++++++++-- .../impl/device/SQLServerDeviceDAOImpl.java | 97 +++++++++++++++++-- 8 files changed, 414 insertions(+), 54 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 467dd238c71..e3d9416a2cb 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 2eaa0a55951..1960d0e41d0 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; @@ -98,6 +94,7 @@ import javax.validation.Valid; import javax.validation.constraints.Size; import javax.ws.rs.*; import javax.ws.rs.core.Response; +import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -105,6 +102,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 +140,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 +154,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 +166,22 @@ 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 (IOException e) { + String msg = "Error occurred while converting custom property string to a Java Map"; + log.error(msg); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } 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 3a24db49f53..2ef62073bd5 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 d9c2c62d47d..c0783fe18f9 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 b3c6b8f18ac..fbd3b05d244 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,14 +93,40 @@ 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; + //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 " + + "AND di.KEY_FIELD = 'serial' " + + "AND di.VALUE_FIELD LIKE ? ) "; + isSerialProvided = true; + } + if (!request.getCustomProperty().isEmpty()) { + if (serial != null) { + sql += "AND "; + } + boolean firstCondition = true; + for (Map.Entry entry : request.getCustomProperty().entrySet()) { + if (!firstCondition) { + sql += "AND "; + } + sql += "EXISTS (" + + "SELECT VALUE_FIELD " + + "FROM DM_DEVICE_INFO di " + + "WHERE di.DEVICE_ID = d.ID " + + "AND di.KEY_FIELD = '" + entry.getKey() + "' " + + "AND di.VALUE_FIELD LIKE ? ) "; + firstCondition = false; + } + } + 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 = ? "; } @@ -143,6 +170,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 +656,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 +726,28 @@ 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 " + + "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 +777,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 +1314,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 +1352,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/OracleDeviceDAOImpl.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/OracleDeviceDAOImpl.java index 722a19b4bf4..cecf4e510ba 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/OracleDeviceDAOImpl.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/OracleDeviceDAOImpl.java @@ -42,6 +42,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. @@ -93,14 +94,40 @@ public class OracleDeviceDAOImpl 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; + //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 " + + "AND di.KEY_FIELD = 'serial' " + + "AND di.VALUE_FIELD LIKE ? ) "; + isSerialProvided = true; + } + if (!request.getCustomProperty().isEmpty()) { + if (serial != null) { + sql += "AND "; + } + boolean firstCondition = true; + for (Map.Entry entry : request.getCustomProperty().entrySet()) { + if (!firstCondition) { + sql += "AND "; + } + sql += "EXISTS (" + + "SELECT VALUE_FIELD " + + "FROM DM_DEVICE_INFO di " + + "WHERE di.DEVICE_ID = d.ID " + + "AND di.KEY_FIELD = '" + entry.getKey() + "' " + + "AND di.VALUE_FIELD LIKE ? ) "; + firstCondition = false; + } + } + 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 = ? "; } @@ -144,6 +171,11 @@ public class OracleDeviceDAOImpl 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())); @@ -454,6 +486,8 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl { boolean isStatusProvided = false; Date since = request.getSince(); boolean isSinceProvided = false; + String serial = request.getSerialNumber(); + boolean isSerialProvided = false; try { conn = getConnection(); @@ -522,6 +556,28 @@ public class OracleDeviceDAOImpl 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 " + + "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 +607,14 @@ public class OracleDeviceDAOImpl 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()); @@ -1035,6 +1099,17 @@ public class OracleDeviceDAOImpl 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"; @@ -1059,6 +1134,12 @@ public class OracleDeviceDAOImpl 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/PostgreSQLDeviceDAOImpl.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/PostgreSQLDeviceDAOImpl.java index 7b0cd9369b8..c467165851f 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/PostgreSQLDeviceDAOImpl.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/PostgreSQLDeviceDAOImpl.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,14 +93,40 @@ public class PostgreSQLDeviceDAOImpl 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; + //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 " + + "AND di.KEY_FIELD = 'serial' " + + "AND di.VALUE_FIELD LIKE ? ) "; + isSerialProvided = true; + } + if (!request.getCustomProperty().isEmpty()) { + if (serial != null) { + sql += "AND "; + } + boolean firstCondition = true; + for (Map.Entry entry : request.getCustomProperty().entrySet()) { + if (!firstCondition) { + sql += "AND "; + } + sql += "EXISTS (" + + "SELECT VALUE_FIELD " + + "FROM DM_DEVICE_INFO di " + + "WHERE di.DEVICE_ID = d.ID " + + "AND di.KEY_FIELD = '" + entry.getKey() + "' " + + "AND di.VALUE_FIELD LIKE ? ) "; + firstCondition = false; + } + } + 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 = ? "; } @@ -138,6 +165,11 @@ public class PostgreSQLDeviceDAOImpl 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 (isDeviceTypeProvided) { stmt.setString(paramIdx++, deviceType); @@ -435,6 +467,8 @@ public class PostgreSQLDeviceDAOImpl extends AbstractDeviceDAOImpl { boolean isStatusProvided = false; Date since = request.getSince(); boolean isSinceProvided = false; + String serial = request.getSerialNumber(); + boolean isSerialProvided = false; try { conn = getConnection(); @@ -502,6 +536,28 @@ public class PostgreSQLDeviceDAOImpl 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 " + + "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 ? OFFSET ?"; try (PreparedStatement stmt = conn.prepareStatement(sql)) { @@ -531,6 +587,14 @@ public class PostgreSQLDeviceDAOImpl 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.getRowCount()); stmt.setInt(paramIdx, request.getStartIndex()); @@ -1014,6 +1078,17 @@ public class PostgreSQLDeviceDAOImpl 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 ? OFFSET ?"; @@ -1038,6 +1113,12 @@ public class PostgreSQLDeviceDAOImpl 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 3a7f0f95b97..5628b77a2d1 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,14 +95,40 @@ 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; + //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 " + + "AND di.KEY_FIELD = 'serial' " + + "AND di.VALUE_FIELD LIKE ? ) "; + isSerialProvided = true; + } + if (!request.getCustomProperty().isEmpty()) { + if (serial != null) { + sql += "AND "; + } + boolean firstCondition = true; + for (Map.Entry entry : request.getCustomProperty().entrySet()) { + if (!firstCondition) { + sql += "AND "; + } + sql += "EXISTS (" + + "SELECT VALUE_FIELD " + + "FROM DM_DEVICE_INFO di " + + "WHERE di.DEVICE_ID = d.ID " + + "AND di.KEY_FIELD = '" + entry.getKey() + "' " + + "AND di.VALUE_FIELD LIKE ? ) "; + firstCondition = false; + } + } + 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 = ? "; } @@ -145,6 +172,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 +487,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 +556,28 @@ 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 " + + "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 +607,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 +947,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 +982,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);