From 7f327bac0850a7748baab5f65969af4b4a0e2257 Mon Sep 17 00:00:00 2001 From: Kavin Prathaban Date: Tue, 7 Feb 2023 06:52:04 +0000 Subject: [PATCH] Change the device status and see the device status lifecycle history (#58) ## Purpose * Fixes https://roadmap.entgra.net/issues/9266 ## Feature * Change device's status and view device's status life-cycle history ## Approach * Created a API for change status and store changed status in to database. * Created another API to view the device's life-cycle status history. * lifecycle of the status is as shown in the diagram. * lifecycle Status are taken from a xml file. Co-authored-by: prathabanKavin Co-authored-by: Pahansith Gunathilake Reviewed-on: https://repository.entgra.net/community/device-mgt-core/pulls/58 Co-authored-by: Kavin Prathaban Co-committed-by: Kavin Prathaban --- .../jaxrs/beans/LifecycleStateDeviceList.java | 47 +++++ .../admin/DeviceManagementAdminService.java | 146 +++++++++++++++ .../DeviceManagementAdminServiceImpl.java | 105 +++++++++++ .../device/mgt/jaxrs/util/Constants.java | 1 + .../mgt/jaxrs/util/DeviceMgtAPIUtils.java | 13 ++ .../mgt/common/DeviceManagementConstants.java | 1 + .../mgt/common/LifecycleStateDevice.java | 96 ++++++++++ .../mgt/DeviceLifecycleState.java | 80 ++++++++ .../exceptions/DeviceStatusException.java | 48 +++++ .../exceptions/InvalidStatusException.java | 46 +++++ .../config/DeviceConfigurationManager.java | 1 + .../lifecycleState/DeviceLifecycleConfig.java | 46 +++++ .../DeviceLifecycleConfigManager.java | 89 +++++++++ .../mgt/core/dao/DeviceLifecycleDAO.java | 72 ++++++++ .../core/dao/DeviceManagementDAOFactory.java | 4 + .../core/dao/impl/DeviceLifecycleDAOImpl.java | 174 ++++++++++++++++++ .../mgt/core/dao/impl/EnrollmentDAOImpl.java | 19 +- .../internal/DeviceManagementDataHolder.java | 10 + .../DeviceManagementServiceComponent.java | 18 ++ .../DeviceLifecycleStateManager.java | 79 ++++++++ .../DeviceManagementProviderServiceImpl.java | 5 +- .../service/DeviceStateManagementService.java | 53 ++++++ .../DeviceStateManagementServiceImpl.java | 120 ++++++++++++ .../src/test/resources/sql/h2.sql | 2 + .../main/resources/conf/lifecycle-states.xml | 116 ++++++++++++ .../src/main/resources/conf/mdm-ui-config.xml | 1 + .../src/main/resources/dbscripts/cdm/h2.sql | 2 + .../main/resources/dbscripts/cdm/mysql.sql | 1 + 28 files changed, 1389 insertions(+), 6 deletions(-) create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/LifecycleStateDeviceList.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/LifecycleStateDevice.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/configuration/mgt/DeviceLifecycleState.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/DeviceStatusException.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/InvalidStatusException.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/lifecycleState/DeviceLifecycleConfig.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/lifecycleState/DeviceLifecycleConfigManager.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceLifecycleDAO.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/DeviceLifecycleDAOImpl.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/lifeCycle/DeviceLifecycleStateManager.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceStateManagementService.java create mode 100644 components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceStateManagementServiceImpl.java create mode 100644 features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/lifecycle-states.xml diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/LifecycleStateDeviceList.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/LifecycleStateDeviceList.java new file mode 100644 index 0000000000..8f726ffb58 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/LifecycleStateDeviceList.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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 org.wso2.carbon.device.mgt.jaxrs.beans; + +import io.swagger.annotations.ApiModelProperty; +import org.wso2.carbon.device.mgt.common.LifecycleStateDevice; + +import java.util.ArrayList; +import java.util.List; + +public class LifecycleStateDeviceList extends BasePaginatedResult { + + private List lifecycleStates = new ArrayList<>(); + + @ApiModelProperty(value = "List of lifecycleStates history returned") + public List getLifecycleStates() { + return lifecycleStates; + } + + public void setLifecycleStates(List lifecycleStates) { + this.lifecycleStates = lifecycleStates; + } + + @Override + public String toString() { + return "LifecycleStateDeviceList{" + + "lifecycleStates=" + lifecycleStates + + '}'; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/DeviceManagementAdminService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/DeviceManagementAdminService.java index b0c850de95..17136a7e51 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/DeviceManagementAdminService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/admin/DeviceManagementAdminService.java @@ -34,6 +34,7 @@ */ package org.wso2.carbon.device.mgt.jaxrs.service.api.admin; +import io.entgra.application.mgt.common.dto.ApplicationDTO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; @@ -49,6 +50,8 @@ import org.apache.axis2.transport.http.HTTPConstants; import org.wso2.carbon.apimgt.annotations.api.Scope; import org.wso2.carbon.apimgt.annotations.api.Scopes; import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceList; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.util.Constants; @@ -119,6 +122,13 @@ import java.util.List; roles = {"Internal/devicemgt-admin"}, permissions = {"/device-mgt/admin/devices/usage/view"} ), + @Scope( + name = "Change device status.", + description = "Change device status.", + key = "perm:admin:devices:change-status", + roles = {"Internal/devicemgt-admin"}, + permissions = {"/device-mgt/admin/devices/change-status"} + ), } ) public interface DeviceManagementAdminService { @@ -505,4 +515,140 @@ public interface DeviceManagementAdminService { @QueryParam("endDate") Timestamp endDate); + @POST + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + @Path("/status") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + consumes = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Update and post device's State", + notes = "Use this API to change the state of the device", + tags = "Device Management Administrative Service", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:admin:devices:change-status") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 201, + message = "OK. \n Successfully added a lifecycle state.", + response = ApplicationDTO.class), + @ApiResponse( + code = 400, + message = "Bad Request. \n " + + "Lifecycle State changing request contains unacceptable or vulnerable data"), + @ApiResponse( + code = 403, + message = "Don't have permission to change the lifecycle state of a lifecycle state."), + @ApiResponse( + code = 404, + message = "NOT FOUND. \n Error occurred while adding new lifecycle state.", + response = io.entgra.application.mgt.common.ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Error occurred adding a lifecycle state.", + response = io.entgra.application.mgt.common.ErrorResponse.class) + }) + Response changeDeviceStatus( + @ApiParam( + name = "deviceId", + value = "The device identifier of the device.", + required = true) + @QueryParam("deviceId") + @Size(max = 45) + String deviceId, + @ApiParam( + name = "nextStatus", + value = "The device's next state.", + required = true) + @QueryParam("nextStatus") + EnrolmentInfo.Status nextStatus); + + @GET + @Produces(MediaType.APPLICATION_JSON) + @Path("/{type}/{deviceId}/lifecycle") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Get Device's lifecycle history", + notes = "Get the lifecycle history of the device, since the enrolement", + tags = "Device Management Administrative Service", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:admin:devices:view") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the status history of matching devices.", + response = List.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. Empty body because the client already has the latest version" + + " of the requested resource.\n"), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "Not Found. \n A device with the specified device type and id was not found.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n " + + "Server error occurred while retrieving the device details.", + response = ErrorResponse.class) + }) + Response getDeviceLifecycle( + @ApiParam( + name = "DeviceId", + value = "Device ID.", + required = true) + @PathParam("deviceId") + @Size(max = 45) + String id, + @ApiParam( + name = "type", + value = "The device type, such as ios, android, or windows.", + required = true) + @PathParam("type") + @Size(max = 45) + String type, + @ApiParam( + name = "offset", + value = "The starting pagination index for the complete list of qualified items.", + required = false, + defaultValue = "0") + @QueryParam("offset") + int offset, + @ApiParam( + name = "limit", + value = "Provide how many device details you require from the starting pagination index/offset.", + required = false, + defaultValue = "5") + @QueryParam("limit") + int limit) throws DeviceManagementException; + } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/DeviceManagementAdminServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/DeviceManagementAdminServiceImpl.java index acadf926f2..847a416fae 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/DeviceManagementAdminServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/admin/DeviceManagementAdminServiceImpl.java @@ -40,9 +40,12 @@ import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +import org.wso2.carbon.device.mgt.common.LifecycleStateDevice; import org.wso2.carbon.device.mgt.common.MDMAppConstants; import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.PaginationResult; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; @@ -50,14 +53,18 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration import org.wso2.carbon.device.mgt.common.exceptions.BadRequestException; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.common.exceptions.DeviceNotFoundException; +import org.wso2.carbon.device.mgt.common.exceptions.DeviceStatusException; import org.wso2.carbon.device.mgt.common.exceptions.InvalidDeviceException; +import org.wso2.carbon.device.mgt.common.exceptions.InvalidStatusException; import org.wso2.carbon.device.mgt.common.exceptions.UserNotFoundException; import org.wso2.carbon.device.mgt.common.PaginationResult; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceList; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; +import org.wso2.carbon.device.mgt.jaxrs.beans.LifecycleStateDeviceList; import org.wso2.carbon.device.mgt.jaxrs.service.api.admin.DeviceManagementAdminService; import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil; +import org.wso2.carbon.device.mgt.jaxrs.util.Constants; import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.core.service.RealmService; @@ -283,4 +290,102 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } } + + /** + * This change the device status + * + * @param deviceId Id of the device + * @param nextStatus next status of the device + * @return response + */ + @POST + @Path("/status") + public Response changeDeviceStatus( + @QueryParam("deviceId") String deviceId, + @QueryParam("nextStatus") EnrolmentInfo.Status nextStatus) { + + try { + if (nextStatus == null) { + return Response.status(Response.Status.BAD_REQUEST).entity( + new ErrorResponse.ErrorResponseBuilder().setMessage("Next status is required") + .build()).build(); + } + RequestValidationUtil.validateDeviceIdentifier(Constants.ANY, deviceId); + DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService(); + Device device = dms.getDevice(deviceId, false); + if (device == null) { + String message = "Device does not exist with id '" + deviceId + "'"; + log.error(message); + return Response.status(Response.Status.NOT_FOUND).entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(message).build()).build(); + } + LifecycleStateDevice updatedInfo = DeviceMgtAPIUtils.getDeviceStateManagementService() + .changeDeviceStatus(device.getEnrolmentInfo(), nextStatus); + return Response.status(Response.Status.OK).entity(updatedInfo).build(); + } catch (InvalidStatusException e) { + String msg = "Error occured while changing status: Invalid status or invalid status change"; + log.error(msg, e); + return Response.status(Response.Status.BAD_REQUEST).entity(msg).build(); + } catch (DeviceManagementException e) { + String msg = "Error occurred while getting the device '" + deviceId + "'"; + log.error(msg, e); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } catch (DeviceStatusException e) { + String msg = "Error occurred while getting device Status"; + log.error(msg, e); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } + } + + /** + * Get the devicelifecycle history + * + * @param type Device type + * @param deviceId Device id + * @param offset is starting number of the record which we want tot get + * @param limit is the number of records we want starting from offset + * @return lifecycle history + */ + + @Override + @GET + @Path("/{type}/{deviceId}/lifecycle") + public Response getDeviceLifecycle( + @PathParam("type") String type, + @PathParam("deviceId") String deviceId, + @QueryParam("offset") int offset, + @QueryParam("limit") int limit) { + + try { + RequestValidationUtil.validatePaginationParameters(offset, limit); + PaginationRequest request = new PaginationRequest(offset, limit); + + RequestValidationUtil.validateDeviceIdentifier(type, deviceId); + DeviceManagementProviderService deviceManagementProviderService = + DeviceMgtAPIUtils.getDeviceManagementService(); + DeviceIdentifier deviceIdentifier = new DeviceIdentifier(deviceId, type); + Device device = deviceManagementProviderService.getDevice(deviceIdentifier, false); + if (device == null) { + return Response.status(Response.Status.NOT_FOUND).build(); + } + LifecycleStateDeviceList states = new LifecycleStateDeviceList(); + PaginationResult result = DeviceMgtAPIUtils.getDeviceStateManagementService() + .getDeviceLifecycleHistory(request, device); + states.setLifecycleStates((List) result.getData()); + states.setCount(result.getRecordsTotal()); + return Response.status(Response.Status.OK).entity(states).build(); + } catch (DeviceManagementException e) { + String msg = "Error occurred while getting the device '" + deviceId + "'"; + log.error(msg); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } catch (DeviceStatusException e) { + String msg = "Error occurred while getting device Status"; + log.error(msg, e); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/Constants.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/Constants.java index d7462993a9..95fadfb452 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/Constants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/Constants.java @@ -58,6 +58,7 @@ public class Constants { "core.polcy.AndroidPolicyPayloadValidator"; public static final String IOS = "ios"; public static final String WINDOWS = "windows"; + public static final String ANY = "any"; public final class OperationStatus { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java index 92bc2790d4..5806d948c1 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java @@ -86,6 +86,7 @@ import org.wso2.carbon.device.mgt.core.permission.mgt.PermissionUtils; import org.wso2.carbon.device.mgt.core.privacy.PrivacyComplianceProvider; import org.wso2.carbon.device.mgt.core.search.mgt.SearchManagerService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; +import org.wso2.carbon.device.mgt.core.service.DeviceStateManagementService; import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService; import org.wso2.carbon.device.mgt.core.traccar.api.service.DeviceAPIClientService; import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceTypeVersionWrapper; @@ -271,6 +272,18 @@ public class DeviceMgtAPIUtils { } } + public static DeviceStateManagementService getDeviceStateManagementService() { + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + DeviceStateManagementService deviceStateManagementService = + (DeviceStateManagementService) ctx.getOSGiService(DeviceStateManagementService.class, null); + if (deviceStateManagementService == null) { + String msg = "DeviceStateManagementService service has not initialized."; + log.error(msg); + throw new IllegalStateException(msg); + } + return deviceStateManagementService; + } + public static DeviceManagementProviderService getDeviceManagementService() { PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); DeviceManagementProviderService deviceManagementProviderService = diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceManagementConstants.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceManagementConstants.java index 154594678c..3bbaf47250 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceManagementConstants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceManagementConstants.java @@ -28,6 +28,7 @@ public final class DeviceManagementConstants { public static final String SECURE_VAULT_NS = "http://org.wso2.securevault/configuration"; public static final String DEVICE_CONFIG_XML_NAME = "cdm-config.xml"; public static final String UI_CONFIG_XML_NAME = "mdm-ui-config.xml"; + public static final String DEVICE_LIFECYCLE_STATES_XML_NAME = "lifecycle-states.xml"; } public static final class SecureValueProperties { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/LifecycleStateDevice.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/LifecycleStateDevice.java new file mode 100644 index 0000000000..4cdcf47492 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/LifecycleStateDevice.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2023, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved. + * + * Entgra (pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.common; + +import java.util.Date; + +/** + * Information of the device lifecycle + */ +public class LifecycleStateDevice { + + private int deviceId; + private String currentStatus; + private String previousStatus; + private String updatedBy; + private Date updatedAt; + + public LifecycleStateDevice() { + } + + public LifecycleStateDevice(int deviceId, String currentStatus, String previousStatus, String updatedBy, + Date updatedAt) { + this.deviceId = deviceId; + this.currentStatus = currentStatus; + this.previousStatus = previousStatus; + this.updatedBy = updatedBy; + this.updatedAt = updatedAt; + } + + public String getCurrentStatus() { + return currentStatus; + } + + public void setCurrentStatus(String currentStatus) { + this.currentStatus = currentStatus; + } + + public String getPreviousStatus() { + return previousStatus; + } + + public void setPreviousStatus(String previousStatus) { + this.previousStatus = previousStatus; + } + + public String getUpdatedBy() { + return updatedBy; + } + + public void setUpdatedBy(String updatedBy) { + this.updatedBy = updatedBy; + } + + public Date getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + } + + public int getDeviceId() { + return deviceId; + } + + public void setDeviceId(int deviceId) { + this.deviceId = deviceId; + } + + @Override + public String toString() { + return "LifecycleStateDevice{" + + "deviceId=" + deviceId + + ", currentStatus='" + currentStatus + '\'' + + ", previousStatus='" + previousStatus + '\'' + + ", updatedBy='" + updatedBy + '\'' + + ", updatedAt=" + updatedAt + + '}'; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/configuration/mgt/DeviceLifecycleState.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/configuration/mgt/DeviceLifecycleState.java new file mode 100644 index 0000000000..e625c3a8c6 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/configuration/mgt/DeviceLifecycleState.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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. + * + */ +/* + * Copyright (c) 2023, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved. + * + * Entgra (pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.common.configuration.mgt; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.List; + +/** + * Bean of the DeviceLifecycleState + */ +@XmlRootElement(name = "LifecycleState") +public class DeviceLifecycleState { + + private String name; + private List proceedingStates; + + @XmlAttribute(name = "name") + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @XmlElementWrapper(name = "ProceedingStates") + @XmlElement(name = "State") + public List getProceedingStates() { + return proceedingStates; + } + + public void setProceedingStates(List proceedingStates) { + this.proceedingStates = proceedingStates; + } + + @Override + public String toString() { + return "DeviceLifecycleState{" + + "name='" + name + '\'' + + ", proceedingStates=" + proceedingStates + + '}'; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/DeviceStatusException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/DeviceStatusException.java new file mode 100644 index 0000000000..63a80b7fff --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/DeviceStatusException.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved. + * + * Entgra (pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.common.exceptions; + +public class DeviceStatusException extends Exception{ + + private static final long serialVersionUID = 1608833587090532707L; + + public DeviceStatusException() { + } + + public DeviceStatusException(String msg, Exception nestedEx) { + super(msg, nestedEx); + } + + + public DeviceStatusException(String message) { + super(message); + } + + public DeviceStatusException(String message, Throwable cause) { + super(message, cause); + } + + public DeviceStatusException(Throwable cause) { + super(cause); + } + + public DeviceStatusException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/InvalidStatusException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/InvalidStatusException.java new file mode 100644 index 0000000000..35f454da73 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/InvalidStatusException.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved. + * + * Entgra (pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.device.mgt.common.exceptions; + +public class InvalidStatusException extends Exception{ + + private static final long serialVersionUID = -7379721600057895944L; + + + public InvalidStatusException() { + } + + public InvalidStatusException(String message) { + super(message); + } + + public InvalidStatusException(String message, Throwable cause) { + super(message, cause); + } + + public InvalidStatusException(Throwable cause) { + super(cause); + } + + public InvalidStatusException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceConfigurationManager.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceConfigurationManager.java index 027ddd2417..0ea2660762 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceConfigurationManager.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/DeviceConfigurationManager.java @@ -40,6 +40,7 @@ public class DeviceConfigurationManager { private static final String DEVICE_MGT_CONFIG_PATH = CarbonUtils.getCarbonConfigDirPath() + File.separator + DeviceManagementConstants.DataSourceProperties.DEVICE_CONFIG_XML_NAME; + private static final String DEVICE_MGT_CONFIG_SCHEMA_PATH = "resources/config/schema/device-mgt-config-schema.xsd"; public static DeviceConfigurationManager getInstance() { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/lifecycleState/DeviceLifecycleConfig.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/lifecycleState/DeviceLifecycleConfig.java new file mode 100644 index 0000000000..b1484abc08 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/lifecycleState/DeviceLifecycleConfig.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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 org.wso2.carbon.device.mgt.core.config.lifecycleState; + +import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceLifecycleState; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.List; + +/** + * Represents Device lifecycle status configuration. + */ +@XmlRootElement(name = "LifecycleManagementConfiguration") +public class DeviceLifecycleConfig { + + private List deviceLifecycleStates; + + @XmlElementWrapper(name = "LifecycleStates") + @XmlElement(name = "LifecycleState") + public List getDeviceLifecycleStates() { + return deviceLifecycleStates; + } + + public void setDeviceLifecycleStates(List deviceLifecycleStates) { + this.deviceLifecycleStates = deviceLifecycleStates; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/lifecycleState/DeviceLifecycleConfigManager.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/lifecycleState/DeviceLifecycleConfigManager.java new file mode 100644 index 0000000000..3d0ae0b25f --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/lifecycleState/DeviceLifecycleConfigManager.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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 org.wso2.carbon.device.mgt.core.config.lifecycleState; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; +import org.wso2.carbon.utils.CarbonUtils; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import java.io.File; + +/** + * Class responsible for the LifecycleStates configuration initialization. + */ +public class DeviceLifecycleConfigManager { + + private static final Log log = LogFactory.getLog(DeviceLifecycleConfigManager.class); + private DeviceLifecycleConfig deviceLifecycleConfig; + private static volatile DeviceLifecycleConfigManager deviceLifecycleConfigManager; + private static final String DEVICE_LIFECYCLE_PATH = CarbonUtils.getCarbonConfigDirPath() + File.separator + + DeviceManagementConstants.DataSourceProperties.DEVICE_LIFECYCLE_STATES_XML_NAME; + + private DeviceLifecycleConfigManager() { + } + + public static DeviceLifecycleConfigManager getInstance() { + if (deviceLifecycleConfigManager == null) { + synchronized (DeviceLifecycleConfigManager.class) { + if (deviceLifecycleConfigManager == null) { + deviceLifecycleConfigManager = new DeviceLifecycleConfigManager(); + try { + deviceLifecycleConfigManager.initConfig(); + } catch (Exception e) { + log.error(e); + } + } else { + try { + deviceLifecycleConfigManager.initConfig(); + } catch (Exception e) { + log.error(e); + } + } + } + } + return deviceLifecycleConfigManager; + } + + public synchronized void initConfig() { + try { + File deviceLifecycleConfig = new File(DEVICE_LIFECYCLE_PATH); + JAXBContext jaxbContext = JAXBContext.newInstance(DeviceLifecycleConfig.class); + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + this.deviceLifecycleConfig = (DeviceLifecycleConfig) unmarshaller.unmarshal(deviceLifecycleConfig); + + } catch (JAXBException e) { + String msg = "Error occured while initializing deviceLifecycle config"; + log.error(msg, e); + throw new RuntimeException(e); + } catch (Exception e) { + String msg = "Error(Exception) occured while initializing deviceLifecycle config"; + log.error(msg, e); + throw new RuntimeException(e); + } + } + + public DeviceLifecycleConfig getDeviceLifecycleConfig() { + return deviceLifecycleConfig; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceLifecycleDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceLifecycleDAO.java new file mode 100644 index 0000000000..88039e119b --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceLifecycleDAO.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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 org.wso2.carbon.device.mgt.core.dao; + +import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +import org.wso2.carbon.device.mgt.common.LifecycleStateDevice; + +import java.util.List; + +/** + * Device status relevent DAO activity + */ +public interface DeviceLifecycleDAO { + + /** + * can change the relevent device's status + * + * @param enrolmentId Enrolment Id + * @param status changing status + * @param tenantId tenantId + * @return true or false + * @throws DeviceManagementDAOException when device no found + */ + boolean changeStatus(int enrolmentId, EnrolmentInfo.Status status, int tenantId) throws DeviceManagementDAOException; + + /** + * Add the changed status + * + * @param enrolmentId Enrolment Id + * @param currentStatus Current Status + * @param previousStatus Previous Status + * @param deviceId Id of the device + * @return Added or not, true or false + * @throws DeviceManagementDAOException When device not found + */ + boolean addStatus(int enrolmentId, EnrolmentInfo.Status currentStatus, EnrolmentInfo.Status previousStatus, + int deviceId) throws DeviceManagementDAOException; + + /** + * Get Device ID + * + * @param enrolmentId Enrolment ID + * @return Device id + * @throws DeviceManagementDAOException when device not found + */ + int getDeviceId(int enrolmentId) throws DeviceManagementDAOException; + + /** + * Get the lifecycle history of the device + * + * @param id id of the device + * @return List of LifecycleStateDevice + */ + List getDeviceLifecycle(int id) throws DeviceManagementDAOException; +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java index cbd7c697f4..5157860705 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java @@ -125,6 +125,10 @@ public class DeviceManagementDAOFactory { return new EnrollmentDAOImpl(); } + public static DeviceLifecycleDAO getDeviceLifecycleDAO() { + return new DeviceLifecycleDAOImpl(); + } + public static TrackerDAO getTrackerDAO() { if (databaseEngine != null) { switch (databaseEngine) { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/DeviceLifecycleDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/DeviceLifecycleDAOImpl.java new file mode 100644 index 0000000000..d01960383f --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/DeviceLifecycleDAOImpl.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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 org.wso2.carbon.device.mgt.core.dao.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; +import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +import org.wso2.carbon.device.mgt.common.LifecycleStateDevice; +import org.wso2.carbon.device.mgt.core.dao.DeviceLifecycleDAO; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class DeviceLifecycleDAOImpl implements DeviceLifecycleDAO { + + private static final Log log = LogFactory.getLog(DeviceLifecycleDAOImpl.class); + + private Connection getConnection() throws SQLException { + return DeviceManagementDAOFactory.getConnection(); + } + + @Override + public boolean changeStatus(int enrolmentId, EnrolmentInfo.Status status, int tenantId) + throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + Timestamp updateTime = new Timestamp(new Date().getTime()); + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET STATUS = ?, DATE_OF_LAST_UPDATE = ? WHERE ID = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, status.toString()); + stmt.setTimestamp(2, updateTime); + stmt.setInt(3, enrolmentId); + stmt.setInt(4, tenantId); + int updatedRowCount = stmt.executeUpdate(); + if (updatedRowCount != 1) { + throw new DeviceManagementDAOException("Error occurred while setting the status of device enrolment: " + + updatedRowCount + " rows were updated instead of one row!!!"); + } + } catch (SQLException e) { + String msg = "Error occurred while changing status of the device which has " + enrolmentId + " enrolmentId"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return true; + } + + @Override + public boolean addStatus(int enrolmentId, EnrolmentInfo.Status currentStatus, EnrolmentInfo.Status previousStatus, + int deviceId) throws DeviceManagementDAOException { + Connection conn; + String changedBy = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername(); + if (changedBy == null) { + changedBy = DeviceManagementConstants.MaintenanceProperties.MAINTENANCE_USER; + } + PreparedStatement stmt = null; + Timestamp updateTime = new Timestamp(new Date().getTime()); + try { + conn = this.getConnection(); + String sql = "INSERT INTO DM_DEVICE_STATUS (ENROLMENT_ID, DEVICE_ID, STATUS, UPDATE_TIME, CHANGED_BY, " + + "PREVIOUS_STATUS) VALUES(?, ?, ?, ?, ?, ?)"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, enrolmentId); + stmt.setInt(2, deviceId); + stmt.setString(3, currentStatus.toString()); + stmt.setTimestamp(4, updateTime); + stmt.setString(5, changedBy); + stmt.setString(6, previousStatus.toString()); + stmt.executeUpdate(); + } catch (SQLException e) { + String msg = "Error occurred while inserting device lifecycle"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return true; + } + + public int getDeviceId(int enrolmentId) throws DeviceManagementDAOException { + int deviceId; + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + String sql = "SELECT DEVICE_ID FROM DM_ENROLMENT WHERE ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, enrolmentId); + rs = stmt.executeQuery(); + if (rs.next()) { + deviceId = rs.getInt("DEVICE_ID"); + } else { + // if there were no records corresponding to the enrolment id this is a problem. i.e. enrolment + // id is invalid + throw new DeviceManagementDAOException("Error occurred while getting the status of device enrolment: " + + "no record for enrolment id " + enrolmentId); + } + } catch (SQLException e) { + String msg = "Error occurred while getiing the device if which has " + enrolmentId + " enrolmentId"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return deviceId; + } + + @Override + public List getDeviceLifecycle(int id) throws DeviceManagementDAOException { + List result = new ArrayList<>(); + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + String sql = "SELECT DEVICE_ID, STATUS, UPDATE_TIME, CHANGED_BY, PREVIOUS_STATUS FROM DM_DEVICE_STATUS " + + "WHERE DEVICE_ID = ?"; + + stmt = conn.prepareStatement(sql); + stmt.setInt(1, id); + rs = stmt.executeQuery(); + + while (rs.next()) { + LifecycleStateDevice lifecycleStateDevice = new LifecycleStateDevice( + rs.getInt("DEVICE_ID"), + rs.getString("STATUS"), + rs.getString("PREVIOUS_STATUS"), + rs.getString("CHANGED_BY"), + new Date(rs.getTimestamp("UPDATE_TIME").getTime()) + ); + result.add(lifecycleStateDevice); + } + } catch (SQLException e) { + String msg = "Error occurred while getiing the device lifecycle which has " + id + " deviceId"; + log.error(msg, e); + throw new DeviceManagementDAOException(msg, e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + return result; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java index 7b3e08cd50..2ae2fb8b60 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java @@ -348,7 +348,7 @@ public class EnrollmentDAOImpl implements EnrollmentDAO { DeviceManagementDAOUtil.cleanupResources(stmt, null); // if there was no record for the enrolment or the previous status is not the same as the current status // we'll add a record - if (previousStatus == null || previousStatus != status){ + if (previousStatus == null || previousStatus != status) { if (deviceId == -1) { // we need the device id in order to add a new record, therefore we get it from the enrolment table sql = "SELECT DEVICE_ID FROM DM_ENROLMENT WHERE ID = ?"; @@ -364,8 +364,16 @@ public class EnrollmentDAOImpl implements EnrollmentDAO { } DeviceManagementDAOUtil.cleanupResources(stmt, null); } + sql = "INSERT INTO DM_DEVICE_STATUS (ENROLMENT_ID, DEVICE_ID, STATUS, UPDATE_TIME, CHANGED_BY"; + if (previousStatus != null) { + sql += ", PREVIOUS_STATUS"; + } + sql += ") VALUES(?, ?, ?, ?, ?"; + if (previousStatus != null) { + sql += ", ?"; + } + sql += ")"; - sql = "INSERT INTO DM_DEVICE_STATUS (ENROLMENT_ID, DEVICE_ID, STATUS, UPDATE_TIME, CHANGED_BY) VALUES(?, ?, ?, ?, ?)"; stmt = conn.prepareStatement(sql); Timestamp updateTime = new Timestamp(new Date().getTime()); stmt.setInt(1, enrolmentId); @@ -373,9 +381,10 @@ public class EnrollmentDAOImpl implements EnrollmentDAO { stmt.setString(3, status.toString()); stmt.setTimestamp(4, updateTime); stmt.setString(5, changedBy); - stmt.execute(); - } else { - // no need to update status since the last recorded status is the same as the current status + if (previousStatus != null) { + stmt.setString(6, previousStatus.toString()); + } + stmt.executeUpdate(); } } catch (SQLException e) { throw new DeviceManagementDAOException("Error occurred while setting the status of device", e); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java index 6a69cb02ba..a5331d3c0e 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementDataHolder.java @@ -34,6 +34,7 @@ import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManag import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.dto.DeviceTypeServiceIdentifier; import org.wso2.carbon.device.mgt.core.geo.task.GeoFenceEventOperationManager; +import org.wso2.carbon.device.mgt.core.lifeCycle.DeviceLifecycleStateManager; import org.wso2.carbon.device.mgt.core.operation.timeout.task.OperationTimeoutTaskManagerService; import org.wso2.carbon.device.mgt.core.privacy.PrivacyComplianceProvider; import org.wso2.carbon.device.mgt.core.push.notification.mgt.PushNotificationProviderRepository; @@ -86,6 +87,7 @@ public class DeviceManagementDataHolder { private OperationTimeoutTaskManagerService operationTimeoutTaskManagerService; private DeviceAPIClientService deviceAPIClientService; + private DeviceLifecycleStateManager deviceLifecycleStateManager; private final Map deviceStatusTaskPluginConfigs = Collections.synchronizedMap( new HashMap<>()); @@ -359,4 +361,12 @@ public class DeviceManagementDataHolder { public void setDeviceAPIClientService(DeviceAPIClientService deviceAPIClientService) { this.deviceAPIClientService = deviceAPIClientService; } + + public DeviceLifecycleStateManager getDeviceLifecycleStateManager() { + return deviceLifecycleStateManager; + } + + public void setDeviceLifecycleStateManager(DeviceLifecycleStateManager deviceLifecycleStateManager) { + this.deviceLifecycleStateManager = deviceLifecycleStateManager; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java index a266a40499..1efe03c5f9 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java @@ -25,6 +25,7 @@ import org.osgi.service.component.ComponentContext; import org.wso2.carbon.core.ServerStartupObserver; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException; import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService; +import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceLifecycleState; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfigurationManagementService; import org.wso2.carbon.device.mgt.common.event.config.EventConfigurationProviderService; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; @@ -48,6 +49,7 @@ import org.wso2.carbon.device.mgt.core.authorization.DeviceAccessAuthorizationSe import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager; import org.wso2.carbon.device.mgt.core.config.DeviceManagementConfig; import org.wso2.carbon.device.mgt.core.config.datasource.DataSourceConfig; +import org.wso2.carbon.device.mgt.core.config.lifecycleState.DeviceLifecycleConfigManager; import org.wso2.carbon.device.mgt.core.config.tenant.PlatformConfigurationManagementServiceImpl; import org.wso2.carbon.device.mgt.core.config.ui.UIConfigurationManager; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; @@ -58,6 +60,7 @@ import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManag import org.wso2.carbon.device.mgt.core.device.details.mgt.impl.DeviceInformationManagerImpl; import org.wso2.carbon.device.mgt.core.event.config.EventConfigurationProviderServiceImpl; import org.wso2.carbon.device.mgt.core.geo.service.GeoLocationProviderServiceImpl; +import org.wso2.carbon.device.mgt.core.lifeCycle.DeviceLifecycleStateManager; import org.wso2.carbon.device.mgt.core.metadata.mgt.MetadataManagementServiceImpl; import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataManagementDAOFactory; import org.wso2.carbon.device.mgt.core.notification.mgt.NotificationManagementServiceImpl; @@ -76,6 +79,8 @@ import org.wso2.carbon.device.mgt.core.search.mgt.SearchManagerService; import org.wso2.carbon.device.mgt.core.search.mgt.impl.SearchManagerServiceImpl; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderServiceImpl; +import org.wso2.carbon.device.mgt.core.service.DeviceStateManagementService; +import org.wso2.carbon.device.mgt.core.service.DeviceStateManagementServiceImpl; import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService; import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderServiceImpl; import org.wso2.carbon.device.mgt.core.task.DeviceTaskManagerService; @@ -274,6 +279,19 @@ public class DeviceManagementServiceComponent { if (log.isDebugEnabled()) { log.debug("Device management core bundle has been successfully initialized"); } + + /* Initializing DeviceLifecycleState Configuration */ + List deviceLifecycleStates = DeviceLifecycleConfigManager.getInstance(). + getDeviceLifecycleConfig().getDeviceLifecycleStates(); + DeviceLifecycleStateManager deviceLifecycleStateManager = new DeviceLifecycleStateManager(); + deviceLifecycleStateManager.init(deviceLifecycleStates); + DeviceManagementDataHolder.getInstance().setDeviceLifecycleStateManager(deviceLifecycleStateManager); + componentContext.getBundleContext().registerService(DeviceLifecycleStateManager.class.getName(), + deviceLifecycleStateManager, null); + + DeviceStateManagementService deviceStateManagementService = new DeviceStateManagementServiceImpl(); + componentContext.getBundleContext().registerService(DeviceStateManagementService.class.getName(), + deviceStateManagementService, null); } catch (Throwable e) { log.error("Error occurred while initializing device management core bundle", e); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/lifeCycle/DeviceLifecycleStateManager.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/lifeCycle/DeviceLifecycleStateManager.java new file mode 100644 index 0000000000..3bf86d35f0 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/lifeCycle/DeviceLifecycleStateManager.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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 org.wso2.carbon.device.mgt.core.lifeCycle; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceLifecycleState; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/* this class has the methods to check whether the status is valid or status change is valid +deviceLifecycleStates details are coming from lifecycle-states.xml file*/ +public class DeviceLifecycleStateManager { + private Map deviceLifecycleStates; + private static final Log log = LogFactory.getLog(DeviceLifecycleStateManager.class); + + public Map getDeviceLifecycleStates() { + return deviceLifecycleStates; + } + + public void setDeviceLifecycleStates(Map deviceLifecycleStates) { + this.deviceLifecycleStates = deviceLifecycleStates; + } + + public void init(List states) { + deviceLifecycleStates = new HashMap<>(); + for (DeviceLifecycleState deviceLifecycleState : states) { + deviceLifecycleStates.put(deviceLifecycleState.getName(), deviceLifecycleState); + } + } + + public List getNextLifecycleStates(String currentLifecycleState) { + return deviceLifecycleStates.get(currentLifecycleState).getProceedingStates(); + } + + public boolean isValidStateChange(String currentStatus, String nextStatus) { + boolean validChange = false; + List proceedingstates = deviceLifecycleStates.get(currentStatus).getProceedingStates(); + for (String proceedingState : proceedingstates) { + if (proceedingState.equals(nextStatus)) { + validChange = true; + break; + } + } + return validChange; + } + + public boolean isValidState(String nextStatus) { + boolean isValid = false; + List states = new ArrayList<>(deviceLifecycleStates.keySet()); + for (String state : states) { + if (state.equals(nextStatus)) { + isValid = true; + break; + } + } + return isValid; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java index 7bb7e7c627..dfeaa0fb5b 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java @@ -2123,10 +2123,11 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv log.debug("get status history of device: " + device.getDeviceIdentifier()); } try { + DeviceManagementDAOFactory.openConnection(); int tenantId = this.getTenantId(); return deviceStatusDAO.getStatus(device.getId(), tenantId, fromDate, toDate, billingStatus); } catch (DeviceManagementDAOException e) { - DeviceManagementDAOFactory.rollbackTransaction(); +// DeviceManagementDAOFactory.rollbackTransaction(); String msg = "Error occurred while retrieving status history"; log.error(msg, e); throw new DeviceManagementException(msg, e); @@ -2134,6 +2135,8 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv String msg = "Error occurred in retrieving status history for device :" + device.getDeviceIdentifier(); log.error(msg, e); throw new DeviceManagementException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceStateManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceStateManagementService.java new file mode 100644 index 0000000000..6bd87cd294 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceStateManagementService.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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 org.wso2.carbon.device.mgt.core.service; + +import org.wso2.carbon.device.mgt.common.*; +import org.wso2.carbon.device.mgt.common.exceptions.DeviceStatusException; +import org.wso2.carbon.device.mgt.common.exceptions.InvalidStatusException; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; + +import java.util.List; + +/** + * This interface manages the device lifecycle, such as status change and add status to table + */ +public interface DeviceStateManagementService { + + /** + * This method change the device status and store it in a table + * + * @param enrolmentInfo Enrollment Information about the device + * @param nextStatus Next status of the device + * @return LifecycleStateDevice which contain current and previous status + * @throws InvalidStatusException If there is a invalid status or invalid status change + * @throws DeviceManagementDAOException if the device cannot be found + */ + LifecycleStateDevice changeDeviceStatus(EnrolmentInfo enrolmentInfo, EnrolmentInfo.Status nextStatus) + throws InvalidStatusException, DeviceStatusException; + + /** + * Get the lifecycle history of the relevant device + * + * @param device Device + * @return List of LifecycleStateDevice + */ + PaginationResult getDeviceLifecycleHistory(PaginationRequest request, Device device) throws DeviceStatusException; +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceStateManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceStateManagementServiceImpl.java new file mode 100644 index 0000000000..63ba1e6366 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceStateManagementServiceImpl.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2023, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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 org.wso2.carbon.device.mgt.core.service; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.CarbonContext; +import org.wso2.carbon.device.mgt.common.*; +import org.wso2.carbon.device.mgt.common.exceptions.DeviceStatusException; +import org.wso2.carbon.device.mgt.common.exceptions.IllegalTransactionStateException; +import org.wso2.carbon.device.mgt.common.exceptions.InvalidStatusException; +import org.wso2.carbon.device.mgt.common.exceptions.TransactionManagementException; +import org.wso2.carbon.device.mgt.core.dao.DeviceLifecycleDAO; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; +import org.wso2.carbon.device.mgt.core.lifeCycle.DeviceLifecycleStateManager; +import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; + +import java.sql.SQLException; +import java.util.List; + +public class DeviceStateManagementServiceImpl implements DeviceStateManagementService { + + private static final Log log = LogFactory.getLog(DeviceStateManagementServiceImpl.class); + private final DeviceLifecycleDAO deviceLifecycleDAO; + private final DeviceLifecycleStateManager deviceLifecycleStateManager; + + public DeviceStateManagementServiceImpl() { + this.deviceLifecycleDAO = DeviceManagementDAOFactory.getDeviceLifecycleDAO(); + deviceLifecycleStateManager = DeviceManagementDataHolder.getInstance().getDeviceLifecycleStateManager(); + } + + @Override + public LifecycleStateDevice changeDeviceStatus(EnrolmentInfo enrolmentInfo, EnrolmentInfo.Status nextStatus) throws + InvalidStatusException, DeviceStatusException { + LifecycleStateDevice lifecycleStateDevice = new LifecycleStateDevice(); + EnrolmentInfo.Status currentStatus = enrolmentInfo.getStatus(); + if (deviceLifecycleStateManager.isValidState(nextStatus.toString())){ + if (deviceLifecycleStateManager.isValidStateChange(currentStatus.toString(), nextStatus.toString())) { + lifecycleStateDevice.setCurrentStatus(nextStatus.toString()); + lifecycleStateDevice.setPreviousStatus(currentStatus.toString()); + } else { + String msg ="'" + currentStatus + "' to '" + nextStatus + "' is not a valid Status change. Enter " + + "valid Status"; + log.error(msg); + throw new InvalidStatusException(msg); + } + } else { + String msg = "'" + nextStatus +"' is not a valid Status. Check the Status"; + log.error(msg); + throw new InvalidStatusException(msg); + } + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + int enrolmentId = enrolmentInfo.getId(); + try { + DeviceManagementDAOFactory.beginTransaction(); + int deviceId = deviceLifecycleDAO.getDeviceId(enrolmentId); + deviceLifecycleDAO.changeStatus(enrolmentId, EnrolmentInfo.Status.valueOf( + lifecycleStateDevice.getCurrentStatus()), tenantId); + deviceLifecycleDAO.addStatus(enrolmentId, + EnrolmentInfo.Status.valueOf(lifecycleStateDevice.getCurrentStatus()), + EnrolmentInfo.Status.valueOf(lifecycleStateDevice.getPreviousStatus()), deviceId); + DeviceManagementDAOFactory.commitTransaction(); + return lifecycleStateDevice; + } catch (DeviceManagementDAOException e) { + DeviceManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred in updating status or storing device status"; + log.error(msg, e); + throw new DeviceStatusException(msg, e); + } catch (IllegalTransactionStateException e) { + String msg = "Error occurred while updating and storing(Transaction Error) device status"; + log.error(msg, e); + throw new DeviceStatusException(msg, e); + } catch (TransactionManagementException e) { + String msg = "Error occurred in DeviceManagementDAOFactory"; + log.error(msg, e); + throw new InvalidStatusException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } + + @Override + public PaginationResult getDeviceLifecycleHistory(PaginationRequest request, Device device) throws DeviceStatusException { + int id = device.getId(); + PaginationResult paginationResult = new PaginationResult(); + try { + DeviceManagementDAOFactory.openConnection(); + List listLifecycle = deviceLifecycleDAO.getDeviceLifecycle(id); + paginationResult.setData(listLifecycle); + return paginationResult; + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while getting lifrcycle history"; + log.error(msg, e); + throw new DeviceStatusException(msg, e); + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + } + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/sql/h2.sql b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/sql/h2.sql index d3b81f2655..8682e9e7db 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/sql/h2.sql +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/sql/h2.sql @@ -106,12 +106,14 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_STATUS ( STATUS VARCHAR(50) DEFAULT NULL, UPDATE_TIME TIMESTAMP DEFAULT NULL, CHANGED_BY VARCHAR(255) NOT NULL, + PREVIOUS_STATUS VARCHAR(50) DEFAULT NULL, PRIMARY KEY (ID), CONSTRAINT fk_dm_device_status_device FOREIGN KEY (DEVICE_ID) REFERENCES DM_DEVICE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT fk_dm_device_status_enrolment FOREIGN KEY (ENROLMENT_ID) REFERENCES DM_ENROLMENT (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ); + CREATE TABLE IF NOT EXISTS DM_ENROLMENT_OP_MAPPING ( ID INTEGER AUTO_INCREMENT NOT NULL, ENROLMENT_ID INTEGER NOT NULL, diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/lifecycle-states.xml b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/lifecycle-states.xml new file mode 100644 index 0000000000..3954e9b849 --- /dev/null +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/lifecycle-states.xml @@ -0,0 +1,116 @@ + + + + + + + + ACTIVE + + + + + UNREACHABLE + REMOVED + + + + + INACTIVE + REMOVED + + + + + REMOVED + + + + + REMOVED + + + + + REMOVED + + + + + REMOVED + + + + + REMOVED + + + + + REMOVED + + + + + REMOVED + + + + + REMOVED + + + + + REMOVED + + + + + REMOVED + + + + + REMOVED + + + + + REMOVED + + + + + REMOVED + + + + + REMOVED + + + + + ACTIVE + CREATED + + + + \ No newline at end of file diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml index 3ecfc5c1db..9e2761a6c8 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml @@ -124,6 +124,7 @@ perm:users:send-invitation perm:admin-users:view perm:admin:devices:update-enrollment + perm:admin:devices:change-status perm:groups:devices perm:groups:update perm:groups:add diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql index 0e8d1b8466..da7e7dbc34 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql @@ -115,12 +115,14 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_STATUS ( STATUS VARCHAR(50) DEFAULT NULL, UPDATE_TIME TIMESTAMP DEFAULT NULL, CHANGED_BY VARCHAR(255) NOT NULL, + PREVIOUS_STATUS VARCHAR(50) DEFAULT NULL, PRIMARY KEY (ID), CONSTRAINT fk_dm_device_status_device FOREIGN KEY (DEVICE_ID) REFERENCES DM_DEVICE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT fk_dm_device_status_enrolment FOREIGN KEY (ENROLMENT_ID) REFERENCES DM_ENROLMENT (ID) ON DELETE CASCADE ON UPDATE CASCADE ); + CREATE TABLE IF NOT EXISTS DM_ENROLMENT_OP_MAPPING ( ID INTEGER AUTO_INCREMENT NOT NULL, ENROLMENT_ID INTEGER NOT NULL, diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql index 33ac7964dd..f925e646f6 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql @@ -129,6 +129,7 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_STATUS ( STATUS VARCHAR(50) DEFAULT NULL, UPDATE_TIME TIMESTAMP DEFAULT NULL, CHANGED_BY VARCHAR(255) NOT NULL, + PREVIOUS_STATUS VARCHAR(50) DEFAULT NULL, PRIMARY KEY (ID), CONSTRAINT FK_DM_DEVICE_STATUS_DEVICE FOREIGN KEY (DEVICE_ID) REFERENCES DM_DEVICE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION,