Merge branch 'update-operation' into 'master'

Update operation status API

Closes product-iots#485

See merge request entgra/carbon-device-mgt!512
reporting
Dharmakeerthi Lasantha 5 years ago
commit df1cda1e00

@ -0,0 +1,62 @@
/*
* Copyright (c) 2020, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.jaxrs.beans;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
/**
* This is used to map the status of an operation.
*/
@ApiModel(
value = "OperationStatusBean",
description = "This class carries all information related map statuses of the operations."
)
public class OperationStatusBean {
@ApiModelProperty(
name = "operationId",
value = "Operation Id.",
required = true
)
int operationId;
@ApiModelProperty(
name = "status",
value = "Status of the Operation.",
required = true
)
private String status;
public int getOperationId() {
return operationId;
}
public void setOperationId(int operationId) {
this.operationId = operationId;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}

@ -64,6 +64,7 @@ import org.wso2.carbon.device.mgt.jaxrs.beans.ApplicationList;
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.OperationRequest;
import org.wso2.carbon.device.mgt.jaxrs.beans.OperationStatusBean;
import org.wso2.carbon.device.mgt.jaxrs.util.Constants;
import javax.validation.Valid;
@ -2135,4 +2136,56 @@ public interface DeviceManagementService {
required = true)
@PathParam("packageName")
String packageName);
@PUT
@Path("/{deviceType}/{id}/operation")
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "PUT",
value = "Update status of a given opeation",
notes = "Updates the status of a given operation of a given device in Entgra IoT Server.",
tags = "Device Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:operations")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully updated the operation status.",
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 = 400,
message = "Bad Request. \n Invalid request or validation error.",
response = ErrorResponse.class),
@ApiResponse(
code = 500,
message = "Error occurred while updating operation status.",
response = ErrorResponse.class)
})
Response updateOperationStatus(
@ApiParam(
name = "device-type",
value = "The device type, such as ios, android, or windows.")
@PathParam("deviceType") String deviceType,
@ApiParam(
name = "id",
value = "The device identifier")
@PathParam("id") String deviceId,
OperationStatusBean operationStatusBean);
}

@ -65,6 +65,7 @@ import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceTypeNotFoundException;
import org.wso2.carbon.device.mgt.common.exceptions.InvalidConfigurationException;
import org.wso2.carbon.device.mgt.common.exceptions.InvalidDeviceException;
import org.wso2.carbon.device.mgt.common.exceptions.BadRequestException;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup;
import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
@ -80,20 +81,22 @@ import org.wso2.carbon.device.mgt.common.search.SearchContext;
import org.wso2.carbon.device.mgt.core.app.mgt.ApplicationManagementProviderService;
import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceDetailsMgtException;
import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManager;
import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder;
import org.wso2.carbon.device.mgt.core.dto.DeviceType;
import org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation;
import org.wso2.carbon.device.mgt.core.operation.mgt.ConfigOperation;
import org.wso2.carbon.device.mgt.core.operation.mgt.ProfileOperation;
import org.wso2.carbon.device.mgt.core.search.mgt.SearchManagerService;
import org.wso2.carbon.device.mgt.core.search.mgt.SearchMgtException;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil;
import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceCompliance;
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.OperationList;
import org.wso2.carbon.device.mgt.jaxrs.beans.OperationRequest;
import org.wso2.carbon.device.mgt.jaxrs.beans.ComplianceDeviceList;
import org.wso2.carbon.device.mgt.jaxrs.beans.ApplicationList;
import org.wso2.carbon.device.mgt.jaxrs.beans.OperationStatusBean;
import org.wso2.carbon.device.mgt.jaxrs.beans.ComplianceDeviceList;
import org.wso2.carbon.device.mgt.jaxrs.service.api.DeviceManagementService;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.InputValidationException;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil;
@ -1225,4 +1228,50 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
}
}
@PUT
@Path("/{deviceType}/{id}/operation")
@Override
public Response updateOperationStatus(
@PathParam("deviceType") String deviceType,
@PathParam("id") String deviceId,
OperationStatusBean operationStatusBean) {
if (log.isDebugEnabled()) {
log.debug("Requesting device information from " + deviceId);
}
if (operationStatusBean == null) {
String errorMessage = "Request does not contain the required payload.";
log.error(errorMessage);
return Response.status(Response.Status.BAD_REQUEST).entity(errorMessage).build();
}
DeviceIdentifier deviceIdentifier = new DeviceIdentifier(deviceId, deviceType);
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
try {
Device device = DeviceMgtAPIUtils.getDeviceManagementService()
.getDevice(deviceIdentifier, false);
DeviceType deviceTypeObj = DeviceManagerUtil.getDeviceType(
deviceType, tenantId);
if (deviceTypeObj == null) {
String msg = "Error, device of type: " + deviceType + " does not exist";
log.error(msg);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
}
Operation operation = DeviceMgtAPIUtils.validateOperationStatusBean(operationStatusBean);
operation.setId(operationStatusBean.getOperationId());
DeviceMgtAPIUtils.getDeviceManagementService().updateOperation(device, operation);
return Response.status(Response.Status.OK).entity("OperationStatus updated successfully.").build();
} catch (DeviceManagementException e) {
String msg = "Error occurred when fetching device " + deviceIdentifier.toString();
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} catch (OperationManagementException e) {
String msg = "Error occurred when updating operation of device " + deviceIdentifier;
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
} catch (BadRequestException e) {
String msg = "Error occured due to invalid request";
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
}
}
}

