Merge pull request #509 from hasuniea/windows10

Windows10 Location support
revert-dabc3590
Rasika Perera 8 years ago committed by GitHub
commit 7d07585cf1

@ -218,6 +218,8 @@ public final class PluginConstants {
public static final String BATTERY_CHARGE_REMAINING = "BATTERY_CHARGE_REMAINING";
public static final String BATTERY_ESTIMATED_RUNTIME = "BATTERY_ESTIMATED_RUNTIME";
public static final String MOBILE_ID = "MOBILE_ID";
public static final String LONGITUDE = "LONGITUDE";
public static final String LATITUDE = "LATITUDE";
}
@ -267,6 +269,11 @@ public final class PluginConstants {
public static final String DEVICE_PASSWORD_STATUS = "DEVICE_PASSWORD_STATUS";
public static final String DEVICE_PASSCODE_DELETE = "DEVICE_PASSCODE_DELETE";
public static final String DEVICE_INFO = "DEVICE_INFO";
public static final String POLICY_REVOKE = "POLICY_REVOKE";
public static final String DEVICE_LOCATION = "DEVICE_LOCATION";
public static final String LONGITUDE = "LONGITUDE";
public static final String LATITUDE = "LATITUDE";
public static final String DEVICE_REBOOT = "DEVICE_REBOOT";
}
/**

@ -29,6 +29,7 @@ import org.wso2.carbon.device.mgt.common.InvalidDeviceException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation;
import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementService;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
@ -239,4 +240,16 @@ public class WindowsAPIUtils {
(DeviceInformationManager) ctx.getOSGiService(DeviceInformationManager.class, null);
informationManager.addDeviceInfo(deviceId, deviceInfo);
}
/**
* This method is used to update device location.
* @param deviceLocation Device coordination related information.
* @throws DeviceDetailsMgtException Error occurs while updating Device location.
*/
public static void updateDeviceLocation(DeviceLocation deviceLocation) throws DeviceDetailsMgtException {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceInformationManager informationManager =
(DeviceInformationManager) ctx.getOSGiService(DeviceInformationManager.class, null);
informationManager.addDeviceLocation(deviceLocation);
}
}

