Merge pull request #485 from hasuniea/windows10

adding Windows10 operation and policy support
revert-dabc3590
Charitha Goonetilleke 8 years ago committed by GitHub
commit 8b258ce24f

@ -31,6 +31,8 @@ public final class PluginConstants {
"org.wso2.carbon.device.mgt.mobile.windows.api.services.wstep.CertificateEnrollmentService";
public static final String CERTIFICATE_ENROLLMENT_POLICY_SERVICE_ENDPOINT =
"org.wso2.carbon.device.mgt.mobile.windows.api.services.xcep.CertificateEnrollmentPolicyService";
public static final String ENROLLMENT_SERVICE_ENDPOINT =
"org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.EnrollmentService";
//Services' target namespaces
public static final String DISCOVERY_SERVICE_TARGET_NAMESPACE =
@ -81,10 +83,8 @@ public final class PluginConstants {
"/ENROLLMENTSERVER/PolicyEnrollmentWebservice.svc";
public static final String CERTIFICATE_ENROLLMENT_SERVICE_URL =
"/ENROLLMENTSERVER/DeviceEnrollmentWebservice.svc";
public static final String ONPREMISE_CERTIFICATE_ENROLLMENT_POLICY =
"/ENROLLMENTSERVER/ONPREMISE/PolicyEnrollmentWebservice.svc";
public static final String ONPREMISE_CERTIFICATE_ENROLLMENT_SERVICE_URL =
"/ENROLLMENTSERVER/ONPREMISE/DeviceEnrollmentWebservice.svc";
public static final String ENROLLMENT_SERVICE_URL =
"/ENROLLMENTSERVER/Win10DeviceEnrollmentWebservice.svc";
public static final String WAB_URL = "/windows-web-agent/enrollments/windows/login-agent";
}
@ -125,7 +125,6 @@ public final class PluginConstants {
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd#base64binary";
public static final String CA_CERT = "cacert";
public static final String X_509 = "X.509";
public static final String PROPERTIES_XML = "properties.xml";
public static final String WAP_PROVISIONING_XML = "wap-provisioning.xml";
public static final String PROVIDER = "BC";
public static final String ALGORITHM = "SHA1withRSA";
@ -153,6 +152,9 @@ public final class PluginConstants {
public static final int DOMAIN_POSITION = 7;
public static final String ENROLL_SUBDOMAIN = "https://EnterpriseEnrollment.";
public static final String SYNCML_PROVISIONING_SERVICE_URL = "/Syncml/initialquery";
public static final String SYNCML_PROVISIONING_WIN10_SERVICE_URL = "/devicemgt";
public static final String ENROLLMENT_DISPOSITION_MESSAGE = "http://schemas.microsoft.com/windows/pki/" +
"2009/01/enrollment";
}
/**
@ -205,6 +207,18 @@ public final class PluginConstants {
public static final String MANUFACTURER = "MANUFACTURER";
public static final String LANGUAGE = "LANGUAGE";
public static final String RESOLUTION = "RESOLUTION";
// windows 10 codes
public static final String TOTAL_RAM = "TOTAL_RAM";// available ram in MB
public static final String TOTAL_STORAGE = "TOTAL_STORAGE";
public static final String OS_PLATFORM = "OS_PLATFORM";
public static final String DEVICE_TYPE = "DEVICE_TYPE";
public static final String BATTERY_QUERY = "BATTERY_QUERY";
public static final String BATTERY_STATUS = "BATTERY_STATUS";
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";
}
/**
@ -252,6 +266,7 @@ public final class PluginConstants {
public static final String ENCRYPT_STORAGE_STATUS = "ENCRYPT_STORAGE_STATUS";
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";
}
/**
@ -289,7 +304,6 @@ public final class PluginConstants {
public static final String DEFAULT_AUTH_POLICY = "Federated";
}
/**
* Policy Configuration related constants.
*/
@ -311,4 +325,31 @@ public final class PluginConstants {
public static final String MAX_CONNECTION_PER_HOST = "MaxConnectionsPerHost";
public static final String MAX_TOTAL_CONNECTIONS = "MaxTotalConnections";
}
/**
* Windows version(8.1/10) related constants.
*/
public final class WindowsVersionProperties {
private WindowsVersionProperties() {
throw new AssertionError();
}
public static final String REQUESTED_WIN10_VERSION = "3.0";
public static final String REQUESTED_WIN81_VERSION = "2.0";
}
/**
* Windows enrollment property constants.
*/
public final class WindowsEnrollmentProperties {
private WindowsEnrollmentProperties() {
throw new AssertionError();
}
public static final int WIN_DEVICE_ID = 12;
public static final int WIN_DEVICE_NAME = 2;
public static final int WIN_DEVICE_VERSION = 15;
public static final int WIN_DEVICE_IMEI = 3;
}
}

@ -28,10 +28,13 @@ import org.wso2.carbon.device.mgt.common.DeviceManagementException;
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.notification.mgt.NotificationManagementService;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
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.core.device.details.mgt.DeviceInformationManager;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.beans.ErrorResponse;
@ -222,4 +225,18 @@ public class WindowsAPIUtils {
return null;
}
}
/**
* This method is used to update Device Information.
* @param deviceId DeviceID to need to update.
* @param deviceInfo Device Info to be update/
* @throws DeviceDetailsMgtException Error occurs while updating Device Info.
*/
public static void updateDeviceInfo(DeviceIdentifier deviceId, DeviceInfo deviceInfo)
throws DeviceDetailsMgtException {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceInformationManager informationManager =
(DeviceInformationManager) ctx.getOSGiService(DeviceInformationManager.class, null);
informationManager.addDeviceInfo(deviceId, deviceInfo);
}
}

