From 3631acfe45e8d233b47a2c4f7cf8e636c1ca128b Mon Sep 17 00:00:00 2001 From: Sasini_Sandamali Date: Tue, 10 Oct 2023 12:20:40 +0530 Subject: [PATCH] Add new get device activities API --- .../api/jaxrs/beans/DeviceActivityList.java | 51 ++++ .../api/ActivityInfoProviderService.java | 125 +++++++++ .../impl/ActivityProviderServiceImpl.java | 240 ++++++++++++---- .../impl/ActivityProviderServiceImplTest.java | 94 +++++++ .../common/operation/mgt/DeviceActivity.java | 205 ++++++++++++++ .../operation/mgt/OperationManager.java | 5 + .../operation/mgt/OperationManagerImpl.java | 31 ++ .../core/operation/mgt/dao/OperationDAO.java | 6 + .../mgt/dao/impl/GenericOperationDAOImpl.java | 264 ++++++++++++++++++ .../mgt/dao/util/OperationDAOUtil.java | 36 ++- .../DeviceManagementProviderService.java | 6 + .../DeviceManagementProviderServiceImpl.java | 14 + 12 files changed, 1013 insertions(+), 64 deletions(-) create mode 100644 components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/beans/DeviceActivityList.java create mode 100644 components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/operation/mgt/DeviceActivity.java 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/beans/DeviceActivityList.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/beans/DeviceActivityList.java new file mode 100644 index 0000000000..a538ea4d33 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.api/src/main/java/io/entgra/device/mgt/core/device/mgt/api/jaxrs/beans/DeviceActivityList.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.google.gson.Gson; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.DeviceActivity; + +import java.util.List; + +@ApiModel(value = "ListOfDeviceActivities", description = "This contains a set of device activities that " + + "matches a given" + + " criteria as a collection") +public class DeviceActivityList extends BasePaginatedResult { + + private List activities; + + @ApiModelProperty(value = "List of device activity Ids") + @JsonProperty("activities") + public List getList() { + return activities; + } + + public void setList(List activities) { + this.activities = activities; + } + + @Override + public String toString() { + return new Gson().toJson(this); + } + +} 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/ActivityInfoProviderService.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/ActivityInfoProviderService.java index b1fd4c9791..6bd31e76be 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/ActivityInfoProviderService.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/ActivityInfoProviderService.java @@ -385,6 +385,131 @@ public interface ActivityInfoProviderService { defaultValue = "5") @QueryParam("limit") int limit); + @GET + @Path("/devices") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting Device Activity Details", + notes = "Get the details of the operations/activities executed by the server on the devices registered" + + " with WSO2 EMM, during a defined time period.", + tags = "Device Activity Info Provider", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:get-activity") + }) + }, + nickname = "getDeviceActivitiesWithFilters" + ) + @ApiResponses(value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the device activity details.", + response = ActivityList.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource was last modified.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 304, + message = "Not Modified. \n Empty body because the client already has the latest version of the" + + " requested resource.\n"), + @ApiResponse( + code = 401, + message = "Unauthorized. \n Unauthorized request."), + @ApiResponse( + code = 404, + message = "Not Found. \n No activities found.", + response = ErrorResponse.class), + @ApiResponse( + code = 406, + message = "Not Acceptable.\n The requested media type is not supported"), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while fetching the activity data.", + response = ErrorResponse.class) + }) + Response getDeviceActivities( + @ApiParam( + name = "offset", + value = "The starting pagination index for the complete list of qualified items.", + defaultValue = "0") + @DefaultValue("0") @QueryParam("offset") int offset, + @ApiParam( + name = "limit", + value = "Provide how many activity details you require from the starting pagination index/offset.", + defaultValue = "5") + @DefaultValue("20") @QueryParam("limit") int limit, + @ApiParam( + name = "since", + value = "Checks if the requested variant was created since the specified date-time.\n" + + "Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z.\n" + + "Example: Mon, 05 Jan 2014 15:10:00 +0200" + ) + @QueryParam("since") String since, + @ApiParam( + name = "initiatedBy", + value = "The user, who initiated the operation. If is done by the task, the SYSTEM will be returned." + + " And if a user adds the operation, username is returned" + ) + @QueryParam("initiatedBy") String initiatedBy, + @ApiParam( + name = "operationCode", + value = "Operation Code to filter" + ) + @QueryParam("operationCode") String operationCode, + @ApiParam( + name = "operationId", + value = "Operation Id to filter" + ) + @QueryParam("operationId") int operationId, + @ApiParam( + name = "deviceType", + value = "Device Type to filter" + ) + @QueryParam("deviceType") String deviceType, + @ApiParam( + name = "deviceId", + value = "Device Id to filter" + ) + @QueryParam("deviceId") List deviceIds, + @ApiParam( + name = "type", + value = "Operation type to filter" + ) + @QueryParam("type") String type, + @ApiParam( + name = "status", + value = "Operation response status to filter" + ) + @QueryParam("status") String status, + @ApiParam( + name = "If-Modified-Since", + value = "Checks if the requested variant was modified, since the specified date-time\n." + + "Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z\n." + + "Example: Mon, 05 Jan 2014 15:10:00 +0200" + ) + @HeaderParam("If-Modified-Since") String ifModifiedSince, + @ApiParam( + name = "startTimestamp", + value = "Starting unix timestamp value for filtering activities" + ) + @QueryParam("startTimestamp") long startTimestamp, + @ApiParam( + name = "endTimestamp", + value = "Ending unix timestamp value for filtering activities" + ) + @QueryParam("endTimestamp") long endTimestamp); + @GET @ApiOperation( produces = MediaType.APPLICATION_JSON, 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/ActivityProviderServiceImpl.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/ActivityProviderServiceImpl.java index 0474a81a79..2fca4e46f3 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/ActivityProviderServiceImpl.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/ActivityProviderServiceImpl.java @@ -29,6 +29,7 @@ import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.Operation; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.OperationManagementException; import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService; import io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans.ActivityList; +import io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans.DeviceActivityList; import io.entgra.device.mgt.core.device.mgt.api.jaxrs.beans.ErrorResponse; import io.entgra.device.mgt.core.device.mgt.api.jaxrs.common.ActivityIdList; import io.entgra.device.mgt.core.device.mgt.api.jaxrs.service.api.ActivityInfoProviderService; @@ -246,6 +247,130 @@ public class ActivityProviderServiceImpl implements ActivityInfoProviderService } } + @GET + @Path("/devices") + @Override + public Response getDeviceActivities(@DefaultValue("0") @QueryParam("offset") int offset, + @DefaultValue("20") @QueryParam("limit") int limit, + @QueryParam("since") String since, + @QueryParam("initiatedBy") String initiatedBy, + @QueryParam("operationCode") String operationCode, + @QueryParam("operationId") int operationId, + @QueryParam("deviceType") String deviceType, + @QueryParam("deviceId") List deviceIds, + @QueryParam("type") String type, + @QueryParam("status") String status, + @HeaderParam("If-Modified-Since") String ifModifiedSince, + @QueryParam("startTimestamp") long startTimestamp, + @QueryParam("endTimestamp") long endTimestamp) { + + long ifModifiedSinceTimestamp; + long sinceTimestamp; + long timestamp = 0; + boolean isTimeDurationProvided = false; + if (log.isDebugEnabled()) { + log.debug("getDeviceActivities since: " + since + " , offset: " + offset + " ,limit: " + limit + " ," + + "ifModifiedSince: " + ifModifiedSince); + } + RequestValidationUtil.validatePaginationParameters(offset, limit); + if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) { + Date ifSinceDate; + SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z"); + try { + ifSinceDate = format.parse(ifModifiedSince); + } catch (ParseException e) { + return Response.status(400).entity( + new ErrorResponse.ErrorResponseBuilder().setMessage( + "Invalid date string is provided in 'If-Modified-Since' header").build()).build(); + } + ifModifiedSinceTimestamp = ifSinceDate.getTime(); + timestamp = ifModifiedSinceTimestamp / 1000; + } else if (since != null && !since.isEmpty()) { + Date sinceDate; + SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z"); + try { + sinceDate = format.parse(since); + } catch (ParseException e) { + return Response.status(400).entity( + new ErrorResponse.ErrorResponseBuilder().setMessage( + "Invalid date string is provided in 'since' filter").build()).build(); + } + sinceTimestamp = sinceDate.getTime(); + timestamp = sinceTimestamp / 1000; + } else if (startTimestamp > 0 && endTimestamp > 0) { + RequestValidationUtil.validateTimeDuration(startTimestamp, endTimestamp); + isTimeDurationProvided = true; + } + + if (timestamp == 0 && !isTimeDurationProvided) { + //If timestamp is not sent by the user, a default value is set, that is equal to current time-12 hours. + long time = System.currentTimeMillis() / 1000; + timestamp = time - 42300; + } + if (log.isDebugEnabled()) { + log.debug("getDeviceActivities final timestamp " + timestamp); + } + DeviceActivityList deviceActivityList = new DeviceActivityList(); + DeviceManagementProviderService dmService; + ActivityPaginationRequest activityPaginationRequest = new ActivityPaginationRequest(offset, limit); + try { + if (log.isDebugEnabled()) { + log.debug("Calling database to get device activities."); + } + dmService = DeviceMgtAPIUtils.getDeviceManagementService(); + if (initiatedBy != null && !initiatedBy.isEmpty()) { + activityPaginationRequest.setInitiatedBy(initiatedBy); + } + if (operationCode != null && !operationCode.isEmpty()) { + activityPaginationRequest.setOperationCode(operationCode); + } + if (operationId > 0) { + activityPaginationRequest.setOperationId(operationId); + } + if (deviceType != null && !deviceType.isEmpty()) { + activityPaginationRequest.setDeviceType(deviceType); + } + if (deviceIds != null && !deviceIds.isEmpty()) { + activityPaginationRequest.setDeviceIds(deviceIds); + } + if (type != null && !type.isEmpty()) { + activityPaginationRequest.setType(Operation.Type.valueOf(type.toUpperCase())); + } + if (status != null && !status.isEmpty()) { + activityPaginationRequest.setStatus(Operation.Status.valueOf(status.toUpperCase())); + } + if (timestamp > 0) { + activityPaginationRequest.setSince(timestamp); + } else { + activityPaginationRequest.setStartTimestamp(startTimestamp); + activityPaginationRequest.setEndTimestamp(endTimestamp); + } + if (log.isDebugEnabled()) { + log.debug("Device Activity request: " + new Gson().toJson(activityPaginationRequest)); + } + int count = dmService.getDeviceActivitiesCount(activityPaginationRequest); + if (log.isDebugEnabled()) { + log.debug("Filtered Device Activity count: " + count); + } + if (count > 0) { + deviceActivityList.setList(dmService.getDeviceActivities(activityPaginationRequest)); + if (log.isDebugEnabled()) { + log.debug("Fetched Device Activity count: " + deviceActivityList.getList().size()); + } + } else if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) { + return Response.notModified().build(); + } + deviceActivityList.setCount(count); + return Response.ok().entity(deviceActivityList).build(); + } catch (OperationManagementException e) { + String msg + = "ErrorResponse occurred while fetching the device activities updated after given time stamp."; + log.error(msg, e); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } + } + @GET @Override public Response getActivities(@DefaultValue("0") @QueryParam("offset") int offset, @@ -306,69 +431,64 @@ public class ActivityProviderServiceImpl implements ActivityInfoProviderService if (log.isDebugEnabled()) { log.debug("getActivities final timestamp " + timestamp); } - Response response = validateAdminPermission(); - if (response == null) { - ActivityList activityList = new ActivityList(); - DeviceManagementProviderService dmService; - ActivityPaginationRequest activityPaginationRequest = new ActivityPaginationRequest(offset, limit); - try { - if (log.isDebugEnabled()) { - log.debug("Calling database to get activities."); - } - dmService = DeviceMgtAPIUtils.getDeviceManagementService(); - if (initiatedBy != null && !initiatedBy.isEmpty()) { - activityPaginationRequest.setInitiatedBy(initiatedBy); - } - if (operationCode != null && !operationCode.isEmpty()) { - activityPaginationRequest.setOperationCode(operationCode); - } - if (operationId > 0) { - activityPaginationRequest.setOperationId(operationId); - } - if (deviceType != null && !deviceType.isEmpty()) { - activityPaginationRequest.setDeviceType(deviceType); - } - if (deviceIds != null && !deviceIds.isEmpty()) { - activityPaginationRequest.setDeviceIds(deviceIds); - } - if (type != null && !type.isEmpty()) { - activityPaginationRequest.setType(Operation.Type.valueOf(type.toUpperCase())); - } - if (status != null && !status.isEmpty()) { - activityPaginationRequest.setStatus(Operation.Status.valueOf(status.toUpperCase())); - } - if (timestamp > 0) { - activityPaginationRequest.setSince(timestamp); - } else { - activityPaginationRequest.setStartTimestamp(startTimestamp); - activityPaginationRequest.setEndTimestamp(endTimestamp); - } - if (log.isDebugEnabled()) { - log.debug("Activity request: " + new Gson().toJson(activityPaginationRequest)); - } - int count = dmService.getActivitiesCount(activityPaginationRequest); + ActivityList activityList = new ActivityList(); + DeviceManagementProviderService dmService; + ActivityPaginationRequest activityPaginationRequest = new ActivityPaginationRequest(offset, limit); + try { + if (log.isDebugEnabled()) { + log.debug("Calling database to get activities."); + } + dmService = DeviceMgtAPIUtils.getDeviceManagementService(); + if (initiatedBy != null && !initiatedBy.isEmpty()) { + activityPaginationRequest.setInitiatedBy(initiatedBy); + } + if (operationCode != null && !operationCode.isEmpty()) { + activityPaginationRequest.setOperationCode(operationCode); + } + if (operationId > 0) { + activityPaginationRequest.setOperationId(operationId); + } + if (deviceType != null && !deviceType.isEmpty()) { + activityPaginationRequest.setDeviceType(deviceType); + } + if (deviceIds != null && !deviceIds.isEmpty()) { + activityPaginationRequest.setDeviceIds(deviceIds); + } + if (type != null && !type.isEmpty()) { + activityPaginationRequest.setType(Operation.Type.valueOf(type.toUpperCase())); + } + if (status != null && !status.isEmpty()) { + activityPaginationRequest.setStatus(Operation.Status.valueOf(status.toUpperCase())); + } + if (timestamp > 0) { + activityPaginationRequest.setSince(timestamp); + } else { + activityPaginationRequest.setStartTimestamp(startTimestamp); + activityPaginationRequest.setEndTimestamp(endTimestamp); + } + if (log.isDebugEnabled()) { + log.debug("Activity request: " + new Gson().toJson(activityPaginationRequest)); + } + int count = dmService.getActivitiesCount(activityPaginationRequest); + if (log.isDebugEnabled()) { + log.debug("Filtered Activity count: " + count); + } + if (count > 0) { + activityList.setList(dmService.getActivities(activityPaginationRequest)); if (log.isDebugEnabled()) { - log.debug("Filtered Activity count: " + count); - } - if (count > 0) { - activityList.setList(dmService.getActivities(activityPaginationRequest)); - if (log.isDebugEnabled()) { - log.debug("Fetched Activity count: " + activityList.getList().size()); - } - } else if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) { - return Response.notModified().build(); + log.debug("Fetched Activity count: " + activityList.getList().size()); } - activityList.setCount(count); - return Response.ok().entity(activityList).build(); - } catch (OperationManagementException e) { - String msg - = "ErrorResponse occurred while fetching the activities updated after given time stamp."; - log.error(msg, e); - return Response.serverError().entity( - new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } else if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) { + return Response.notModified().build(); } - } else { - return response; + activityList.setCount(count); + return Response.ok().entity(activityList).build(); + } catch (OperationManagementException e) { + String msg + = "ErrorResponse occurred while fetching the activities updated after given time stamp."; + log.error(msg, e); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); } } 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/ActivityProviderServiceImplTest.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/ActivityProviderServiceImplTest.java index 0e3d23d705..5a6d9d0983 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/ActivityProviderServiceImplTest.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/ActivityProviderServiceImplTest.java @@ -34,6 +34,9 @@ import org.wso2.carbon.context.PrivilegedCarbonContext; import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; import io.entgra.device.mgt.core.device.mgt.common.authorization.DeviceAccessAuthorizationService; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.Activity; +import io.entgra.device.mgt.core.device.mgt.common.ActivityPaginationRequest; +import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.DeviceActivity; +import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.Operation; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.OperationManagementException; import io.entgra.device.mgt.core.device.mgt.core.authorization.DeviceAccessAuthorizationServiceImpl; import io.entgra.device.mgt.core.device.mgt.core.service.DeviceManagementProviderService; @@ -47,6 +50,7 @@ import io.entgra.device.mgt.core.policy.mgt.core.util.PolicyManagerUtil; import javax.ws.rs.core.Response; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import static org.mockito.MockitoAnnotations.initMocks; @@ -63,6 +67,12 @@ public class ActivityProviderServiceImplTest { private static final Log log = LogFactory.getLog(ActivityProviderServiceImplTest.class); private static final String TEST_ACTIVITY_ID = "ACTIVITY_1"; private static final String IF_MODIFIED_SINCE = "01Aug2018"; + private static final String SINCE = "Fri, 06 Oct 2023 15:30:00 GMT"; + private static final String DEVICE_TYPE_2 = "power-meter"; + private static final Operation.Status STATUS = Operation.Status.NOTNOW; + private static final Operation.Type TYPE = Operation.Type.PROFILE; + private static final String INITIATED_BY = "admin"; + private static final int OPERATION_ID = 158572; private static final String DEVICE_TYPE = "android"; private static final String DEVICE_ID = "1234567"; private static final String OPERATION_CODE = "111222"; @@ -71,7 +81,10 @@ public class ActivityProviderServiceImplTest { private static final String TEST_ACTIVITY_ID_LIST = "ACTIVITY_1,ACTIVITY_2"; private static final List idList = new ArrayList(); private static final List activities = new ArrayList<>(); + private static final List deviceActivities = new ArrayList<>(); private static final ActivityIdList activityList = new ActivityIdList(TEST_ACTIVITY_ID_LIST); + + private static final ActivityPaginationRequest activityPaginationRequest = new ActivityPaginationRequest(LIMIT,OFFSET); private static final ActivityIdList activityListEmpty = new ActivityIdList(""); private List idList1; @@ -108,6 +121,23 @@ public class ActivityProviderServiceImplTest { activity2.setActivityId("ACTIVITY_2"); activities.add(activity1); activities.add(activity2); + DeviceActivity deviceActivity1 = new DeviceActivity(); + DeviceActivity deviceActivity2 = new DeviceActivity(); + deviceActivity1.setActivityId("ACTIVITY_3"); + deviceActivity2.setActivityId("ACTIVITY_4"); + deviceActivities.add(deviceActivity1); + deviceActivities.add(deviceActivity2); + activityPaginationRequest.setDeviceIds(Collections.singletonList(DEVICE_ID)); + activityPaginationRequest.setOperationCode(OPERATION_CODE); + activityPaginationRequest.setDeviceType(DEVICE_TYPE_2); + activityPaginationRequest.setOperationId(OPERATION_ID); + activityPaginationRequest.setInitiatedBy(INITIATED_BY); + activityPaginationRequest.setStatus(STATUS); + activityPaginationRequest.setType(TYPE); + activityPaginationRequest.setStartTimestamp(0); + activityPaginationRequest.setEndTimestamp(0); + activityPaginationRequest.setLimit(LIMIT); + activityPaginationRequest.setOffset(OFFSET); } @Test(description = @@ -186,6 +216,70 @@ public class ActivityProviderServiceImplTest { Mockito.reset(this.deviceManagementProviderService); } + @Test(description = "This method tests trying to get details activity IDs when call with data") + public void testGetActivitiesWithActivityPaginationRequest() throws OperationManagementException { + PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "isAdmin")).toReturn(true); + PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService")) + .toReturn(this.deviceManagementProviderService); + + Mockito.when(this.deviceManagementProviderService.getActivitiesCount(Mockito.any())).thenReturn(2); + Mockito.when(this.deviceManagementProviderService.getActivities(Mockito.any())).thenReturn(activities); + Response response = this.activityInfoProviderService.getActivities( + OFFSET, LIMIT, SINCE, INITIATED_BY, OPERATION_CODE, OPERATION_ID, + DEVICE_TYPE_2, Collections.singletonList(DEVICE_ID), TYPE.toString(), STATUS.toString(), null, 0, 0); + + Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); + Assert.assertNotNull(response); + Mockito.reset(this.deviceManagementProviderService); + } + + @Test(description = "This method tests trying to get details device activity IDs when call with empty data") + public void testGetActivitiesWithEmptyActivityPaginationRequest() throws OperationManagementException { + PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "isAdmin")).toReturn(true); + PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService")) + .toReturn(this.deviceManagementProviderService); + + Response response = this.activityInfoProviderService.getActivities( + OFFSET, 0, null, null, null, 0, + null, null, null, null, null, 0, 0); + + Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); + Assert.assertEquals(response.getEntity().toString(), "{\"count\":0}"); + Mockito.reset(this.deviceManagementProviderService); + } + + @Test(description = "This method tests trying to get details device activity IDs when call with data") + public void testGetDeviceActivitiesWithActivityPaginationRequest() throws OperationManagementException { + PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "isAdmin")).toReturn(true); + PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService")) + .toReturn(this.deviceManagementProviderService); + + Mockito.when(this.deviceManagementProviderService.getDeviceActivitiesCount(Mockito.any())).thenReturn(2); + Mockito.when(this.deviceManagementProviderService.getDeviceActivities(Mockito.any())).thenReturn(deviceActivities); + Response response = this.activityInfoProviderService.getDeviceActivities( + OFFSET, LIMIT, SINCE, INITIATED_BY, OPERATION_CODE, OPERATION_ID, + DEVICE_TYPE_2, Collections.singletonList(DEVICE_ID), TYPE.toString(), STATUS.toString(), null, 0, 0); + + Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); + Assert.assertNotNull(response); + Mockito.reset(this.deviceManagementProviderService); + } + + @Test(description = "This method tests trying to get details activity IDs when call with empty data") + public void testGetDeviceActivitiesWithEmptyActivityPaginationRequest() { + PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "isAdmin")).toReturn(true); + PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService")) + .toReturn(this.deviceManagementProviderService); + + Response response = this.activityInfoProviderService.getDeviceActivities( + OFFSET, 0, null, null, null, 0, + null, null, null, null, null, 0, 0); + + Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode()); + Assert.assertEquals(response.getEntity().toString(), "{\"count\":0}"); + Mockito.reset(this.deviceManagementProviderService); + } + @Test(description = "This method tests trying to get details of a list activity IDs which does not exists") public void testGetActivitiesWithNonExistingActivityIdList() throws OperationManagementException { PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "isAdmin")).toReturn(true); 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/operation/mgt/DeviceActivity.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/operation/mgt/DeviceActivity.java new file mode 100644 index 0000000000..b7153fc435 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/operation/mgt/DeviceActivity.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2018 - 2023, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +package io.entgra.device.mgt.core.device.mgt.common.operation.mgt; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; + +import java.util.List; + +@ApiModel(value = "DeviceActivity", description = "An activity instance carries a unique identifier that can be " + + "used to identify a particular operation instance uniquely") +public class DeviceActivity { + + public enum Type { + CONFIG, MESSAGE, INFO, COMMAND, PROFILE, POLICY + } + + public enum Status { + IN_PROGRESS, PENDING, COMPLETED, ERROR, REPEATED, INVALID, UNAUTHORIZED, NOTNOW, REQUIRED_CONFIRMATION, CONFIRMED + } + + @ApiModelProperty( + name = "activityId", + value = "Device Activity identifier", + required = true, + example = "ACTIVITY_1") + @JsonProperty("activityId") + private String activityId; + @ApiModelProperty( + name = "code", + value = "Device Activity code", + required = true, + example = "DEVICE_RING") + @JsonProperty("code") + private String code; + @ApiModelProperty( + name = "operationId", + value = "Operation Id", + required = false, + example = "10") + @JsonProperty("operationId") + private int operationId; + @ApiModelProperty( + name = "type", + value = "Activity type", + required = true, + allowableValues = "CONFIG, MESSAGE, INFO, COMMAND, PROFILE, POLICY", + example = "COMMAND") + @JsonProperty("type") + private Type type; + + @ApiModelProperty( + name = "status", + value = "Status of the device activity performed.", + required = true, + example = "PENDING") + @JsonProperty("status") + private Status status; + @ApiModelProperty( + name = "createdTimeStamp", + value = "Timestamp recorded when the activity took place", + required = true, + example = "Thu Oct 06 11:18:47 IST 2016") + @JsonProperty("createdTimestamp") + private String createdTimeStamp; + @ApiModelProperty( + name = "deviceActivities", + value = "Collection of devices activities corresponding to the activity", + required = true) + @JsonProperty("deviceActivities") + private List deviceActivities; + @ApiModelProperty( + name = "initiatedBy", + value = "Initiated user", + required = true) + @JsonProperty("initiatedBy") + private String initiatedBy; + @ApiModelProperty( + name = "deviceIdentifier", + value = "Device identifier of the device.", + required = true) + @JsonProperty("deviceIdentifier") + private DeviceIdentifier deviceIdentifier; + @ApiModelProperty( + name = "responses", + value = "Responses received from devices.", + required = true) + @JsonProperty("responses") + private List responses; + @ApiModelProperty( + name = "updatedTimestamp ", + value = "Last updated time of the activity.", + required = true, + example = "Thu Oct 06 11:18:47 IST 2016") + @JsonProperty("updatedTimestamp") + private String updatedTimestamp; + + public DeviceIdentifier getDeviceIdentifier() { + return deviceIdentifier; + } + + public void setDeviceIdentifier(DeviceIdentifier deviceIdentifier) { + this.deviceIdentifier = deviceIdentifier; + } + + public List getResponses() { + return responses; + } + + public void setResponses(List responses) { + this.responses = responses; + } + + public String getUpdatedTimestamp() { + return updatedTimestamp; + } + + public void setUpdatedTimestamp(String updatedTimestamp) { + this.updatedTimestamp = updatedTimestamp; + } + + public String getActivityId() { + return activityId; + } + + public void setActivityId(String activityId) { + this.activityId = activityId; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public int getOperationId() { + return operationId; + } + + public void setOperationId(int operationId) { + this.operationId = operationId; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } + + public String getCreatedTimeStamp() { + return createdTimeStamp; + } + + public void setCreatedTimeStamp(String createdTimeStamp) { + this.createdTimeStamp = createdTimeStamp; + } + + public List getDeviceActivities() { + return deviceActivities; + } + + public void setDeviceActivities(List deviceActivities) { + this.deviceActivities = deviceActivities; + } + + public String getInitiatedBy() { + return initiatedBy; + } + + public void setInitiatedBy(String initiatedBy) { + this.initiatedBy = initiatedBy; + } +} + 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/operation/mgt/OperationManager.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/operation/mgt/OperationManager.java index 542b5c8450..e7fa23304e 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/operation/mgt/OperationManager.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.common/src/main/java/io/entgra/device/mgt/core/device/mgt/common/operation/mgt/OperationManager.java @@ -128,6 +128,11 @@ public interface OperationManager { int getActivitiesCount(ActivityPaginationRequest activityPaginationRequest) throws OperationManagementException; + List getDeviceActivities(ActivityPaginationRequest activityPaginationRequest) throws OperationManagementException; + + int getDeviceActivitiesCount(ActivityPaginationRequest activityPaginationRequest) + throws OperationManagementException; + List getFilteredActivities(String operationCode, int limit, int offset) throws OperationManagementException; int getTotalCountOfFilteredActivities(String operationCode) throws OperationManagementException; 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/operation/mgt/OperationManagerImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/OperationManagerImpl.java index 42fac254ec..c7a86bfb82 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/OperationManagerImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/OperationManagerImpl.java @@ -41,6 +41,7 @@ import io.entgra.device.mgt.core.device.mgt.common.exceptions.InvalidDeviceExcep import io.entgra.device.mgt.core.device.mgt.common.exceptions.TransactionManagementException; import io.entgra.device.mgt.core.device.mgt.common.group.mgt.DeviceGroupConstants; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.Activity; +import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.DeviceActivity; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.ActivityStatus; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.Operation; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.OperationManagementException; @@ -1303,6 +1304,36 @@ public class OperationManagerImpl implements OperationManager { } } + @Override + public List getDeviceActivities(ActivityPaginationRequest activityPaginationRequest) + throws OperationManagementException { + try { + OperationManagementDAOFactory.openConnection(); + return operationDAO.getDeviceActivities(activityPaginationRequest); + } catch (SQLException e) { + throw new OperationManagementException("Error occurred while opening a connection to the data source.", e); + } catch (OperationManagementDAOException e) { + throw new OperationManagementException("Error occurred while getting the device activity list.", e); + } finally { + OperationManagementDAOFactory.closeConnection(); + } + } + + @Override + public int getDeviceActivitiesCount(ActivityPaginationRequest activityPaginationRequest) + throws OperationManagementException { + try { + OperationManagementDAOFactory.openConnection(); + return operationDAO.getDeviceActivitiesCount(activityPaginationRequest); + } catch (SQLException e) { + throw new OperationManagementException("Error occurred while opening a connection to the data source.", e); + } catch (OperationManagementDAOException e) { + throw new OperationManagementException("Error occurred while getting the device activity count.", e); + } finally { + OperationManagementDAOFactory.closeConnection(); + } + } + @Override public List getFilteredActivities(String operationCode, int limit, int offset) throws OperationManagementException { try { 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/operation/mgt/dao/OperationDAO.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/OperationDAO.java index 2b5658d85f..4fe22494c6 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/OperationDAO.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/OperationDAO.java @@ -22,6 +22,7 @@ import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; import io.entgra.device.mgt.core.device.mgt.common.PaginationRequest; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.Activity; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.OperationResponse; +import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.DeviceActivity; import io.entgra.device.mgt.core.device.mgt.core.dto.operation.mgt.Operation; import io.entgra.device.mgt.core.device.mgt.core.dto.operation.mgt.OperationResponseMeta; import io.entgra.device.mgt.core.device.mgt.core.operation.mgt.OperationMapping; @@ -118,4 +119,9 @@ public interface OperationDAO { int getActivitiesCount(ActivityPaginationRequest activityPaginationRequest) throws OperationManagementDAOException; + List getDeviceActivities(ActivityPaginationRequest activityPaginationRequest) + throws OperationManagementDAOException; + + int getDeviceActivitiesCount(ActivityPaginationRequest activityPaginationRequest) + throws OperationManagementDAOException; } 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/operation/mgt/dao/impl/GenericOperationDAOImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java index 5d964d4a53..319e2d09f8 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/impl/GenericOperationDAOImpl.java @@ -26,6 +26,7 @@ import io.entgra.device.mgt.core.device.mgt.common.ActivityPaginationRequest; import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; import io.entgra.device.mgt.core.device.mgt.common.PaginationRequest; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.Activity; +import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.DeviceActivity; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.ActivityHolder; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.ActivityStatus; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.OperationResponse; @@ -399,6 +400,51 @@ public class GenericOperationDAOImpl implements OperationDAO { } } + public OperationResponse populateResponse(ResultSet rs) throws SQLException { + OperationResponse response = new OperationResponse(); + + DeviceActivity deviceActivity = new DeviceActivity(); + int responseId = 0; + List operationResponses = new ArrayList<>(); + List largeResponseIDs = new ArrayList<>(); + + if (rs.getTimestamp("RECEIVED_TIMESTAMP") != null) { + Timestamp receivedTimestamp = rs.getTimestamp("RECEIVED_TIMESTAMP"); + response.setReceivedTimeStamp(new Date(receivedTimestamp.getTime()).toString()); + } + response.setResponse(rs.getString("OPERATION_RESPONSE")); + + int deviceOpId = rs.getInt("OPERATION_ID"); + String deviceActivityId = DeviceManagementConstants.OperationAttributes.ACTIVITY + deviceOpId; + String deviceIdentifierId = rs.getString("DEVICE_IDENTIFICATION"); + + if (rs.getInt("UPDATED_TIMESTAMP") != 0) { + responseId = rs.getInt("OP_RES_ID"); + if (rs.getBoolean("IS_LARGE_RESPONSE")) { + largeResponseIDs.add(responseId); + } else { + deviceActivity.setResponses(operationResponses); + } + } + if (!largeResponseIDs.isEmpty()) { + Map>> largeOperationResponses = null; + try { + largeOperationResponses = getLargeOperationResponsesInBulk(largeResponseIDs); + if (!largeOperationResponses.isEmpty()) { + Map> largeResponse = largeOperationResponses.get(deviceActivityId); + if (largeResponse != null) { + response = largeResponse.get(deviceIdentifierId).get(0); + } + } + } catch (OperationManagementDAOException e) { + log.warn("Unable to get operation response for Operation ID: " + deviceOpId + + ", Error: " + e.getErrorMessage()); + } + } + + return response; + } + @Override public Activity getActivity(int operationId) throws OperationManagementDAOException { @@ -2566,4 +2612,222 @@ public class GenericOperationDAOImpl implements OperationDAO { return 0; } + @Override + public List getDeviceActivities(ActivityPaginationRequest activityPaginationRequest) + throws OperationManagementDAOException { + List finalizedActivitiesList = new ArrayList<>(); + try { + boolean isTimeDurationFilteringProvided = false; + Connection conn = OperationManagementDAOFactory.getConnection(); + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + StringBuilder sql = new StringBuilder("SELECT " + + " eom.*," + + " opr.ID AS OP_RES_ID," + + " opr.RECEIVED_TIMESTAMP," + + " opr.OPERATION_RESPONSE, " + + " opr.IS_LARGE_RESPONSE " + + "FROM(" + + " SELECT * " + + " FROM " + + " DM_ENROLMENT_OP_MAPPING " + + " WHERE " + + " TENANT_ID = ? "); + + if (activityPaginationRequest.getStartTimestamp() > 0 && activityPaginationRequest.getEndTimestamp() > 0) { + isTimeDurationFilteringProvided = true; + sql.append("AND CREATED_TIMESTAMP BETWEEN ? AND ? "); + } + if (activityPaginationRequest.getDeviceType() != null) { + sql.append("AND DEVICE_TYPE = ? "); + } + if (activityPaginationRequest.getDeviceIds() != null && !activityPaginationRequest.getDeviceIds().isEmpty()) { + sql.append("AND DEVICE_IDENTIFICATION IN ("); + for (int i = 0; i < activityPaginationRequest.getDeviceIds().size() - 1; i++) { + sql.append("?, "); + } + sql.append("?) "); + } + if (activityPaginationRequest.getOperationId() > 0) { + sql.append("AND OPERATION_ID = ? "); + } + if (activityPaginationRequest.getOperationCode() != null) { + sql.append("AND OPERATION_CODE = ? "); + } + if (activityPaginationRequest.getInitiatedBy() != null) { + sql.append("AND INITIATED_BY = ? "); + } + if (activityPaginationRequest.getSince() != 0) { + sql.append("AND UPDATED_TIMESTAMP > ? "); + } + if (activityPaginationRequest.getType() != null) { + sql.append("AND TYPE = ? "); + } + if (activityPaginationRequest.getStatus() != null) { + sql.append("AND STATUS = ? "); + } + + sql.append("ORDER BY ID ASC limit ? , ? ) eom " + + "LEFT JOIN DM_DEVICE_OPERATION_RESPONSE opr ON eom.ID = opr.EN_OP_MAP_ID"); + + int index = 1; + try (PreparedStatement stmt = conn.prepareStatement(sql.toString())) { + stmt.setInt(index++, tenantId); + if (isTimeDurationFilteringProvided) { + stmt.setLong(index++, activityPaginationRequest.getStartTimestamp()); + stmt.setLong(index++, activityPaginationRequest.getEndTimestamp()); + } + if (activityPaginationRequest.getDeviceType() != null) { + stmt.setString(index++, activityPaginationRequest.getDeviceType()); + } + if (activityPaginationRequest.getDeviceIds() != null && !activityPaginationRequest.getDeviceIds().isEmpty()) { + for (String deviceId : activityPaginationRequest.getDeviceIds()) { + stmt.setString(index++, deviceId); + } + } + if (activityPaginationRequest.getOperationId() > 0) { + stmt.setInt(index++, activityPaginationRequest.getOperationId()); + } + if (activityPaginationRequest.getOperationCode() != null) { + stmt.setString(index++, activityPaginationRequest.getOperationCode()); + } + + if (activityPaginationRequest.getInitiatedBy() != null) { + stmt.setString(index++, activityPaginationRequest.getInitiatedBy()); + } + if (activityPaginationRequest.getSince() != 0) { + stmt.setLong(index++, activityPaginationRequest.getSince()); + } + if (activityPaginationRequest.getType() != null) { + stmt.setString(index++, activityPaginationRequest.getType().name()); + } + if (activityPaginationRequest.getStatus() != null) { + stmt.setString(index++, activityPaginationRequest.getStatus().name()); + } + + stmt.setInt(index++, activityPaginationRequest.getOffset()); + stmt.setInt(index, activityPaginationRequest.getLimit()); + + try (ResultSet rs = stmt.executeQuery()) { + Map activities = new HashMap<>(); + + while (rs.next()) { + int activityId = rs.getInt("ID"); + DeviceActivity deviceActivity = activities.get(activityId); + if (deviceActivity == null) { + deviceActivity = OperationDAOUtil.populateActivity(rs); + activities.put(activityId, deviceActivity); + } + deviceActivity.getResponses().add(populateResponse(rs)); + } + for (int activityId : activities.keySet()) { + DeviceActivity deviceActivity = activities.get(activityId); + finalizedActivitiesList.add(deviceActivity); + } + } + + } + } catch (SQLException e) { + String msg = "Error occurred while getting the operation details from the database."; + log.error(msg, e); + throw new OperationManagementDAOException(msg, e); + } + return finalizedActivitiesList; + } + + + @Override + public int getDeviceActivitiesCount(ActivityPaginationRequest activityPaginationRequest) + throws OperationManagementDAOException { + try { + boolean isTimeDurationFilteringProvided = false; + Connection conn = OperationManagementDAOFactory.getConnection(); + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + StringBuilder sql = new StringBuilder(); + + + sql.append("SELECT count(DISTINCT ID) AS ACTIVITY_COUNT " + + "FROM DM_ENROLMENT_OP_MAPPING WHERE TENANT_ID = ? "); + + if (activityPaginationRequest.getDeviceType() != null) { + sql.append("AND DEVICE_TYPE = ? "); + } + if (activityPaginationRequest.getDeviceIds() != null && !activityPaginationRequest.getDeviceIds().isEmpty()) { + sql.append("AND DEVICE_IDENTIFICATION IN ("); + for (int i = 0; i < activityPaginationRequest.getDeviceIds().size() - 1; i++) { + sql.append("?, "); + } + sql.append("?) "); + } + if (activityPaginationRequest.getOperationCode() != null) { + sql.append("AND OPERATION_CODE = ? "); + } + if (activityPaginationRequest.getOperationId() > 0) { + sql.append("AND OPERATION_ID = ? "); + } + if (activityPaginationRequest.getInitiatedBy() != null) { + sql.append("AND INITIATED_BY = ? "); + } + if (activityPaginationRequest.getSince() != 0) { + sql.append("AND UPDATED_TIMESTAMP > ? "); + } + if (activityPaginationRequest.getType() != null) { + sql.append("AND TYPE = ? "); + } + if (activityPaginationRequest.getStatus() != null) { + sql.append("AND STATUS = ? "); + } + + if (activityPaginationRequest.getStartTimestamp() > 0 && activityPaginationRequest.getEndTimestamp() > 0) { + isTimeDurationFilteringProvided = true; + sql.append("AND CREATED_TIMESTAMP BETWEEN ? AND ? "); + } + + int index = 1; + try (PreparedStatement stmt = conn.prepareStatement(sql.toString())) { + stmt.setInt(index++, tenantId); + if (activityPaginationRequest.getDeviceType() != null) { + stmt.setString(index++, activityPaginationRequest.getDeviceType()); + } + if (activityPaginationRequest.getDeviceIds() != null && !activityPaginationRequest.getDeviceIds().isEmpty()) { + for (String deviceId : activityPaginationRequest.getDeviceIds()) { + stmt.setString(index++, deviceId); + } + } + if (activityPaginationRequest.getOperationCode() != null) { + stmt.setString(index++, activityPaginationRequest.getOperationCode()); + } + if (activityPaginationRequest.getOperationId() > 0) { + stmt.setInt(index++, activityPaginationRequest.getOperationId()); + } + if (activityPaginationRequest.getInitiatedBy() != null) { + stmt.setString(index++, activityPaginationRequest.getInitiatedBy()); + } + if (activityPaginationRequest.getSince() != 0) { + stmt.setLong(index++, activityPaginationRequest.getSince()); + } + if (activityPaginationRequest.getType() != null) { + stmt.setString(index++, activityPaginationRequest.getType().name()); + } + if (activityPaginationRequest.getStatus() != null) { + stmt.setString(index++, activityPaginationRequest.getStatus().name()); + } + + if (isTimeDurationFilteringProvided) { + stmt.setLong(index++, activityPaginationRequest.getStartTimestamp()); + stmt.setLong(index, activityPaginationRequest.getEndTimestamp()); + } + + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + return rs.getInt("ACTIVITY_COUNT"); + } + } + } + } catch (SQLException e) { + String msg = "Error occurred while getting the operation details from the database."; + log.error(msg, e); + throw new OperationManagementDAOException(msg, e); + } + return 0; + } } 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/operation/mgt/dao/util/OperationDAOUtil.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/util/OperationDAOUtil.java index 178cf8f8b3..e36828233f 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/util/OperationDAOUtil.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/operation/mgt/dao/util/OperationDAOUtil.java @@ -21,6 +21,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import io.entgra.device.mgt.core.device.mgt.common.DeviceIdentifier; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.Activity; +import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.DeviceActivity; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.ActivityHolder; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.ActivityMapper; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.ActivityStatus; @@ -38,6 +39,8 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Date; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -136,8 +139,9 @@ public class OperationDAOUtil { public static OperationResponse getLargeOperationResponse(ResultSet rs) throws ClassNotFoundException, IOException, SQLException { OperationResponse response = new OperationResponse(); - if (rs.getTimestamp("RECEIVED_TIMESTAMP") != (null)) { - response.setReceivedTimeStamp(rs.getTimestamp("RECEIVED_TIMESTAMP").toString()); + if (rs.getTimestamp("RECEIVED_TIMESTAMP") != null) { + Timestamp receivedTimestamp = rs.getTimestamp("RECEIVED_TIMESTAMP"); + response.setReceivedTimeStamp(new Date(receivedTimestamp.getTime()).toString()); } ByteArrayInputStream bais = null; ObjectInputStream ois = null; @@ -171,8 +175,9 @@ public class OperationDAOUtil { public static OperationResponse getOperationResponse(ResultSet rs) throws SQLException { OperationResponse response = new OperationResponse(); - if (rs.getTimestamp("RECEIVED_TIMESTAMP") != (null)) { - response.setReceivedTimeStamp(rs.getTimestamp("RECEIVED_TIMESTAMP").toString()); + if (rs.getTimestamp("RECEIVED_TIMESTAMP") != null) { + Timestamp receivedTimestamp = rs.getTimestamp("RECEIVED_TIMESTAMP"); + response.setReceivedTimeStamp(new Date(receivedTimestamp.getTime()).toString()); } if (rs.getString("OPERATION_RESPONSE") != null) { response.setResponse(rs.getString("OPERATION_RESPONSE")); @@ -302,4 +307,27 @@ public class OperationDAOUtil { throw new OperationManagementDAOException(msg, e); } } + + public static DeviceActivity populateActivity(ResultSet rs) throws SQLException { + DeviceActivity deviceActivity = new DeviceActivity(); + List operationResponses = new ArrayList<>(); + + deviceActivity.setType(DeviceActivity.Type.valueOf(rs.getString("TYPE"))); + deviceActivity.setCreatedTimeStamp(new Date(rs.getLong(("CREATED_TIMESTAMP")) * 1000).toString()); + deviceActivity.setActivityId(OperationDAOUtil.getActivityId(rs.getInt("OPERATION_ID"))); + deviceActivity.setCode(rs.getString("OPERATION_CODE")); + deviceActivity.setOperationId(rs.getInt("OPERATION_ID")); + deviceActivity.setInitiatedBy(rs.getString("INITIATED_BY")); + + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(); + deviceIdentifier.setId(rs.getString("DEVICE_IDENTIFICATION")); + deviceIdentifier.setType(rs.getString("DEVICE_TYPE")); + deviceActivity.setDeviceIdentifier(deviceIdentifier); + deviceActivity.setStatus(DeviceActivity.Status.valueOf(rs.getString("STATUS"))); + if (rs.getInt("UPDATED_TIMESTAMP") != 0) { + deviceActivity.setResponses(operationResponses); + } + deviceActivity.setUpdatedTimestamp(new Date(rs.getLong(("UPDATED_TIMESTAMP")) * 1000).toString()); + return deviceActivity; + } } 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/service/DeviceManagementProviderService.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderService.java index cb372841e6..d3b12e9816 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderService.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderService.java @@ -39,6 +39,7 @@ import io.entgra.device.mgt.core.device.mgt.common.geo.service.GeoQuery; import io.entgra.device.mgt.core.device.mgt.common.invitation.mgt.DeviceEnrollmentInvitationDetails; import io.entgra.device.mgt.core.device.mgt.common.license.mgt.License; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.Activity; +import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.DeviceActivity; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.Operation; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.OperationManagementException; import io.entgra.device.mgt.core.device.mgt.common.policy.mgt.PolicyMonitoringManager; @@ -1004,6 +1005,11 @@ public interface DeviceManagementProviderService { int getActivitiesCount(ActivityPaginationRequest activityPaginationRequest) throws OperationManagementException; + List getDeviceActivities(ActivityPaginationRequest activityPaginationRequest) throws OperationManagementException; + + int getDeviceActivitiesCount(ActivityPaginationRequest activityPaginationRequest) + throws OperationManagementException; + License getLicenseConfig (String deviceTypeName) throws DeviceManagementException; /** 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/service/DeviceManagementProviderServiceImpl.java b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderServiceImpl.java index 344325ae10..ea61d118f7 100644 --- a/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderServiceImpl.java +++ b/components/device-mgt/io.entgra.device.mgt.core.device.mgt.core/src/main/java/io/entgra/device/mgt/core/device/mgt/core/service/DeviceManagementProviderServiceImpl.java @@ -93,6 +93,7 @@ import io.entgra.device.mgt.core.device.mgt.common.license.mgt.LicenseManagement import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.Metadata; import io.entgra.device.mgt.core.device.mgt.common.metadata.mgt.MetadataManagementService; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.Activity; +import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.DeviceActivity; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.Operation; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.OperationManagementException; import io.entgra.device.mgt.core.device.mgt.common.operation.mgt.OperationManager; @@ -2564,6 +2565,19 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv .getActivitiesCount(activityPaginationRequest); } + @Override + public List getDeviceActivities(ActivityPaginationRequest activityPaginationRequest) + throws OperationManagementException { + return DeviceManagementDataHolder.getInstance().getOperationManager().getDeviceActivities(activityPaginationRequest); + } + + @Override + public int getDeviceActivitiesCount(ActivityPaginationRequest activityPaginationRequest) + throws OperationManagementException { + return DeviceManagementDataHolder.getInstance().getOperationManager() + .getDeviceActivitiesCount(activityPaginationRequest); + } + @Override public List getMonitoringOperationList(String deviceType) { int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();