@ -43,8 +43,6 @@ public class OperationCode {
ENCRYPT_STORAGE_STATUS("./Vendor/MSFT/PolicyManager/Device/Security/RequireDeviceEncryption"),
DEVICE_PASSWORD_STATUS("./Vendor/MSFT/PolicyManager/Device/DeviceLock/DevicePasswordEnabled"),
DEVICE_PASSCODE_DELETE("./Vendor/MSFT/PolicyManager/My/DeviceLock"),
LONGITUDE("./Vendor/MSFT/RemoteFind/Location/Longitude"),
LATITUDE("./Vendor/MSFT/RemoteFind/Location/Latitude"),
// Windows10 operation codes
TOTAL_RAM("./DevDetail/Ext/Microsoft/TotalRAM"),
@ -56,6 +54,8 @@ public class OperationCode {
BATTERY_STATUS("./Vendor/MSFT/DeviceStatus/Battery/Status"),
BATTERY_CHARGE_REMAINING("./Vendor/MSFT/DeviceStatus/Battery/EstimatedChargeRemaining"),
BATTERY_ESTIMATED_RUNTIME("./Vendor/MSFT/DeviceStatus/Battery/EstimatedRuntime"),
LONGITUDE("./Vendor/MSFT/RemoteFind/Location/Longitude"),
LATITUDE("./Vendor/MSFT/RemoteFind/Location/Latitude"),
TEST("./Vendor/MSFT/DiagnosticLog/EtwLog/Collectors");
private final String code;
@ -91,7 +91,10 @@ public class OperationCode {
BATTERY_STATUS("./Vendor/MSFT/DeviceStatus/Battery/Status"),
BATTERY_CHARGE_REMAINING("./Vendor/MSFT/DeviceStatus/Battery/EstimatedChargeRemaining"),
BATTERY_ESTIMATED_RUNTIME("./Vendor/MSFT/DeviceStatus/Battery/EstimatedRuntime"),
TEST("./Vendor/MSFT/DiagnosticLog/EtwLog/Collectors");
LONGITUDE("./Vendor/MSFT/RemoteFind/Location/Longitude"),
LATITUDE("./Vendor/MSFT/RemoteFind/Location/Latitude"),
TEST("./Vendor/MSFT/DiagnosticLog/EtwLog/Collectors"),
DEVICE_REBOOT("./Vendor/MSFT/Reboot/RebootNow");
private final String code;

@ -25,11 +25,13 @@ import org.json.JSONObject;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation;
import org.wso2.carbon.device.mgt.common.notification.mgt.Notification;
import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementException;
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.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceDetailsMgtException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.WindowsAPIUtils;
import org.wso2.carbon.device.mgt.mobile.windows.api.services.syncml.beans.Profile;
@ -239,6 +241,33 @@ public class OperationHandler {
}
}
public void updateDeviceLocationStatus(SyncmlDocument syncmlDocument) throws OperationManagementException {
List<? extends Operation> pendingDataOperations;
List<StatusTag> statuses = syncmlDocument.getBody().getStatus();
DeviceIdentifier deviceIdentifier = convertToDeviceIdentifierObject(
syncmlDocument.getHeader().getSource().getLocURI());
try {
pendingDataOperations = WindowsAPIUtils.getPendingOperations(deviceIdentifier);
} catch (DeviceManagementException e) {
throw new OperationManagementException("Error occurred in getting pending operation.");
}
for (Operation operation : pendingDataOperations) {
if (PluginConstants.OperationCodes.DEVICE_LOCATION.equals(operation.getCode())) {
for (StatusTag statusTag : statuses) {
if (Constants.GET.equals(statusTag.getCommand()) && statusTag.getTargetReference() != null
&& OperationCode.Command.LATITUDE.getCode().equals(statusTag.getTargetReference())) {
if (Constants.SyncMLResponseCodes.ACCEPTED.equals(statusTag.getData())) {
operation.setStatus(Operation.Status.COMPLETED);
} else {
operation.setStatus(Operation.Status.ERROR);
}
}
}
updateStatus(syncmlDocument.getHeader().getSource().getLocURI(),
pendingDataOperations);
}
}
}
/**
* Get pending operations.
@ -253,14 +282,20 @@ public class OperationHandler {
SyncmlBody syncmlBody = syncmlDocument.getBody();
List<? extends Operation> pendingOperations;
DeviceIdentifier deviceIdentifier = convertToDeviceIdentifierObject(syncmlHeader.getSource().getLocURI());
int sessionId = syncmlHeader.getSessionId();
int msgId = syncmlHeader.getMsgID();
if (!(PluginConstants.SyncML.SYNCML_FIRST_MESSAGE_ID == msgId &&
PluginConstants.SyncML.SYNCML_FIRST_SESSION_ID == sessionId)) {
List<StatusTag> statuses = syncmlBody.getStatus();
for (StatusTag status : statuses ) {
if (OperationCode.Command.LATITUDE.getCode().equals(status.getTargetReference()) &&
Constants.SyncMLResponseCodes.ACCEPTED.equals(status.getData())) {
updateLocation(syncmlDocument);
}
if (OperationCode.Command.TOTAL_RAM.getCode().equals(status.getTargetReference()) &&
Constants.SyncMLResponseCodes.ACCEPTED.equals(status.getData())) {
if ((syncmlBody.getResults() != null)) {
updateDeviceInfo(syncmlDocument);
}
}
}
UpdateUriOperations(syncmlDocument);
generateComplianceFeatureStatus(syncmlDocument);
pendingOperations = WindowsAPIUtils.getDeviceManagementService().getPendingOperations(deviceIdentifier);
@ -568,4 +603,33 @@ public class OperationHandler {
throw new WindowsOperationException("Error occurred while updating Device info operation status.");
}
}
private void updateLocation(SyncmlDocument syncmlDocument) throws WindowsOperationException {
List<ItemTag> deviceInformations = syncmlDocument.getBody().getResults().getItem();
DeviceIdentifier deviceIdentifier = convertToDeviceIdentifierObject(
syncmlDocument.getHeader().getSource().getLocURI());
DeviceLocation deviceLocation = new DeviceLocation();
deviceLocation.setDeviceIdentifier(deviceIdentifier);
for (ItemTag item : deviceInformations) {
String source = item.getSource().getLocURI();
if (OperationCode.Info.LONGITUDE.getCode().equals(source)) {
String longitude = item.getData();
deviceLocation.setLongitude(Double.parseDouble(longitude));
}
if (OperationCode.Info.LATITUDE.getCode().equals(source)) {
Double latitude = Double.parseDouble(item.getData());
deviceLocation.setLatitude(latitude);
}
}
try {
WindowsAPIUtils.updateDeviceLocation(deviceLocation);
updateDeviceLocationStatus(syncmlDocument);
} catch (DeviceDetailsMgtException e) {
throw new WindowsOperationException("Error occurred while updating Device Location.");
} catch (OperationManagementException e) {
throw new WindowsOperationException("Error occurred while updating Device Location operation status.");
}
}
}

@ -240,7 +240,6 @@ public class OperationReply {
List<ItemTag> replaceItems = new ArrayList<>();
SequenceTag monitorSequence = new SequenceTag();
List<Operation> deviceInfoOperations;
if (operations != null) {
for (Operation operation : operations) {
Operation.Type type = operation.getType();
@ -293,6 +292,23 @@ public class OperationReply {
SequenceTag sequence = buildSequence(operation, sequenceElement);
syncmlBody.setSequence(sequence);
}
if (PluginConstants.OperationCodes.DEVICE_LOCATION.equals(operation.getCode())) {
Operation longitudeOperation = new Operation();
Operation latitudeOperation = new Operation();
longitudeOperation.setCode(PluginConstants.OperationCodes.LONGITUDE);
latitudeOperation.setCode(PluginConstants.OperationCodes.LATITUDE);
List<Operation> deviceLocationOperations = new ArrayList<>();
deviceLocationOperations.add(latitudeOperation);
deviceLocationOperations.add(longitudeOperation);
for (Operation infoOperation : deviceLocationOperations) {
ItemTag deviceInfo = appendGetInfo(infoOperation);
getElements.add(deviceInfo);
}
}
if (PluginConstants.OperationCodes.DEVICE_REBOOT.equals(operation.getCode())) {
execElement = executeCommand(operation);
executeElements.add(execElement);
}
if ((PluginConstants.OperationCodes.MONITOR.equals(operation.getCode()))) {
GetTag monitorGetElement = new GetTag();
List<ItemTag> monitorItems;
@ -561,8 +577,7 @@ public class OperationReply {
return execElement;
}
public SequenceTag buildSequence(Operation operation, SequenceTag sequenceElement) throws
JSONException,
public SequenceTag buildSequence(Operation operation, SequenceTag sequenceElement) throws JSONException,
SyncmlOperationException {
sequenceElement.setCommandId(operation.getId());
@ -580,7 +595,6 @@ public class OperationReply {
sequenceElement.setExec(execElement);
sequenceElement.setGet(getElements);
return sequenceElement;
} else if ((PluginConstants.OperationCodes.POLICY_BUNDLE.equals(operation.getCode()))) {
List<? extends Operation> policyOperations;
try {

@ -62,11 +62,11 @@ import javax.ws.rs.core.Response;
}
),
tags = {
@Tag(name = "devicemgt_windows", description = "")
@Tag(name = "windows", description = "")
}
)
@Api(value = "Windows Configuration Management",
description = "This carries all the resources related to Windows configurations management functionalities")
description = "This carries all the resources related to Windows configurations management functionality")
@WebService
@Path("/configuration")
@Produces({"application/json", "application/xml"})

@ -95,6 +95,18 @@ import java.util.List;
description = "Lock reset on Windows devices",
key = "perm:windows:lock-reset",
permissions = {"/device-mgt/devices/owning-device/operations/windows/lock-reset"}
),
@Scope(
name = "Reboot",
description = "Lock reset on Windows devices",
key = "perm:windows:reboot",
permissions = {"/device-mgt/devices/owning-device/operations/windows/reboot"}
),
@Scope(
name = "Device Location",
description = "Lock reset on Windows devices",
key = "perm:windows:location",
permissions = {"/device-mgt/devices/owning-device/operations/windows/location"}
)
}
)
@ -395,4 +407,134 @@ public interface DeviceManagementAdminService {
value = "Provide the ID of the A Windows device. Multiple device IDs can be added by " +
"using comma separated values. ",
required = true) List<String> deviceIds) throws WindowsDeviceEnrolmentException;
@POST
@Path("/location")
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Requesting Location Coordinates",
responseContainer = "List",
notes = "Request location coordinates of Windows devices. \n" +
"Example: In situations where you have lost your device and need to find out where it is, " +
"you can use this REST API to get the location of the device.",
response = Activity.class,
tags = "Windows Device Management Administrative Service",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:windows:location")
})
}
)
@ApiResponses(value = {
@ApiResponse(
code = 201,
message = "Created. \n Get-location operation has successfully been scheduled",
response = Activity.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "URL of the activity instance that refers to the " +
"scheduled operation."),
@ResponseHeader(
name = "Content-Type",
description = "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 = 303,
message = "See Other. \n The source can be retrieved from the URL specified in the" +
" location header.",
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "The Source URL of the document.")}),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error."),
@ApiResponse(
code = 415,
message = "Unsupported media type. \n The format of the requested entity was not supported."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while adding a new get-location operation.")})
Response getDeviceLocation(
@ApiParam(
name = "deviceIDs",
value = "Provide the ID of the Windows device. Multiple device IDs can be added by " +
"using comma separated values. ",
required = true)
List<String> deviceIDs);
@POST
@Path("/reboot")
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Rebooting Windows Devices",
notes = "Reboot or restart your Windows devices.",
response = Activity.class,
tags = "Windows Device Management Administrative Service",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:windows:reboot")
})
}
)
@ApiResponses(value = {
@ApiResponse(
code = 201,
message = "Created. \n Successfully scheduled the device reboot operation.",
response = Activity.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "URL of the activity instance that refers to the scheduled operation."),
@ResponseHeader(
name = "Content-Type",
description = "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 = 303,
message = "See Other. \n The source can be retrieved from the URL specified in the location header.\n",
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "The Source URL of the document.")}),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error."),
@ApiResponse(
code = 415,
message = "Unsupported media type. \n The format of the requested entity was not supported.\n"),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while adding the new device reboot operation.")
})
Response rebootDevice(
@ApiParam(
name = "deviceIDs",
value = "Provide the ID of the Android device. Multiple device IDs can be added using comma separated values. ",
required = true)
List<String> deviceIDs);
}

@ -36,7 +36,7 @@ import javax.ws.rs.core.Response;
/**
* Interface for Syncml message flow.
* Interface for Windows 10 Device management phase.
*/
@SwaggerDefinition(
info = @Info(
@ -44,18 +44,18 @@ import javax.ws.rs.core.Response;
title = "",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "Syncml Endpoint"),
@ExtensionProperty(name = "name", value = "Windows 10 Device management"),
@ExtensionProperty(name = "context",
value = "/api/device-mgt/windows/v1.0/syncmlmgt"),
value = "/api/device-mgt/windows/v1.0/management"),
})
}
),
tags = {
@Tag(name = "devicemgt_windows", description = "")
@Tag(name = "windows", description = "")
}
)
@Api(value = "Windows syncml service to initialize management session",
description = "This carries all the resources related to Windows syncml message flow.")
@Api(value = "Windows 10 Device management",
description = "This carries all the resources related to Windows 10 management session message flow.")
@Path("/devicemgt")
public interface DeviceManagementService {
@Path("/pending-operations")

@ -44,17 +44,17 @@ import javax.ws.rs.core.Response;
title = "",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "Windows Binary security token provider"),
@ExtensionProperty(name = "name", value = "Windows Binary Security Token Service"),
@ExtensionProperty(name = "context",
value = "/api/device-mgt/windows/v1.0/federated"),
})
}
),
tags = {
@Tag(name = "devicemgt_windows", description = "")
@Tag(name = "windows", description = "")
}
)
@Api(value = "Windows BST Management",
@Api(value = "Windows Binary Security Token Service",
description = "This carries all the resources related to Windows Binary security token management.")
@WebService
@Path("/bst")

@ -48,17 +48,17 @@ import javax.xml.ws.soap.SOAPBinding;
title = "",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "Windows Discovery service provider"),
@ExtensionProperty(name = "name", value = "Windows Discovery Service"),
@ExtensionProperty(name = "context",
value = "/api/device-mgt/windows/v1.0/discovery/post"),
})
}
),
tags = {
@Tag(name = "devicemgt_windows", description = "")
@Tag(name = "windows", description = "")
}
)
@Api(value = "Windows Discovery service",
@Api(value = "Windows Discovery Service",
description = "This carries all the resources related to Windows Discovery service.")
@WebService(targetNamespace = PluginConstants.DISCOVERY_SERVICE_TARGET_NAMESPACE,
name = "IDiscoveryService")
@ -133,54 +133,4 @@ public interface DiscoveryService {
javax.xml.ws.Holder<DiscoveryResponse> response
) throws WindowsDeviceEnrolmentException;
@ApiOperation(
httpMethod = "GET",
value = "Device ping the server to check whether it is running or not.",
notes = ".",
tags = "Windows Discovery service.",
authorizations = {
@Authorization(
value = "permission",
scopes = {@AuthorizationScope(scope = "/device-mgt/devices/enroll/windows",
description = "Ping the Discovery service")}
)
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Server is already running."),
@ApiResponse(
code = 303,
message = "See Other. \n The source can be retrieved from the URL specified " +
"in the location header.",
responseHeaders = {
@ResponseHeader(name = "Content-Location",
description = "Source URL of the document.")
}),
@ApiResponse(
code = 304,
message = "Not Modified. \n " +
"Empty body because the client already has the latest version of " +
"the requested resource."),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error. You must provide" +
" the device identifier. Additionally, the device identifier can be combined" +
" with either the device type" +
" OR the from and to date."),
@ApiResponse(
code = 404,
message = "Not Found. \n The specified resource does not exist."),
@ApiResponse(
code = 500,
message = "Error occurred while pinging the server.")
})
@GET
@WebMethod
@WebResult()
Response discoverGet();
}

@ -101,21 +101,6 @@ public class DiscoveryServiceImpl implements DiscoveryService {
}
}
/**
* This is the first method called through device. The device checks the availability of the
* Service end point by calling this method.
*
* @return - HTTP 200OK message
*/
@Override
public Response discoverGet() {
if (log.isDebugEnabled()) {
log.debug("Discovery service end point was triggered via GET method.");
}
return Response.ok().build();
}
/**
* Get authentication policy from the tenant configuration, otherwise set default value as Federated.
*

@ -18,6 +18,7 @@
package org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment;
import io.swagger.annotations.*;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WAPProvisioningException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsDeviceEnrolmentException;
@ -27,12 +28,32 @@ import org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.beans.R
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.ws.rs.POST;
import javax.xml.ws.BindingType;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
import javax.xml.ws.soap.SOAPBinding;
import java.io.UnsupportedEncodingException;
@SwaggerDefinition(
info = @Info(
version = "1.0.0",
title = "",
extensions = {
@io.swagger.annotations.Extension(properties = {
@ExtensionProperty(name = "name", value = "Windows 10 Enrollment Service"),
@ExtensionProperty(name = "context",
value = "/api/device-mgt/windows/v1.0/deviceenrolment/enrollment"),
})
}
),
tags = {
@Tag(name = "windows", description = "")
}
)
@Api(value = "Windows 10 Enrollment Service",
description = "This carries all the resources related to Windows enrollment.")
@WebService(targetNamespace = PluginConstants.DEVICE_ENROLLMENT_SERVICE_TARGET_NAMESPACE, name = "enrollment")
@BindingType(value = SOAPBinding.SOAP12HTTP_BINDING)
public interface EnrollmentService {
@ -42,6 +63,60 @@ public interface EnrollmentService {
@WebMethod(operationName = "RequestSecurityToken")
@ResponseWrapper(localName = "RequestSecurityTokenResponseCollection", targetNamespace =
PluginConstants.WS_TRUST_TARGET_NAMESPACE)
@POST
@ApiOperation(
httpMethod = "POST",
value = "Signing the certificate signing request(CSR) and provide request security token response.",
notes = "Using this API to fetching more information to enroll the Device and " +
"getting pending operations.",
tags = "Windows 10 Device Enrollment Service.",
authorizations = {
@Authorization(
value = "permission",
scopes = {@AuthorizationScope(
scope = "/device-mgt/devices/enroll/windows",
description = "Signing the certificate signing request(CSR) " +
"and provide request security token response")}
)
}
)
@ApiResponses(value = {
@ApiResponse(
code = 200,
message = "Ok.Successfully signed the CSR.",
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "URL of the activity instance that refers to the scheduled operation."),
@ResponseHeader(
name = "Content-Type",
description = "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 = 303,
message = "See Other. \n The source can be retrieved from the URL specified in the location header.",
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "The Source URL of the document.")}),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error."),
@ApiResponse(
code = 415,
message = "Unsupported media type. \n The format of the requested entity was not supported.\n"),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while Signing the CSR.")
})
void requestSecurityToken(
@WebParam(name = "TokenType", targetNamespace = PluginConstants.WS_TRUST_TARGET_NAMESPACE)
String tokenType,

@ -25,9 +25,8 @@ import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ContextItem", namespace = PluginConstants.SOAP_AUTHORIZATION_TARGET_NAMESPACE,
propOrder = {"Name" , "Value"})
@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(name = "ContextItem", namespace = PluginConstants.SOAP_AUTHORIZATION_TARGET_NAMESPACE)
public class ContextItem {
@XmlElement(required = true, namespace = PluginConstants.SOAP_AUTHORIZATION_TARGET_NAMESPACE)

@ -19,6 +19,7 @@
package org.wso2.carbon.device.mgt.mobile.windows.api.services.impl;
import com.ibm.wsdl.OperationImpl;
import io.swagger.annotations.ApiParam;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
@ -29,6 +30,7 @@ import org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.BadRequestException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.UnexpectedServerErrorException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsDeviceEnrolmentException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsOperationsException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.Message;
@ -268,4 +270,70 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe
new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(errorMessage).build());
}
}
@POST
@Path("/location")
public Response getDeviceLocation(@ApiParam(
name = "deviceIDs",
value = "Provide the ID of the Windows device. Multiple device IDs can be added by " +
"using comma separated values. ",
required = true) List<String> deviceIDs) {
if (log.isDebugEnabled()) {
log.debug("Invoking Windows device location operation.");
}
try {
CommandOperation operation = new CommandOperation();
operation.setCode(PluginConstants.OperationCodes.DEVICE_LOCATION);
operation.setType(Operation.Type.COMMAND);
return WindowsAPIUtils.getOperationResponse(deviceIDs, operation);
} catch (InvalidDeviceException e) {
String errorMessage = "Invalid Device Identifiers found.";
log.error(errorMessage, e);
throw new BadRequestException(
new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(errorMessage).build());
} catch (OperationManagementException e) {
String errorMessage = "Issue in retrieving operation management service instance";
log.error(errorMessage, e);
throw new UnexpectedServerErrorException(
new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(errorMessage).build());
} catch (DeviceManagementException e) {
String errorMessage = "Issue in retrieving device management service instance";
log.error(errorMessage, e);
throw new UnexpectedServerErrorException(
new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(errorMessage).build());
}
}
@POST
@Path("/reboot")
public Response rebootDevice(@ApiParam(
name = "deviceIDs",
value = "Provide the ID of the Windows device. Multiple device IDs can be " +
"added using comma separated values.",
required = true) List<String> deviceIDs) {
if (log.isDebugEnabled()) {
log.debug("Invoking Windows reboot-device device operation");
}
try {
CommandOperation operation = new CommandOperation();
operation.setCode(PluginConstants.OperationCodes.DEVICE_REBOOT);
operation.setType(Operation.Type.COMMAND);
return WindowsAPIUtils.getOperationResponse(deviceIDs, operation);
} catch (InvalidDeviceException e) {
String errorMessage = "Invalid Device Identifiers found.";
log.error(errorMessage, e);
throw new BadRequestException(
new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(errorMessage).build());
} catch (OperationManagementException e) {
String errorMessage = "Issue in retrieving operation management service instance";
log.error(errorMessage, e);
throw new UnexpectedServerErrorException(
new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(errorMessage).build());
} catch (DeviceManagementException e) {
String errorMessage = "Issue in retrieving device management service instance";
log.error(errorMessage, e);
throw new UnexpectedServerErrorException(
new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(errorMessage).build());
}
}
}

@ -35,7 +35,7 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* Interface for Syncml message flow.
* Interface for Windows 8.1 enrollment flow.
*/
@SwaggerDefinition(
info = @Info(
@ -43,17 +43,17 @@ import javax.ws.rs.core.Response;
title = "",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "Syncml Endpoint"),
@ExtensionProperty(name = "name", value = "Windows 8.1 Device Management Service"),
@ExtensionProperty(name = "context",
value = "/api/device-mgt/windows/v1.0/syncml"),
})
}
),
tags = {
@Tag(name = "devicemgt_windows", description = "")
@Tag(name = "windows", description = "")
}
)
@Api(value = "Windows syncml service",
@Api(value = "Windows 8.1 Device Management Service",
description = "This carries all the resources related to Windows syncml message flow.")
@Path("/devicemanagement")
public interface SyncmlService {

@ -235,7 +235,6 @@ public class SyncmlServiceImpl implements SyncmlService {
String devLang;
String vendor;
String macAddress;
String resolution;
String modVersion;
boolean status = false;
String user;

@ -47,14 +47,14 @@ import java.io.UnsupportedEncodingException;
title = "",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "Windows enrollment service provider"),
@ExtensionProperty(name = "name", value = "Windows 8.1 Enrollment Service"),
@ExtensionProperty(name = "context",
value = "/api/device-mgt/windows/v1.0/deviceenrolment/wstep"),
})
}
),
tags = {
@Tag(name = "devicemgt_windows", description = "")
@Tag(name = "windows", description = "")
}
)
@Api(value = "Windows Enrollment service Management",

@ -47,17 +47,17 @@ import javax.xml.ws.soap.SOAPBinding;
title = "",
extensions = {
@io.swagger.annotations.Extension(properties = {
@ExtensionProperty(name = "name", value = "Windows Enrollment policy service"),
@ExtensionProperty(name = "name", value = "Windows Enrollment policy Service"),
@ExtensionProperty(name = "context",
value = "/api/device-mgt/windows/v1.0/certificatepolicy/xcep"),
})
}
),
tags = {
@Tag(name = "devicemgt_windows", description = "")
@Tag(name = "windows", description = "")
}
)
@Api(value = "Windows enrollment policy Management",
@Api(value = "Windows Enrollment policy Service",
description = "This carries all the resources related to Windows enrollment policy.")
@WebService(targetNamespace = PluginConstants.CERTIFICATE_ENROLLMENT_POLICY_SERVICE_TARGET_NAMESPACE,
name = "IPolicy")

@ -62,8 +62,11 @@
</context-param>
<context-param>
<param-name>nonSecuredEndPoints</param-name>
<param-value>/discovery/get,/discovery/post,/certificatepolicy/xcep,
,/deviceenrolment/wstep,/syncml/devicemanagement/request,/deviceenrolment/enrollment,/management/devicemgt/pending-operations
<param-value>/api/device-mgt/windows/v1.0/discovery/get,/api/device-mgt/windows/v1.0/discovery/post,
/api/device-mgt/windows/v1.0/certificatepolicy/xcep,/api/device-mgt/windows/v1.0/deviceenrolment/wstep,
/api/device-mgt/windows/v1.0/syncml/devicemanagement/request,
/api/device-mgt/windows/v1.0/deviceenrolment/enrollment,
/api/device-mgt/windows/v1.0/management/devicemgt/pending-operations
</param-value>
</context-param>
</web-app>

@ -1,6 +1,6 @@
{{unit "cdmf.unit.device.type.windows.leaflet"}}
{{unit "cdmf.unit.lib.qrcode"}}
{{unit "cdmf.unit.device.type.windows.qr-modal"}}
{{unit "cdmf.unit.device.type.qr-modal"}}
{{#if deviceFound}}
{{#if isAuthorized}}

@ -62,73 +62,6 @@ function onRequest(context) {
viewModel["ownership"] = filteredDeviceData["enrolmentInfo"]["ownership"];
}
}
if (filteredDeviceData["initialDeviceInfo"]) {
viewModel["deviceInfoAvailable"] = true;
if (filteredDeviceData["initialDeviceInfo"]["IMEI"]) {
viewModel["imei"] = filteredDeviceData["initialDeviceInfo"]["IMEI"];
}
if (!filteredDeviceData["latestDeviceInfo"]) {
if (filteredDeviceData["initialDeviceInfo"]["OS_BUILD_DATE"]) {
if (filteredDeviceData["initialDeviceInfo"]["OS_BUILD_DATE"] != "0") {
viewModel["osBuildDate"] = new Date(filteredDeviceData["initialDeviceInfo"]["OS_BUILD_DATE"] * 1000);
}
}
if (filteredDeviceData["initialDeviceInfo"]["LATITUDE"] && filteredDeviceData["initialDeviceInfo"]["LONGITUDE"]) {
viewModel["location"] = {};
viewModel["location"]["latitude"] = filteredDeviceData["initialDeviceInfo"]["LATITUDE"];
viewModel["location"]["longitude"] = filteredDeviceData["initialDeviceInfo"]["LONGITUDE"];
}
if (filteredDeviceData["initialDeviceInfo"]["VENDOR"] && filteredDeviceData["initialDeviceInfo"]["DEVICE_MODEL"]) {
viewModel["vendor"] = filteredDeviceData["initialDeviceInfo"]["VENDOR"];
viewModel["model"] = filteredDeviceData["initialDeviceInfo"]["DEVICE_MODEL"];
}
if (filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]) {
if (deviceType == "android") {
viewModel["BatteryLevel"] = {};
viewModel["BatteryLevel"]["value"] = filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["BATTERY_LEVEL"];
viewModel["internalMemory"] = {};
viewModel["internalMemory"]["total"] = Math.
round(filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["INTERNAL_TOTAL_MEMORY"] * 100) / 100;
if (filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["INTERNAL_TOTAL_MEMORY"] != 0) {
viewModel["internalMemory"]["usage"] = Math.
round((filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["INTERNAL_TOTAL_MEMORY"] -
filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["INTERNAL_AVAILABLE_MEMORY"])
/ filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["INTERNAL_TOTAL_MEMORY"] * 10000) / 100;
} else {
viewModel["internalMemory"]["usage"] = 0;
}
viewModel["externalMemory"] = {};
viewModel["externalMemory"]["total"] = Math.
round(filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["EXTERNAL_TOTAL_MEMORY"] * 100) / 100;
if (filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["EXTERNAL_TOTAL_MEMORY"] != 0) {
viewModel["externalMemory"]["usage"] = Math.
round((filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["EXTERNAL_TOTAL_MEMORY"] -
filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["EXTERNAL_AVAILABLE_MEMORY"])
/ filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["EXTERNAL_TOTAL_MEMORY"] * 10000) / 100;
} else {
viewModel["externalMemory"]["usage"] = 0;
}
} else if (deviceType == "ios") {
viewModel["BatteryLevel"] = {};
viewModel["BatteryLevel"]["value"] = Math. round(filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["BatteryLevel"] * 10000) / 100;
viewModel["internalMemory"] = {};
viewModel["internalMemory"]["total"] = Math.
round(filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["DeviceCapacity"] * 100) / 100;
if (filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["DeviceCapacity"] != 0) {
viewModel["internalMemory"]["usage"] = Math.
round((filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["DeviceCapacity"] -
filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["AvailableDeviceCapacity"])
/ filteredDeviceData["initialDeviceInfo"]["DEVICE_INFO"]["DeviceCapacity"] * 10000) / 100;
} else {
viewModel["internalMemory"]["usage"] = 0;
}
}
}
}
}
if (filteredDeviceData["latestDeviceInfo"]) {
viewModel["deviceInfoAvailable"] = true;
if (filteredDeviceData["latestDeviceInfo"]["osBuildDate"]) {

@ -143,9 +143,10 @@ var windowsOperationModule = function () {
"DISENROLL": "disenroll",
"DEVICE_RING": "ring-device",
"LOCK_RESET": "lock-reset",
"WIPE_DATA": "wipe-data"
"WIPE_DATA": "wipe-data",
"DEVICE_LOCATION": "location",
"DEVICE_REBOOT": "reboot"
};
//return "/mdm-windows-agent/services/windows/operation/" + featureMap[operationCode];
return "/api/device-mgt/windows/v1.0/operation/admin/devices/" + featureMap[operationCode];
};
@ -160,7 +161,9 @@ var windowsOperationModule = function () {
"DEVICE_RING": "fw-dial-up",
"DISENROLL": "fw-export",
"LOCK_RESET": "fw-key",
"WIPE_DATA": "fw-delete"
"WIPE_DATA": "fw-delete",
"DEVICE_LOCATION": "location",
"DEVICE_REBOOT": "fw-refresh"
};
return featureMap[operationCode];
};

@ -32,7 +32,7 @@ parser.getResult();
var os = parser.getOS();
var platform = os.name;
if (platform != "Windows Phone") {
if (platform != "Windows Phone" && platform != "Windows") {
response.sendRedirect(mdmProps["appContext"] + "enrollments/error/unintentional-request");
} else if (session.get("lastAccessedPage") != "login-agent") {
response.sendRedirect(mdmProps["appContext"] + "enrollments/error/unintentional-request");

@ -27,7 +27,7 @@ parser.getResult();
var os = parser.getOS();
var platform = os.name;
if (platform != "Windows Phone") {
if (platform != "Windows Phone" && platform != "Windows") {
response.sendRedirect(mdmProps["appContext"] + "enrollments/error/unintentional-request");
} else if (session.get("lastAccessedPage") != "license-agent") {
response.sendRedirect(mdmProps["appContext"] + "enrollments/error/unintentional-request");

@ -18,7 +18,7 @@ under the License. --}}
{{#zone "accessControl"}}
{{
unit "mdm.unit.enrollments.access-control"
allowedPlatform = "Windows Phone"
allowedPlatform = ["Windows Phone", "Windows"]
currentPage = "invoke-agent"
nextPage = "login-agent"
}}

@ -29,11 +29,7 @@ function onRequest(context) {
parser.getResult();
var userAgentPlatform = parser.getOS()["name"];
if (userAgentPlatform != context.unit.params["allowedPlatform"]) {
// if userAgentPlatform is not allowed
log.error("platform not allowed");
response.sendRedirect(context.app.context + "/enrollments/error/unintentional-request");
} else {
if (context.unit.params["allowedPlatform"].indexOf(userAgentPlatform) !== -1) {
var lastPage = context.unit.params["lastPage"];
var nextPage = context.unit.params["nextPage"];
var currentPage = context.unit.params["currentPage"];
@ -44,9 +40,7 @@ function onRequest(context) {
if (!session.get("lastAccessedPage")) {
// meaning a middle page is accessed at first
response.sendRedirect(context.app.context + "/enrollments/error/unintentional-request");
} else if (!(session.get("lastAccessedPage") == currentPage) &&
!(session.get("lastAccessedPage") == lastPage) &&
!(session.get("lastAccessedPage") == nextPage)) {
} else if (!(session.get("lastAccessedPage") == currentPage) && !(session.get("lastAccessedPage") == lastPage) && !(session.get("lastAccessedPage") == nextPage)) {
response.sendRedirect(context.app.context + "/enrollments/error/unintentional-request");
} else if (currentPage) {
// if currentPage is set, update lastAccessedPage as currentPage
@ -57,8 +51,7 @@ function onRequest(context) {
if (!session.get("lastAccessedPage")) {
// this means the last page is accessed at first
response.sendRedirect(context.app.context + "/enrollments/error/unintentional-request");
} else if (!(session.get("lastAccessedPage") == currentPage) &&
!(session.get("lastAccessedPage") == lastPage)) {
} else if (!(session.get("lastAccessedPage") == currentPage) && !(session.get("lastAccessedPage") == lastPage)) {
response.sendRedirect(context.app.context + "/enrollments/error/unintentional-request");
} else if (currentPage) {
// if currentPage is set, update lastAccessedPage as currentPage
@ -69,6 +62,10 @@ function onRequest(context) {
// if currentPage is set, update lastAccessedPage as currentPage
session.put("lastAccessedPage", currentPage);
}
} else {
// if userAgentPlatform is not allowed
log.error("platform not allowed");
response.sendRedirect(context.app.context + "/enrollments/error/unintentional-request");
}
if (log.isDebugEnabled()) {

@ -24,11 +24,27 @@
<License>
<Language>en_US</Language>
<Version>1.0.0</Version>
<Text>This End User License Agreement ("Agreement") is a legal agreement between you ("You") and WSO2, Inc., regarding the enrollment of Your personal mobile device ("Device") in SoR's mobile device management program, and the loading to and removal from Your Device and Your use of certain applications and any associated software and user documentation, whether provided in "online" or electronic format, used in connection with the operation of or provision of services to WSO2, Inc., BY SELECTING "I ACCEPT" DURING INSTALLATION, YOU ARE ENROLLING YOUR DEVICE, AND THEREBY AUTHORIZING SOR OR ITS AGENTS TO INSTALL, UPDATE AND REMOVE THE APPS FROM YOUR DEVICE AS DESCRIBED IN THIS AGREEMENT. YOU ARE ALSO EXPLICITLY ACKNOWLEDGING AND AGREEING THAT (1) THIS IS A BINDING CONTRACT AND (2) YOU HAVE READ AND AGREE TO THE TERMS OF THIS AGREEMENT.
<Text>This End User License Agreement ("Agreement") is a legal agreement between you ("You") and WSO2, Inc.,
regarding the enrollment of Your personal mobile device ("Device") in SoR's mobile device management
program, and the loading to and removal from Your Device and Your use of certain applications and any
associated software and user documentation, whether provided in "online" or electronic format, used in
connection with the operation of or provision of services to WSO2, Inc.,
BY SELECTING "I ACCEPT" DURING INSTALLATION, YOU ARE ENROLLING YOUR DEVICE,
AND THEREBY AUTHORIZING SOR OR ITS AGENTS TO INSTALL, UPDATE AND REMOVE THE APPS FROM YOUR DEVICE AS
DESCRIBED IN THIS AGREEMENT. YOU ARE ALSO EXPLICITLY ACKNOWLEDGING AND AGREEING THAT (1)
THIS IS A BINDING CONTRACT AND (2) YOU HAVE READ AND AGREE TO THE TERMS OF THIS AGREEMENT.
IF YOU DO NOT ACCEPT THESE TERMS, DO NOT ENROLL YOUR DEVICE AND DO NOT PROCEED ANY FURTHER.
You agree that: (1) You understand and agree to be bound by the terms and conditions contained in this Agreement, and (2) You are at least 21 years old and have the legal capacity to enter into this Agreement as defined by the laws of Your jurisdiction. SoR shall have the right, without prior notice, to terminate or suspend (i) this Agreement, (ii) the enrollment of Your Device, or (iii) the functioning of the Apps in the event of a violation of this Agreement or the cessation of Your relationship with SoR (including termination of Your employment if You are an employee or expiration or termination of Your applicable franchise or supply agreement if You are a franchisee of or supplier to the WSO2 WSO2, Inc., system). SoR expressly reserves all rights not expressly granted herein.
You agree that: (1) You understand and agree to be bound by the terms and conditions
contained in this Agreement, and (2) You are at least 21 years old and have the legal capacity to enter
into this Agreement as defined by the laws of Your jurisdiction. SoR shall have the right,
without prior notice, to terminate or suspend (i) this Agreement, (ii) the enrollment of
Your Device, or (iii) the functioning of the Apps in the event of a violation of this Agreement or
the cessation of Your relationship with SoR (including termination of Your employment
if You are an employee or expiration or termination of Your applicable franchise or supply agreement
if You are a franchisee of or supplier to the WSO2 WSO2, Inc., system). SoR expressly
reserves all rights not expressly granted herein.
</Text>
</License>
@ -64,32 +80,44 @@
<Features>
<Feature code="DISENROLL">
<Name>Disenroll</Name>
<Description>Lock the device</Description>
<Operation context="/api/device-mgt/windows/v1.0/admin/devices/disenroll-devices" method="POST" type="application/json">
<Description>Dis-enrol the device</Description>
<Operation context="/api/device-mgt/windows/v1.0/admin/devices/disenroll-devices" method="POST"
type="application/json">
</Operation>
</Feature>
<Feature code="WIPE_DATA">
<Name>Wipe Data</Name>
<Description>Lock the device</Description>
<Operation context="/api/device-mgt/windows/v1.0/admin/devices/wipe-devices" method="POST" type="application/json">
<Description>Wipe the device</Description>
<Operation context="/api/device-mgt/windows/v1.0/admin/devices/wipe-devices" method="POST"
type="application/json">
</Operation>
</Feature>
<Feature code="DEVICE_RING">
<Name>Ring</Name>
<Description>Lock the device</Description>
<Operation context="/api/device-mgt/windows/v1.0/admin/devices/ring-devices" method="POST" type="application/json">
<Description>Ring the device</Description>
<Operation context="/api/device-mgt/windows/v1.0/admin/devices/ring-devices" method="POST"
type="application/json">
</Operation>
</Feature>
<Feature code="DEVICE_LOCK">
<Name>Device Lock</Name>
<Description>Lock the device</Description>
<Operation context="/api/device-mgt/windows/v1.0/admin/devices/lock-devices" method="POST" type="application/json">
<Operation context="/api/device-mgt/windows/v1.0/admin/devices/lock-devices" method="POST"
type="application/json">
</Operation>
</Feature>
<Feature code="LOCK_RESET">
<Name>Device Lock Reset</Name>
<Description>Lock the device</Description>
<Operation context="/api/device-mgt/windows/v1.0/admin/devices/lock-reset-devices" method="POST" type="application/json">
<Description>Lock Reset the device</Description>
<Operation context="/api/device-mgt/windows/v1.0/admin/devices/lock-reset-devices" method="POST"
type="application/json">
</Operation>
</Feature>
<Feature code="DEVICE_LOCATION">
<Name>Location</Name>
<Description>Request coordinates of device location</Description>
<Operation context="/api/device-mgt/windows/v1.0/admin/devices/location" method="POST"
type="application/json">
</Operation>
</Feature>
<Feature code="DEVICE_INFO">
@ -117,6 +145,10 @@
<Name>DEVICE_INFO</Name>
<RecurrentTimes>1</RecurrentTimes>
</Operation>
<Operation>
<Name>DEVICE_LOCATION</Name>
<RecurrentTimes>1</RecurrentTimes>
</Operation>
</Operations>
</TaskConfiguration>

Loading…
Cancel
Save