@ -27,6 +27,7 @@ public class Constants {
public static final String INITIAL_NONCE = "ZHVtbXk=";
public static final String DISENROLL_ALERT_DATA = "1226";
public static final String INITIAL_ALERT_DATA = "1201";
public static final String INITIAL_WIN10_ALERT_DATA = "1224";
public static final int EMPTY = 0;
public static final String SYNCML_ROOT_ELEMENT_NAME = "SyncML";

@ -0,0 +1,90 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.operations.util;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import java.util.ArrayList;
import java.util.List;
public class HeartBeatDeviceInfo {
public List<Operation> getDeviceInfo() {
List<Operation> deviceInfoOperations = new ArrayList<>();
Operation osVersion = new Operation();
osVersion.setCode(PluginConstants.SyncML.SOFTWARE_VERSION);
deviceInfoOperations.add(osVersion);
Operation imsi = new Operation();
imsi.setCode(PluginConstants.SyncML.IMSI);
deviceInfoOperations.add(imsi);
Operation imei = new Operation();
imei.setCode(PluginConstants.SyncML.IMEI);
deviceInfoOperations.add(imei);
Operation deviceID = new Operation();
deviceID.setCode(PluginConstants.SyncML.DEV_ID);
deviceInfoOperations.add(deviceID);
Operation manufacturer = new Operation();
manufacturer.setCode(PluginConstants.SyncML.MANUFACTURER);
deviceInfoOperations.add(manufacturer);
Operation model = new Operation();
model.setCode(PluginConstants.SyncML.MODEL);
deviceInfoOperations.add(model);
Operation language = new Operation();
language.setCode(PluginConstants.SyncML.LANGUAGE);
deviceInfoOperations.add(language);
Operation vendor = new Operation();
vendor.setCode(PluginConstants.SyncML.VENDOR);
deviceInfoOperations.add(vendor);
Operation macaddress = new Operation();
macaddress.setCode(PluginConstants.SyncML.MAC_ADDRESS);
deviceInfoOperations.add(macaddress);
Operation resolution = new Operation();
resolution.setCode(PluginConstants.SyncML.RESOLUTION);
deviceInfoOperations.add(resolution);
Operation deviceName = new Operation();
deviceName.setCode(PluginConstants.SyncML.DEVICE_NAME);
deviceInfoOperations.add(deviceName);
Operation totalRam = new Operation();
totalRam.setCode(PluginConstants.SyncML.TOTAL_RAM);
deviceInfoOperations.add(totalRam);
Operation availableStorage = new Operation();
availableStorage.setCode(PluginConstants.SyncML.TOTAL_STORAGE);
deviceInfoOperations.add(availableStorage);
Operation remainingBattery = new Operation();
remainingBattery.setCode(PluginConstants.SyncML.BATTERY_CHARGE_REMAINING);
deviceInfoOperations.add(remainingBattery);
return deviceInfoOperations;
}
}

@ -44,8 +44,19 @@ public class OperationCode {
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");
LATITUDE("./Vendor/MSFT/RemoteFind/Location/Latitude"),
// Windows10 operation codes
TOTAL_RAM("./DevDetail/Ext/Microsoft/TotalRAM"),
TOTAL_STORAGE("./DevDetail/Ext/Microsoft/TotalStorage"),
OS_PLATFORM("./DevDetail/Ext/Microsoft/OSPlatform"),
MOBILE_ID("./DevDetail/Ext/Microsoft/MobileID"),
DEVICE_TYPE("./DevDetail/DevTyp"),
BATTERY_QUERY("./Vendor/MSFT/DeviceStatus/Battery"),
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");
private final String code;
Info(String code) {
@ -69,7 +80,18 @@ public class OperationCode {
CAMERA_STATUS("./Vendor/MSFT/PolicyManager/Device/Camera/AllowCamera"),
ENCRYPT_STORAGE_STATUS("./Vendor/MSFT/PolicyManager/Device/Security/RequireDeviceEncryption"),
DEVICE_PASSWORD_ENABLE("./Vendor/MSFT/PolicyManager/My/DeviceLock/DevicePasswordEnabled"),
DEVICE_PASSCODE_DELETE("./Vendor/MSFT/PolicyManager/My/DeviceLock");
DEVICE_PASSCODE_DELETE("./Vendor/MSFT/PolicyManager/My/DeviceLock"),
// Windows10 operation codes
TOTAL_RAM("./DevDetail/Ext/Microsoft/TotalRAM"),
TOTAL_STORAGE("./DevDetail/Ext/Microsoft/TotalStorage"),
OS_PLATFORM("./DevDetail/Ext/Microsoft/OSPlatform"),
MOBILE_ID("./DevDetail/Ext/Microsoft/MobileID"),
DEVICE_TYPE("./DevDetail/DevTyp"),
BATTERY_QUERY("./Vendor/MSFT/DeviceStatus/Battery"),
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");
private final String code;

@ -24,6 +24,7 @@ import org.json.JSONException;
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.notification.mgt.Notification;
import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementException;
import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementService;
@ -87,7 +88,7 @@ public class OperationHandler {
Notification lockResetNotification = new Notification();
lockResetNotification.setOperationId(status.getCommandReference());
lockResetNotification.setStatus(String.valueOf(Notification.Status.NEW));
// lockResetNotification.setDeviceIdentifier(deviceIdentifier);
lockResetNotification.setDescription(
Constants.SyncMLResponseCodes.LOCK_RESET_NOTIFICATION);
nmService.addNotification(deviceIdentifier, lockResetNotification);
@ -152,7 +153,6 @@ public class OperationHandler {
Notification lockResetNotification = new Notification();
lockResetNotification.setOperationId(status.getCommandReference());
lockResetNotification.setStatus(String.valueOf(Notification.Status.NEW));
// lockResetNotification.setDeviceIdentifier(deviceIdentifier);
lockResetNotification.setDescription(Constants.SyncMLResponseCodes.LOCK_RESET_NOTIFICATION);
nmService.addNotification(deviceIdentifier, lockResetNotification);
@ -166,7 +166,7 @@ public class OperationHandler {
}
}
/***
/**
* Update status of the ring operation.
*
* @param status Ring status of the device.
@ -194,7 +194,7 @@ public class OperationHandler {
}
}
/***
/**
* Update the status of the DataWipe operation.
*
* @param status Status of the data wipe.
@ -223,6 +223,23 @@ public class OperationHandler {
}
}
public void updateDeviceInfoStatus(DeviceIdentifier deviceIdentifier) throws OperationManagementException {
List<? extends Operation> pendingDeviceInfoOperations;
try {
pendingDeviceInfoOperations = WindowsAPIUtils.getPendingOperations(deviceIdentifier);
} catch (DeviceManagementException e) {
throw new OperationManagementException("Error occurred while getting pending operations.");
}
for (Operation operation : pendingDeviceInfoOperations) {
if (PluginConstants.OperationCodes.DEVICE_INFO.equals(operation.getCode())) {
operation.setStatus(Operation.Status.COMPLETED);
updateStatus(deviceIdentifier.getId(), pendingDeviceInfoOperations);
}
}
}
/**
* Get pending operations.
*
@ -232,13 +249,20 @@ public class OperationHandler {
*/
public List<? extends Operation> getPendingOperations(SyncmlDocument syncmlDocument)
throws OperationManagementException, WindowsOperationException {
SyncmlHeader syncmlHeader = syncmlDocument.getHeader();
SyncmlBody syncmlBody = syncmlDocument.getBody();
List<? extends Operation> pendingOperations;
DeviceIdentifier deviceIdentifier = convertToDeviceIdentifierObject(
syncmlDocument.getHeader().getSource().getLocURI());
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)) {
if ((syncmlBody.getResults() != null)) {
updateDeviceInfo(syncmlDocument);
}
}
UpdateUriOperations(syncmlDocument);
generateComplianceFeatureStatus(syncmlDocument);
pendingOperations = WindowsAPIUtils.getDeviceManagementService().getPendingOperations(deviceIdentifier);
return pendingOperations;
}
@ -487,4 +511,61 @@ public class OperationHandler {
}
}
public void updateDeviceInfo(SyncmlDocument syncmlDocument) throws WindowsOperationException {
String softwareVersion;
String imsi;
String imei;
String model;
String vendor;
String totalRAM;
String deviceID = null;
String totalStorage;
List<ItemTag> deviceInformations = syncmlDocument.getBody().getResults().getItem();
DeviceInfo deviceInfo = new DeviceInfo();
for (ItemTag item : deviceInformations) {
String source = item.getSource().getLocURI();
if (OperationCode.Info.SOFTWARE_VERSION.getCode().equals(source)) {
softwareVersion = item.getData();
deviceInfo.setOsVersion(softwareVersion);
}
if (OperationCode.Info.IMSI.getCode().equals(source)) {
imsi = item.getData();
deviceInfo.setIMSI(imsi);
}
if (OperationCode.Info.IMEI.getCode().equals(source)) {
imei = item.getData();
deviceInfo.setIMEI(imei);
}
if (OperationCode.Info.DEVICE_MODEL.getCode().equals(source)) {
model = item.getData();
deviceInfo.setDeviceModel(model);
}
if (OperationCode.Info.VENDOR.getCode().equals(source)) {
vendor = item.getData();
deviceInfo.setVendor(vendor);
}
if (OperationCode.Info.TOTAL_RAM.getCode().equals(source)) {
totalRAM = item.getData();
deviceInfo.setAvailableRAMMemory(Double.parseDouble(totalRAM));
}
if (OperationCode.Info.TOTAL_STORAGE.getCode().equals(source)) {
totalStorage = item.getData();
deviceInfo.setInternalAvailableMemory(Double.parseDouble(totalStorage));
}
if (OperationCode.Info.DEV_ID.getCode().equals(source)) {
deviceID = item.getData();
}
}
DeviceIdentifier deviceIdentifier = convertToDeviceIdentifierObject(deviceID);
try {
WindowsAPIUtils.updateDeviceInfo(deviceIdentifier, deviceInfo);
updateDeviceInfoStatus(deviceIdentifier);
} catch (org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceDetailsMgtException e) {
throw new WindowsOperationException("Error occurred while adding Device info.");
} catch (OperationManagementException e) {
throw new WindowsOperationException("Error occurred while updating Device info operation status.");
}
}
}

@ -70,6 +70,36 @@ public class OperationReply {
replySyncmlDocument = new SyncmlDocument();
}
public OperationReply() {
}
/**
* Generate Device payloads.
*
* @param syncmlDocument Parsed syncml payload from the syncml engine.
* @param operations Operations for generate payload.
* @return String type syncml payload.
* @throws WindowsOperationException
* @throws PolicyManagementException
* @throws org.wso2.carbon.policy.mgt.common.FeatureManagementException
*/
public String generateReply(SyncmlDocument syncmlDocument, List<? extends Operation> operations)
throws SyncmlMessageFormatException, SyncmlOperationException {
OperationReply operationReply;
SyncmlGenerator generator;
SyncmlDocument syncmlResponse;
if (operations == null) {
operationReply = new OperationReply(syncmlDocument);
} else {
operationReply = new OperationReply(syncmlDocument, operations);
}
syncmlResponse = operationReply.generateReply();
generator = new SyncmlGenerator();
return generator.generatePayload(syncmlResponse);
}
public SyncmlDocument generateReply() throws SyncmlMessageFormatException, SyncmlOperationException {
generateHeader();
generateBody();
@ -199,8 +229,8 @@ public class OperationReply {
}
private void appendOperations(SyncmlBody syncmlBody) throws PolicyManagementException,
FeatureManagementException, JSONException,
SyncmlOperationException {
FeatureManagementException, JSONException, SyncmlOperationException {
GetTag getElement = new GetTag();
List<ItemTag> getElements = new ArrayList<>();
List<ExecuteTag> executeElements = new ArrayList<>();
@ -209,6 +239,7 @@ public class OperationReply {
ReplaceTag replaceElement = new ReplaceTag();
List<ItemTag> replaceItems = new ArrayList<>();
SequenceTag monitorSequence = new SequenceTag();
List<Operation> deviceInfoOperations;
if (operations != null) {
for (Operation operation : operations) {
@ -216,8 +247,10 @@ public class OperationReply {
switch (type) {
case POLICY:
if (this.syncmlDocument.getBody().getAlert() != null) {
if ((Constants.INITIAL_ALERT_DATA.equals(this.syncmlDocument.getBody()
.getAlert().getData()))) {
if ((Constants.INITIAL_ALERT_DATA.equals(this.syncmlDocument.getBody().getAlert()
.getData())) || Constants.INITIAL_WIN10_ALERT_DATA.
equals(this.syncmlDocument.getBody()
.getAlert().getData())) {
SequenceTag policySequence = new SequenceTag();
policySequence = buildSequence(operation, policySequence);
syncmlBody.setSequence(policySequence);
@ -288,6 +321,20 @@ public class OperationReply {
}
}
}
if (PluginConstants.OperationCodes.DEVICE_INFO.equals(operation.getCode())) {
if (this.syncmlDocument.getBody().getAlert() != null) {
if ((Constants.INITIAL_ALERT_DATA.equals(this.syncmlDocument.getBody().getAlert()
.getData())) || Constants.INITIAL_WIN10_ALERT_DATA.
equals(this.syncmlDocument.getBody()
.getAlert().getData())) {
HeartBeatDeviceInfo heartBeatDeviceInfo = new HeartBeatDeviceInfo();
deviceInfoOperations = heartBeatDeviceInfo.getDeviceInfo();
for (Operation infoOperation : deviceInfoOperations) {
ItemTag deviceInfo = appendGetInfo(infoOperation);
getElements.add(deviceInfo);
}
}
}
break;
}
}
@ -309,6 +356,7 @@ public class OperationReply {
syncmlBody.setAtomicTag(atomicTagElement);
syncmlBody.setReplace(replaceElement);
}
}
private ItemTag appendExecInfo(Operation operation) {
ItemTag item = new ItemTag();

@ -66,8 +66,8 @@ import javax.ws.rs.core.Response;
description = "This carries all the resources related to Windows configurations management functionalities")
@WebService
@Path("/configuration")
@Produces({"application/json", "application/xml"})
@Consumes({"application/json", "application/xml"})
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public interface ConfigurationMgtService {
@GET

@ -36,8 +36,7 @@ import java.util.List;
/**
* Interface for Admin operations persisting. This interface accepts operations added via UI.
*/
@Api(value = "Windows Device Management Administrative Service",
description = "Device management related admin APIs.")
@SwaggerDefinition(
info = @Info(
@ -56,10 +55,12 @@ import java.util.List;
@Tag(name = "devicemgt_windows", description = "")
}
)
@Api(value = "Windows Device Management Administrative Service",
description = "Device management related admin APIs.")
@WebService
@Path("/admin/devices")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/operation/admin/devices")
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public interface DeviceManagementAdminService {
@POST
@ -367,7 +368,6 @@ public interface DeviceManagementAdminService {
message = "Internal Server Error. \n " +
"Server error occurred while adding adding a lock-reset operation.")
})
//
Response lockReset(@HeaderParam("Accept") String acceptHeader, @ApiParam(
name = "deviceIDs",
value = "Provide the ID of the A Windows device. Multiple device IDs can be added by " +

@ -0,0 +1,122 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.services;
import io.swagger.annotations.*;
import org.w3c.dom.Document;
import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsConfigurationException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsDeviceEnrolmentException;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.WindowsOperationException;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* Interface for Syncml message flow.
*/
@SwaggerDefinition(
info = @Info(
version = "1.0.0",
title = "",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "Syncml Endpoint"),
@ExtensionProperty(name = "context",
value = "/api/device-mgt/windows/v1.0/syncmlmgt"),
})
}
),
tags = {
@Tag(name = "devicemgt_windows", description = "")
}
)
@Api(value = "Windows syncml service to initialize management session",
description = "This carries all the resources related to Windows syncml message flow.")
@Path("/devicemgt")
public interface DeviceManagementService {
@Path("/pending-operations")
@POST
@Consumes({PluginConstants.SYNCML_MEDIA_TYPE, MediaType.APPLICATION_XML})
@Produces(PluginConstants.SYNCML_MEDIA_TYPE)
@ApiOperation(
httpMethod = "POST",
value = "Getting pending operations for Windows device.",
notes = "Using this API to fetching more information to enroll the Device and " +
"getting pending operations.",
tags = "Windows Device Management Administrative Service",
authorizations = {
@Authorization(
value = "permission",
scopes = {@AuthorizationScope(
scope = "/device-mgt/devices/enroll/windows",
description = "Getting pending operations and " +
"device information to enroll the device")}
)
}
)
@ApiResponses(value = {
@ApiResponse(
code = 201,
message = "Ok. \n Successfully getting pending operations.",
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 getting pending operations.")
})
Response getResponse(Document request) throws WindowsDeviceEnrolmentException, WindowsOperationException,
NotificationManagementException, WindowsConfigurationException;
}

@ -18,47 +18,46 @@
package org.wso2.carbon.device.mgt.mobile.windows.api.services.discovery.beans;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.*;
import java.io.Serializable;
import java.util.List;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "DiscoveryRequest")
@ApiModel(value = "DiscoveryRequest",
description = "Discover request related information.")
@XmlType(name = "DiscoveryRequest", namespace = "http://schemas.microsoft.com/windows/management/2012/01/enrollment")
@SuppressWarnings("unused")
public class DiscoveryRequest implements Serializable {
@ApiModelProperty(name = "emailId", value = "User email address which is submitted to the workplace app" +
" once sign in .", required = true)
@XmlElement(name = "EmailAddress", required = true)
private String emailId;
@ApiModelProperty(name = "version", value = "OS version on the Windows Device.", required = true)
@XmlElement(name = "RequestVersion")
private String version;
@ApiModelProperty(name = "deviceType", value = "Type of the Device(LapTop/Mobile Device).", required = true)
@XmlElement(name = "DeviceType")
private String deviceType;
@XmlElement(name = "OSEdition")
private String osEdition;
@XmlElement(name = "ApplicationVersion")
private String applicationVersion;
@XmlElementWrapper(name = "AuthPolicies")
@XmlElement(name = "AuthPolicy", required = true)
private List<String> authenticationPolicies;
public String getEmailId() {
return emailId;
}
public String getVersion() {
return version;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
@ -70,4 +69,21 @@ public class DiscoveryRequest implements Serializable {
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
public List<String> getAuthenticationPolicies() {
return authenticationPolicies;
}
public void setAuthenticationPolicies(List<String> authenticationPolicies) {
this.authenticationPolicies = authenticationPolicies;
}
public String getOsEdition() {
return osEdition;
}
public void setOsEdition(String osEdition) {
this.osEdition = osEdition;
}
}

@ -41,6 +41,9 @@ public class DiscoveryResponse implements Serializable {
@XmlElement(name = "AuthenticationServiceUrl")
private String authenticationServiceUrl;
@XmlElement(name = "EnrollmentVersion")
private String enrollmentVersion;
public void setAuthenticationServiceUrl(String authenticationServiceUrl) {
this.authenticationServiceUrl = authenticationServiceUrl;
}
@ -73,4 +76,12 @@ public class DiscoveryResponse implements Serializable {
this.enrollmentServiceUrl = enrollmentServiceUrl;
}
public String getEnrollmentVersion() {
return enrollmentVersion;
}
public void setEnrollmentVersion(String enrollmentVersion) {
this.enrollmentVersion = enrollmentVersion;
}
}

@ -68,9 +68,23 @@ public class DiscoveryServiceImpl implements DiscoveryService {
String emailId = discoveryRequest.getEmailId();
String[] userDomains = emailId.split(DELIMITER);
String domain = userDomains[DOMAIN_SEGMENT];
DiscoveryResponse discoveryResponse;
if (PluginConstants.WindowsVersionProperties.REQUESTED_WIN10_VERSION.equals(discoveryRequest.getVersion()) &&
FEDERATED.equals(getAuthPolicy())) {
discoveryResponse = new DiscoveryResponse();
DiscoveryResponse discoveryResponse = new DiscoveryResponse();
if (FEDERATED.equals(getAuthPolicy())) {
discoveryResponse.setAuthPolicy(FEDERATED);
discoveryResponse.setEnrollmentVersion(PluginConstants.WindowsVersionProperties.REQUESTED_WIN10_VERSION);
discoveryResponse.setEnrollmentPolicyServiceUrl(PluginConstants.Discovery.DEVICE_ENROLLMENT_SUBDOMAIN +
domain + PluginConstants.Discovery.
CERTIFICATE_ENROLLMENT_POLICY_SERVICE_URL);
discoveryResponse.setEnrollmentServiceUrl(PluginConstants.Discovery.DEVICE_ENROLLMENT_SUBDOMAIN +
domain + PluginConstants.Discovery.
ENROLLMENT_SERVICE_URL);
discoveryResponse.setAuthenticationServiceUrl(PluginConstants.Discovery.DEVICE_ENROLLMENT_SUBDOMAIN +
domain + PluginConstants.Discovery.WAB_URL);
} else {
discoveryResponse = new DiscoveryResponse();
discoveryResponse.setAuthPolicy(FEDERATED);
discoveryResponse.setEnrollmentPolicyServiceUrl(PluginConstants.Discovery.DEVICE_ENROLLMENT_SUBDOMAIN +
domain + PluginConstants.Discovery.

@ -0,0 +1,61 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment;
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;
import org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.beans.AdditionalContext;
import org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.beans.RequestSecurityTokenResponse;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
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;
@WebService(targetNamespace = PluginConstants.DEVICE_ENROLLMENT_SERVICE_TARGET_NAMESPACE, name = "enrollment")
@BindingType(value = SOAPBinding.SOAP12HTTP_BINDING)
public interface EnrollmentService {
@RequestWrapper(localName = "RequestSecurityToken", targetNamespace = PluginConstants
.WS_TRUST_TARGET_NAMESPACE)
@WebMethod(operationName = "RequestSecurityToken")
@ResponseWrapper(localName = "RequestSecurityTokenResponseCollection", targetNamespace =
PluginConstants.WS_TRUST_TARGET_NAMESPACE)
void requestSecurityToken(
@WebParam(name = "TokenType", targetNamespace = PluginConstants.WS_TRUST_TARGET_NAMESPACE)
String tokenType,
@WebParam(name = "RequestType", targetNamespace = PluginConstants.WS_TRUST_TARGET_NAMESPACE)
String requestType,
@WebParam(name = "BinarySecurityToken", targetNamespace = PluginConstants
.WS_SECURITY_TARGET_NAMESPACE)
String binarySecurityToken,
@WebParam(name = "AdditionalContext", targetNamespace = PluginConstants
.SOAP_AUTHORIZATION_TARGET_NAMESPACE)
AdditionalContext additionalContext,
@WebParam(mode = WebParam.Mode.OUT, name = "RequestSecurityTokenResponse",
targetNamespace = PluginConstants.WS_TRUST_TARGET_NAMESPACE)
javax.xml.ws.Holder<RequestSecurityTokenResponse> response) throws
WindowsDeviceEnrolmentException, UnsupportedEncodingException,
WAPProvisioningException;
}

@ -0,0 +1,48 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.beans;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import java.util.ArrayList;
import java.util.List;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "OIDCollection", namespace = PluginConstants.SOAP_AUTHORIZATION_TARGET_NAMESPACE,
propOrder = {"contextitem"})
@SuppressWarnings("unused")
public class AdditionalContext {
@XmlElement(name = "ContextItem", required = true,
namespace = PluginConstants.SOAP_AUTHORIZATION_TARGET_NAMESPACE)
protected List<ContextItem> contextitem;
public List<ContextItem> getcontextitem() {
if (contextitem == null) {
contextitem = new ArrayList<ContextItem>();
}
return this.contextitem;
}
}

@ -0,0 +1,63 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.beans;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BinarySecurityToken", namespace = PluginConstants.WS_SECURITY_TARGET_NAMESPACE,
propOrder = {"ValueType", "EncodingType"})
@SuppressWarnings("unused")
public class BinarySecurityToken {
@XmlAttribute(name = "ValueType")
protected String ValueType;
@XmlAttribute(name = "EncodingType")
protected String EncodingType;
@XmlValue
protected String Token;
public void setValueType(String valuetype) {
this.ValueType = valuetype;
}
public String getValueType() {
return this.ValueType;
}
public void setEncodingType(String encodingtype) {
this.EncodingType = encodingtype;
}
public String getEncodingType() {
return this.EncodingType;
}
public void setToken(String token) {
this.Token = token;
}
public String getToken() {
return this.Token;
}
}

@ -0,0 +1,54 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.beans;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import javax.xml.bind.annotation.XmlAccessType;
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"})
public class ContextItem {
@XmlElement(required = true, namespace = PluginConstants.SOAP_AUTHORIZATION_TARGET_NAMESPACE)
protected String Name;
@XmlElement(required = true, namespace = PluginConstants.SOAP_AUTHORIZATION_TARGET_NAMESPACE)
protected String Value;
public String getValue() {
return Value;
}
public void setValue(String value) {
Value = value;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
}

@ -0,0 +1,42 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.beans;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "RequestedSecurityToken", namespace = PluginConstants.WS_TRUST_TARGET_NAMESPACE,
propOrder = {"binarySecurityToken"})
@SuppressWarnings("unused")
public class RequestSecurityToken {
@XmlElement(name = "BinarySecurityToken", required = true,
namespace = PluginConstants.WS_SECURITY_TARGET_NAMESPACE)
protected BinarySecurityToken binarySecurityToken;
public void setBinarySecurityToken(BinarySecurityToken binarysecuritytoken) {
this.binarySecurityToken = binarysecuritytoken;
}
}

@ -0,0 +1,82 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.beans;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
import java.io.Serializable;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "RequestSecurityTokenResponse", namespace = PluginConstants.WS_TRUST_TARGET_NAMESPACE,
propOrder = {"TokenType", "DispositionMessage", "RequestedSecurityToken", "RequestID"})
@SuppressWarnings("unused")
public class RequestSecurityTokenResponse implements Serializable {
@XmlElement(name = "TokenType", namespace = PluginConstants.WS_TRUST_TARGET_NAMESPACE)
private String TokenType;
// Windows 10 property
@XmlElement(name = "DispositionMessage", namespace = PluginConstants.ENROLLMENT_POLICY_TARGET_NAMESPACE)
private String DispositionMessage;
@XmlElement(name = "RequestedSecurityToken", required = true,
namespace = PluginConstants.WS_TRUST_TARGET_NAMESPACE)
private org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.beans.RequestedSecurityToken RequestedSecurityToken;
@XmlElement(name = "RequestID", namespace = PluginConstants.ENROLLMENT_POLICY_TARGET_NAMESPACE)
private int RequestID;
public String getTokenType() {
return TokenType;
}
public void setTokenType(String tokenType) {
TokenType = tokenType;
}
public org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.beans.RequestedSecurityToken getRequestedSecurityToken() {
return RequestedSecurityToken;
}
public void setRequestedSecurityToken(org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.beans.RequestedSecurityToken
requestedSecurityToken) {
RequestedSecurityToken = requestedSecurityToken;
}
public int getRequestID() {
return RequestID;
}
public void setRequestID(int requestID) {
RequestID = requestID;
}
public String getDispositionMessage() {
return DispositionMessage;
}
public void setDispositionMessage(String dispositionMessage) {
DispositionMessage = dispositionMessage;
}
}

@ -0,0 +1,42 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.beans;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "RequestedSecurityToken", namespace = PluginConstants.WS_TRUST_TARGET_NAMESPACE,
propOrder = {"binarySecurityToken"})
public class RequestedSecurityToken {
@XmlElement(name = "BinarySecurityToken", required = true,
namespace = PluginConstants.WS_SECURITY_TARGET_NAMESPACE)
protected BinarySecurityToken binarySecurityToken;
public void setBinarySecurityToken(BinarySecurityToken binarysecuritytoken) {
this.binarySecurityToken = binarysecuritytoken;
}
}

@ -0,0 +1,27 @@
/*
* 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.
*/
@XmlSchema(namespace = "http://www.w3.org/2003/05/soap-envelope",
xmlns = {
@XmlNs(prefix = "", namespaceURI = "http://www.w3.org/2003/05/soap-envelope")
}, elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.beans;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlSchema;

@ -0,0 +1,433 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.impl;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.CastUtils;
import org.apache.cxf.jaxws.context.WrappedMessageContext;
import org.apache.cxf.message.Message;
import org.w3c.dom.*;
import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException;
import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementServiceImpl;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.*;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.beans.CacheEntry;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.CertificateGenerationException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.SyncmlMessageFormatException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WAPProvisioningException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsDeviceEnrolmentException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.DeviceUtil;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.WindowsAPIUtils;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.util.SyncmlCredentialUtil;
import org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.EnrollmentService;
import org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.beans.*;
import org.wso2.carbon.device.mgt.mobile.windows.api.services.syncml.beans.WindowsDevice;
import org.wso2.carbon.policy.mgt.common.PolicyManagementException;
import org.wso2.carbon.policy.mgt.core.PolicyManagerService;
import org.xml.sax.SAXException;
import javax.annotation.Resource;
import javax.jws.WebService;
import javax.servlet.ServletContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.ws.BindingType;
import javax.xml.ws.Holder;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.soap.Addressing;
import javax.xml.ws.soap.SOAPBinding;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
/**
* Implementation class of Windows10 Enrollment process.
*/
@WebService(endpointInterface = PluginConstants.ENROLLMENT_SERVICE_ENDPOINT,
targetNamespace = PluginConstants.DEVICE_ENROLLMENT_SERVICE_TARGET_NAMESPACE)
@Addressing(enabled = true, required = true)
@BindingType(value = SOAPBinding.SOAP12HTTP_BINDING)
public class EnrollmentServiceImpl implements EnrollmentService {
private static Log log = LogFactory.getLog(EnrollmentServiceImpl.class);
private X509Certificate rootCACertificate;
private String pollingFrequency;
private String provisioningURL;
private String domain;
@Resource
private WebServiceContext context;
@Override
public void requestSecurityToken(String tokenType, String requestType, String binarySecurityToken,
AdditionalContext additionalContext,
Holder<RequestSecurityTokenResponse> response)
throws WindowsDeviceEnrolmentException, UnsupportedEncodingException, WAPProvisioningException {
String headerBinarySecurityToken = null;
String headerTo = null;
String encodedWap;
List<Header> headers = getHeaders();
for (Header headerElement : headers != null ? headers : null) {
String nodeName = headerElement.getName().getLocalPart();
if (PluginConstants.SECURITY.equals(nodeName)) {
Element element = (Element) headerElement.getObject();
headerBinarySecurityToken = element.getFirstChild().getFirstChild().getTextContent();
}
if (PluginConstants.TO.equals(nodeName)) {
Element toElement = (Element) headerElement.getObject();
headerTo = toElement.getFirstChild().getTextContent();
}
}
try {
enrollDevice(additionalContext, headerBinarySecurityToken);
} catch (DeviceManagementException e) {
throw new WindowsDeviceEnrolmentException("Error occurred while enrolling the device.");
} catch (PolicyManagementException e) {
throw new WindowsDeviceEnrolmentException("Error occurred while enforcing windows policies.");
}
String[] splitEmail = headerTo.split("(/ENROLLMENTSERVER)");
String email = splitEmail[PluginConstants.CertificateEnrolment.EMAIL_SEGMENT];
String[] splitDomain = email.split("(EnterpriseEnrollment.)");
domain = splitDomain[PluginConstants.CertificateEnrolment.DOMAIN_SEGMENT];
provisioningURL = PluginConstants.CertificateEnrolment.ENROLL_SUBDOMAIN + domain +
PluginConstants.CertificateEnrolment.SYNCML_PROVISIONING_WIN10_SERVICE_URL;
List<ConfigurationEntry> tenantConfigurations;
try {
if ((tenantConfigurations = WindowsAPIUtils.getTenantConfigurationData()) != null) {
for (ConfigurationEntry configurationEntry : tenantConfigurations) {
if ((PluginConstants.TenantConfigProperties.NOTIFIER_FREQUENCY.equals(
configurationEntry.getName()))) {
pollingFrequency = configurationEntry.getValue().toString();
} else {
pollingFrequency = PluginConstants.TenantConfigProperties.DEFAULT_FREQUENCY;
}
}
} else {
pollingFrequency = PluginConstants.TenantConfigProperties.DEFAULT_FREQUENCY;
String msg = "Tenant configurations are not initialized yet.";
log.error(msg);
}
ServletContext ctx = (ServletContext) context.getMessageContext().
get(MessageContext.SERVLET_CONTEXT);
File wapProvisioningFile = (File) ctx.getAttribute(PluginConstants.CONTEXT_WAP_PROVISIONING_FILE);
if (log.isDebugEnabled()) {
log.debug("Received CSR from Device:" + binarySecurityToken);
}
String wapProvisioningFilePath = wapProvisioningFile.getPath();
RequestSecurityTokenResponse requestSecurityTokenResponse = new RequestSecurityTokenResponse();
requestSecurityTokenResponse.setTokenType(PluginConstants.CertificateEnrolment.TOKEN_TYPE);
encodedWap = prepareWapProvisioningXML(binarySecurityToken, wapProvisioningFilePath,
headerBinarySecurityToken);
RequestedSecurityToken requestedSecurityToken = new RequestedSecurityToken();
BinarySecurityToken binarySecToken = new BinarySecurityToken();
binarySecToken.setValueType(PluginConstants.CertificateEnrolment.VALUE_TYPE);
binarySecToken.setEncodingType(PluginConstants.CertificateEnrolment.ENCODING_TYPE);
binarySecToken.setToken(encodedWap);
requestedSecurityToken.setBinarySecurityToken(binarySecToken);
requestSecurityTokenResponse.setRequestedSecurityToken(requestedSecurityToken);
requestSecurityTokenResponse.setRequestID(PluginConstants.CertificateEnrolment.REQUEST_ID);
response.value = requestSecurityTokenResponse;
} catch (CertificateGenerationException e) {
String msg = "Problem occurred while generating certificate.";
log.error(msg, e);
throw new WindowsDeviceEnrolmentException(msg, e);
} catch (WAPProvisioningException e) {
String msg = "Problem occurred while generating wap-provisioning file.";
log.error(msg, e);
throw new WindowsDeviceEnrolmentException(msg, e);
} catch (DeviceManagementException e) {
String msg = "Error occurred while getting tenant configurations.";
log.error(msg);
throw new WindowsDeviceEnrolmentException(msg, e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
/**
* Method used to Convert the Document object into a String.
*
* @param document - Wap provisioning XML document
* @return - String representation of wap provisioning XML document
* @throws TransformerException
*/
private String convertDocumentToString(Document document) throws TransformerException {
DOMSource DOMSource = new DOMSource(document);
StringWriter stringWriter = new StringWriter();
StreamResult streamResult = new StreamResult(stringWriter);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(DOMSource, streamResult);
return stringWriter.toString();
}
/**
* This method prepares the wap-provisioning file by including relevant certificates etc.
*
* @param binarySecurityToken - CSR from device
* @param wapProvisioningFilePath - File path of wap-provisioning file
* @return - base64 encoded final wap-provisioning file as a String
* @throws CertificateGenerationException
* @throws org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WAPProvisioningException
*/
private String prepareWapProvisioningXML(String binarySecurityToken, String wapProvisioningFilePath,
String headerBst) throws CertificateGenerationException,
WAPProvisioningException,
WindowsDeviceEnrolmentException {
String rootCertEncodedString;
String signedCertEncodedString;
X509Certificate signedCertificate;
String provisioningXmlString;
CertificateManagementServiceImpl certMgtServiceImpl = CertificateManagementServiceImpl.getInstance();
Base64 base64Encoder = new Base64();
try {
rootCACertificate = (X509Certificate) certMgtServiceImpl.getCACertificate();
rootCertEncodedString = base64Encoder.encodeAsString(rootCACertificate.getEncoded());
signedCertificate = certMgtServiceImpl.getSignedCertificateFromCSR(binarySecurityToken);
signedCertEncodedString = base64Encoder.encodeAsString(signedCertificate.getEncoded());
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
builder = domFactory.newDocumentBuilder();
Document document = builder.parse(wapProvisioningFilePath);
NodeList wapParm = document.getElementsByTagName(PluginConstants.CertificateEnrolment.PARM);
Node caCertificatePosition = wapParm.item(PluginConstants.CertificateEnrolment.CA_CERTIFICATE_POSITION);
//Adding SHA1 CA certificate finger print to wap-provisioning xml.
caCertificatePosition.getParentNode().getAttributes().getNamedItem(PluginConstants.
CertificateEnrolment.TYPE).setTextContent(String.valueOf(
DigestUtils.sha1Hex(rootCACertificate.getEncoded())).toUpperCase());
//Adding encoded CA certificate to wap-provisioning file after removing new line
// characters.
NamedNodeMap rootCertAttributes = caCertificatePosition.getAttributes();
Node rootCertNode =
rootCertAttributes.getNamedItem(PluginConstants.CertificateEnrolment.VALUE);
rootCertEncodedString = rootCertEncodedString.replaceAll("\n", "");
rootCertNode.setTextContent(rootCertEncodedString);
if (log.isDebugEnabled()) {
log.debug("Root certificate: " + rootCertEncodedString);
}
Node signedCertificatePosition = wapParm.item(PluginConstants.CertificateEnrolment.
SIGNED_CERTIFICATE_POSITION);
//Adding SHA1 signed certificate finger print to wap-provisioning xml.
signedCertificatePosition.getParentNode().getAttributes().getNamedItem(PluginConstants.
CertificateEnrolment.TYPE).setTextContent(String.valueOf(
DigestUtils.sha1Hex(signedCertificate.getEncoded())).toUpperCase());
//Adding encoded signed certificate to wap-provisioning file after removing new line
// characters.
NamedNodeMap clientCertAttributes = signedCertificatePosition.getAttributes();
Node clientEncodedNode =
clientCertAttributes.getNamedItem(PluginConstants.CertificateEnrolment.VALUE);
signedCertEncodedString = signedCertEncodedString.replaceAll("\n", "");
clientEncodedNode.setTextContent(signedCertEncodedString);
if (log.isDebugEnabled()) {
log.debug("Signed certificate: " + signedCertEncodedString);
}
//Adding domainName to wap-provisioning xml.
Node domainPosition = wapParm.item(PluginConstants.CertificateEnrolment.DOMAIN_POSITION);
NamedNodeMap domainAttribute = domainPosition.getAttributes();
Node domainNode = domainAttribute.getNamedItem(PluginConstants.CertificateEnrolment.VALUE);
domainNode.setTextContent(domain);
//Adding Next provisioning service URL to wap-provisioning xml.
Node syncmlServicePosition = wapParm.item(PluginConstants.CertificateEnrolment.
SYNCML_PROVISIONING_ADDR_POSITION);
NamedNodeMap syncmlServiceAttribute = syncmlServicePosition.getAttributes();
Node syncmlServiceNode = syncmlServiceAttribute.getNamedItem(PluginConstants.CertificateEnrolment.VALUE);
syncmlServiceNode.setTextContent(provisioningURL);
// Adding user name auth token to wap-provisioning xml.
Node userNameAuthPosition = wapParm.item(PluginConstants.CertificateEnrolment.APPAUTH_USERNAME_POSITION);
NamedNodeMap appServerAttribute = userNameAuthPosition.getAttributes();
Node authNameNode = appServerAttribute.getNamedItem(PluginConstants.CertificateEnrolment.VALUE);
String userName = getRequestedUser(headerBst);
//CacheEntry cacheEntry = (CacheEntry) DeviceUtil.getCacheEntry(headerBst);
// String userName = cacheEntry.getUsername();
authNameNode.setTextContent(userName);
DeviceUtil.removeToken(headerBst);
String password = DeviceUtil.generateRandomToken();
Node passwordAuthPosition = wapParm.item(PluginConstants.CertificateEnrolment.APPAUTH_PASSWORD_POSITION);
NamedNodeMap appSrvPasswordAttribute = passwordAuthPosition.getAttributes();
Node authPasswordNode = appSrvPasswordAttribute.getNamedItem(PluginConstants.CertificateEnrolment.VALUE);
authPasswordNode.setTextContent(password);
String requestSecurityTokenResponse = SyncmlCredentialUtil.generateRST(userName, password);
DeviceUtil.persistChallengeToken(requestSecurityTokenResponse, null, userName);
// Get device polling frequency from the tenant Configurations.
Node numberOfFirstRetries = wapParm.item(PluginConstants.CertificateEnrolment.POLLING_FREQUENCY_POSITION);
NamedNodeMap pollingAttributes = numberOfFirstRetries.getAttributes();
Node pollValue = pollingAttributes.getNamedItem(PluginConstants.CertificateEnrolment.VALUE);
pollValue.setTextContent(pollingFrequency);
provisioningXmlString = convertDocumentToString(document);
} catch (ParserConfigurationException e) {
throw new WAPProvisioningException("Problem occurred while creating configuration request", e);
} catch (CertificateEncodingException e) {
throw new WindowsDeviceEnrolmentException("Error occurred while encoding certificates.", e);
} catch (SAXException e) {
throw new WAPProvisioningException("Error occurred while parsing wap-provisioning.xml file.", e);
} catch (TransformerException e) {
throw new WAPProvisioningException("Error occurred while transforming wap-provisioning.xml file.", e);
} catch (IOException e) {
throw new WAPProvisioningException("Error occurred while getting wap-provisioning.xml file.", e);
} catch (SyncmlMessageFormatException e) {
throw new WindowsDeviceEnrolmentException("Error occurred while generating password hash value.", e);
} catch (KeystoreException e) {
throw new CertificateGenerationException("CA certificate cannot be generated.", e);
}
return base64Encoder.encodeAsString(provisioningXmlString.getBytes());
}
/**
* This method get the soap request header contents.
*
* @return List of SOAP headers.
*/
private List<Header> getHeaders() {
MessageContext messageContext = context.getMessageContext();
if (messageContext == null || !(messageContext instanceof WrappedMessageContext)) {
return null;
}
Message message = ((WrappedMessageContext) messageContext).getWrappedMessage();
return CastUtils.cast((List<?>) message.get(Header.HEADER_LIST));
}
/**
* This method to getting RSTR requested user from the Cache.
*
* @param bst Binary Security token which has given from BST Endpoint.
* @return User for given token.
*/
private String getRequestedUser(String bst) {
CacheEntry cacheEntry = (CacheEntry) DeviceUtil.getCacheEntry(bst);
String userName = cacheEntry.getUsername();
return userName;
}
/**
* This Method to generate windows device.
*
* @param windowsDevice Requested Device with properties.
* @return Value added Device.
*/
private Device generateDevice(WindowsDevice windowsDevice) {
Device generatedDevice = new Device();
Device.Property OSVersionProperty = new Device.Property();
OSVersionProperty.setName(PluginConstants.SyncML.OS_VERSION);
OSVersionProperty.setValue(windowsDevice.getOsVersion());
Device.Property IMSEIProperty = new Device.Property();
IMSEIProperty.setName(PluginConstants.SyncML.IMSI);
IMSEIProperty.setValue(windowsDevice.getImsi());
Device.Property IMEIProperty = new Device.Property();
IMEIProperty.setName(PluginConstants.SyncML.IMEI);
IMEIProperty.setValue(windowsDevice.getImei());
List<Device.Property> propertyList = new ArrayList<>();
propertyList.add(OSVersionProperty);
propertyList.add(IMSEIProperty);
propertyList.add(IMEIProperty);
EnrolmentInfo enrolmentInfo = new EnrolmentInfo();
enrolmentInfo.setOwner(windowsDevice.getUser());
enrolmentInfo.setOwnership(EnrolmentInfo.OwnerShip.BYOD);
enrolmentInfo.setStatus(EnrolmentInfo.Status.ACTIVE);
generatedDevice.setEnrolmentInfo(enrolmentInfo);
generatedDevice.setDeviceIdentifier(windowsDevice.getDeviceId());
generatedDevice.setProperties(propertyList);
generatedDevice.setType(windowsDevice.getDeviceType());
generatedDevice.setName(windowsDevice.getDeviceName());
return generatedDevice;
}
/**
* This method to enroll windows10 Device.
*
* @param requestContextItems Context values to enroll the device.
* @param headerBinarySecurityToken SOAP request header value to identify the user.
* @throws DeviceManagementException Exception occurs while enrolling the Device.
* @throws PolicyManagementException Exception occurs while getting effective policies.
*/
private void enrollDevice(AdditionalContext requestContextItems, String headerBinarySecurityToken)
throws DeviceManagementException, PolicyManagementException {
WindowsDevice windowsDevice = new WindowsDevice();
windowsDevice.setDeviceType(DeviceManagementConstants.MobileDeviceTypes.
MOBILE_DEVICE_TYPE_WINDOWS);
windowsDevice.setUser(getRequestedUser(headerBinarySecurityToken));
List<ContextItem> contextItems = requestContextItems.getcontextitem();
for (int x = 0; x < contextItems.size(); x++) {
switch (x) {
case PluginConstants.WindowsEnrollmentProperties.WIN_DEVICE_NAME:
windowsDevice.setDeviceName(contextItems.get(x).getValue());
case PluginConstants.WindowsEnrollmentProperties.WIN_DEVICE_IMEI:
windowsDevice.setImei(contextItems.get(x).getValue());
case PluginConstants.WindowsEnrollmentProperties.WIN_DEVICE_ID:
windowsDevice.setDeviceId(contextItems.get(x).getValue());
case PluginConstants.WindowsEnrollmentProperties.WIN_DEVICE_VERSION:
windowsDevice.setOsVersion(contextItems.get(x).getValue());
}
}
Device device = generateDevice(windowsDevice);
WindowsAPIUtils.getDeviceManagementService().enrollDevice(device);
PolicyManagerService policyManagerService = WindowsAPIUtils.getPolicyManagerService();
policyManagerService.getEffectivePolicy(new DeviceIdentifier(windowsDevice.getDeviceId(), device.getType()));
}
}

@ -0,0 +1,141 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.bouncycastle.asn1.x509.*;
import org.bouncycastle.cert.CertIOException;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.CertificateGenerationException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WAPProvisioningException;
import javax.security.auth.x500.X500Principal;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.List;
/**
* Class for generating signed certificate for CSR form device.
*/
public class CertificateSigningService {
private static final long MILLI_SECONDS = 1000L * 60 * 60 * 24;
private enum PropertyIndex {
COMMON_NAME_INDEX(0),
NOT_BEFORE_DAYS_INDEX(1),
NOT_AFTER_DAYS_INDEX(2);
private final int itemPosition;
private PropertyIndex(final int itemPosition) {
this.itemPosition = itemPosition;
}
public int getValue() {
return this.itemPosition;
}
}
private static Log log = LogFactory.getLog(
CertificateSigningService.class);
/**
* Implement certificate signing task using CSR received from the device and the MDM server key
* store.
* @param jcaRequest - CSR from the device
* @param privateKey - Private key of CA certificate in MDM server
* @param caCert - CA certificate in MDM server
* @param certParameterList - Parameter list for Signed certificate generation
* @return - Signed certificate for CSR from device
* @throws CertificateGenerationException
* @throws WAPProvisioningException
*/
public static X509Certificate signCSR(JcaPKCS10CertificationRequest jcaRequest,
PrivateKey privateKey, X509Certificate caCert,
List certParameterList) throws
CertificateGenerationException,
WAPProvisioningException {
String commonName =
(String) certParameterList.get(PropertyIndex.COMMON_NAME_INDEX.getValue());
int notBeforeDays =
(Integer) certParameterList.get(PropertyIndex.NOT_BEFORE_DAYS_INDEX.getValue());
int notAfterDays =
(Integer) certParameterList.get(PropertyIndex.NOT_AFTER_DAYS_INDEX.getValue());
X509v3CertificateBuilder certificateBuilder;
X509Certificate signedCertificate;
try {
ContentSigner signer;
BigInteger serialNumber = BigInteger.valueOf(new SecureRandom().
nextInt(Integer.MAX_VALUE));
Date notBeforeDate = new Date(System.currentTimeMillis() -
(MILLI_SECONDS * notBeforeDays));
Date notAfterDate = new Date(System.currentTimeMillis() +
(MILLI_SECONDS * notAfterDays));
certificateBuilder =
new JcaX509v3CertificateBuilder(caCert, serialNumber, notBeforeDate, notAfterDate,
new X500Principal(commonName),
jcaRequest.getPublicKey());
//Adding extensions to the signed certificate.
certificateBuilder.addExtension(Extension.keyUsage, true,
new KeyUsage(KeyUsage.digitalSignature));
certificateBuilder.addExtension(Extension.extendedKeyUsage, false,
new ExtendedKeyUsage(KeyPurposeId.id_kp_clientAuth));
certificateBuilder.addExtension(Extension.basicConstraints, true,
new BasicConstraints(false));
signer = new JcaContentSignerBuilder(PluginConstants.CertificateEnrolment.ALGORITHM).
setProvider(PluginConstants.CertificateEnrolment.PROVIDER).build(privateKey);
signedCertificate = new JcaX509CertificateConverter().setProvider(
PluginConstants.CertificateEnrolment.PROVIDER).getCertificate(
certificateBuilder.build(signer));
} catch (InvalidKeyException e) {
throw new CertificateGenerationException("CSR's public key is invalid", e);
} catch (NoSuchAlgorithmException e) {
throw new CertificateGenerationException("Certificate cannot be generated", e);
}
catch (CertIOException e) {
throw new CertificateGenerationException(
"Cannot add extension(s) to signed certificate", e);
}
catch (OperatorCreationException e) {
throw new CertificateGenerationException("Content signer cannot be created", e);
}
catch (CertificateException e) {
throw new CertificateGenerationException("Signed certificate cannot be generated", e);
}
return signedCertificate;
}
}

@ -0,0 +1,94 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.KeyStoreGenerationException;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
/**
* Class for MDM Keystore operations.
*/
public class KeyStoreGenerator {
private static final Log log = LogFactory.getLog(
KeyStoreGenerator.class);
/**
* This method loads the MDM keystore.
* @param keyStore - MDM Keystore
* @param keyStorePassword - Keystore Password
* @param keyStorePath - Keystore path
* @throws KeyStoreGenerationException
*/
public static void loadToStore(KeyStore keyStore,
char[] keyStorePassword,
String keyStorePath) throws KeyStoreGenerationException {
FileInputStream fileInputStream = null;
try {
if (keyStorePath != null) {
fileInputStream = new FileInputStream(keyStorePath);
keyStore.load(fileInputStream, keyStorePassword);
}
} catch (NoSuchAlgorithmException e) {
throw new KeyStoreGenerationException(
"Requested cryptographic algorithm is not available in the environment.", e);
} catch (CertificateException e) {
throw new KeyStoreGenerationException("Error working with certificate related to, " +
keyStorePath, e);
} catch (IOException e) {
throw new KeyStoreGenerationException("File error while working with file, " +
keyStorePath, e);
} finally {
try {
if (fileInputStream != null) {
fileInputStream.close();
}
} catch (IOException e) {
throw new KeyStoreGenerationException("File error while closing the file, " +
keyStorePath, e);
}
}
}
/**
* This method is for retrieving instance of Key Store.
* @return Keystore object
* @throws KeyStoreGenerationException
*/
public static KeyStore getKeyStore() throws KeyStoreGenerationException {
try {
return KeyStore.getInstance(PluginConstants.CertificateEnrolment.JKS);
} catch (KeyStoreException e) {
String msg = "KeyStore error while creating new JKS.";
log.error(msg, e);
throw new KeyStoreGenerationException(msg, e);
}
}
}

@ -0,0 +1,200 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import org.joda.time.format.ISODateTimeFormat;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import javax.ws.rs.core.Response;
import javax.xml.namespace.QName;
import javax.xml.soap.*;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;
/**
* Class responsible for adding Timestamp security header in SOAP message and adding Content-length
* in the HTTP header for avoiding HTTP chunking.
*/
public class MessageHandler implements SOAPHandler<SOAPMessageContext> {
public static final String TIME_ZONE = "Z";
public static final int VALIDITY_TIME = 5;
public static final int TIMESTAMP_END_INDEX = 6;
public static final int TIMESTAMP_BEGIN_INDEX = 0;
private static Log log = LogFactory.getLog(
MessageHandler.class);
/**
* This method resolves the security header coming in the SOAP message.
* @return - Security Header
*/
@Override
public Set<QName> getHeaders() {
QName securityHeader = new QName(PluginConstants.WS_SECURITY_TARGET_NAMESPACE, PluginConstants.SECURITY);
HashSet<QName> headers = new HashSet<QName>();
headers.add(securityHeader);
return headers;
}
/**
* This method adds Timestamp for SOAP header, and adds Content-length for HTTP header for
* avoiding HTTP chunking.
*
* @param context - Context of the SOAP Message
*/
@Override
public boolean handleMessage(SOAPMessageContext context) {
Boolean outBoundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outBoundProperty) {
SOAPMessage message = context.getMessage();
SOAPHeader header = null;
SOAPEnvelope envelope = null;
try {
header = message.getSOAPHeader();
envelope = message.getSOAPPart().getEnvelope();
} catch (SOAPException e) {
Response.serverError().entity("SOAP message content cannot be read.").build();
}
try {
if ((header == null) && (envelope != null)) {
header = envelope.addHeader();
}
} catch (SOAPException e) {
Response.serverError().entity("SOAP header cannot be added.").build();
}
SOAPFactory soapFactory = null;
try {
soapFactory = SOAPFactory.newInstance();
} catch (SOAPException e) {
Response.serverError().entity("Cannot get an instance of SOAP factory.").build();
}
QName qNamesSecurity = new QName(PluginConstants.WS_SECURITY_TARGET_NAMESPACE,
PluginConstants.CertificateEnrolment.SECURITY);
SOAPHeaderElement Security = null;
Name attributeName = null;
try {
if (header != null) {
Security = header.addHeaderElement(qNamesSecurity);
}
if (soapFactory != null) {
attributeName =
soapFactory.createName(PluginConstants.CertificateEnrolment.TIMESTAMP_ID,
PluginConstants.CertificateEnrolment.TIMESTAMP_U,
PluginConstants.CertificateEnrolment
.WSS_SECURITY_UTILITY);
}
} catch (SOAPException e) {
Response.serverError().entity("Security header cannot be added.").build();
}
QName qNameTimestamp = new QName(PluginConstants.CertificateEnrolment.WSS_SECURITY_UTILITY,
PluginConstants.CertificateEnrolment.TIMESTAMP);
SOAPHeaderElement timestamp = null;
try {
if (header != null) {
timestamp = header.addHeaderElement(qNameTimestamp);
timestamp.addAttribute(attributeName,
PluginConstants.CertificateEnrolment.TIMESTAMP_0);
}
} catch (SOAPException e) {
Response.serverError().entity("Exception while adding timestamp header.").build();
}
DateTime dateTime = new DateTime();
DateTime expiredDateTime = dateTime.plusMinutes(VALIDITY_TIME);
String createdISOTime = dateTime.toString(ISODateTimeFormat.dateTime());
String expiredISOTime = expiredDateTime.toString(ISODateTimeFormat.dateTime());
createdISOTime = createdISOTime.substring(TIMESTAMP_BEGIN_INDEX,
createdISOTime.length() -
TIMESTAMP_END_INDEX);
createdISOTime = createdISOTime + TIME_ZONE;
expiredISOTime = expiredISOTime.substring(TIMESTAMP_BEGIN_INDEX,
expiredISOTime.length() -
TIMESTAMP_END_INDEX);
expiredISOTime = expiredISOTime + TIME_ZONE;
QName qNameCreated = new QName(PluginConstants.CertificateEnrolment.WSS_SECURITY_UTILITY,
PluginConstants.CertificateEnrolment.CREATED);
SOAPHeaderElement SOAPHeaderCreated = null;
try {
if (header != null) {
SOAPHeaderCreated = header.addHeaderElement(qNameCreated);
SOAPHeaderCreated.addTextNode(createdISOTime);
}
} catch (SOAPException e) {
Response.serverError().entity("Exception while creating SOAP header.").build();
}
QName qNameExpires = new QName(PluginConstants.CertificateEnrolment.WSS_SECURITY_UTILITY,
PluginConstants.CertificateEnrolment.EXPIRES);
SOAPHeaderElement SOAPHeaderExpires = null;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
String messageString = null;
try {
if (header != null) {
SOAPHeaderExpires = header.addHeaderElement(qNameExpires);
SOAPHeaderExpires.addTextNode(expiredISOTime);
}
if ((timestamp != null) && (Security != null)) {
timestamp.addChildElement(SOAPHeaderCreated);
timestamp.addChildElement(SOAPHeaderExpires);
Security.addChildElement(timestamp);
}
message.saveChanges();
message.writeTo(outputStream);
messageString = new String(outputStream.toByteArray(),
PluginConstants.CertificateEnrolment.UTF_8);
} catch (SOAPException e) {
Response.serverError().entity("Exception while creating timestamp SOAP header.")
.build();
} catch (IOException e) {
Response.serverError().entity("Exception while writing message to output stream.")
.build();
}
Map<String, List<String>> headers =
(Map<String, List<String>>) context.get(MessageContext.HTTP_REQUEST_HEADERS);
headers = new HashMap<String, List<String>>();
if (messageString != null) {
headers.put(PluginConstants.CONTENT_LENGTH, Arrays.asList(String.valueOf(
messageString.length())));
}
context.put(MessageContext.HTTP_REQUEST_HEADERS, headers);
}
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
return true;
}
@Override
public void close(MessageContext context) {
}
}

@ -31,6 +31,7 @@ import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.Unexpecte
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsConfigurationException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.WindowsAPIUtils;
import org.wso2.carbon.device.mgt.mobile.windows.api.services.ConfigurationMgtService;
import javax.ws.rs.core.MediaType;
import javax.jws.WebService;
import javax.ws.rs.*;
@ -39,9 +40,9 @@ import java.util.ArrayList;
import java.util.List;
@WebService
@Produces({"application/json", "application/xml"})
@Consumes({"application/json", "application/xml"})
@Path("/")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Path("/configuration")
public class ConfigurationMgtServiceImpl implements ConfigurationMgtService {
private static Log log = LogFactory.getLog(

@ -35,9 +35,7 @@ import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.Message;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.WindowsAPIUtils;
import org.wso2.carbon.device.mgt.mobile.windows.api.services.DeviceManagementAdminService;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
@ -46,6 +44,9 @@ import java.util.List;
* Implementation class of operations interface. Each method in this class receives the operations comes via UI
* and persists those in the correct format.
*/
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Path("/admin/devices")
public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminService {
private static Log log = LogFactory.getLog(OperationImpl.class);
@ -102,7 +103,7 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe
* @throws WindowsDeviceEnrolmentException
*/
@POST
@Path("/disenroll")
@Path("/disenroll-devices")
public Response disenroll(@HeaderParam("Accept") String acceptHeader, List<String> deviceIDs)
throws WindowsDeviceEnrolmentException {
@ -143,7 +144,7 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe
* @throws WindowsDeviceEnrolmentException
*/
@POST
@Path("/wipe-data")
@Path("/wipe-devices")
public Response wipe(@HeaderParam("Accept") String acceptHeader, List<String> deviceids)
throws WindowsDeviceEnrolmentException {
@ -186,7 +187,7 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe
* @throws WindowsDeviceEnrolmentException
*/
@POST
@Path("/ring-device")
@Path("/ring-devices")
public Response ring(@HeaderParam("Accept") String acceptHeader, List<String> deviceIDs)
throws WindowsDeviceEnrolmentException {
@ -234,7 +235,7 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe
* @throws WindowsDeviceEnrolmentException
*/
@POST
@Path("/lock-reset")
@Path("/lock-reset-devices")
public Response lockReset(@HeaderParam("Accept") String acceptHeader, List<String> deviceIDs)
throws WindowsDeviceEnrolmentException {

@ -0,0 +1,203 @@
/*
* 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.
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.services.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
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.DeviceManagementConstants;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.device.details.*;
import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementException;
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.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.beans.CacheEntry;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.SyncmlMessageFormatException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.SyncmlOperationException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsConfigurationException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsDeviceEnrolmentException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.AuthenticationInfo;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.DeviceUtil;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.WindowsAPIUtils;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.*;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.util.*;
import org.wso2.carbon.device.mgt.mobile.windows.api.operations.util.DeviceInfo;
import org.wso2.carbon.device.mgt.mobile.windows.api.services.DeviceManagementService;
import org.wso2.carbon.policy.mgt.common.PolicyManagementException;
import org.wso2.carbon.policy.mgt.core.PolicyManagerService;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List;
import static org.wso2.carbon.device.mgt.mobile.windows.api.common.util.WindowsAPIUtils.convertToDeviceIdentifierObject;
public class DeviceManagementServiceImpl implements DeviceManagementService {
private static Log log = LogFactory.getLog(
org.wso2.carbon.device.mgt.mobile.windows.api.services.syncml.impl.SyncmlServiceImpl.class);
@Override
public Response getResponse(Document request) throws WindowsDeviceEnrolmentException, WindowsOperationException,
NotificationManagementException, WindowsConfigurationException {
int msgId;
int sessionId;
String user;
String token;
String response;
SyncmlDocument syncmlDocument;
List<? extends Operation> pendingOperations;
OperationHandler operationHandler = new OperationHandler();
OperationReply operationReply = new OperationReply();
try {
if (SyncmlParser.parseSyncmlPayload(request) != null) {
syncmlDocument = SyncmlParser.parseSyncmlPayload(request);
SyncmlHeader syncmlHeader = syncmlDocument.getHeader();
sessionId = syncmlHeader.getSessionId();
user = syncmlHeader.getSource().getLocName();
DeviceIdentifier deviceIdentifier = convertToDeviceIdentifierObject(syncmlHeader.getSource().
getLocURI());
msgId = syncmlHeader.getMsgID();
if ((PluginConstants.SyncML.SYNCML_FIRST_MESSAGE_ID == msgId) &&
(PluginConstants.SyncML.SYNCML_FIRST_SESSION_ID == sessionId)) {
token = syncmlHeader.getCredential().getData();
CacheEntry cacheToken = (CacheEntry) DeviceUtil.getCacheEntry(token);
if ((cacheToken.getUsername() != null) && (cacheToken.getUsername().equals(user))) {
if (modifyEnrollWithMoreDetail(request)) {
pendingOperations = operationHandler.getPendingOperations(syncmlDocument);
response = operationReply.generateReply(syncmlDocument,pendingOperations);
return Response.status(Response.Status.OK).entity(response).build();
} else {
String msg = "Error occurred in while modify the enrollment.";
log.error(msg);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
}
} else {
String msg = "Authentication failure due to incorrect credentials.";
log.error(msg);
return Response.status(Response.Status.UNAUTHORIZED).entity(msg).build();
}
} else {
if ((syncmlDocument.getBody().getAlert() != null)) {
if (!syncmlDocument.getBody().getAlert().getData().equals(Constants.DISENROLL_ALERT_DATA)) {
pendingOperations = operationHandler.getPendingOperations(syncmlDocument);
return Response.ok().entity(operationReply.generateReply(
syncmlDocument, pendingOperations)).build();
} else {
if (WindowsAPIUtils.getDeviceManagementService().getDevice(deviceIdentifier) != null) {
WindowsAPIUtils.getDeviceManagementService().disenrollDevice(deviceIdentifier);
return Response.ok().entity(operationReply.generateReply(syncmlDocument, null)).build();
} else {
String msg = "Enrolled device can not be found in the server.";
log.error(msg);
return Response.status(Response.Status.NOT_FOUND).entity(msg).build();
}
}
} else {
pendingOperations = operationHandler.getPendingOperations(syncmlDocument);
return Response.ok().entity(operationReply.generateReply(
syncmlDocument, pendingOperations)).build();
}
}
}
} catch (SyncmlMessageFormatException e) {
String msg = "Error occurred while parsing syncml request.";
log.error(msg, e);
throw new WindowsOperationException(msg, e);
} catch (OperationManagementException e) {
String msg = "Cannot access operation management service.";
log.error(msg, e);
throw new WindowsOperationException(msg, e);
} catch (SyncmlOperationException e) {
String msg = "Error occurred while getting effective feature.";
log.error(msg, e);
throw new WindowsConfigurationException(msg, e);
} catch (DeviceManagementException e) {
String msg = "Failure occurred in dis-enrollment flow.";
log.error(msg, e);
throw new WindowsOperationException(msg, e);
}
return null;
}
/**
* Enroll phone device
*
* @param request Device syncml request for the server side.
* @return enroll state
* @throws WindowsDeviceEnrolmentException
* @throws WindowsOperationException
*/
private boolean modifyEnrollWithMoreDetail(Document request) throws WindowsDeviceEnrolmentException,
WindowsOperationException {
String devMan;
String devMod;
boolean status = false;
String user;
SyncmlDocument syncmlDocument;
try {
syncmlDocument = SyncmlParser.parseSyncmlPayload(request);
ReplaceTag replace = syncmlDocument.getBody().getReplace();
List<ItemTag> itemList = replace.getItems();
devMan = itemList.get(PluginConstants.SyncML.DEVICE_MAN_POSITION).getData();
devMod = itemList.get(PluginConstants.SyncML.DEVICE_MODEL_POSITION).getData();
user = syncmlDocument.getHeader().getSource().getLocName();
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
authenticationInfo.setUsername(user);
WindowsAPIUtils.startTenantFlow(authenticationInfo);
DeviceIdentifier deviceIdentifier = convertToDeviceIdentifierObject(syncmlDocument.
getHeader().getSource().getLocURI());
Device existingDevice = WindowsAPIUtils.getDeviceManagementService().getDevice(deviceIdentifier);
if (!existingDevice.getProperties().isEmpty()) {
List<Device.Property> existingProperties = new ArrayList<>();
Device.Property vendorProperty = new Device.Property();
vendorProperty.setName(PluginConstants.SyncML.VENDOR);
vendorProperty.setValue(devMan);
existingProperties.add(vendorProperty);
Device.Property deviceModelProperty = new Device.Property();
deviceModelProperty.setName(PluginConstants.SyncML.MODEL);
deviceModelProperty.setValue(devMod);
existingProperties.add(deviceModelProperty);
existingDevice.setProperties(existingProperties);
existingDevice.setDeviceIdentifier(syncmlDocument.getHeader().getSource().getLocURI());
existingDevice.setType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_WINDOWS);
status = WindowsAPIUtils.getDeviceManagementService().modifyEnrollment(existingDevice);
return status;
}
} catch (DeviceManagementException e) {
throw new WindowsDeviceEnrolmentException("Failure occurred while enrolling device.", e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
return status;
}
}

@ -31,6 +31,7 @@ public class WindowsDevice {
private String manufacturer;
private String model;
private String user;
private String deviceName;
public String getImei() {
return imei;
@ -96,5 +97,13 @@ public class WindowsDevice {
this.user = user;
}
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
}

@ -235,6 +235,7 @@ public class SyncmlServiceImpl implements SyncmlService {
String devLang;
String vendor;
String macAddress;
String resolution;
String modVersion;
boolean status = false;
String user;
@ -323,11 +324,10 @@ public class SyncmlServiceImpl implements SyncmlService {
deviceModelProperty.setValue(devMod);
existingProperties.add(deviceModelProperty);
existingDevice.setName(deviceName);
existingDevice.setProperties(existingProperties);
existingDevice.setName(deviceName);
existingDevice.setDeviceIdentifier(syncmlDocument.getHeader().getSource().getLocURI());
existingDevice.setType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_WINDOWS);
status = WindowsAPIUtils.getDeviceManagementService().modifyEnrollment(existingDevice);
// call effective policy for the enrolling device.
PolicyManagerService policyManagerService = WindowsAPIUtils.getPolicyManagerService();

@ -1,26 +0,0 @@
<!--
~ 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.
-->
<WindowsPlugin>
<AuthPolicy>Federated</AuthPolicy>
<Password>wso2carbon</Password>
<PrivateKeyPassword>cacert</PrivateKeyPassword>
<SignedCertCN>CN=mdmcn</SignedCertCN>
<SignedCertNotBefore>3</SignedCertNotBefore>
<SignedCertNotAfter>300</SignedCertNotAfter>
<domain>wso2.com</domain>
</WindowsPlugin>

@ -0,0 +1,76 @@
<wap-provisioningdoc version="1.1">
<characteristic type="CertificateStore">
<characteristic type="Root">
<characteristic type="System">
<characteristic type="031336C933CC7E228B88880D78824FB2909A0A2F">
<parm name="EncodedCertificate" value="B64 encoded cert insert here" />
</characteristic>
</characteristic>
</characteristic>
</characteristic>
<characteristic type="CertificateStore">
<characteristic type="My" >
<characteristic type="User">
<characteristic type="F9A4F20FC50D990FDD0E3DB9AFCBF401818D5462">
<parm name="EncodedCertificate" value="B64EncodedCertInsertedHere" />
</characteristic>
<characteristic type="PrivateKeyContainer"/>
<!-- This tag must be present for XML syntax correctness. -->
</characteristic>
<characteristic type="WSTEP">
<characteristic type="Renew">
<!--If the datatype for ROBOSupport, RenewPeriod, and RetryInterval tags exist, they must be set explicitly. -->
<parm name="ROBOSupport" value="true" datatype="boolean"/>
<parm name="RenewPeriod" value="60" datatype="integer"/>
<parm name="RetryInterval" value="4" datatype="integer"/>
</characteristic>
</characteristic>
</characteristic>
</characteristic>
<characteristic type="APPLICATION">
<parm name="APPID" value="w7"/>
<parm name="PROVIDER-ID" value="TestMDMServer"/>
<parm name="NAME" value="Microsoft"/>
<parm name="ADDR" value="https://DM.contoso.com:443/omadm/Windows.ashx"/>
<parm name="CONNRETRYFREQ" value="6" />
<parm name="INITIALBACKOFFTIME" value="30000" />
<parm name="MAXBACKOFFTIME" value="120000" />
<parm name="BACKCOMPATRETRYDISABLED" />
<parm name="DEFAULTENCODING" value="application/vnd.syncml.dm+wbxml" />
<parm name="SSLCLIENTCERTSEARCHCRITERIA" value=
"Subject=DC%3dcom%2cDC%3dmicrosoft%2cCN%3dUsers%2cCN%3dAdministrator&amp;amp;Stores=My%5CUser"/>
<characteristic type="APPAUTH">
<parm name="AAUTHLEVEL" value="CLIENT"/>
<parm name="AAUTHTYPE" value="DIGEST"/>
<parm name="AAUTHSECRET" value="password1"/>
<parm name="AAUTHDATA" value="B64encodedBinaryNonceInsertedHere"/>
</characteristic>
<characteristic type="APPAUTH">
<parm name="AAUTHLEVEL" value="APPSRV"/>
<parm name="AAUTHTYPE" value="BASIC"/>
<parm name="AAUTHNAME" value="testclient"/>
<parm name="AAUTHSECRET" value="password2"/>
</characteristic>
</characteristic>
<characteristic type="DMClient"> <!-- In Windows 10, an enrollment server should use DMClient CSP XML to configure DM polling schedules. -->
<characteristic type="Provider">
<!-- ProviderID in DMClient CSP must match to PROVIDER-ID in w7 APPLICATION characteristics -->
<characteristic type="TestMDMServer">
<parm name="UPN" value="UserPrincipalName@contoso.com" datatype="string" />
<characteristic type="Poll">
<parm name="NumberOfFirstRetries" value="8" datatype="integer" />
<parm name="IntervalForFirstSetOfRetries" value="15" datatype="integer" />
<parm name="NumberOfSecondRetries" value="5" datatype="integer" />
<parm name="IntervalForSecondSetOfRetries" value="3" datatype="integer" />
<parm name="NumberOfRemainingScheduledRetries" value="0" datatype="integer" />
<!-- Windows 10 supports MDM push for real-time communication. The DM client long term polling schedules retry waiting interval should be more than 24 hours (1440) to reduce the impact to data consumption and battery life. Refer to the DMClient Configuration Service Provider section for information about polling schedule parameters.-->
<parm name="IntervalForRemainingScheduledRetries" value="1560" datatype="integer" />
<parm name="PollOnLogin" value="true" datatype="boolean" />
</characteristic>
<parm name="EntDeviceName" value="Administrator_Windows" datatype="string" />
</characteristic>
</characteristic>
</characteristic>
<!-- For Windows 10, we removed EnterpriseAppManagement from the enrollment
protocol. -->
</wap-provisioningdoc>

@ -64,24 +64,27 @@
</jaxws:handlers>
</jaxws:endpoint>
<!--XCEP endpoint for OnPremise Auth-Policy-->
<!--WSTEP Endpoint for Federated Auth-Policy-->
<jaxws:endpoint
id="EnrollmentPolicyServiceOnPremise"
implementor="org.wso2.carbon.device.mgt.mobile.windows.api.services.xcep.impl.CertificateEnrollmentPolicyServiceImpl"
address="/certificatepolicy/xcep/onpremise">
id="CertificateEnrollmentService"
implementor="org.wso2.carbon.device.mgt.mobile.windows.api.services.wstep.impl.CertificateEnrollmentServiceImpl"
address="/deviceenrolment/wstep">
<jaxws:properties>
<entry key="ws-security.ut.validator" value-ref="customvalidatoronpremise"/>
<entry key="ws-security.bst.validator" value-ref="customvalidator"/>
</jaxws:properties>
<jaxws:inInterceptors>
<ref bean="wss4jInInterceptor"/>
<ref bean="wss4jInInterceptor_federated"/>
</jaxws:inInterceptors>
<jaxws:handlers>
<ref bean="serviceOptionsHandler"/>
</jaxws:handlers>
</jaxws:endpoint>
<!--WSTEP Endpoint for Federated Auth-Policy-->
<!-- Enrollment Endpoint for windows 10 -->
<jaxws:endpoint
id="CertificateEnrollmentService"
implementor="org.wso2.carbon.device.mgt.mobile.windows.api.services.wstep.impl.CertificateEnrollmentServiceImpl"
address="/deviceenrolment/wstep">
id="EnrollmentService"
implementor="org.wso2.carbon.device.mgt.mobile.windows.api.services.enrollment.impl.EnrollmentServiceImpl"
address="/deviceenrolment/enrollment">
<jaxws:properties>
<entry key="ws-security.bst.validator" value-ref="customvalidator"/>
</jaxws:properties>
@ -97,42 +100,27 @@
<jaxrs:server id="Syncmlinitial" address="/syncml">
<jaxrs:serviceBeans>
<ref bean="Syncml_initial_bean"/>
<ref bean="swaggerResource"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider"/>
<ref bean="swaggerWriter"/>
</jaxrs:providers>
</jaxrs:server>
<!--BST provider Endpoint for returning binary security token after authentication-->
<jaxrs:server id="bstprovider" address="/federated">
<!--Syncml Windows 10 device mgt Endpoint-->
<jaxrs:server id="Win10devicemgtSession" address="/management">
<jaxrs:serviceBeans>
<ref bean="bstProviderService"/>
<ref bean="swaggerResource"/>
<ref bean="devicemgt_bean"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider"/>
<ref bean="swaggerWriter"/>
</jaxrs:providers>
</jaxrs:server>
<!--Endpoint for UI admin operations-->
<jaxrs:server id="adminoperations" address="/windows">
<!--BST provider Endpoint for returning binary security token after authentication-->
<jaxrs:server id="bstprovider" address="/federated">
<jaxrs:serviceBeans>
<ref bean="deviceMgtAdminService"/>
<ref bean="swaggerResource"/>
<ref bean="bstProviderService"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider"/>
<ref bean="swaggerWriter"/>
</jaxrs:providers>
</jaxrs:server>
<!-- Endpoint for Configurations -->
<jaxrs:server id="configurationService" address="/configuration">
<jaxrs:server id="services" address="/">
<jaxrs:serviceBeans>
<ref bean="configurationMgtService"/>
<ref bean="deviceMgtAdminService"/>
<ref bean="swaggerResource"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
@ -140,8 +128,13 @@
<ref bean="errorHandler"/>
<ref bean="swaggerWriter"/>
</jaxrs:providers>
<jaxrs:properties>
<!-- This is added to catch interceptor level exceptions in GlobalThrowableMapper. -->
<entry key="map.cxf.interceptor.fault" value="true" />
</jaxrs:properties>
</jaxrs:server>
<bean id="bstProviderService"
class="org.wso2.carbon.device.mgt.mobile.windows.api.services.authbst.impl.BSTProviderImpl"/>
<bean id="deviceMgtAdminService"
@ -184,6 +177,8 @@
</bean>
<bean id="Syncml_initial_bean"
class="org.wso2.carbon.device.mgt.mobile.windows.api.services.syncml.impl.SyncmlServiceImpl"/>
<bean id="devicemgt_bean"
class="org.wso2.carbon.device.mgt.mobile.windows.api.services.impl.DeviceManagementServiceImpl"/>
<bean id="customvalidator"
class="org.wso2.carbon.device.mgt.mobile.windows.api.common.util.BSTValidator"/>
<bean id="customvalidatoronpremise"

@ -67,6 +67,7 @@
<context-param>
<param-name>nonSecuredEndPoints</param-name>
<param-value>/discovery/get,/discovery/post,/certificatepolicy/xcep,
,/deviceenrolment/wstep,/syncml/devicemanagement/request</param-value>
,/deviceenrolment/wstep,/syncml/devicemanagement/request,/deviceenrolment/enrollment,/management/devicemgt/pending-operations
</param-value>
</context-param>
</web-app>

@ -1,19 +1,19 @@
{{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.windows.operation-bar"}}
{{#if deviceFound}}
{{#if isAuthorized}}
{{#zone "device-details-header"}}
<h1 class="page-sub-title device-id device-select"
data-deviceid="{{deviceView.deviceIdentifier}}" data-type="{{deviceView.type}}"
data-ownership="{{deviceView.ownership}}">
Device {{deviceView.name}}
{{#if deviceView.model}}
data-deviceid="{{device.deviceIdentifier}}" data-type="{{device.type}}"
data-ownership="{{device.ownership}}"
data-owner="{{device.owner}}">
Device {{device.name}}
{{#if device.model}}
<span class="lbl-device">
( {{deviceView.vendor}} {{deviceView.model}} )
( {{device.vendor}} {{device.model}} )
</span>
{{/if}}
</h1>
@ -26,83 +26,84 @@
</div>
<table class="table table-responsive table-striped" id="members">
<tbody>
{{#if deviceView.deviceIdentifier}}
{{#if device.deviceIdentifier}}
<tr role="row" class="odd">
<td class="sorting_1" style="padding:10px 15px; width: 15%;">Device ID</td>
<td style="padding:10px 15px;">{{deviceView.deviceIdentifier}}</td>
<td style="padding:10px 15px;">{{device.deviceIdentifier}}</td>
</tr>
{{/if}}
{{#if deviceView.name}}
{{#if device.name}}
<tr role="row" class="even">
<td class="sorting_1" style="padding:10px 15px; width: 15%;">Name</td>
<td style="padding:10px 15px;">{{deviceView.name}}</td>
<td style="padding:10px 15px;">{{device.name}}</td>
</tr>
{{/if}}
{{#if deviceView.vendor}}
{{#if deviceView.model}}
{{#if device.vendor}}
{{#if device.model}}
<tr role="row" class="odd">
<td class="sorting_1" style="padding:10px 15px; width: 15%;">Model</td>
<td style="padding:10px 15px;">{{deviceView.vendor}} {{deviceView.model}}</td>
<td style="padding:10px 15px;">{{device.vendor}}
{{device.model}}</td>
</tr>
{{/if}}
{{/if}}
{{#if deviceView.status}}
{{#if device.status}}
<tr role="row" class="even">
<td class="sorting_1" style="padding:10px 15px; width: 15%;">Status</td>
<td style="padding:10px 15px;">
{{#equal deviceView.status "ACTIVE"}}<span><i
{{#equal device.status "ACTIVE"}}<span><i
class="fw fw-ok icon-success"></i>Active</span>{{/equal}}
{{#equal deviceView.status "INACTIVE"}}<span><i
{{#equal device.status "INACTIVE"}}<span><i
class="fw fw-warning icon-warning"></i>Inactive</span>{{/equal}}
{{#equal deviceView.status "BLOCKED"}}<span><i
{{#equal device.status "BLOCKED"}}<span><i
class="fw fw-remove icon-danger"></i>Blocked</span>{{/equal}}
{{#equal deviceView.status "REMOVED"}}<span><i
{{#equal device.status "REMOVED"}}<span><i
class="fw fw-delete icon-danger"></i>Removed</span>{{/equal}}
</td>
</tr>
{{/if}}
{{#if deviceView.owner}}
{{#if device.owner}}
<tr role="row" class="odd">
<td class="sorting_1" style="padding:10px 15px; width: 15%;">Owner</td>
<td style="padding:10px 15px;">{{deviceView.owner}}</td>
<td style="padding:10px 15px;">{{device.owner}}</td>
</tr>
{{/if}}
{{#if deviceView.ownership}}
{{#if device.ownership}}
<tr role="row" class="even">
<td class="sorting_1" style="padding:10px 15px; width: 15%;">Ownership</td>
<td style="padding:10px 15px;">{{deviceView.ownership}}</td>
<td style="padding:10px 15px;">{{device.ownership}}</td>
</tr>
{{/if}}
{{#if deviceView.imei}}
{{#if device.imei}}
<tr role="row" class="even">
<td class="sorting_1" style="padding:10px 15px; width: 15%;">IMEI</td>
<td style="padding:10px 15px;">{{deviceView.imei}}</td>
<td style="padding:10px 15px;">{{device.imei}}</td>
</tr>
{{/if}}
{{#if deviceView.udid}}
{{#if device.udid}}
<tr role="row" class="odd">
<td class="sorting_1" style="padding:10px 15px; width: 15%;">UDID</td>
<td style="padding:10px 15px;">{{deviceView.udid}}</td>
<td style="padding:10px 15px;">{{device.udid}}</td>
</tr>
{{/if}}
{{#if deviceView.osBuildDate}}
{{#if device.osBuildDate}}
<tr role="row" class="even">
<td class="sorting_1" style="padding:10px 15px; width: 15%;">Firmware Build
Date
</td>
<td style="padding:10px 15px;">{{deviceView.osBuildDate}}</td>
<td style="padding:10px 15px;">{{device.osBuildDate}}</td>
</tr>
{{/if}}
{{#if deviceView.phoneNumber}}
{{#if device.phoneNumber}}
<tr role="row" class="odd">
<td class="sorting_1" style="padding:10px 15px; width: 15%;">Phone Number</td>
<td style="padding:10px 15px;">{{deviceView.phoneNumber}}</td>
<td style="padding:10px 15px;">{{device.phoneNumber}}</td>
</tr>
{{/if}}
{{#if deviceView.lastUpdatedTime}}
{{#if device.lastUpdatedTime}}
<tr role="row" class="even">
<td class="sorting_1" style="padding:10px 15px; width: 15%;">Last Update</td>
<td style="padding:10px 15px;">{{deviceView.lastUpdatedTime}}</td>
<td style="padding:10px 15px;">{{device.lastUpdatedTime}}</td>
</tr>
{{/if}}
</tbody>
@ -110,47 +111,30 @@
</div>
{{/zone}}
{{#zone "device-opetations"}}
{{#if deviceView.isNotRemoved}}
{{#if device.isNotRemoved}}
<div style="background: #11375B; color: #fff; padding: 10px; margin-bottom: 5px">
Operations
</div>
<div class="add-margin-top-4x">
{{unit "cdmf.unit.device.operation-bar" device=deviceView backendApiUri=backendApiUri autoCompleteParams=autoCompleteParams}}
{{unit "cdmf.unit.device.type.windows.new.operation-bar" device=device
backendApiUri=backendApiUri autoCompleteParams=autoCompleteParams}}
</div>
{{/if}}
{{/zone}}
</div>
{{#zone "device-detail-properties"}}
<div class="media tab-responsive">
<div class="media-left col-xs-1 col-sm-1 col-md-2 col-lg-2 hidden-xs">
<ul class="list-group nav nav-pills nav-stacked" role="tablist">
{{#if deviceView.isNotWindows}}
<li role="presentation" class="list-group-item active">
<a href="#device_details_tab" role="tab" data-toggle="tab"
aria-controls="device_details_tab">
<i class="icon fw fw-mobile"></i><span class="hidden-sm">Device Details</span>
</a>
</li>
{{/if}}
{{#if deviceView.isNotWindows}}
<li role="presentation" class="list-group-item">
{{else}}
<li role="presentation" class="list-group-item active">
{{/if}}
{{#zone "device-details-tab-injected"}}
<li role="presentation" class="list-group-item">
<a href="#policy_compliance_tab" role="tab" data-toggle="tab"
aria-controls="policy_compliance_tab">
<i class="icon fw fw-policy"></i><span class="hidden-sm">Policy Compliance</span>
</a>
</li>
{{#if deviceView.isNotWindows}}
<li role="presentation" class="list-group-item">
<a href="#device_location_tab" role="tab" data-toggle="tab"
data-lat="{{deviceView.location.latitude}}"
data-long="{{deviceView.location.longitude}}"
data-lat="{{device.location.latitude}}"
data-long="{{device.location.longitude}}"
aria-controls="device_location_tab">
<i class="icon fw fw-map-location"></i><span
class="hidden-sm">Device Location</span>
@ -162,22 +146,9 @@
<i class="icon fw fw-application"></i><span class="hidden-sm">Installed Applications</span>
</a>
</li>
{{/if}}
{{#if deviceView.isNotRemoved}}
<li role="presentation" class="list-group-item">
<a href="#event_log_tab" role="tab" data-toggle="tab" aria-controls="event_log_tab">
<i class="icon fw fw-text"></i><span class="hidden-sm">Operations Log</span>
</a>
</li>
{{/if}}
</ul>
</div>
<div class="media-body add-padding-left-5x remove-padding-xs">
<div class="panel-group tab-content remove-padding" id="tabs" role="tablist"
data-status="{{deviceView.isNotRemoved}}" aria-multiselectable="true">
<div class="arrow-left hidden-xs"></div>
{{/zone}}
{{#if deviceView.isNotWindows}}
{{#zone "device-details-tab-contents"}}
<div class="panel panel-default" role="tabpanel" id="device_details_tab">
<div class="panel-heading visible-xs collapsed" id="device_details">
<h4 class="panel-title">
@ -195,30 +166,24 @@
<div class="panel-body ">
<div class="device-detail-body">
<!-- device summary -->
{{#equal deviceView.type "windows"}}
<div class="message message-info">
<h4 class="remove-margin"><i class="icon fw fw-info"></i>Not
available yet</h4>
</div>
{{/equal}}
{{#if deviceView.deviceInfoAvailable}}
{{#if deviceView.BatteryLevel}}
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6">
<div class="col-md-12">
<div class="wr-stats-board-tile">
<div class="tile-name">BATTERY</div>
<div>
<div class="tile-icon"><i
class="fw fw-battery"></i></div>
<div class="tile-stats">
{{deviceView.BatteryLevel.value}} %
</div>
</div>
</div>
</div>
</div>
{{/if}}
<!--{{#if deviceView.cpuUsage}}-->
{{#if device.deviceInfoAvailable}}
<!--{{#if device.BatteryLevel}}-->
<!--<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6">-->
<!--<div class="col-md-12">-->
<!--<div class="wr-stats-board-tile">-->
<!--<div class="tile-name">Remaining BATTERY</div>-->
<!--<div>-->
<!--<div class="tile-icon"><i-->
<!--class="fw fw-battery"></i></div>-->
<!--<div class="tile-stats">-->
<!--{{device.BatteryLevel.value}}-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<!--{{/if}}-->
<!--{{#if device.cpuUsage}}-->
<!--<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6">-->
<!--<div class="col-md-12">-->
<!--<div class="wr-stats-board-tile">-->
@ -226,62 +191,42 @@
<!--<div>-->
<!--<div class="tile-icon"><i class="fw fw-dashboard"></i></div>-->
<!--<div class="tile-stats">-->
<!--{{deviceView.cpuUsage.value}} %-->
<!--{{device.cpuUsage.value}} %-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<!--{{/if}}-->
{{#if deviceView.ramUsage}}
{{#if device.ramUsage}}
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6">
<div class="col-md-12">
<div class="wr-stats-board-tile">
<div class="tile-name">RAM Usage</div>
<div class="tile-name">Available RAM</div>
<div>
<div class="tile-icon"><i
class="fw fw-hardware"></i></div>
<div class="tile-stats">
{{deviceView.ramUsage.value}} %
{{device.ramUsage
.value}} MB
</div>
</div>
</div>
</div>
</div>
{{/if}}
{{#if deviceView.internalMemory}}
{{#if device.internalMemory}}
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6">
<div class="col-md-12">
<div class="wr-stats-board-tile">
<div class="tile-name">Local Storage</div>
<div class="tile-name">Available Local Storage</div>
<div>
<div class="tile-icon"><i
class="fw fw-hdd"></i>
</div>
<div class="tile-stats">
{{deviceView.internalMemory.usage}} %
<span class="tile-stats-free">
TOTAL OF {{deviceView.internalMemory.total}} GB
</span>
</div>
</div>
</div>
</div>
</div>
{{/if}}
{{#if deviceView.externalMemory}}
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-6">
<div class="col-md-12">
<div class="wr-stats-board-tile">
<div class="tile-name">External Storage</div>
<div>
<div class="tile-icon"><i
class="fw fw-usb-drive"></i></div>
<div class="tile-stats">
{{deviceView.externalMemory.usage}} %
<span class="tile-stats-free">
TOTAL OF {{deviceView.externalMemory.total}} GB
</span>
{{device.internalMemory
.value}} GB
</div>
</div>
</div>
@ -301,8 +246,9 @@
</div>
</div>
</div>
{{/if}}
{{/zone}}
{{#zone "device-view-tab-injected-conents"}}
<div class="panel panel-default visible-xs-block" role="tabpanel"
id="policy_compliance_tab">
<div class="panel-heading visible-xs collapsed" id="policy_compliance">
@ -343,6 +289,7 @@
</div>
</div>
</div>
<div class="panel panel-default visible-xs-block" role="tabpanel"
id="device_location_tab">
<div class="panel-heading visible-xs collapsed" id="device_location">
@ -359,10 +306,10 @@
<div id="collapseThree" class="panel-collapse collapse in" role="tabpanel"
aria-labelledby="device_location">
<div class="panel-body">
{{#if deviceView.location}}
{{#if device.location}}
<div id="device-location"
data-lat="{{deviceView.location.latitude}}"
data-long="{{deviceView.location.longitude}}">
data-lat="{{device.location.latitude}}"
data-long="{{device.location.longitude}}">
</div>
{{else}}
<div id="map-error" class="message message-warning">
@ -378,6 +325,7 @@
</div>
</div>
</div>
<div class="panel panel-default visible-xs-block" role="tabpanel"
id="installed_applications_tab">
<div class="panel-heading visible-xs collapsed" id="installed_applications">
@ -423,63 +371,10 @@
</div>
</div>
</div>
<div class="panel panel-default visible-xs-block" role="tabpanel" id="event_log_tab">
<div class="panel-heading visible-xs collapsed" id="event_log">
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#tabs"
href="#collapseFive" aria-expanded="true" aria-controls="collapseFive">
<i class="fw fw-text fw-2x"></i>
Operations Log
<i class="caret-updown fw fw-down"></i>
</a>
</h4>
</div>
<div class="panel-heading display-none-xs">
Operations Log
<span>
<a href="javascript:void(0);" id="refresh-operations">
<i class="fw fw-refresh"></i>
</a>
</span>
</div>
<div id="collapseFive" class="panel-collapse collapse in" role="tabpanel"
aria-labelledby="event_log">
<div class="panel-body">
<span class="visible-xs add-padding-2x text-right">
<a href="javascript:void(0);" id="refresh-operations">
<i class="fw fw-refresh"></i>
</a>
</span>
<div id="operations-spinner" class="wr-advance-operations-init hidden">
<i class="fw fw-settings fw-spin fw-2x"></i> Loading Operations Log...
</div>
<div id="operations-log-container">
<div class="message message-info">
<h4 class="remove-margin">
<i class="icon fw fw-info"></i>
There are no operations, performed yet on this device.
</h4>
</div>
</div>
<table class="table table-striped table-hover table-bordered display data-table"
id="operations-log-table">
<thead>
<tr class="sort-row">
<th>Operation Code</th>
<th>Status</th>
<th>Request created at</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
{{/zone}}
</div>
</div>
{{else}}
<h1 class="page-sub-title">
@ -500,19 +395,13 @@
{{#if isAuthorized}}
<!--suppress HtmlUnknownTarget -->
<script id="policy-view" src="{{@unit.publicUri}}/templates/policy-compliance.hbs"
data-device-id="{{deviceView.deviceIdentifier}}" data-device-type="{{deviceView
.type}}"
data-device-id="{{device.deviceIdentifier}}" data-device-type="{{device.type}}"
type="text/x-handlebars-template"></script>
<!--suppress HtmlUnknownTarget -->
<script id="applications-list" src="{{@unit.publicUri}}/templates/applications-list.hbs"
data-device-id="{{deviceView.deviceIdentifier}}" data-device-type="{{deviceView
.type}}"
data-device-id="{{device.deviceIdentifier}}" data-device-type="{{device.type}}"
type="text/x-handlebars-template"></script>
<!--suppress HtmlUnknownTarget -->
<script id="operations-log" src="{{@unit.publicUri}}/templates/operations-log.hbs"
data-device-id="{{deviceView.deviceIdentifier}}" data-device-type="{{deviceView
.type}}"
type="text/x-handlebars-template"></script>
{{js "js/device-detail.js"}}
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true"></script>
{{js "js/load-map.js"}}

@ -36,9 +36,6 @@ function onRequest(context) {
if (filteredDeviceData["type"]) {
viewModel["type"] = filteredDeviceData["type"];
viewModel.isNotWindows = true;
if (viewModel["deviceType"] == "windows") {
viewModel.isNotWindows = false;
}
}
if (filteredDeviceData["deviceIdentifier"]) {
viewModel["deviceIdentifier"] = filteredDeviceData["deviceIdentifier"];
@ -156,48 +153,18 @@ function onRequest(context) {
viewModel["BatteryLevel"] = {};
viewModel["BatteryLevel"]["value"] = filteredDeviceData["latestDeviceInfo"]["batteryLevel"];
viewModel["cpuUsage"] = {};
viewModel["cpuUsage"]["value"] = filteredDeviceData["latestDeviceInfo"]["cpuUsage"];
viewModel["ramUsage"] = {};
if (filteredDeviceData["latestDeviceInfo"]["totalRAMMemory"] != 0) {
viewModel["ramUsage"]["value"] = Math.
round((filteredDeviceData["latestDeviceInfo"]["totalRAMMemory"] -
filteredDeviceData["latestDeviceInfo"]["availableRAMMemory"])
/ filteredDeviceData["latestDeviceInfo"]["totalRAMMemory"] * 10000) / 100;
} else {
viewModel["ramUsage"]["value"] = 0;
}
viewModel["ramUsage"]["value"] = (filteredDeviceData["latestDeviceInfo"]["availableRAMMemory"]);
viewModel["internalMemory"] = {};
viewModel["internalMemory"]["total"] = Math.
round(filteredDeviceData["latestDeviceInfo"]["internalTotalMemory"] * 100) / 100;
if (filteredDeviceData["latestDeviceInfo"]["internalTotalMemory"] != 0) {
viewModel["internalMemory"]["usage"] = Math.
round((filteredDeviceData["latestDeviceInfo"]["internalTotalMemory"] -
filteredDeviceData["latestDeviceInfo"]["internalAvailableMemory"])
/ filteredDeviceData["latestDeviceInfo"]["internalTotalMemory"] * 10000) / 100;
} else {
viewModel["internalMemory"]["usage"] = 0;
}
viewModel["internalMemory"]["value"] = Math.round((filteredDeviceData["latestDeviceInfo"]["internalAvailableMemory"]) / 1024);
viewModel["externalMemory"] = {};
viewModel["externalMemory"]["total"] = Math.
round(filteredDeviceData["latestDeviceInfo"]["externalTotalMemory"] * 100) / 100;
if (filteredDeviceData["latestDeviceInfo"]["externalTotalMemory"] != 0) {
viewModel["externalMemory"]["usage"] = Math.
round((filteredDeviceData["latestDeviceInfo"]["externalTotalMemory"] -
filteredDeviceData["latestDeviceInfo"]["externalAvailableMemory"])
/ filteredDeviceData["latestDeviceInfo"]["externalTotalMemory"] * 10000) / 100;
} else {
viewModel["externalMemory"]["usage"] = 0;
}
}
if (!filteredDeviceData["initialDeviceInfo"] && !filteredDeviceData["latestDeviceInfo"]) {
viewModel["deviceInfoAvailable"] = false;
}
deviceViewData["deviceView"] = viewModel;
deviceViewData["device"] = viewModel;
} else if (response["status"] == "unauthorized") {
deviceViewData["deviceFound"] = true;
deviceViewData["isAuthorized"] = false;
@ -207,5 +174,11 @@ function onRequest(context) {
} else {
deviceViewData["deviceFound"] = false;
}
var autoCompleteParams = [
{"name" : "deviceId", "value" : deviceId}
];
deviceViewData["autoCompleteParams"] = autoCompleteParams;
return deviceViewData;
}

@ -22,6 +22,7 @@ var InitiateViewOption = null;
var deviceId = $(".device-id");
var deviceIdentifier = deviceId.data("deviceid");
var deviceType = deviceId.data("type");
var ownership = deviceId.data("ownership");
var payload = [deviceIdentifier];
var operationTable;
var serviceUrl;
@ -111,9 +112,6 @@ var InitiateViewOption = null;
$(document).ready(function() {
$(".device-detail-body").removeClass("hidden");
$("#loading-content").remove();
console.log("##### something went wrong here!" + deviceType)
loadOperationBar(deviceType);
loadOperationsLog(false);
loadApplicationsList();
loadPolicyCompliance();
@ -126,14 +124,10 @@ var InitiateViewOption = null;
$("#apps-spinner").removeClass("hidden");
loadApplicationsList();
});
$("#refresh-operations").click(function () {
$("#operations-spinner").removeClass("hidden");
loadOperationsLog(true);
});
});
function loadOperationsLog(update) {
var owner = $("#device-owner").data("owner");
var operationsLogTable = "#operations-log-table";
if (update) {
operationTable = $(operationsLogTable).DataTable();
@ -148,8 +142,8 @@ var InitiateViewOption = null;
pageLength : 10,
order: [],
ajax: {
url: "/emm/api/operation/paginate",
data: {deviceId : deviceIdentifier, deviceType: deviceType},
url: "/devicemgt/api/operation/paginate",
data: {deviceId : deviceIdentifier, deviceType: deviceType, owner:owner},
dataSrc: function (json) {
$("#operations-spinner").addClass("hidden");
$("#operations-log-container").empty();

@ -1,24 +0,0 @@
<table class="table table-striped table-hover table-bordered display data-table" id="operations-log-table">
<thead>
<tr class="sort-row">
<th>Operation Code</th>
<th>Status</th>
<th>Request created at</th>
</tr>
</thead>
<tbody>
{{#each operations}}
<tr data-type="selectable" data-id="{{id}}">
<td data-display="{{code}}" data-grid-label="Code">{{code}}</td>
<td data-display="{{status}}" data-grid-label="Status">
{{#equal status "COMPLETED"}}<span><i class="fw fw-ok icon-success"></i> Completed</span>{{/equal}}
{{#equal status "PENDING"}}<span><i class="fw fw-warning icon-warning"></i> Pending</span>{{/equal}}
{{#equal status "ERROR"}}<span><i class="fw fw-error icon-danger"></i> Error</span>{{/equal}}
{{#equal status "IN_PROGRESS"}}<span><i class="fw fw-ok icon-warning"></i> In Progress</span>{{/equal}}
</td>
<td data-display="{{createdTimeStamp}}" data-grid-label="Created Timestamp">{{createdTimeStamp}}</td>
</tr>
{{/each}}
<br class="c-both" />
</tbody>
</table>

@ -0,0 +1,146 @@
{{!
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.
}}
{{#if control_operations}}
<div class="wr-operations" style="height: 87px; display: block;"
xmlns="http://www.w3.org/1999/html">
<style>
::-webkit-input-placeholder {
color: #B8B8B8;
}
::-moz-placeholder {
color: #B8B8B8;
}
:-ms-input-placeholder {
color: #B8B8B8;
}
input:-moz-placeholder {
color: #B8B8B8;
}
</style>
{{#each control_operations}}
<a href="javascript:operationSelect('{{operation}}')">
{{#if iconFont}}
<i class="fw {{iconFont}}"></i>
{{else}}
{{#if icon}}
<img src="{{@app.context}}/{{icon}}" style="width: 48px;"/>
{{else}}
<i class="fw fw-service"></i>
{{/if}}
{{/if}}
<span>{{name}}</span>
</a>
<div class="operation" data-operation-code="{{operation}}">
<div class="content">
<div class="row">
<div class="col-lg-5 col-md-6 col-centered">
<h3>
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw {{iconFont}} fw-stack-1x"></i>
</span>
{{name}}
<br>
</h3>
<h4>
{{description}}
<br>
</h4>
<form action="{{params.0.uri}}" method="{{params.0.method}}"
style="padding-bottom: 20px;"
data-payload="{{payload}}" id="form-{{operation}}"
data-device-id="{{../device.deviceIdentifier}}"
data-content-type="{{params.0.contentType}}"
data-operation-code="{{operation}}">
{{#each params.0.pathParams}}
<input type="{{type}}" id="{{name}}" placeholder="{{name}}" class="form-control" data-param-type="path" value="{{value}}" />
<br />
{{/each}}
{{#each params.0.formParams}}
<input type="{{type}}" id="{{name}}" name="{{name}}" placeholder="{{name}}" class="form-control" data-param-type="form" value="{{value}}" />
<br />
{{/each}}
{{#each params.0.queryParams}}
<input type="{{type}}" id="{{name}}" placeholder="{{name}}" class="form-control" data-param-type="query" value="{{value}}" />
<br />
{{/each}}
{{#each uiParams}}
{{#equal this.type "checkbox"}}
<input type="{{this.type}}" id="{{this.id}}"
class="checkbox"
placeholder="{{this.label}}"
data-param-type="form"/>
{{this.label}}
<br/>
{{/equal}}
{{#equal this.type "text"}}
<input type="{{this.type}}" id="{{this.id}}"
placeholder="{{this.label}}" class="form-control"
data-param-type="form" value=""/>
<br/>
{{/equal}}
{{/each}}
<button id="btnSend" type="button" onclick="submitForm('form-{{operation}}')" class="btn btn-default">&nbsp;&nbsp;&nbsp;&nbsp;Send
to Device&nbsp;&nbsp;&nbsp;&nbsp;</button>
<label id="lblSending" class="wr-input-label hidden"><i
class="fw fw-lifecycle fw-spin fw-2x"></i> Sending..</label>
<label id="lblSent" class="wr-input-label hidden"><i
class="fw fw-check fw-2x"></i> Sent</label>
</form>
</div>
</div>
</div>
</div>
{{/each}}
</div>
{{else}}
<div align="center">
<h4 style="color: #D8000C"><i class="icon fw fw-error" style="color: #D8000C"></i>
Operations Loading Failed!</h4>
</div>
{{/if}}
<div id="operation-response-template" style="display: none">
<div class="content">
<div class="row">
<div class="col-lg-5 col-md-6 col-centered">
<h3>
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i id="status-icon" class="fw fw-error fw-stack-1x"></i>
</span>
<br>
</h3>
<h4>
<span id="title"></span>
<br>
</h4>
<span id="description"></span>
</div>
</div>
</div>
</div>
{{#zone "bottomJs"}}
{{js "js/operation-bar.js"}}
{{/zone}}

@ -0,0 +1,65 @@
/*
* 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.
*/
function onRequest(context) {
var log = new Log("operation.js");
var operationModule = require("/app/modules/business-controllers/operation.js")["operationModule"];
var device = context.unit.params.device;
var autoCompleteParams = context.unit.params.autoCompleteParams;
var encodedFeaturePayloads=context.unit.params.encodedFeaturePayloads;
var controlOperations = operationModule.getControlOperations(device.type);
var queryParams = [];
var formParams = [];
var pathParams = [];
for (var i = 0; i < controlOperations.length; i++) {
var currentParamList = controlOperations[i]["params"];
var uiParamList = controlOperations[i]["uiParams"];
for (var j = 0; j < currentParamList.length; j++) {
var currentParam = currentParamList[j];
currentParamList[j]["formParams"] = processParams(currentParam["formParams"], autoCompleteParams);
currentParamList[j]["queryParams"] = processParams(currentParam["queryParams"], autoCompleteParams);
currentParamList[j]["pathParams"] = processParams(currentParam["pathParams"], autoCompleteParams);
}
controlOperations[i]["uiParams"] = uiParamList;
if (encodedFeaturePayloads) {
controlOperations[i]["payload"] = getPayload(encodedFeaturePayloads, controlOperations[i]["operation"]);
}
}
return {"control_operations": controlOperations, "device": device};
}
function processParams(paramsList, autoCompleteParams) {
for (var i = 0; i < paramsList.length; i++) {
var paramName = paramsList[i];
var paramValue = "";
var paramType = "text";
for (var k = 0; k < autoCompleteParams.length; k++) {
if (paramName == autoCompleteParams[k].name) {
paramValue = autoCompleteParams[k].value;
paramType = "hidden";
}
}
paramsList[i] = {"name": paramName, "value": paramValue, "type": paramType};
}
return paramsList;
}
function getPayload(featuresPayload, featureCode){
var featuresJSONPayloads = JSON.parse(featuresPayload);
return featuresJSONPayloads[featureCode];
}

@ -0,0 +1,227 @@
/*
* 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.
*/
/*
* On operation click function.
* @param selection: Selected operation
*/
function operationSelect(selection) {
$(modalPopupContent).addClass("operation-data");
$(modalPopupContent).html($(" .operation[data-operation-code=" + selection + "]").html());
$(modalPopupContent).data("operation-code", selection);
showPopup();
}
function submitForm(formId) {
var form = $("#" + formId);
var uri = form.attr("action");
var deviceId = form.data("device-id");
var contentType = form.data("content-type");
var operationCode = form.data("operation-code");
var uriencodedQueryStr = "";
var uriencodedFormStr = "";
var payload = {};
form.find("input").each(function () {
var input = $(this);
if (input.data("param-type") == "path") {
uri = uri.replace("{" + input.attr("id") + "}", input.val());
} else if (input.data("param-type") == "query") {
var prefix = (uriencodedQueryStr == "") ? "?" : "&";
uriencodedQueryStr += prefix + input.attr("id") + "=" + input.val();
} else if (input.data("param-type") == "form") {
var prefix = (uriencodedFormStr == "") ? "" : "&";
uriencodedFormStr += prefix + input.attr("id") + "=" + input.val();
if(input.attr("type") == "text"){
payload[input.attr("id")] = input.val();
} else if(input.attr("type") == "checkbox"){
payload[input.attr("id")] = input.is(":checked");
}
}
});
uri += uriencodedQueryStr;
var httpMethod = form.attr("method").toUpperCase();
//var contentType = form.attr("enctype");
if (contentType == undefined || contentType == "") {
contentType = "application/x-www-form-urlencoded";
payload = uriencodedFormStr;
}
//setting responses callbacks
var defaultStatusClasses = "fw fw-stack-1x";
var content = $("#operation-response-template").find(".content");
var title = content.find("#title");
var statusIcon = content.find("#status-icon");
var description = content.find("#description");
description.html("");
var successCallBack = function (response) {
var res = response;
try {
res = JSON.parse(response).messageFromServer;
} catch (err) {
//do nothing
}
title.html("Operation Triggered!");
statusIcon.attr("class", defaultStatusClasses + " fw-check");
description.html(res);
console.log("success!");
$(modalPopupContent).html(content.html());
};
var errorCallBack = function (response) {
console.log(response);
title.html("An Error Occurred!");
statusIcon.attr("class", defaultStatusClasses + " fw-error");
var reason = (response.responseText == "null")?response.statusText:response.responseText;
try {
reason = JSON.parse(reason).message;
} catch (err) {
//do nothing
}
description.html(reason);
console.log("Error!");
$(modalPopupContent).html(content.html());
};
//executing http request
if (httpMethod == "GET") {
invokerUtil.get(uri, successCallBack, errorCallBack, contentType);
} else if (httpMethod == "POST") {
var deviceList = [deviceId];
payload = generatePayload(operationCode, payload, deviceList);
invokerUtil.post(uri, payload, successCallBack, errorCallBack, contentType);
} else if (httpMethod == "PUT") {
invokerUtil.put(uri, payload, successCallBack, errorCallBack, contentType);
} else if (httpMethod == "DELETE") {
invokerUtil.delete(uri, successCallBack, errorCallBack, contentType);
} else {
title.html("An Error Occurred!");
statusIcon.attr("class", defaultStatusClasses + " fw-error");
description.html("This operation requires http method: " + httpMethod + " which is not supported yet!");
$(modalPopupContent).html(content.html());
}
}
$(document).on('submit', 'form', function (e) {
cosole.log("darn!!");
e.preventDefault();
var postOperationRequest = $.ajax({
url: $(this).attr("action") + '&' + $(this).serialize(),
method: "post"
});
var btnSubmit = $('#btnSend', this);
btnSubmit.addClass('hidden');
var lblSending = $('#lblSending', this);
lblSending.removeClass('hidden');
var lblSent = $('#lblSent', this);
postOperationRequest.done(function (data) {
lblSending.addClass('hidden');
lblSent.removeClass('hidden');
setTimeout(function () {
hidePopup();
}, 3000);
});
postOperationRequest.fail(function (jqXHR, textStatus) {
lblSending.addClass('hidden');
lblSent.addClass('hidden');
});
});
// Constants to define operation types available
var operationTypeConstants = {
"PROFILE": "profile",
"CONFIG": "config",
"COMMAND": "command"
};
var generatePayload = function (operationCode, operationData, deviceList) {
var payload;
var operationType;
switch (operationCode) {
case windowsOperationConstants["CAMERA_OPERATION_CODE"]:
operationType = operationTypeConstants["PROFILE"];
payload = {
"operation": {
"enabled": operationData["cameraEnabled"]
}
};
break;
case windowsOperationConstants["CHANGE_LOCK_CODE_OPERATION_CODE"]:
operationType = operationTypeConstants["PROFILE"];
payload = {
"operation": {
"lockCode": operationData["lockCode"]
}
};
break;
case windowsOperationConstants["ENCRYPT_STORAGE_OPERATION_CODE"]:
operationType = operationTypeConstants["PROFILE"];
payload = {
"operation": {
"encrypted": operationData["encryptStorageEnabled"]
}
};
break;
case windowsOperationConstants["NOTIFICATION_OPERATION_CODE"]:
operationType = operationTypeConstants["PROFILE"];
payload = {
"operation": {
"message": operationData["message"]
}
};
break;
case windowsOperationConstants["PASSCODE_POLICY_OPERATION_CODE"]:
operationType = operationTypeConstants["PROFILE"];
payload = {
"operation": {
"allowSimple": operationData["passcodePolicyAllowSimple"],
"requireAlphanumeric": operationData["passcodePolicyRequireAlphanumeric"],
"minLength": operationData["passcodePolicyMinLength"],
"minComplexChars": operationData["passcodePolicyMinComplexChars"],
"maxPINAgeInDays": operationData["passcodePolicyMaxPasscodeAgeInDays"],
"pinHistory": operationData["passcodePolicyPasscodeHistory"],
"maxFailedAttempts": operationData["passcodePolicyMaxFailedAttempts"]
}
};
break;
default:
// If the operation is neither of above, it is a command operation
operationType = operationTypeConstants["COMMAND"];
// Operation payload of a command operation is simply an array of device IDs
payload = deviceList;
}
if (operationType == operationTypeConstants["PROFILE"] && deviceList) {
payload["deviceIDs"] = deviceList;
}
return payload;
};
// Constants to define Windows Operation Constants
var windowsOperationConstants = {
"PASSCODE_POLICY_OPERATION_CODE": "PASSCODE_POLICY",
"CAMERA_OPERATION_CODE": "CAMERA",
"ENCRYPT_STORAGE_OPERATION_CODE": "ENCRYPT_STORAGE",
"NOTIFICATION_OPERATION_CODE": "NOTIFICATION",
"CHANGE_LOCK_CODE_OPERATION_CODE": "CHANGE_LOCK_CODE"
};

@ -146,7 +146,7 @@ var windowsOperationModule = function () {
"WIPE_DATA": "wipe-data"
};
//return "/mdm-windows-agent/services/windows/operation/" + featureMap[operationCode];
return "/api/device-mgt/windows/v1.0/services/windows/admin/devices/" + featureMap[operationCode];
return "/api/device-mgt/windows/v1.0/operation/admin/devices/" + featureMap[operationCode];
};
/**

@ -3,6 +3,77 @@
"label": "Windows",
"category": "mobile",
"analyticsEnabled": "false",
"groupingEnabled": "false"
"groupingEnabled": "false",
"features": {
"DEVICE_RING": {
"icon": "fw-dial-up"
},
"DEVICE_LOCK": {
"icon": "fw-lock"
},
"DEVICE_LOCATION": {
"icon": "fw-map-location"
},
"CLEAR_PASSWORD": {
"icon": "fw-clear"
},
"DEVICE_REBOOT": {
"icon": "fw-refresh"
},
"UPGRADE_FIRMWARE": {
"icon": "fw-hardware",
"formParams": [
{
"type": "checkbox",
"id": "immediate",
"optional": true,
"label": "Instant Upgrade",
"helper": "Once enabled, device firmware upgrade process will start instantly."
},
{
"type": "text",
"id": "schedule",
"optional": false,
"label": "Enter the date and time to schedule firmware upgrade."
},
{
"type": "text",
"id": "server",
"optional": true,
"label": "Enter firmware upgrade server URL (ie. http://abc.com or http://abc.com/ota)"
}
]
},
"DEVICE_MUTE": {
"icon": "fw-mute"
},
"NOTIFICATION": {
"icon": "fw-message",
"formParams": [
{
"type": "text",
"id": "messageText",
"optional": false,
"label": "Title Here..."
},
{
"type": "text",
"id": "messageTitle",
"optional": false,
"label": "Message Here..."
}
]
},
"LOCK_RESET": {
"icon": "fw-security"
},
"DISENROLL": {
"icon": "fw-block"
},
"WIPE_DATA": {
"icon": "fw-delete"
}
}
}
}

@ -62,55 +62,63 @@
</DataSource>
<Features>
<Feature code="DEVICE_LOCK">
<Name>Device Lock</Name>
<Description>Lock the device</Description>
<Operation context="windows/lock-devices" method="POST">
</Operation>
</Feature>
<Feature code="DISENROLL">
<Name>Device Lock</Name>
<Name>Disenroll</Name>
<Description>Lock the device</Description>
<Operation context="windows/disenroll-devices" method="POST">
<Operation context="/api/device-mgt/windows/v1.0/admin/devices/disenroll-devices" method="POST" type="application/json">
</Operation>
</Feature>
<Feature code="WIPE_DATA">
<Name>Device Lock</Name>
<Name>Wipe Data</Name>
<Description>Lock the device</Description>
<Operation context="windows/wipe-devices" method="POST">
<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">
</Operation>
</Feature>
<Feature code="DEVICE_LOCK">
<Name>Device Lock</Name>
<Description>Lock the device</Description>
<Operation context="windows/ring-devices" method="POST">
<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</Name>
<Name>Device Lock Reset</Name>
<Description>Lock the device</Description>
<Operation context="windows/lock-reset-devices" method="POST">
<Operation context="/api/device-mgt/windows/v1.0/admin/devices/lock-reset-devices" method="POST" type="application/json">
</Operation>
</Feature>
<Feature code="DEVICE_INFO">
<Name>Device info</Name>
<Description>Request device information</Description>
</Feature>
<Feature code="PASSCODE_POLICY">
<Name>Password Policy</Name>
<Description>Set passcode policy</Description>
<Operation context="" method="POST">
</Operation>
</Feature>
<Feature code="CAMERA">
<Name>Camera Enable/Disable</Name>
<Description>Enable/Disable camera</Description>
<Operation context="" method="POST">
</Operation>
</Feature>
<Feature code="ENCRYPT_STORAGE">
<Name>Encrypt Storage</Name>
<Description>Encrypt the device storage</Description>
<Operation context="" method="POST">
</Operation>
</Feature>
</Features>
<TaskConfiguration>
<Enable>true</Enable>
<Frequency>60000</Frequency>
<Operations>
<Operation>
<Name>DEVICE_INFO</Name>
<RecurrentTimes>1</RecurrentTimes>
</Operation>
</Operations>
</TaskConfiguration>
<DeviceAuthorizationConfig>
<authorizationRequired>false</authorizationRequired>

@ -22,6 +22,7 @@ org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../dep
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.windows.type-view);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.windows.leaflet);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.windows.operation-bar);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.windows.new.operation-bar);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.windows.operation-mod);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../deployment/server/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.windows.date-range-picker);\
org.eclipse.equinox.p2.touchpoint.natives.remove(path:${installFolder}/../../../dbscripts/cdm/plugins/windows);\

Loading…
Cancel
Save