@ -60,6 +60,15 @@ public class Constants {
public static final String WINDOWS = "windows";
public final class OperationStatus {
private OperationStatus () { throw new AssertionError(); }
public static final String COMPLETED = "completed";
public static final String ERROR = "error";
public static final String IN_PROGRESS = "in_progress";
public static final String PENDING = "pending";
public static final String NOTNOW = "notnow";
public static final String REPEATED = "repeated";
}
public final class ErrorMessages {
private ErrorMessages () { throw new AssertionError(); }

@ -38,6 +38,7 @@ import org.wso2.carbon.core.util.Utils;
import org.wso2.carbon.device.mgt.analytics.data.publisher.service.EventsPublisherService;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
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.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
@ -46,6 +47,7 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfigurationManagementService;
import org.wso2.carbon.device.mgt.common.geo.service.GeoLocationProviderService;
import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementService;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagerService;
import org.wso2.carbon.device.mgt.common.report.mgt.ReportManagementService;
import org.wso2.carbon.device.mgt.common.spi.DeviceTypeGeneratorService;
@ -58,6 +60,7 @@ import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.core.service.GroupManagementProviderService;
import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceTypeVersionWrapper;
import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.jaxrs.beans.OperationStatusBean;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.EventAttributeList;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.InputValidationException;
import org.wso2.carbon.event.processor.stub.EventProcessorAdminServiceStub;
@ -816,4 +819,48 @@ public class DeviceMgtAPIUtils {
}
}
}
/**
* This method validates the status of the operation
*
* @param operationStatusBean {@link OperationStatusBean} object
* @return {@link Operation} Returns Operation object with status set.
* @throws {@link BadRequestException} If invalid status received
*/
public static Operation validateOperationStatusBean(OperationStatusBean operationStatusBean)
throws BadRequestException {
Operation operation = new Operation();
if (operationStatusBean.getStatus() != null) {
switch (operationStatusBean.getStatus().toLowerCase()) {
case Constants.OperationStatus.COMPLETED:
operation.setStatus(Operation.Status.COMPLETED);
break;
case Constants.OperationStatus.ERROR:
operation.setStatus(Operation.Status.ERROR);
break;
case Constants.OperationStatus.IN_PROGRESS:
operation.setStatus(Operation.Status.IN_PROGRESS);
break;
case Constants.OperationStatus.PENDING:
operation.setStatus(Operation.Status.PENDING);
break;
case Constants.OperationStatus.NOTNOW:
operation.setStatus(Operation.Status.NOTNOW);
break;
case Constants.OperationStatus.REPEATED:
operation.setStatus(Operation.Status.REPEATED);
break;
default:
String msg = "Invalid operation status. Valid operations: " +
"[IN_PROGRESS, PENDING, COMPLETED, ERROR, REPEATED, NOTNOW]";
log.error(msg);
throw new BadRequestException(msg);
}
} else {
String msg = "Payload does not contain status value";
log.error(msg);
throw new BadRequestException(msg);
}
return operation;
}
}

@ -122,4 +122,14 @@ public interface OperationManager {
*/
NotificationStrategy getNotificationStrategy();
}
/**
* Check if an operation exists for a given device identifier and operation id
*
* @param deviceId Device identifier of the device
* @param operationId Id of the operation
* @return true if operation already exists, else false
* @throws {@link OperationManagementException}
*/
boolean isOperationExist(DeviceIdentifier deviceId, int operationId) throws OperationManagementException;
}

@ -1209,4 +1209,51 @@ public class OperationManagerImpl implements OperationManager {
}
return operations;
}
@Override
public boolean isOperationExist(DeviceIdentifier deviceId, int operationId)
throws OperationManagementException {
if (log.isDebugEnabled()) {
log.debug("Operation Id: " + operationId + " Device Type: " + deviceId.getType() + " Device Identifier: " +
deviceId.getId());
}
if (!isActionAuthorized(deviceId)) {
String msg = "User '" + getUser() + "' is not authorized to access the '" +
deviceId.getType() + "' device, which carries the identifier '" +
deviceId.getId() + "'";
log.error(msg);
throw new OperationManagementException(msg);
}
EnrolmentInfo enrolmentInfo = this.getActiveEnrolmentInfo(deviceId);
if (enrolmentInfo == null) {
String msg = "Device not found for given device identifier: " +
deviceId.getId() + " type: " + deviceId.getType();
log.error(msg);
throw new OperationManagementException(msg);
}
try {
OperationManagementDAOFactory.openConnection();
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation deviceSpecificOperation = operationDAO.
getOperationByDeviceAndId(enrolmentInfo.getId(),
operationId);
if (deviceSpecificOperation == null) {
return false;
} else {
return true;
}
} catch (OperationManagementDAOException e) {
String msg = "Error occurred while checking if operation with operation id "
+ operationId +" exist for " + deviceId.getType() + "' device '" + deviceId.getId() + "'";
log.error(msg, e);
throw new OperationManagementException(msg, e);
} catch (SQLException e) {
String msg = "Error occurred while opening connection to the data source";
log.error(msg, e);
throw new OperationManagementException(msg,
e);
} finally {
OperationManagementDAOFactory.closeConnection();
}
}
}

@ -903,4 +903,14 @@ public interface DeviceManagementProviderService {
List<String> getAppVersions(String packageName) throws ApplicationManagementException;
int getFunctioningDevicesInSystem() throws DeviceManagementException;
/**
* Check if an operation exists for a given device identifier and operation id
*
* @param deviceId Device identifier of the device
* @param operationId Id of the operation
* @return true if operation already exists, else false
* @throws {@link OperationManagementException}
*/
boolean isOperationExist(DeviceIdentifier deviceId, int operationId) throws OperationManagementException;
}

@ -92,6 +92,7 @@ import org.wso2.carbon.device.mgt.common.exceptions.InvalidDeviceException;
import org.wso2.carbon.device.mgt.common.exceptions.TransactionManagementException;
import org.wso2.carbon.device.mgt.common.exceptions.UnauthorizedDeviceAccessException;
import org.wso2.carbon.device.mgt.common.exceptions.UserNotFoundException;
import org.wso2.carbon.device.mgt.common.exceptions.BadRequestException;
import org.wso2.carbon.device.mgt.common.app.mgt.Application;
import org.wso2.carbon.device.mgt.common.configuration.mgt.AmbiguousConfigurationException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
@ -1916,9 +1917,17 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
"Device not found for device id:" + device.getDeviceIdentifier() + " " + "type:" +
device.getType());
}
pluginRepository.getOperationManager(device.getType(), this.getTenantId())
.updateOperation(enrolmentInfo.getId(), operation);
try {
DeviceIdentifier deviceIdentifier = new DeviceIdentifier(device.getDeviceIdentifier(), device.getType());
if (!pluginRepository.getOperationManager(device.getType(), this.getTenantId())
.isOperationExist(deviceIdentifier, operation.getId())) {
String msg = "Operation with operation id: " + operation.getId()
+ " does not exist.";
log.error(msg);
throw new BadRequestException(msg);
}
pluginRepository.getOperationManager(device.getType(), this.getTenantId())
.updateOperation(enrolmentInfo.getId(), operation);
if (DeviceManagerUtil.isPublishOperationResponseEnabled()) {
List<String> permittedOperations = DeviceManagerUtil.getEnabledOperationsForResponsePublish();
if (permittedOperations.contains(operation.getCode())
@ -1945,6 +1954,10 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
String msg = "Error occurred while publishing event.";
log.error(msg, e);
throw new OperationManagementException(msg, e);
} catch (BadRequestException e) {
String msg = "Error occured due to invalid request";
log.error(msg, e);
throw new OperationManagementException(msg, e);
}
}
@ -4169,4 +4182,10 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
DeviceManagementDAOFactory.closeConnection();
}
}
@Override
public boolean isOperationExist(DeviceIdentifier deviceId, int operationId) throws OperationManagementException {
return pluginRepository.getOperationManager(deviceId.getType(), this.getTenantId())
.isOperationExist(deviceId, operationId);
}
}

Loading…
Cancel
Save