fixed conflicts

revert-dabc3590
Chatura Dilan 8 years ago
commit 49d81766f6

@ -50,6 +50,12 @@
android:label="@string/app_name" >
</service>
<service
android:name="org.wso2.carbon.iot.android.sense.event.streams.battery.BatteryReaderService"
android:enabled="true"
android:label="@string/app_name" >
</service>
<service android:name="org.wso2.carbon.iot.android.sense.event.streams.activity.ActivityReceiver"/>
<receiver android:name="org.wso2.carbon.iot.android.sense.event.SenseScheduleReceiver" >

@ -18,16 +18,18 @@ import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
/**
* This creates and AlarmManagerService that triggers the data uploader service with a 30 seconds interval.
*/
public class DataPublisherReceiver extends BroadcastReceiver {
private static int ALARM_INTERVAL = 30000;
private static int ALARM_INTERVAL = 1000;
@Override
public void onReceive(Context context, Intent intent) {
AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Log.i("Data Publisher", "triggered");
Intent i = new Intent(context, DataPublisherService.class);
PendingIntent pending = PendingIntent.getService(context, 0, i, 0);
service.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), ALARM_INTERVAL, pending);

@ -25,7 +25,7 @@ import java.util.Calendar;
* This is a service which triggers to collect
*/
public class SenseScheduleReceiver extends BroadcastReceiver {
private static final int ALARM_INTERVAL = 5000;
private static final int ALARM_INTERVAL = 1000;
@Override
public void onReceive(Context context, Intent intent) {
@ -35,7 +35,7 @@ public class SenseScheduleReceiver extends BroadcastReceiver {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 30);
cal.add(Calendar.SECOND, 10);
service.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), ALARM_INTERVAL, pending);
}

@ -56,7 +56,7 @@ public class SenseService extends Service {
SenseDataReceiverManager.registerActivityDataReceiver(this);
SenseDataReceiverManager.registerSmsDataReceiver(this);
SenseDataReceiverManager.registerAppDataReceiver(this);
SenseDataReceiverManager.registerNetworkDataReceiver(this);
SenseDataReceiverManager.registerNetworkDataReader(this);
//service will not be stopped until we manually stop the service
return Service.START_NOT_STICKY;
@ -70,7 +70,7 @@ public class SenseService extends Service {
SenseDataReceiverManager.unregisterActivityDataReceiver(this);
SenseDataReceiverManager.unregisterSmsDataReceiver(this);
SenseDataReceiverManager.unregisterAppDataReceiver(this);
SenseDataReceiverManager.unregisterNetworkDataReceiver(this);
SenseDataReceiverManager.unregisterNetworkDataReader();
SenseWakeLock.releaseCPUWakeLock();
super.onDestroy();

@ -13,10 +13,15 @@
*/
package org.wso2.carbon.iot.android.sense.event.streams.battery;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.BatteryManager;
import android.util.Log;
import org.wso2.carbon.iot.android.sense.data.publisher.DataPublisherService;
import org.wso2.carbon.iot.android.sense.util.SenseDataHolder;
/**
@ -24,21 +29,20 @@ import org.wso2.carbon.iot.android.sense.util.SenseDataHolder;
*/
public class BatteryDataReceiver extends BroadcastReceiver {
private final long ALARM_INTERVAL = 1000;
/**
* when the data is retreived then its added to a inmemory map.
* When the data is retrieved then its added to a in memory map.
*
* @param context of the reciever.
* @param intent of the reciver
* @param context of the receiver.
* @param intent of the receiver
*/
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BATTERY_OKAY.equals(intent.getAction())) {
SenseDataHolder.getBatteryDataHolder().add(new BatteryData(BatteryData.State.OK));
} else if (Intent.ACTION_BATTERY_LOW.equals(intent.getAction())) {
SenseDataHolder.getBatteryDataHolder().add(new BatteryData(BatteryData.State.LOW));
} else {
SenseDataHolder.getBatteryDataHolder().add(new BatteryData(intent));
}
AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Log.i("Battery Data Receiver", "Triggered");
Intent i = new Intent(context, BatteryReaderService.class);
PendingIntent pending = PendingIntent.getService(context, 0, i, 0);
service.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), ALARM_INTERVAL, pending);
}
}

@ -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.iot.android.sense.event.streams.battery;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import org.wso2.carbon.iot.android.sense.util.SenseDataHolder;
public class BatteryReaderService extends IntentService {
private Context context;
public BatteryReaderService() {
super("BatteryReaderService");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
protected void onHandleIntent(Intent intent) {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_BATTERY_LOW);
intentFilter.addAction(Intent.ACTION_BATTERY_OKAY);
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
Intent intent1 = registerReceiver(null, intentFilter);
Log.i("Battery Data", String.valueOf(intent1.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)));
if (Intent.ACTION_BATTERY_OKAY.equals(intent.getAction())) {
SenseDataHolder.getBatteryDataHolder().add(new BatteryData(BatteryData.State.OK));
} else if (Intent.ACTION_BATTERY_LOW.equals(intent.getAction())) {
SenseDataHolder.getBatteryDataHolder().add(new BatteryData(BatteryData.State.LOW));
} else {
SenseDataHolder.getBatteryDataHolder().add(new BatteryData(intent1));
}
}
}

@ -23,19 +23,16 @@ import java.util.Date;
public class NetworkData {
//Mobile or Wifi
private String DATA_TYPE;
private String type;
private long dataReceived;
private long dataSent;
private long timeStamp;
public NetworkData(long received, long sent) {
this.dataReceived = received;
this.dataSent = sent;
this.timeStamp = new Date().getTime();
public NetworkData() {
}
public String getDataType() {
return DATA_TYPE;
return type;
}
public long getDataReceived() {
@ -57,4 +54,16 @@ public class NetworkData {
public long getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(long timeStamp) {
this.timeStamp = timeStamp;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}

@ -0,0 +1,97 @@
/*
* 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.iot.android.sense.event.streams.data;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.TrafficStats;
import android.os.AsyncTask;
import android.os.Handler;
import android.util.Log;
import org.wso2.carbon.iot.android.sense.util.SenseDataHolder;
import java.util.Date;
/**
* Class to read data sent and received by the device.
*/
public class NetworkDataReader extends AsyncTask<Void, Void, Long> {
private NetworkData networkData;
private Context context;
private Handler mHandler = new Handler();
private long mStartRX = 0;
private long mStartTX = 0;
private final String WIFI = "WIFI";
private final String MOBILE = "MOBILE";
private String connectionType;
public NetworkDataReader(Context context) {
this.context = context;
}
@Override
protected Long doInBackground(Void... voids) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
networkData = new NetworkData();
if (getConnectionType(connectivityManager, ConnectivityManager.TYPE_WIFI)) {
connectionType = WIFI;
} else if (getConnectionType(connectivityManager, ConnectivityManager.TYPE_MOBILE)) {
connectionType = MOBILE;
}
mStartRX = TrafficStats.getTotalRxBytes();
mStartTX = TrafficStats.getTotalTxBytes();
if (mStartRX == TrafficStats.UNSUPPORTED || mStartTX == TrafficStats.UNSUPPORTED) {
Log.e("ERROR", "Not connected.");
} else {
mHandler.postDelayed(mRunnable, 10000);
}
return null;
}
/**
* Collect data sent and received with in 10 second time frames.
*/
private final Runnable mRunnable = new Runnable() {
public void run() {
long rxBytes = TrafficStats.getTotalRxBytes() - mStartRX;
long txBytes = TrafficStats.getTotalTxBytes() - mStartTX;
Log.i("Usage: ", String.valueOf(rxBytes) + " " + String.valueOf(txBytes) + " " + System.currentTimeMillis());
networkData.setType(connectionType);
networkData.setTimeStamp(new Date().getTime());
networkData.setDataSent(txBytes);
networkData.setDataReceived(rxBytes);
SenseDataHolder.getNetworkDataHolder().add(networkData);
mHandler.postDelayed(mRunnable, 10000);
}
};
/**
* Get the type of the connection currently have.
*/
private boolean getConnectionType(ConnectivityManager manager, Integer type) {
NetworkInfo networkInfo = manager.getNetworkInfo(type);
return networkInfo.isConnected();
}
}

@ -1,42 +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.
*/
package org.wso2.carbon.iot.android.sense.event.streams.data;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import org.wso2.carbon.iot.android.sense.util.SenseDataHolder;
public class NetworkDataReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
long sent = android.net.TrafficStats.getTotalTxBytes();
long received = android.net.TrafficStats.getTotalRxBytes();
Log.d("NetworkData :", "Received: " + sent + " Received : " + received);
NetworkData networkData = new NetworkData(received, sent);
SenseDataHolder.getNetworkDataHolder().add(networkData);
}
}

@ -56,6 +56,7 @@ public class SenseClientAsyncExecutor extends AsyncTask<String, Void, Map<String
private final static String TAG = "SenseService Client";
private static final String STATUS = "status";
private final String PASSWORD_GRANT_TYPE = "password";
private final static String DEVICE_NAME = Build.MANUFACTURER + " " + Build.MODEL;
private Context context;
@ -116,7 +117,7 @@ public class SenseClientAsyncExecutor extends AsyncTask<String, Void, Map<String
new BasicAuthRequestInterceptor(apiApplicationKey.getConsumerKey(), apiApplicationKey.getConsumerSecret()))
.contract(new JAXRSContract()).encoder(new JacksonEncoder()).decoder(new JacksonDecoder())
.target(TokenIssuerService.class, endpoint + SenseConstants.TOKEN_ISSUER_CONTEXT);
accessTokenInfo = tokenIssuerService.getToken("password", username, password, "device_" + deviceId);
accessTokenInfo = tokenIssuerService.getToken(PASSWORD_GRANT_TYPE, username, password, "device_" + deviceId);
//DeviceRegister
AndroidSenseManagerService androidSenseManagerService = Feign.builder().client(disableHostnameVerification)

@ -35,7 +35,7 @@ import org.wso2.carbon.iot.android.sense.event.streams.activity.ActivityReceiver
import org.wso2.carbon.iot.android.sense.event.streams.application.ApplicationDataReceiver;
import org.wso2.carbon.iot.android.sense.event.streams.battery.BatteryDataReceiver;
import org.wso2.carbon.iot.android.sense.event.streams.call.CallDataReceiver;
import org.wso2.carbon.iot.android.sense.event.streams.data.NetworkDataReceiver;
import org.wso2.carbon.iot.android.sense.event.streams.data.NetworkDataReader;
import org.wso2.carbon.iot.android.sense.event.streams.screen.ScreenDataReceiver;
import org.wso2.carbon.iot.android.sense.event.streams.sms.SmsDataReceiver;
@ -52,7 +52,7 @@ public class SenseDataReceiverManager {
private static ApplicationDataReceiver appDataReceiver;
private static NetworkDataReceiver networkDataReceiver;
private static NetworkDataReader networkDataReader;
private SenseDataReceiverManager() {
@ -174,20 +174,20 @@ public class SenseDataReceiverManager {
context.unregisterReceiver(appDataReceiver);
appDataReceiver = null;
}
} public static void registerNetworkDataReceiver(Context context) {
if (networkDataReceiver == null) {
networkDataReceiver = new NetworkDataReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_MANAGE_NETWORK_USAGE);
context.registerReceiver(networkDataReceiver, intentFilter);
}
public static void registerNetworkDataReader(Context context) {
if (networkDataReader == null) {
networkDataReader = new NetworkDataReader(context);
networkDataReader.execute();
}
}
public static void unregisterNetworkDataReceiver(Context context) {
if (networkDataReceiver != null) {
context.unregisterReceiver(networkDataReceiver);
public static void unregisterNetworkDataReader() {
if (networkDataReader != null) {
networkDataReader.cancel(true);
}
networkDataReceiver = null;
networkDataReader = null;
}

@ -21,7 +21,7 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
/**
* This hold the api defintion that is used as a contract with netflix feign.
* This hold the api definition that is used as a contract with netflix feign.
*/
@Path("/token")
public interface TokenIssuerService {
@ -30,4 +30,10 @@ public interface TokenIssuerService {
@Produces(MediaType.APPLICATION_JSON)
AccessTokenInfo getToken(@QueryParam("grant_type") String grant, @QueryParam("username") String username,
@QueryParam("password") String password, @QueryParam("deviceId") String deviceId);
@POST
@Produces(MediaType.APPLICATION_JSON)
AccessTokenInfo getRefreshToken(@QueryParam("grant_type") String grantType, @QueryParam("refreshToken") String refreshToken);
}

@ -0,0 +1,19 @@
@Plan:name('Android-Battery-ExecutionPlan')
@Plan:description('Find the battery status of the android device.')
@Import('org.wso2.iot.android.battery:1.0.0')
define stream BatteryStream (meta_owner string, meta_deviceId string, meta_timestamp long, level int, state string, status string, temperature int);
@Export('org.wso2.iot.android.battery.stats:1.0.0')
define stream BatteryStatsStream (meta_owner string, meta_deviceId string, meta_timestamp long, level int, state
string, status string, temperature int, year int, month int, day int, hour int, minute int);
partition with (meta_deviceId of BatteryStream)
begin
from BatteryStream
select meta_owner, meta_deviceId, meta_timestamp, level, state, status, temperature, time:extract(preState.meta_timestamp, 'year') as year, time:extract(preState.meta_timestamp, 'month') as month, time:extract(preState.meta_timestamp, 'day') as day, time:extract(preState.meta_timestamp, 'hour') as hour, time:extract(preState.meta_timestamp, 'minute') as minute
insert into BatteryStatsStream;
end;

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<artifact name= "android_android_battery_executionplan" version="1.0.0" type="event/execution-plan"
serverRole="DataAnalyticsServer">
<file>Android-Battery-ExecutionPlan.siddhiql</file>
</artifact>

@ -11,7 +11,7 @@ define stream CallStatsStream (meta_owner string, meta_deviceId string, meta_tim
partition with (meta_deviceId of CallStream)
begin
from CallStream[type == 'INCOMING' OR type == 'OUTGOING']
from CallStream
select meta_owner, meta_deviceId, meta_timestamp, number, type, (endTime - startTime) as duration, time:extract(meta_timestamp, 'year') as year, time:extract(meta_timestamp, 'month') as month, time:extract(meta_timestamp, 'day') as day, time:extract(meta_timestamp, 'hour') as hour, time:extract(meta_timestamp, 'minute') as minute
insert into CallStatsStream;
end;

@ -1,17 +1,19 @@
{
"provider-conf": {
"streamName": "org.wso2.iot.android.battery:1.0.0",
"provider-name": "realtime"
"tableName": "ORG_WSO2_IOT_ANDROID_BATTERY_STATS",
"query": "",
"limit": "",
"provider-name": "batch"
},
"chart-conf": {
"x": "TIMESTAMP",
"x": "meta_timestamp",
"xType": "time",
"y": "level",
"yType": "number",
"color": "None",
"mode": "stack",
"maxLength": "30",
"gadget-name": "Android Battery Level Chart",
"gadget-name": "Battery History",
"chart-name": "area-chart"
}
}

@ -0,0 +1,9 @@
{
"id": "Android_Battery_History_Chart",
"title": "Battery History",
"type": "gadget",
"thumbnail": "gadget/Android_Battery_History_Chart/thumbnail.png",
"data": {
"url": "gadget/Android_Battery_History_Chart/gadget.xml"
}
}

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Module>
<ModulePrefs title="Android Battery Level Chart" description="This is a template gadget">
<ModulePrefs title="Battery History" description="This is a template gadget">
<Require feature="dynamic-height"/>
<Require feature="wso2-gadgets-identity"/>
</ModulePrefs>
<UserPref name="windowSize"
display_name="Window Size"
default_value="10"/>
<UserPref name="refreshInterval"
display_name="Refresh Interval"
default_value="1000000"/>
<Content type="html">
<![CDATA[
<head>
@ -25,15 +25,13 @@
<script src="/portal/libs/jquery_1.11.0/jquery-1.11.3.min.js"></script>
<!-- provider libs -->
<script src="js/provider-libs/ws-client.js"></script>
<!-- shared libs -->
<script src="/portal/libs/analytics-wso2-2.0.0/d3.min.js"></script>
<script src="/portal/libs/analytics-wso2-2.0.0/vega.js"></script>
<script src="/portal/libs/analytics-wso2-2.0.0/VizGrammar_2.js"></script>
<script src="/portal/libs/analytics-wso2-2.0.0/VizGrammar.min.js"></script>
<script src="/portal/libs/analytics-wso2-2.0.0/wso2gadgets.js"></script>
@ -45,8 +43,6 @@
<!--scripts copied by framework -->
<script src="js/core/provider-client.js"></script>
<script src="js/core/gadget-util.js"></script>
<script src="js/core/area-chart-api.js"></script>
<script src="js/core/gadget-core.js"></script>

@ -0,0 +1,190 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.
*/
var getConfig, validate, getMode, getSchema, getData, registerCallBackforPush;
(function() {
var PROVIDERS_LOCATION = '/extensions/providers/';
var PROVIDER_NAME = 'batch';
var TYPE = "type";
var TABLE_NAME = "tableName";
var HTTPS_TRANSPORT = "https";
var CONTENT_TYPE_JSON = "application/json";
var AUTHORIZATION_HEADER = "Authorization";
var USER_TOKEN = "user";
var TENANT_DOMAIN = "domain";
var CONST_AT = "@";
var USERNAME = "username";
var HTTP_USER_NOT_AUTHENTICATED = 403;
var JS_MAX_VALUE = "9007199254740992";
var JS_MIN_VALUE = "-9007199254740992";
var typeMap = {
"bool" : "string",
"boolean" : "string",
"string" : "string",
"int" : "number",
"integer" : "number",
"long" : "number",
"double" : "number",
"float" : "number",
"time": "time"
};
var log = new Log();
var carbon = require('carbon');
var configs = require('/configs/designer.json');
var utils = require('/modules/utils.js');
var JSUtils = Packages.org.wso2.carbon.analytics.jsservice.Utils;
var AnalyticsCachedJSServiceConnector = Packages.org.wso2.carbon.analytics.jsservice.AnalyticsCachedJSServiceConnector;
var AnalyticsCache = Packages.org.wso2.carbon.analytics.jsservice.AnalyticsCachedJSServiceConnector.AnalyticsCache;
var cacheTimeoutSeconds = 5;
var loggedInUser = null;
if (configs.cacheTimeoutSeconds) {
cacheTimeoutSeconds = parseInt(configs.cacheTimeoutSeconds);
}
var cacheSizeBytes = 1024 * 1024 * 1024; // 1GB
if (configs.cacheSizeBytes) {
cacheSizeBytes = parseInt(configs.cacheSizeBytes);
}
response.contentType = CONTENT_TYPE_JSON;
var authParam = request.getHeader(AUTHORIZATION_HEADER);
if (authParam != null) {
credentials = JSUtils.authenticate(authParam);
loggedInUser = credentials[0];
} else {
var token = session.get(USER_TOKEN);
if (token != null) {
loggedInUser = token[USERNAME] + CONST_AT + token[TENANT_DOMAIN];
} else {
log.error("user is not authenticated!");
response.status = HTTP_USER_NOT_AUTHENTICATED;
print('{ "status": "Failed", "message": "User is not authenticated." }');
return;
}
}
var cache = application.get("AnalyticsWebServiceCache");
if (cache == null) {
cache = new AnalyticsCache(cacheTimeoutSeconds, cacheSizeBytes);
application.put("AnalyticsWebServiceCache", cache);
}
var connector = new AnalyticsCachedJSServiceConnector(cache);
/**
* require the existing config.json and push any dynamic fields that needs to be populated in the UI
*/
getConfig = function() {
var formConfig = require(PROVIDERS_LOCATION + '/' + PROVIDER_NAME + '/config.json');
var tables;
try {
tables = JSON.parse(connector.getTableList(loggedInUser).getMessage());
} catch (e) {
log.error(e);
}
var configs = formConfig.config;
configs.forEach(function(config) {
if (config.fieldName === TABLE_NAME) {
config.valueSet = tables;
}
});
return formConfig;
}
/**
* validate the user input of provider configuration
* @param providerConfig
*/
validate = function(providerConfig) {
/*
validate the form and return
*/
return true;
}
/**
* returns the data mode either push or pull
*/
getMode = function() {
return "PULL";
}
/**
* returns an array of column names & types
* @param providerConfig
*/
getSchema = function(providerConfig) {
var schema = [];
var tableName = providerConfig["tableName"];
var result = connector.getTableSchema(loggedInUser, tableName).getMessage();
result = JSON.parse(result);
var columns = result.columns;
Object.getOwnPropertyNames(columns).forEach(function(name, idx, array) {
var type = "ordinal";
if(columns[name]['type']) {
type = columns[name]['type'];
}
schema.push({
fieldName: name,
fieldType: typeMap[type.toLowerCase()]
});
});
// log.info(schema);
return schema;
};
/**
* returns the actual data
* @param providerConfig
* @param limit
*/
getData = function(providerConfig, limit) {
var tableName = providerConfig.tableName;
var query = providerConfig.query;
var limit = 100;
if (providerConfig.limit) {
limit = providerConfig.limit;
}
var result;
//if there's a filter present, we should perform a Lucene search instead of reading the table
if (query) {
var filter = {
"query": query,
"start": 0,
"count": limit
};
result = connector.search(loggedInUser, tableName, stringify(filter)).getMessage();
} else {
var from = JS_MIN_VALUE;
var to = JS_MAX_VALUE;
result = connector.getRecordsByRange(loggedInUser, tableName, from, to, 0, limit, null).getMessage();
}
result = JSON.parse(result);
var data = [];
for (var i = 0; i < result.length; i++) {
var values = result[i].values;
data.push(values);
}
return data;
};
}());

@ -19,9 +19,14 @@ $(function () {
var schema;
var pref = new gadgets.Prefs();
var refreshInterval;
var providerData;
var CHART_CONF = 'chart-conf';
var PROVIDER_CONF = 'provider-conf';
var REFRESH_INTERVAL = 'refreshInterval';
var init = function () {
$.ajax({
url: gadgetLocation + '/conf.json',
@ -41,17 +46,33 @@ var init = function () {
}
});
getProviderData();
}
});
};
var getProviderData = function (){
$.ajax({
url: gadgetLocation + '/gadget-controller.jag?action=getData',
method: "POST",
data: JSON.stringify(conf),
contentType: "application/json",
async: false,
success: function (data) {
providerData = data;
}
});
return providerData;
};
var drawGadget = function (){
draw('#canvas', conf[CHART_CONF], schema, null);
registerCallBackforPush(conf[PROVIDER_CONF], schema, function(providerData) {
update(providerData);
});
draw('#canvas', conf[CHART_CONF], schema, providerData);
setInterval(function() {
draw('#canvas', conf[CHART_CONF], schema, getProviderData());
},pref.getInt(REFRESH_INTERVAL));
};

@ -14,7 +14,7 @@
* limitations under the License.
*/
var getGadgetLocation = function (callback) {
var gadgetLocation = "/portal/store/carbon.super/fs/gadget/Android_Battery_Level_Chart";
var gadgetLocation = "/portal/store/carbon.super/fs/gadget/Android_Battery_History_Chart";
var PATH_SEPERATOR = "/";
if (gadgetLocation.search("store") != -1) {
wso2.gadgets.identity.getTenantDomain(function (tenantDomain) {

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<artifact name= "android_battery_history_chart_gadget" version="1.0.0" type="dashboards/gadget"
serverRole="DataAnalyticsServer">
<file>Android_Battery_History_Chart</file>
</artifact>

@ -1,9 +0,0 @@
{
"id": "Android_Battery_Level_Chart",
"title": "Android Battery Level Chart",
"type": "gadget",
"thumbnail": "gadget/Android_Battery_Level_Chart/thumbnail.png",
"data": {
"url": "gadget/Android_Battery_Level_Chart/gadget.xml"
}
}

@ -1,51 +0,0 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.
*/
// var registerCallBackforPush;
(function() {
var callback;
/**
* TODO Need to read hostname,port, and tenantId from providerConfig
* @param providerConfig
* @param schema
*/
registerCallBackforPush = function(providerConfig, schema, _callback) {
var streamId = providerConfig['streamName'];
var hostname = window.parent.location.hostname;
var port = window.parent.location.port;
subscribe(streamId.split(":")[0], streamId.split(":")[1],
'10',
onData, onError,
hostname,
port,
'WEBSOCKET'
);
callback = _callback;
};
function onData(streamId, data) {
callback(data);
};
function onError(error) {
console.error(error);
};
}());

@ -1,154 +0,0 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed 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.
*/
var getConfig, validate, getMode, getSchema, getData, registerCallBackforPush;
(function() {
var PROVIDERS_LOCATION = '/extensions/providers/';
var PROVIDER_NAME = 'realtime';
var log = new Log();
var utils = require('/modules/utils.js');
var carbon = require("carbon");
var EventPublisherConstants = Packages.org.wso2.carbon.event.publisher.core.config.EventPublisherConstants;
var eventPublisherService = carbon.server.osgiService('org.wso2.carbon.event.publisher.core.EventPublisherService');
var eventStreamService = carbon.server.osgiService('org.wso2.carbon.event.stream.core.EventStreamService');
var typeMap = {
"bool": "string",
"boolean": "string",
"string": "string",
"int": "number",
"integer": "number",
"long": "number",
"double": "number",
"float": "number",
"time": "time"
};
getConfig = function() {
var formConfig = require(PROVIDERS_LOCATION + '/' + PROVIDER_NAME + '/config.json');
var datasources = [];
try {
var eventPublisherConfigurationList = eventPublisherService.getAllActiveEventPublisherConfigurations();
for (var i = 0; i < eventPublisherConfigurationList.size(); i++) {
var eventPublisherConfiguration = eventPublisherService.getActiveEventPublisherConfiguration(
eventPublisherConfigurationList.get(i).getEventPublisherName());;
var mappingTypeIsWso2 = eventPublisherConfiguration.getOutputMapping()
.getMappingType().equals(EventPublisherConstants.EF_WSO2EVENT_MAPPING_TYPE);
var adapterType = null;
if (eventPublisherConfiguration.getToAdapterConfiguration() != null) {
adapterType = eventPublisherConfiguration.getToAdapterConfiguration().getType();
}
if (mappingTypeIsWso2 && adapterType.trim() == "ui") {
var streamName = eventPublisherConfiguration.getFromStreamName();
var streamVersion = eventPublisherConfiguration.getFromStreamVersion();
var streamId = streamName + ":" + streamVersion;
datasources.push(streamId);
}
}
var datasourceCfg = {
"fieldLabel": "Event Stream",
"fieldName": "streamName",
"fieldType": "dropDown"
};
datasourceCfg['valueSet'] = datasources;
} catch (e) {
log.error(e);
}
formConfig.config.push(datasourceCfg);
return formConfig;
};
/**
* validate the user input of provider configuration
* @param providerConfig
*/
validate = function(providerConfig) {
/*
validate the form and return
*/
return true;
};
/**
* returns the data mode either push or pull
*/
getMode = function() {
return 'push';
};
/**
* returns an array of column names & types
* @param providerConfig
*/
getSchema = function(providerConfig) {
var streamId = providerConfig["streamName"];
var output = [];
output.push({
fieldName: "TIMESTAMP",
fieldType: "time"
});
if (eventStreamService != null) {
var eventStreamConfiguration = eventStreamService.getEventStreamConfiguration(streamId);
if (eventStreamConfiguration != null) {
var metaData = eventStreamConfiguration.getStreamDefinition().getMetaData();
var correlationData = eventStreamConfiguration.getStreamDefinition().getCorrelationData();
var payloadData = eventStreamConfiguration.getStreamDefinition().getPayloadData();
if (metaData != null) {
for (var i = 0; i < metaData.size(); i++) {
var type = metaData.get(i).getType().toString().toLowerCase();
output.push({
fieldName: metaData.get(i).getName(),
fieldType: typeMap[type.toLowerCase()]
});
}
}
if (correlationData != null) {
for (var i = 0; i < correlationData.size(); i++) {
var type = correlationData.get(i).getType().toString().toLowerCase();
output.push({
fieldName: correlationData.get(i).getName(),
fieldType: typeMap[type.toLowerCase()]
});
}
}
if (payloadData != null) {
for (var i = 0; i < payloadData.size(); i++) {
var type = payloadData.get(i).getType().toString().toLowerCase();
output.push({
fieldName: payloadData.get(i).getName(),
fieldType: typeMap[type.toLowerCase()]
});
}
}
}
}
return output;
};
getData = function(providerConfig,limit) {
var data = [];
return data;
};
}());

@ -1,262 +0,0 @@
/*
* Copyright (c) 2015, 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.
*/
var CONSTANTS = {
urlSeperator: '/',
queryParamStreamName : '?streamname=',
queryParamStreamVersion : '&version=',
queryParamLastUpdatedTime : '&lastUpdatedTime=',
urlSecureTransportWebsocket : 'wss://',
urlSecureTransportHttp : 'https://',
colon : ':',
defaultIntervalTime : 10 * 1000,
defaultHostName : 'localhost',
defaultSecurePortNumber : '9443',
defaultMode : 'AUTO',
processModeHTTP : 'HTTP',
processModeWebSocket : 'WEBSOCKET',
processModeAuto : 'AUTO',
numThousand : 1000,
websocketTimeAppender : 400,
websocketSubscriptionEndpoint : 'portal/uipublisher/websocketSubscriptionEndpoint.jag',
httpEventRetrievalEndpoint : 'portal/uipublisher/httpEventRetrievalEndpoint.jag'
};
var websocket = null;
var webSocketUrl;
var httpUrl;
var cepHostName;
var cepPortNumber;
var isErrorOccured = false;
var lastUpdatedtime = -1;
var polingInterval;
var stream;
var streamVersion;
var firstPollingAttempt;
var processMode;
var onSuccessFunction;
var onErrorFunction;
var terminateWebsocketInstance = false;
var pollingContinue = true;
function subscribe(streamName,version,intervalTime,
listeningFuncSuccessData,listeningFuncErrorData,cepHost,cepPort,mode){
stopPollingProcesses();
stream = streamName;
streamVersion = version;
onSuccessFunction = listeningFuncSuccessData;
onErrorFunction = listeningFuncErrorData;
if(intervalTime == null || intervalTime == ""){
polingInterval = CONSTANTS.defaultIntervalTime;
} else{
polingInterval = intervalTime * CONSTANTS.numThousand;
}
if(cepHost == null || cepHost == ""){
cepHostName = CONSTANTS.defaultHostName;
} else{
cepHostName = cepHost;
}
if(cepPort == null || cepPort == ""){
cepPortNumber = CONSTANTS.defaultSecurePortNumber;
} else{
cepPortNumber = cepPort;
}
if(mode == null || mode == ""){
processMode = CONSTANTS.defaultMode;
} else{
processMode = mode;
}
webSocketUrl = CONSTANTS.urlSecureTransportWebsocket + cepHostName + CONSTANTS.colon + cepPortNumber +
CONSTANTS.urlSeperator + CONSTANTS.websocketSubscriptionEndpoint;
if(processMode == CONSTANTS.processModeHTTP){
firstPollingAttempt = true;
pollingContinue = true;
startPoll();
} else{
initializeWebSocket(webSocketUrl);
}
}
/**
* Initializing Web Socket
*/
function initializeWebSocket(webSocketUrl){
websocket = new WebSocket(webSocketUrl);
websocket.onopen = webSocketOnOpen;
websocket.onmessage = webSocketOnMessage;
websocket.onclose = webSocketOnClose;
websocket.onerror = webSocketOnError;
}
function getWebsocketSubscriptionMessage(streamName, streamVersion, streamProperties, streamValues) {
if (streamProperties.length === streamValues.length) {
var message = {};
message.streamName = streamName;
message.streamVersion = streamVersion;
var i;
for (i = 0; i < streamProperties.length; i++) {
message.filterProps = [];
message.filterProps.push({
'name': streamProperties[i],
'value': streamValues[i]
});
}
return JSON.stringify(message);
} else {
console.log('stream properties and values are not in equal size');
}
}
/**
* Web socket On Open
*/
var webSocketOnOpen = function () {
var filterPropNames = ["meta_deviceId"];
var filterPropVals = ["htc"];
var data = getWebsocketSubscriptionMessage(stream, streamVersion, filterPropNames, filterPropVals);
websocket.send(data);
};
/**
* On server sends a message
*/
var webSocketOnMessage = function (evt) {
var event = evt.data;
var array = JSON.parse(event);
constructPayload(array);
};
/**
* On server close
*/
var webSocketOnClose =function (e) {
if(isErrorOccured){
if(processMode != CONSTANTS.processModeWebSocket){
firstPollingAttempt = true;
pollingContinue = true;
startPoll();
}
} else{
if(!terminateWebsocketInstance){
waitForSocketConnection(websocket);
} else{
terminateWebsocketInstance = false;
}
}
};
/**
* On server Error
*/
var webSocketOnError = function (err) {
var error = "Error: Cannot connect to Websocket URL:" + webSocketUrl + " .Hence closing the connection!";
onErrorFunction(error);
isErrorOccured = true;
};
/**
* Gracefully increments the connection retry
*/
var waitTime = CONSTANTS.numThousand;
function waitForSocketConnection(socket, callback){
setTimeout(
function () {
if (socket.readyState === 1) {
initializeWebSocket(webSocketUrl);
console.log("Connection is made");
if(callback != null){
callback();
}
return;
} else {
websocket = new WebSocket(webSocketUrl);
waitTime += CONSTANTS.websocketTimeAppender;
waitForSocketConnection(websocket, callback);
}
}, waitTime);
}
/**
* Polling to retrieve events from http request periodically
*/
function startPoll(){
(function poll(){
setTimeout(function(){
httpUrl = CONSTANTS.urlSecureTransportHttp + cepHostName + CONSTANTS.colon + cepPortNumber +
CONSTANTS.urlSeperator + CONSTANTS.httpEventRetrievalEndpoint + CONSTANTS.queryParamStreamName + stream +
CONSTANTS.queryParamStreamVersion + streamVersion + CONSTANTS.queryParamLastUpdatedTime + lastUpdatedtime;;
$.getJSON(httpUrl, function(responseText) {
if(firstPollingAttempt){
/*var data = $("textarea#idConsole").val();
$("textarea#idConsole").val(data + "Successfully connected to HTTP.");*/
firstPollingAttempt = false;
}
var eventList = $.parseJSON(responseText.events);
if(eventList.length != 0){
lastUpdatedtime = responseText.lastEventTime;
for(var i=0;i<eventList.length;i++){
var arr = eventList[i];
constructPayload(arr);
}
}
if(pollingContinue){
startPoll();
}
})
.fail(function(errorData) {
var errorData = JSON.parse(errorData.responseText);
onErrorFunction(errorData.error);
});
}, polingInterval);
})()
}
function stopPollingProcesses(){
//stopping the Websocket
if(websocket != null){
terminateWebsocketInstance = true;
websocket.close();
}
//stopping the HTTPS Request
pollingContinue = false;
}
function constructPayload(eventsArray){
var streamId = stream + CONSTANTS.colon + streamVersion;
var twoDimentionalArray = [eventsArray];
onSuccessFunction(streamId,twoDimentionalArray);
}

@ -130,13 +130,40 @@ function getWebsocketSubscriptionMessage(streamName, streamVersion, streamProper
}
}
/**
* Get the parameters as query parameters.
* This method parses those parameters and returns.
* */
function getAllQueryParamsFromURL() {
var queryParamList = {}, qParam;
var urlQueryString = decodeURIComponent(window.top.location.search.substring(1));
if (urlQueryString) {
var queryStringPairs = urlQueryString.split('&');
for (var i = 0; i < queryStringPairs.length; i++) {
qParam = queryStringPairs[i].split('=');
queryParamList[qParam[0]] = qParam[1];
}
return queryParamList;
} else {
return null;
}
}
/**
* Web socket On Open
*/
var webSocketOnOpen = function () {
var filterPropNames = ["meta_deviceId"];
var filterPropVals = ["htc"];
var params = getAllQueryParamsFromURL();
var deviceId;
var owner;
if (params) {
owner = params["owner"];
deviceId = params["deviceId"];
}
var filterPropNames = ["meta_owner", "meta_deviceId"];
var filterPropVals = [owner, deviceId];
var data = getWebsocketSubscriptionMessage(stream, streamVersion, filterPropNames, filterPropVals);
websocket.send(data);
};

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Analytics>
<Editable>true</Editable>
<Name>AndriodCallScript</Name>
<Script> CREATE TEMPORARY TABLE AndroidBatteryData USING CarbonAnalytics OPTIONS(tableName
"ORG_WSO2_IOT_ANDROID_BATTERY_STATS", incrementalParams "ORG_WSO2_IOT_ANDROID_BATTERY_STATS, DAY");
CREATE TEMPORARY TABLE Android_Battery_Stat_Per_Day USING CarbonAnalytics
OPTIONS (tableName "Android_Battery_Stat_Per_Day",
schema "owner STRING, deviceId STRING, type STRING, level INT -i, year INT -i, month INT -i, day INT -i,
timestamp STRING", primaryKeys "year, month, day, deviceId, owner, type", mergeSchema "false");
INSERT INTO TABLE Android_Battery_Stat_Per_Day
SELECT meta_owner as owner, meta_deviceId as deviceId, type, avg(level) as level, year, month, day,
getDateStartingTime(year, month, day) as timestamp
FROM AndroidBatteryData
GROUP BY year, month, day, meta_deviceId, meta_owner, type ORDER BY timestamp DESC;
INCREMENTAL_TABLE_COMMIT ORG_WSO2_IOT_ANDROID_BATTERY_STATS;
</Script>
<CronExpression>0 0/5 * * * ?</CronExpression>
</Analytics>

@ -17,7 +17,7 @@
~ under the License.
-->
<artifact name= "android_battery_level_chart_gadget" version="1.0.0" type="dashboards/gadget" serverRole="DataAnalyticsServer">
<file>Android_Battery_Level_Chart</file>
<artifact name= "android_battery_script" version="1.0.0" type="analytics/spark" serverRole="DataAnalyticsServer">
<file>AndroidBatteryScript.xml</file>
</artifact>

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<artifact name= "android_battery_stats_event_sink" version="1.0.0" type="analytics/eventstore"
serverRole="DataAnalyticsServer">
<file>org_wso2_iot_android_battery_stats.xml</file>
</artifact>

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<EventStoreConfiguration>
<TableSchema>
<ColumnDefinition>
<Name>meta_owner</Name>
<IsFacet>false</IsFacet>
<EnableIndexing>false</EnableIndexing>
<IsPrimaryKey>false</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>STRING</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>meta_deviceId</Name>
<IsFacet>false</IsFacet>
<EnableIndexing>false</EnableIndexing>
<IsPrimaryKey>false</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>STRING</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>meta_timestamp</Name>
<IsFacet>false</IsFacet>
<EnableIndexing>false</EnableIndexing>
<IsPrimaryKey>false</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>LONG</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>level</Name>
<IsFacet>false</IsFacet>
<EnableIndexing>false</EnableIndexing>
<IsPrimaryKey>false</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>INTEGER</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>state</Name>
<IsFacet>false</IsFacet>
<EnableIndexing>false</EnableIndexing>
<IsPrimaryKey>false</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>STRING</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>status</Name>
<IsFacet>false</IsFacet>
<EnableIndexing>false</EnableIndexing>
<IsPrimaryKey>false</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>LONG</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>temperature</Name>
<IsFacet>false</IsFacet>
<EnableIndexing>false</EnableIndexing>
<IsPrimaryKey>false</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>INTEGER</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>year</Name>
<IsFacet>false</IsFacet>
<EnableIndexing>false</EnableIndexing>
<IsPrimaryKey>false</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>INTEGER</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>month</Name>
<IsFacet>false</IsFacet>
<EnableIndexing>false</EnableIndexing>
<IsPrimaryKey>false</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>INTEGER</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>day</Name>
<IsFacet>false</IsFacet>
<EnableIndexing>false</EnableIndexing>
<IsPrimaryKey>false</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>INTEGER</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>hour</Name>
<IsFacet>false</IsFacet>
<EnableIndexing>false</EnableIndexing>
<IsPrimaryKey>false</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>INTEGER</Type>
</ColumnDefinition>
<ColumnDefinition>
<Name>minute</Name>
<IsFacet>false</IsFacet>
<EnableIndexing>false</EnableIndexing>
<IsPrimaryKey>false</IsPrimaryKey>
<EnableScoreParam>false</EnableScoreParam>
<Type>INTEGER</Type>
</ColumnDefinition>
</TableSchema>
<Source>
<StreamId>org.wso2.iot.android.battery.stats:1.0.0</StreamId>
</Source>
<MergeSchema>false</MergeSchema>
<RecordStoreName>PROCESSED_DATA_STORE</RecordStoreName>
</EventStoreConfiguration>

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<artifact name= "android_battery_stats_streams" version="1.0.0" type="event/stream" serverRole="DataAnalyticsServer">
<file>org.wso2.iot.android.battery.stats_1.0.0.json</file>
</artifact>

@ -0,0 +1,58 @@
{
"name": "org.wso2.iot.android.battery.stats",
"version": "1.0.0",
"nickName": "",
"description": "",
"metaData": [
{
"name": "owner",
"type": "STRING"
},
{
"name": "deviceId",
"type": "STRING"
},
{
"name": "timestamp",
"type": "LONG"
}
],
"payloadData": [
{
"name": "level",
"type": "INT"
},
{
"name": "state",
"type": "STRING"
},
{
"name": "status",
"type": "STRING"
},
{
"name": "temperature",
"type": "INT"
},
{
"name": "year",
"type": "INT"
},
{
"name": "month",
"type": "INT"
},
{
"name": "day",
"type": "INT"
},
{
"name": "hour",
"type": "INT"
},
{
"name": "minute",
"type": "INT"
}
]
}

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<artifact name= "android_battery_stats_ui_event_publisher" version="1.0.0" type="event/publisher"
serverRole="DataAnalyticsServer">
<file>org.wso2.iot.android.battery.stats.ui.publisher.xml</file>
</artifact>

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<eventPublisher name="org.wso2.iot.android.battery.stats.ui.publisher"
processing="enable" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventpublisher">
<from streamName="org.wso2.iot.android.battery.stats" version="1.0.0"/>
<mapping customMapping="disable" type="wso2event"/>
<to eventAdapterType="ui"/>
</eventPublisher>

@ -130,18 +130,45 @@ function getWebsocketSubscriptionMessage(streamName, streamVersion, streamProper
}
}
/**
* Get the parameters as query parameters.
* This method parses those parameters and returns.
* */
function getAllQueryParamsFromURL() {
var queryParamList = {}, qParam;
var urlQueryString = decodeURIComponent(window.top.location.search.substring(1));
if (urlQueryString) {
var queryStringPairs = urlQueryString.split('&');
for (var i = 0; i < queryStringPairs.length; i++) {
qParam = queryStringPairs[i].split('=');
queryParamList[qParam[0]] = qParam[1];
}
return queryParamList;
} else {
return null;
}
}
/**
* Web socket On Open
*/
var webSocketOnOpen = function () {
var filterPropNames = ["meta_deviceId"];
var filterPropVals = ["htc"];
var data = getWebsocketSubscriptionMessage(stream, streamVersion, [], []);
var params = getAllQueryParamsFromURL();
var deviceId;
var owner;
if (params != null) {
owner = params["owner"];
deviceId = params["deviceId"];
}
var filterPropNames = ["meta_owner", "meta_deviceId"];
var filterPropVals = [owner, deviceId];
var data = getWebsocketSubscriptionMessage(stream, streamVersion, filterPropNames, filterPropVals);
websocket.send(data);
};
/**
* On server sends a message
*/

@ -130,18 +130,44 @@ function getWebsocketSubscriptionMessage(streamName, streamVersion, streamProper
}
}
/**
* Get the parameters as query parameters.
* This method parses those parameters and returns.
* */
function getAllQueryParamsFromURL() {
var queryParamList = {}, qParam;
var urlQueryString = decodeURIComponent(window.top.location.search.substring(1));
if (urlQueryString) {
var queryStringPairs = urlQueryString.split('&');
for (var i = 0; i < queryStringPairs.length; i++) {
qParam = queryStringPairs[i].split('=');
queryParamList[qParam[0]] = qParam[1];
}
return queryParamList;
} else {
return null;
}
}
/**
* Web socket On Open
*/
var webSocketOnOpen = function () {
var filterPropNames = ["meta_deviceId"];
var filterPropVals = ["htc"];
var params = getAllQueryParamsFromURL();
var deviceId;
var owner;
if (params) {
owner = params["owner"];
deviceId = params["deviceId"];
}
var filterPropNames = ["meta_owner", "meta_deviceId"];
var filterPropVals = [owner, deviceId];
var data = getWebsocketSubscriptionMessage(stream, streamVersion, filterPropNames, filterPropVals);
websocket.send(data);
};
/**
* On server sends a message
*/

@ -130,18 +130,44 @@ function getWebsocketSubscriptionMessage(streamName, streamVersion, streamProper
}
}
/**
* Get the parameters as query parameters.
* This method parses those parameters and returns.
* */
function getAllQueryParamsFromURL() {
var queryParamList = {}, qParam;
var urlQueryString = decodeURIComponent(window.top.location.search.substring(1));
if (urlQueryString) {
var queryStringPairs = urlQueryString.split('&');
for (var i = 0; i < queryStringPairs.length; i++) {
qParam = queryStringPairs[i].split('=');
queryParamList[qParam[0]] = qParam[1];
}
return queryParamList;
} else {
return null;
}
}
/**
* Web socket On Open
*/
var webSocketOnOpen = function () {
var filterPropNames = ["meta_deviceId"];
var filterPropVals = ["htc"];
var params = getAllQueryParamsFromURL();
var deviceId;
var owner;
if (params) {
owner = params["owner"];
deviceId = params["deviceId"];
}
var filterPropNames = ["meta_owner", "meta_deviceId"];
var filterPropVals = [owner, deviceId];
var data = getWebsocketSubscriptionMessage(stream, streamVersion, filterPropNames, filterPropVals);
websocket.send(data);
};
/**
* On server sends a message
*/

@ -130,18 +130,44 @@ function getWebsocketSubscriptionMessage(streamName, streamVersion, streamProper
}
}
/**
* Get the parameters as query parameters.
* This method parses those parameters and returns.
* */
function getAllQueryParamsFromURL() {
var queryParamList = {}, qParam;
var urlQueryString = decodeURIComponent(window.top.location.search.substring(1));
if (urlQueryString) {
var queryStringPairs = urlQueryString.split('&');
for (var i = 0; i < queryStringPairs.length; i++) {
qParam = queryStringPairs[i].split('=');
queryParamList[qParam[0]] = qParam[1];
}
return queryParamList;
} else {
return null;
}
}
/**
* Web socket On Open
*/
var webSocketOnOpen = function () {
var filterPropNames = ["meta_deviceId"];
var filterPropVals = ["htc"];
var params = getAllQueryParamsFromURL();
var deviceId;
var owner;
if (params) {
owner = params["owner"];
deviceId = params["deviceId"];
}
var filterPropNames = ["meta_owner", "meta_deviceId"];
var filterPropVals = [owner, deviceId];
var data = getWebsocketSubscriptionMessage(stream, streamVersion, filterPropNames, filterPropVals);
websocket.send(data);
};
/**
* On server sends a message
*/

@ -130,18 +130,44 @@ function getWebsocketSubscriptionMessage(streamName, streamVersion, streamProper
}
}
/**
* Get the parameters as query parameters.
* This method parses those parameters and returns.
* */
function getAllQueryParamsFromURL() {
var queryParamList = {}, qParam;
var urlQueryString = decodeURIComponent(window.top.location.search.substring(1));
if (urlQueryString) {
var queryStringPairs = urlQueryString.split('&');
for (var i = 0; i < queryStringPairs.length; i++) {
qParam = queryStringPairs[i].split('=');
queryParamList[qParam[0]] = qParam[1];
}
return queryParamList;
} else {
return null;
}
}
/**
* Web socket On Open
*/
var webSocketOnOpen = function () {
var filterPropNames = ["meta_deviceId"];
var filterPropVals = ["htc"];
var params = getAllQueryParamsFromURL();
var deviceId;
var owner;
if (params) {
owner = params["owner"];
deviceId = params["deviceId"];
}
var filterPropNames = ["meta_owner", "meta_deviceId"];
var filterPropVals = [owner, deviceId];
var data = getWebsocketSubscriptionMessage(stream, streamVersion, filterPropNames, filterPropVals);
websocket.send(data);
};
/**
* On server sends a message
*/

@ -130,18 +130,44 @@ function getWebsocketSubscriptionMessage(streamName, streamVersion, streamProper
}
}
/**
* Get the parameters as query parameters.
* This method parses those parameters and returns.
* */
function getAllQueryParamsFromURL() {
var queryParamList = {}, qParam;
var urlQueryString = decodeURIComponent(window.top.location.search.substring(1));
if (urlQueryString) {
var queryStringPairs = urlQueryString.split('&');
for (var i = 0; i < queryStringPairs.length; i++) {
qParam = queryStringPairs[i].split('=');
queryParamList[qParam[0]] = qParam[1];
}
return queryParamList;
} else {
return null;
}
}
/**
* Web socket On Open
*/
var webSocketOnOpen = function () {
var filterPropNames = ["meta_deviceId"];
var filterPropVals = ["htc"];
var params = getAllQueryParamsFromURL();
var deviceId;
var owner;
if (params) {
owner = params["owner"];
deviceId = params["deviceId"];
}
var filterPropNames = ["meta_owner", "meta_deviceId"];
var filterPropVals = [owner, deviceId];
var data = getWebsocketSubscriptionMessage(stream, streamVersion, filterPropNames, filterPropVals);
websocket.send(data);
};
/**
* On server sends a message
*/

@ -130,18 +130,44 @@ function getWebsocketSubscriptionMessage(streamName, streamVersion, streamProper
}
}
/**
* Get the parameters as query parameters.
* This method parses those parameters and returns.
* */
function getAllQueryParamsFromURL() {
var queryParamList = {}, qParam;
var urlQueryString = decodeURIComponent(window.top.location.search.substring(1));
if (urlQueryString) {
var queryStringPairs = urlQueryString.split('&');
for (var i = 0; i < queryStringPairs.length; i++) {
qParam = queryStringPairs[i].split('=');
queryParamList[qParam[0]] = qParam[1];
}
return queryParamList;
} else {
return null;
}
}
/**
* Web socket On Open
*/
var webSocketOnOpen = function () {
var filterPropNames = ["meta_deviceId"];
var filterPropVals = ["htc"];
var params = getAllQueryParamsFromURL();
var deviceId;
var owner;
if (params) {
owner = params["owner"];
deviceId = params["deviceId"];
}
var filterPropNames = ["meta_owner", "meta_deviceId"];
var filterPropVals = [owner, deviceId];
var data = getWebsocketSubscriptionMessage(stream, streamVersion, filterPropNames, filterPropVals);
websocket.send(data);
};
/**
* On server sends a message
*/

@ -586,9 +586,9 @@
{
"content": {
"data": {
"url": "fs://gadget/Android_Battery_Level_Chart/gadget.xml"
"url": "fs://gadget/Android_Battery_History_Chart/gadget.xml"
},
"id": "Android_Battery_Level_Chart",
"id": "Android_Battery_History_Chart",
"locale_titles": {
"en-US": "History"
},
@ -611,11 +611,11 @@
"title": "History",
"titlePosition": "center"
},
"thumbnail": "fs://gadget/Android_Battery_Level_Chart/thumbnail.png",
"title": "Android Battery Level Chart",
"thumbnail": "fs://gadget/Android_Battery_History_Chart/thumbnail.png",
"title": "Android Battery Hisory Chart",
"type": "gadget"
},
"id": "Android_Battery_Level_Chart-0"
"id": "Android_Battery_History_Chart-0"
}
],
"e": [

@ -38,6 +38,8 @@
serverRole="DataAnalyticsServer"/>
<dependency artifact="android_android_audio_executionplan" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
<dependency artifact="android_android_battery_executionplan" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
<dependency artifact="android_android_call_executionplan" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
<dependency artifact="android_android_data_executionplan" version="1.0.0" include="true"
@ -54,11 +56,20 @@
<dependency artifact="android_audio_streams" version="1.0.0" include="true" serverRole="DataAnalyticsServer"/>
<dependency artifact="android_battery_level_chart_gadget" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
<dependency artifact="android_battery_history_chart_gadget" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
<dependency artifact="android_battery_percentage_chart_gadget" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
<dependency artifact="android_battery_script" version="1.0.0" include="true" serverRole="DataAnalyticsServer"/>
<dependency artifact="android_battery_stats_event_sink" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
<dependency artifact="android_battery_stats_streams" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
<dependency artifact="android_battery_streams" version="1.0.0" include="true" serverRole="DataAnalyticsServer"/>
<dependency artifact="android_battery_ui_event_publisher" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
<dependency artifact="android_battery_stats_ui_event_publisher" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>
<dependency artifact="android_call_script" version="1.0.0" include="true" serverRole="DataAnalyticsServer"/>
<dependency artifact="android_call_stats_event_sink" version="1.0.0" include="true"
serverRole="DataAnalyticsServer"/>

@ -280,11 +280,7 @@ public class AndroidSenseServiceImpl implements AndroidSenseService {
if (added) {
AndroidConfiguration androidConfiguration = new AndroidConfiguration();
androidConfiguration.setTenantDomain(APIUtil.getAuthenticatedUserTenantDomain());
String mqttEndpoint = DEFAULT_MQTT_ENDPOINT;
if (mqttEndpoint.contains(AndroidSenseConstants.LOCALHOST)) {
mqttEndpoint = mqttEndpoint.replace(AndroidSenseConstants.LOCALHOST, APIUtil.getServerUrl());
}
androidConfiguration.setMqttEndpoint(mqttEndpoint);
androidConfiguration.setMqttEndpoint(APIUtil.getMqttEndpoint());
return Response.ok(androidConfiguration.toString()).build();
} else {
return Response.status(Response.Status.NOT_ACCEPTABLE.getStatusCode()).entity(false).build();

@ -17,26 +17,9 @@
*/
function onRequest(context) {
var devices = context.unit.params.devices;
var deviceType = context.uriParams.deviceType;
var user = context.user;
var deviceId = request.getParameter("deviceId");
if (devices) {
return {
"devices": stringify(devices),
"backendApiUri": "/android_sense/stats/"
};
} else if (deviceType != null && deviceType != undefined && deviceId != null && deviceId != undefined) {
var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
var device = deviceModule.viewDevice(deviceType, deviceId);
if (device && device.status != "error") {
return {
"device": device.content,
"backendApiUrl": "/android_sense/stats/" + deviceId + "/sensors/"
};
} else {
response.sendError(404, "Device Id " + deviceId + " of type " + deviceType + " cannot be found!");
exit();
}
}
//Redirects to the portal app as we do not use the old analytics view.
response.sendRedirect(context.app.conf["portalURL"] + "/portal/dashboards/android-iot/real-time?owner=" + user.username + "&deviceId=" + deviceId);
}

@ -41,8 +41,6 @@
data-toggle="tab" aria-controls="device_statistics">Device
Statistics</a>
</li>
<li><a class="list-group-item" href="#device_location" role="tab" data-toggle="tab"
aria-controls="device_location">Device Location</a></li>
<li><a class="list-group-item" href="#event_log" role="tab" data-toggle="tab"
aria-controls="event_log">Operations Log</a></li>
{{/zone}}
@ -53,15 +51,6 @@
<div class="panel-heading">Device Statistics</div>
{{unit "cdmf.unit.device.type.android_sense.realtime.analytics-view" device=device}}
</div>
<div class="panel panel-default tab-pane" id="device_location" role="tabpanel"
aria-labelledby="device_location">
<div class="panel-heading">Device Location</div>
<div class="panel-body">
<div id="map" style="height: 400px;">
</div>
<br class="c-both"/>
</div>
</div>
<div class="panel panel-default tab-pane" id="event_log" role="tabpanel"
aria-labelledby="event_log">
<div class="panel-heading">Operations Log <span><a href="#"
@ -85,9 +74,3 @@
</div>
</div>
{{/zone}}
{{#zone "bottomJs"}}
<script async defer
src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true&callback=initMap">
</script>
{{/zone}}

@ -19,98 +19,7 @@
<div id="chartWrapper">
</div>
<div id="div-chart" data-websocketurl="{{websocketEndpoint}}">
<div id="chartWrapper-battery" class="chartWrapper">
<div id="y_axis-battery" class="custom_y_axis" style="margin-top: -20px;">Battery</div>
<div class="legend_container-battery">
<div id="smoother-battery" title="Smoothing"></div>
<div id="legend-battery"></div>
</div>
<div id="chart-battery" class="custom_rickshaw_graph"></div>
<div class="custom_x_axis">Time</div>
</div>
<div id="chartWrapper-light" class="chartWrapper">
<div id="y_axis-light" class="custom_y_axis" style="margin-top: -20px;">Light</div>
<div class="legend_container-light">
<div id="smoother-light" title="Smoothing"></div>
<div id="legend-light"></div>
</div>
<div id="chart-light" class="custom_rickshaw_graph"></div>
<div class="custom_x_axis">Time</div>
</div>
<div id="chartWrapper-pressure" class="chartWrapper">
<div id="y_axis-pressure" class="custom_y_axis" style="margin-top: -20px;">Pressure</div>
<div class="legend_container-pressure">
<div id="smoother-pressure" title="Smoothing"></div>
<div id="legend-pressure"></div>
</div>
<div id="chart-pressure" class="custom_rickshaw_graph"></div>
<div class="custom_x_axis">Time</div>
</div>
<div id="chartWrapper-proximity" class="chartWrapper">
<div id="y_axis-proximity" class="custom_y_axis" style="margin-top: -20px;">Proximity</div>
<div class="legend_container-proximity">
<div id="smoother-proximity" title="Smoothing"></div>
<div id="legend-proximity"></div>
</div>
<div id="chart-proximity" class="custom_rickshaw_graph"></div>
<div class="custom_x_axis">Time</div>
</div>
<div id="chartWrapper-accelerometer" class="chartWrapper">
<div id="y_axis-accelerometer" class="custom_y_axis" style="margin-top: -20px;">Accelerometer</div>
<div class="legend_container-accelerometer">
<div id="smoother-accelerometer" title="Smoothing"></div>
<div id="legend-accelerometer"></div>
</div>
<div id="chart-accelerometer" class="custom_rickshaw_graph"></div>
<div class="custom_x_axis">Time</div>
</div>
<div id="chartWrapper-magnetic" class="chartWrapper">
<div id="y_axis-magnetic" class="custom_y_axis" style="margin-top: -20px;">Magnetic</div>
<div class="legend_container-magnetic">
<div id="smoother-magnetic" title="Smoothing"></div>
<div id="legend-magnetic"></div>
</div>
<div id="chart-magnetic" class="custom_rickshaw_graph"></div>
<div class="custom_x_axis">Time</div>
</div>
<div id="chartWrapper-rotation" class="chartWrapper">
<div id="y_axis-rotation" class="custom_y_axis" style="margin-top: -20px;">Rotation</div>
<div class="legend_container-rotation">
<div id="smoother-rotation" title="Smoothing"></div>
<div id="legend-rotation"></div>
</div>
<div id="chart-rotation" class="custom_rickshaw_graph"></div>
<div class="custom_x_axis">Time</div>
</div>
<div id="chartWrapper-gyroscope" class="chartWrapper">
<div id="y_axis-gyroscope" class="custom_y_axis" style="margin-top: -20px;">Gyroscope</div>
<div class="legend_container-gyroscope">
<div id="smoother-gyroscope" title="Smoothing"></div>
<div id="legend-gyroscope"></div>
</div>
<div id="chart-gyroscope" class="custom_rickshaw_graph"></div>
<div class="custom_x_axis">Time</div>
</div>
<div id="chartWrapper-gravity" class="chartWrapper">
<div id="y_axis-gravity" class="custom_y_axis" style="margin-top: -20px;">Gravity</div>
<div class="legend_container-gravity">
<div id="smoother-gravity" title="Smoothing"></div>
<div id="legend-gravity"></div>
</div>
<div id="chart-gravity" class="custom_rickshaw_graph"></div>
<div class="custom_x_axis">Time</div>
</div>
</div>
<a class="padding-left"
href="{{@app.context}}/device/{{device.type}}/analytics?deviceId={{device.deviceIdentifier}}&deviceName={{device.name}}">
<span class="fw-stack">

@ -73,8 +73,12 @@ public class ApplicationOperationsImpl implements ApplicationOperations {
getDevicesOfUser(userName);
for (org.wso2.carbon.device.mgt.common.Device device : deviceList) {
if(applicationOperationAction.getApp().getPlatform().equalsIgnoreCase(device.getType())){
deviceIdentifiers.add(getDeviceIdentifierByDevice(device));
if(MDMAppConstants.WEBAPP.equals(applicationOperationAction.getApp().getPlatform()) ||
applicationOperationAction.getApp().getPlatform().equalsIgnoreCase(device.getType())){
if (MDMAppConstants.ACTIVE.equalsIgnoreCase(device.getEnrolmentInfo().
getStatus().toString())) {
deviceIdentifiers.add(getDeviceIdentifierByDevice(device));
}
}
}
}
@ -95,7 +99,9 @@ public class ApplicationOperationsImpl implements ApplicationOperations {
getAllDevicesOfRole(userRole);
for (org.wso2.carbon.device.mgt.common.Device device : deviceList) {
deviceIdentifiers.add(getDeviceIdentifierByDevice(device));
if (MDMAppConstants.ACTIVE.equalsIgnoreCase(device.getEnrolmentInfo().getStatus().toString())) {
deviceIdentifiers.add(getDeviceIdentifierByDevice(device));
}
}
}
} catch (DeviceManagementException devMgtEx) {
@ -176,8 +182,11 @@ public class ApplicationOperationsImpl implements ApplicationOperations {
operation =
IOSApplicationOperationUtil.createInstallAppOperation(mobileApp);
} else {
operation =
IOSApplicationOperationUtil.createAppUninstallOperation(mobileApp);
if (MDMAppConstants.WEBAPP.equals(app.getPlatform())) {
operation = IOSApplicationOperationUtil.createWebClipUninstallOperation(mobileApp);
} else {
operation = IOSApplicationOperationUtil.createAppUninstallOperation(mobileApp);
}
}
}
activity = MDMServiceAPIUtils.getAppManagementService(applicationOperationAction.getTenantId())
@ -225,11 +234,21 @@ public class ApplicationOperationsImpl implements ApplicationOperations {
throws MobileApplicationException {
List<Device> devices;
List<org.wso2.carbon.device.mgt.common.Device> deviceList = null;
try {
List<org.wso2.carbon.device.mgt.common.Device> deviceList = MDMServiceAPIUtils
.getDeviceManagementService(applicationOperationDevice.getTenantId()).
getDevicesOfUser(
applicationOperationDevice.getCurrentUser().getUsername());
if(MDMAppConstants.WEBAPP.equals
(applicationOperationDevice.getPlatform())) {
deviceList = MDMServiceAPIUtils
.getDeviceManagementService(applicationOperationDevice.getTenantId()).
getDevicesOfUser(
applicationOperationDevice.getCurrentUser().getUsername());
} else {
deviceList = MDMServiceAPIUtils
.getDeviceManagementService(applicationOperationDevice.getTenantId()).
getDevicesOfUser(
applicationOperationDevice.getCurrentUser().getUsername(),
applicationOperationDevice.getPlatform());
}
devices = new ArrayList<>(deviceList.size());
if(log.isDebugEnabled()){
log.debug("device list got from mdm "+ deviceList.toString());

@ -23,6 +23,15 @@ import java.io.Serializable;
public class RemoveApplication implements Serializable {
private String bundleId;
private String url;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getBundleId() {
return bundleId;

@ -111,4 +111,21 @@ public class IOSApplicationOperationUtil {
return operation;
}
/**
* Create uninstall operations for webclip.
*
* @param application
* @return Uninstall operation
* @throws DeviceApplicationException
*/
public static Operation createWebClipUninstallOperation(MobileApp application) throws
DeviceApplicationException {
ProfileOperation operation = new ProfileOperation();
operation.setCode(MDMAppConstants.IOSConstants.OPCODE_REMOVE_APPLICATION);
operation.setType(Operation.Type.PROFILE);
RemoveApplication removeApplication = new RemoveApplication();
removeApplication.setUrl(application.getIdentifier());
operation.setPayLoad(removeApplication.toJSON());
return operation;
}
}

@ -0,0 +1,85 @@
{{!
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.
}}
{{#zone "topCss"}}
<style>
.thumbnail.icon:before {
padding-top: 0;
}
</style>
{{/zone}}
{{#zone "device-thumbnail"}}
<img src="{{@unit.publicUri}}/images/respberry-icon.png"/>
{{/zone}}
{{#zone "device-opetations"}}
<div style="background: #11375B; color: #fff; padding: 10px; margin-bottom: 5px">
Operations
</div>
<div class="add-margin-top-4x">
{{unit "iot.unit.device.operation-bar" device=device backendApiUri=backendApiUri autoCompleteParams=autoCompleteParams}}
</div>
{{/zone}}
{{#zone "device-detail-properties"}}
<div class="media">
<div class="media-left col-xs-12 col-sm-2 col-md-2 col-lg-2">
<ul class="list-group" role="tablist">
<li class="active"><a class="list-group-item" href="#device_statistics" role="tab"
data-toggle="tab" aria-controls="device_statistics">Device
Statistics</a>
</li>
<li><a class="list-group-item" href="#event_log" role="tab" data-toggle="tab"
aria-controls="event_log">Operations Log</a></li>
</ul>
</div>
<div class="media-body add-padding-left-5x remove-padding-xs tab-content">
<div class="panel-group tab-content">
<div class="panel panel-default tab-pane active"
id="device_statistics" role="tabpanel" aria-labelledby="device_statistics">
<div class="panel-heading">Device Statistics</div>
{{unit "cdmf.unit.device.type.raspberrypi.realtime.analytics-view" device=device}}
</div>
<div class="panel panel-default tab-pane" id="event_log" role="tabpanel"
aria-labelledby="event_log">
<div class="panel-heading">Operations Log <span><a href="#"
id="refresh-operations"><i
class="fw fw-refresh"></i></a></span></div>
<div class="panel-body">
<div id="operations-spinner" class="wr-advance-operations-init hidden">
<br>
<i class="fw fw-settings fw-spin fw-2x"></i>
Loading Operations Log . . .
<br>
<br>
</div>
<div id="operations-log-container">
<div class="panel-body">
Not available yet
</div>
<br class="c-both"/>
</div>
</div>
</div>
</div>
</div>
</div>
{{/zone}}

@ -276,25 +276,52 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
@Path("/{id}")
@Override
public Response modifyEnrollment(@PathParam("id") String id, @Valid AndroidDevice androidDevice) {
Device device = new Device();
String msg = "";
device.setType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_ANDROID);
if(androidDevice.getEnrolmentInfo().getDateOfEnrolment() <= 0){
msg = "Invalid Enrollment date.";
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
Device device;
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(id);
deviceIdentifier.setType(AndroidConstants.DEVICE_TYPE_ANDROID);
try {
device = AndroidAPIUtils.getDeviceManagementService().getDevice(deviceIdentifier);
} catch (DeviceManagementException e) {
String msg = "Error occurred while getting enrollment details of the Android device that carries the id '" +
id + "'";
log.error(msg, e);
throw new UnexpectedServerErrorException(
new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
}
if(androidDevice.getEnrolmentInfo().getDateOfLastUpdate() <= 0){
msg = "Invalid Last Updated date.";
return Response.status(Response.Status.BAD_REQUEST).entity(msg).build();
if (androidDevice == null) {
String errorMessage = "The payload of the android device enrollment is incorrect.";
log.error(errorMessage);
throw new org.wso2.carbon.mdm.services.android.exception.BadRequestException(
new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(errorMessage).build());
}
if (device == null) {
String errorMessage = "The device to be modified doesn't exist.";
log.error(errorMessage);
throw new org.wso2.carbon.mdm.services.android.exception.NotFoundException(
new ErrorResponse.ErrorResponseBuilder().setCode(404l).setMessage(errorMessage).build());
}
if(androidDevice.getEnrolmentInfo() != null){
device.setEnrolmentInfo(device.getEnrolmentInfo());
}
device.setEnrolmentInfo(androidDevice.getEnrolmentInfo());
device.getEnrolmentInfo().setOwner(AndroidAPIUtils.getAuthenticatedUser());
device.setDeviceInfo(androidDevice.getDeviceInfo());
if(androidDevice.getDeviceInfo() != null) {
device.setDeviceInfo(androidDevice.getDeviceInfo());
}
device.setDeviceIdentifier(androidDevice.getDeviceIdentifier());
device.setDescription(androidDevice.getDescription());
device.setName(androidDevice.getName());
device.setFeatures(androidDevice.getFeatures());
device.setProperties(androidDevice.getProperties());
if(androidDevice.getDescription() != null) {
device.setDescription(androidDevice.getDescription());
}
if(androidDevice.getName() != null) {
device.setName(androidDevice.getName());
}
if(androidDevice.getFeatures() != null) {
device.setFeatures(androidDevice.getFeatures());
}
if(androidDevice.getProperties() != null) {
device.setProperties(androidDevice.getProperties());
}
boolean result;
try {
device.setType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_ANDROID);
@ -313,7 +340,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService {
return Response.status(Response.Status.NOT_MODIFIED).entity(responseMessage).build();
}
} catch (DeviceManagementException e) {
msg = "Error occurred while modifying enrollment of the Android device that carries the id '" +
String msg = "Error occurred while modifying enrollment of the Android device that carries the id '" +
id + "'";
log.error(msg, e);
throw new UnexpectedServerErrorException(

@ -1,32 +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.
}}
{{unit "cdmf.unit.device.type.android.date-range-picker"}}
{{#zone "content"}}
<div id="operations-mod" data-permissions="{{permissions}}" data-device-type="{{deviceType}}" data-ownership="{{ownership}}">
{{unit "cdmf.unit.device.type.android.operation-mod"}}
</div>
{{/zone}}
{{#zone "bottomJs"}}
<!--suppress HtmlUnknownTarget -->
<script id="operations-bar" src="{{@unit.publicUri}}/templates/operations.hbs"
type="text/x-handlebars-template"></script>
{{js "js/operation-bar.js"}}
{{/zone}}

@ -1,106 +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.
*/
function onRequest(context) {
var log = new Log("cdmf.unit.device.type.android.operation-bar");
var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
var viewModel = {};
var permissions = {};
// adding android operations related permission checks
permissions["android"] = [];
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning-device/operations/android/ring")) {
permissions["android"].push("DEVICE_RING");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning-device/operations/android/lock")) {
permissions["android"].push("DEVICE_LOCK");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning-device/operations/android/unlock")) {
permissions["android"].push("DEVICE_UNLOCK");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning-device/operations/android/location")) {
permissions["android"].push("DEVICE_LOCATION");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning-device/operations/android/clear-password")) {
permissions["android"].push("CLEAR_PASSWORD");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning-device/operations/android/reboot")) {
permissions["android"].push("DEVICE_REBOOT");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning-device/operations/android/upgrade-firmware")) {
permissions["android"].push("UPGRADE_FIRMWARE");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning-device/operations/android/mute")) {
permissions["android"].push("DEVICE_MUTE");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning-device/operations/android/send-notification")) {
permissions["android"].push("NOTIFICATION");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning-device/operations/android/change-lock-code")) {
permissions["android"].push("CHANGE_LOCK_CODE");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning-device/operations/android/enterprise-wipe")) {
permissions["android"].push("ENTERPRISE_WIPE");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning-device/operations/android/wipe")) {
permissions["android"].push("WIPE_DATA");
}
// adding ios operations related permission checks
permissions["ios"] = [];
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning/operations/ios/lock")) {
permissions["ios"].push("DEVICE_LOCK");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning/operations/ios/location")) {
permissions["ios"].push("LOCATION");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning/operations/ios/enterprise-wipe")) {
permissions["ios"].push("ENTERPRISE_WIPE");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning/operations/ios/notification")) {
permissions["ios"].push("NOTIFICATION");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning/operations/ios/ring")) {
permissions["ios"].push("RING");
}
// adding windows operations related permission checks
permissions["windows"] = [];
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning/operations/windows/lock")) {
permissions["windows"].push("DEVICE_LOCK");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/disenroll/windows")) {
permissions["windows"].push("DISENROLL");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning/operations/windows/wipe")) {
permissions["windows"].push("WIPE_DATA");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning/operations/windows/ring")) {
permissions["windows"].push("DEVICE_RING");
}
if (userModule.isAuthorized("/permission/admin/device-mgt/devices/owning/operations/windows/lock-reset")) {
permissions["windows"].push("LOCK_RESET");
}
viewModel["permissions"] = stringify(permissions);
viewModel["deviceType"] = context.unit.params.deviceType;
viewModel["ownership"] = context.unit.params.ownership;
return viewModel;
}

@ -1,248 +0,0 @@
/*
* Copyright (c) 2015, 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.
*/
/*
* Setting-up global variables.
*/
var operations = '.wr-operations',
modalPopup = '.modal',
modalPopupContent = modalPopup + ' .modal-content',
navHeight = $('#nav').height(),
headerHeight = $('header').height(),
offset = (headerHeight + navHeight),
deviceSelection = '.device-select',
platformTypeConstants = {
"ANDROID": "android",
"IOS": "ios",
"WINDOWS": "windows"
},
ownershipTypeConstants = {
"BYOD": "BYOD",
"COPE": "COPE"
},
operationBarModeConstants = {
"BULK": "BULK_OPERATION_MODE",
"SINGLE": "SINGLE_OPERATION_MODE"
};
/*
* Function to get selected devices ID's
*/
function getSelectedDeviceIds() {
var deviceIdentifierList = [];
$(deviceSelection).each(function (index) {
var device = $(this);
var deviceId = device.data('deviceid');
var deviceType = device.data('type');
deviceIdentifierList.push({
"id": deviceId,
"type": deviceType
});
});
if (deviceIdentifierList.length == 0) {
var thisTable = $(".DTTT_selected").closest('.dataTables_wrapper').find('.dataTable').dataTable();
thisTable.api().rows().every(function () {
if ($(this.node()).hasClass('DTTT_selected')) {
var deviceId = $(thisTable.api().row(this).node()).data('deviceid');
var deviceType = $(thisTable.api().row(this).node()).data('devicetype');
deviceIdentifierList.push({
"id": deviceId,
"type": deviceType
});
}
});
}
return deviceIdentifierList;
}
/*
* On operation click function.
* @param selection: Selected operation
*/
function operationSelect(selection) {
var deviceIdList = getSelectedDeviceIds();
if (deviceIdList == 0) {
$(modalPopupContent).html($("#errorOperations").html());
} else {
$(modalPopupContent).addClass("operation-data");
$(modalPopupContent).html($(operations + " .operation[data-operation-code=" + selection + "]").html());
$(modalPopupContent).data("operation-code", selection);
}
showPopup();
}
function getDevicesByTypes(deviceList) {
var deviceTypes = {};
$.each(deviceList, function (index, item) {
if (!deviceTypes[item.type]) {
deviceTypes[item.type] = [];
}
if (item.type == platformTypeConstants.ANDROID ||
item.type == platformTypeConstants.IOS || item.type == platformTypeConstants.WINDOWS) {
deviceTypes[item.type].push(item.id);
}
});
return deviceTypes;
}
//function unloadOperationBar() {
// $("#showOperationsBtn").addClass("hidden");
// $(".wr-operations").html("");
//}
function loadOperationBar(deviceType, ownership, mode) {
var operationBar = $("#operations-bar");
var operationBarSrc = operationBar.attr("src");
$.template("operations-bar", operationBarSrc, function (template) {
var serviceURL = "/api/device-mgt/v1.0/devices/" + deviceType + "/*/features";
invokerUtil.get(
serviceURL,
// success callback
function (data) {
var permittedOperations = [];
var i;
var permissionList = $("#operations-mod").data("permissions");
var totalFeatures = JSON.parse(data);
for (i = 0; i < permissionList[deviceType].length; i++) {
var j;
for (j = 0; j < totalFeatures.length; j++) {
if (permissionList[deviceType][i] == totalFeatures[j]["code"]) {
if (deviceType == platformTypeConstants.ANDROID) {
if (totalFeatures[j]["code"] == "DEVICE_UNLOCK") {
if (ownership == ownershipTypeConstants.COPE) {
permittedOperations.push(totalFeatures[j]);
}
} else if (totalFeatures[j]["code"] == "WIPE_DATA") {
if (mode == operationBarModeConstants.BULK) {
if (ownership == ownershipTypeConstants.COPE) {
permittedOperations.push(totalFeatures[j]);
}
} else {
permittedOperations.push(totalFeatures[j]);
}
} else {
permittedOperations.push(totalFeatures[j]);
}
} else {
permittedOperations.push(totalFeatures[j]);
}
}
}
}
var viewModel = {};
permittedOperations = permittedOperations.filter(function (current) {
var iconName;
switch (deviceType) {
case platformTypeConstants.ANDROID:
iconName = operationModule.getAndroidIconForFeature(current.code);
break;
case platformTypeConstants.WINDOWS:
iconName = operationModule.getWindowsIconForFeature(current.code);
break;
case platformTypeConstants.IOS:
iconName = operationModule.getIOSIconForFeature(current.code);
break;
}
/* adding ownership in addition to device-type
as it's vital in cases where UI for the same feature should change
according to ownership
*/
if (ownership) {
current.ownership = ownership;
}
if (iconName) {
current.icon = iconName;
}
return current;
});
viewModel.features = permittedOperations;
var content = template(viewModel);
$(".wr-operations").html(content);
},
// error callback
function (message) {
$(".wr-operations").html(message);
});
});
}
function runOperation(operationName) {
var deviceIdList = getSelectedDeviceIds();
var list = getDevicesByTypes(deviceIdList);
var successCallback = function (data) {
if (operationName == "NOTIFICATION") {
$(modalPopupContent).html($("#messageSuccess").html());
} else {
$(modalPopupContent).html($("#operationSuccess").html());
}
showPopup();
};
var errorCallback = function (data) {
$(modalPopupContent).html($("#errorOperationUnexpected").html());
showPopup();
};
var payload, serviceEndPoint;
if (list[platformTypeConstants.IOS]) {
payload =
operationModule.generatePayload(platformTypeConstants.IOS, operationName, list[platformTypeConstants.IOS]);
serviceEndPoint = operationModule.getIOSServiceEndpoint(operationName);
} else if (list[platformTypeConstants.ANDROID]) {
payload = operationModule
.generatePayload(platformTypeConstants.ANDROID, operationName, list[platformTypeConstants.ANDROID]);
serviceEndPoint = operationModule.getAndroidServiceEndpoint(operationName);
} else if (list[platformTypeConstants.WINDOWS]) {
payload = operationModule.generatePayload(platformTypeConstants.WINDOWS, operationName,
list[platformTypeConstants.WINDOWS]);
serviceEndPoint = operationModule.getWindowsServiceEndpoint(operationName);
}
if (operationName == "NOTIFICATION") {
var errorMsgWrapper = "#notification-error-msg";
var errorMsg = "#notification-error-msg span";
var messageTitle = $("#messageTitle").val();
var messageText = $("#messageText").val();
if (!(messageTitle && messageText)) {
$(errorMsg).text("Enter a message. It cannot be empty.");
$(errorMsgWrapper).removeClass("hidden");
} else {
invokerUtil.post(serviceEndPoint, payload, successCallback, errorCallback);
$(modalPopupContent).removeData();
hidePopup();
}
} else {
invokerUtil.post(serviceEndPoint, payload, successCallback, errorCallback);
$(modalPopupContent).removeData();
hidePopup();
}
}
/*
* DOM ready functions.
*/
$(document).ready(function () {
$(operations).show();
});

@ -1,286 +0,0 @@
<div class="row no-gutter">
<div class="wr-hidden-operations-nav col-lg-4">
<a href="javascript:void(0)" onclick="showAdvanceOperation('security', this)" class="selected">
<span class="wr-hidden-operations-icon fw-stack">
<i class="fw fw-padlock fw-stack-2x"></i>
</span>
Security
</a>
<a href="javascript:void(0)" onclick="showAdvanceOperation('restriction', this)">
<span class="wr-hidden-operations-icon fw-stack">
<i class="fw fw-settings fw-stack-2x"></i>
</span>
Restrictions
</a>
<a href="javascript:void(0)" onclick="showAdvanceOperation('application', this)">
<span class="wr-hidden-operations-icon fw-stack">
<i class="fw fw-padlock fw-stack-2x"></i>
</span>
Applications
</a>
<a href="javascript:void(0)" onclick="showAdvanceOperation('wifi', this)">
<span class="wr-hidden-operations-icon fw-stack">
<i class="fw fw-wifi fw-stack-2x"></i>
</span>
Wi-fi
</a>
</div>
<div class="wr-hidden-operations-content col-lg-8">
<!-- security -->
<div class="wr-hidden-operation" data-operation="security" style="display: block">
<div class="panel panel-default operation-data" data-operation="{{features.ENCRYPT_STORAGE.code}}">
<div class="panel-heading" role="tab">
<h2 class="sub-title panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#enableEncryptionTab"
aria-expanded="true" aria-controls="enableEncryptionTab">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-arrow fw-down-arrow fw-stack-1x"></i>
</span>
Encryption Enable/Disable
</a>
</h2>
</div>
<div id="enableEncryptionTab" class="panel-collapse panel-body collapse in" role="tabpanel"
aria-labelledby="enableEncryptionTab">
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" class="operationDataKeys" id="enableEncryption"
data-key="enableEncryption"/>
<span class="helper" title="Enable Encryption">Enable Encryption<span
class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
</div>
<a href="javascript:runOperation('{{features.ENCRYPT_STORAGE.code}}')" class="btn-operations">Configure</a>
</div>
</div>
<div class="panel panel-default operation-data" data-operation="{{features.PASSCODE_POLICY.code}}">
<div class="panel-heading" role="tab">
<h2 class="sub-title panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#passCodePolicy" aria-expanded="false"
aria-controls="passCodePolicy" class="collapsed">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-arrow fw-down-arrow fw-stack-1x"></i>
</span>
Passcode Policy
</a>
</h2>
</div>
<div id="passCodePolicy" class="panel-collapse panel-body collapse" role="tabpanel"
aria-labelledby="passCodePolicy">
<label class="wr-input-label col-sm-4" for="maxFailedAttempts">Maximum Failed Attempts</label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="maxFailedAttempts"
data-key="maxFailedAttempts" placeholder="Enter maximum Failed Attempts">
</div>
<label class="wr-input-label col-sm-4" for="minLength">Minimum Length</label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="minLength" data-key="minLength"
placeholder="Enter minimum Length">
</div>
<label class="wr-input-label col-sm-4" for="pinHistory">PIN History</label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="pinHistory" data-key="pinHistory"
placeholder="Enter PIN History">
</div>
<label class="wr-input-label col-sm-4" for="minComplexChars">Minimum complex characters</label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="minComplexChars"
data-key="minComplexChars" placeholder="Enter minimum complex characters">
</div>
<label class="wr-input-label col-sm-4" for="lockcode">Minimum PIN Age in days</label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="maxPINAgeInDays"
data-key="maxPINAgeInDays" placeholder="Enter minimum PIN age in days">
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" class="operationDataKeys" id="requireAlphanumeric"
data-key="requireAlphanumeric"/>
<span class="helper" title="Require Alphanumeric">Require Alphanumeric<span
class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" class="operationDataKeys" id="allowSimple" data-key="allowSimple"/>
<span class="helper" title="Allow simple PIN">Allow simple PIN<span
class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
</div>
<a href="javascript:runOperation('{{features.PASSCODE_POLICY.code}}')" class="btn-operations">Configure</a>
</div>
</div>
</div>
<!-- /security -->
<!-- wi-fi -->
<div class="wr-hidden-operation panel-body" data-operation="wifi">
<div class="operation-data" data-operation="{{features.WIFI.code}}">
<label class="wr-input-label" title="Identification of the wireless network to connect to">Service Set
Identifier<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<!--span>Identification of the wireless network to connect to</span-->
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="ssid" data-key="ssid"
placeholder="Enter SSID"/>
</div>
<label class="wr-input-label" title="Password for the wireless network">Password<span
class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<!--span>Password for the wireless network</span-->
<div class="wr-input-control">
<input type="password" class="form-control operationDataKeys" id="password" data-key="password"
placeholder="Password"/>
</div>
<a href="javascript:runOperation('{{features.WIFI.code}}')" class="btn-operations">Configure</a>
</div>
</div>
<!-- /wi-fi -->
<!-- application -->
<div class="wr-hidden-operation" data-operation="application">
<div class="panel panel-default operation-data" data-operation="{{features.INSTALL_APPLICATION.code}}">
<div class="panel-heading" role="tab">
<h2 class="sub-title panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#installApp" aria-expanded="true"
aria-controls="installApp">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-arrow fw-down-arrow fw-stack-1x"></i>
</span>
Install App
</a>
</h2>
</div>
<div id="installApp" class="panel-collapse panel-body collapse in" role="tabpanel"
aria-labelledby="installApp">
<label class="wr-input-label" title="Application Identifier">App Identifier<span
class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="package-name"
data-key="packageName" placeholder="Enter App Identifer"/>
</div>
<div class="wr-input-control">
<label class="wr-input-control dropdown">
<span class="helper" title="App Type">App Type<span
class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
<select class="form-control col-sm-8 operationDataKeys appTypesInput" id="type"
data-key="type">
<option>Public</option>
<option>Enterprise</option>
</select>
</label>
</div>
<label class="wr-input-label" title="URL">URL<span
class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="url" data-key="url"
placeholder="Enter URL"/>
</div>
<a href="javascript:runOperation('{{features.INSTALL_APPLICATION.code}}')" class="btn-operations">Install</a>
</div>
</div>
<div class="panel panel-default operation-data" data-operation="{{features.WEBCLIP.code}}">
<div class="panel-heading" role="tab">
<h2 class="sub-title panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#installWebClip" aria-expanded="true"
aria-controls="installWebClip" class="collapsed">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-arrow fw-down-arrow fw-stack-1x"></i>
</span>
Install Web Clip
</a>
</h2>
</div>
<div id="installWebClip" class="panel-collapse panel-body collapse" role="tabpanel"
aria-labelledby="installWebClip">
<label class="wr-input-label" title="Title of the web clip">Title<span
class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="title" data-key="title"
placeholder="Enter Title"/>
</div>
<label class="wr-input-label" title="URL">URL<span
class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="url" data-key="url"
placeholder="Enter URL"/>
</div>
<a href="javascript:runOperation('{{features.WEBCLIP.code}}')" class="btn-operations">Install</a>
</div>
</div>
<div class="panel panel-default operation-data" data-operation="{{features.UNINSTALL_APPLICATION.code}}">
<div class="panel-heading" role="tab">
<h2 class="sub-title panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#uninstallApp" aria-expanded="true"
aria-controls="uninstallApp" class="collapsed">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-arrow fw-down-arrow fw-stack-1x"></i>
</span>
Uninstall App
</a>
</h2>
</div>
<div id="uninstallApp" class="panel-collapse panel-body collapse" role="tabpanel"
aria-labelledby="uninstallApp">
<label class="wr-input-label" title="Application Identifier">App Identifier<span
class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<!--span>Identification of the wireless network to connect to</span-->
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="package-name"
data-key="packageName" placeholder="Enter App Identifer"/>
</div>
<a href="javascript:runOperation('{{features.UNINSTALL_APPLICATION.code}}')" class="btn-operations">Uninstall</a>
</div>
</div>
</div>
<!-- /application -->
<!-- Restriction -->
<div class="wr-hidden-operation" data-operation="restriction">
<div class="panel panel-default operation-data" data-operation="{{features.CAMERA.code}}">
<div class="panel-heading" role="tab">
<h2 class="sub-title panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#cameraDisable" aria-expanded="true"
aria-controls="cameraDisable">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-arrow fw-down-arrow fw-stack-1x"></i>
</span>
Camera Enable/Disable
</a>
</h2>
</div>
<div id="cameraDisable" class="panel-collapse panel-body collapse in" role="tabpanel"
aria-labelledby="cameraDisable">
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" class="operationDataKeys" id="enableCamera" data-key="enableCamera"
checked/>
<span class="helper" title="Remove App upon dis-enrollment">Enable Camera<span
class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
</div>
<a href="javascript:runOperation('{{features.CAMERA.code}}')" class="btn-operations">Configure</a>
</div>
</div>
</div>
<!-- /Restriction -->
</div>
</div>

@ -1,366 +0,0 @@
<div class="row no-gutter">
<div class="wr-hidden-operations-nav col-lg-4">
<a href="javascript:void(0)" onclick="showAdvanceOperation('{{features.WIFI.code}}', this)" class="selected">
<span class="wr-hidden-operations-icon fw-stack">
<i class="fw fw-wifi fw-stack-2x"></i>
</span>
Wi-fi
</a>
<a href="javascript:void(0)" onclick="showAdvanceOperation('application', this)" >
<span class="wr-hidden-operations-icon fw-stack">
<i class="fw fw-padlock fw-stack-2x"></i>
</span>
Applications
</a>
<a href="javascript:void(0)" onclick="showAdvanceOperation('{{features.RESTRICTION.code}}', this)">
<span class="wr-hidden-operations-icon fw-stack">
<i class="fw fw-settings fw-stack-2x"></i>
</span>
Restrictions
</a>
<a href="javascript:void(0)" onclick="showAdvanceOperation('mail', this)">
<span class="wr-hidden-operations-icon fw-stack">
<i class="fw fw-message fw-stack-2x"></i>
</span>
Mail
</a>
<a href="javascript:void(0)" onclick="showAdvanceOperation('{{features.AIR_PLAY.code}}', this)">
<span class="wr-hidden-operations-icon fw-stack">
<i class="fw fw-service-provider fw-stack-2x"></i>
</span>
Air Play
</a>
</div>
<div class="wr-hidden-operations-content col-lg-8">
<!-- application -->
<div class="wr-hidden-operation" data-operation="application" style="display: block">
<div class="panel panel-default operation-data" data-operation="{{features.INSTALL_STORE_APPLICATION.code}}">
<div class="panel-heading" role="tab">
<h2 class="sub-title panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#installPublicAppiOS" aria-expanded="true" aria-controls="installPublicAppiOS">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-arrow fw-down-arrow fw-stack-1x"></i>
</span>
Install Public App
</a>
</h2>
</div>
<div id="installPublicAppiOS" class="panel-collapse panel-body collapse in" role="tabpanel" aria-labelledby="installPublicAppiOS">
<label class="wr-input-label" for="appIdentifier">App identifier</label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="appIdentifier" data-key="appIdentifier" placeholder="Enter App Identifier">
</div>
<label class="wr-input-label col-sm-4" for="ituneID">iTunes store ID</label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="ituneID" data-key="ituneID" placeholder="Enter iTunes store ID">
</div>
<label class="wr-input-label col-sm-4" for="bundleId">Bundle ID</label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="bundleId" data-key="bundleId" placeholder="Enter Bundle ID">
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" class="operationDataKeys" id="appRemoval" data-key="appRemoval" checked />
<span class="helper" title="Remove App upon dis-enrollment">Remove App upon dis-enrollment<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
<!--span>Enable if target network is not open or broadcasting</span-->
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" class="operationDataKeys" id="backupData" data-key="backupData" checked />
<span class="helper" title="Prevent backup of App data">Prevent backup of App data<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
<!--span>Enable if target network is not open or broadcasting</span-->
</div>
<a href="javascript:runOperation('{{features.INSTALL_STORE_APPLICATION.code}}')" class="btn-operations">Install</a>
</div>
</div>
<div class="panel panel-default operation-data" data-operation="{{features.INSTALL_ENTERPRISE_APPLICATION.code}}">
<div class="panel-heading" role="tab">
<h2 class="sub-title panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#installEnterpriseAppiOS" aria-expanded="true" aria-controls="installPublicAppiOS" class="collapsed">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-arrow fw-down-arrow fw-stack-1x"></i>
</span>
Install Enterprise App
</a>
</h2>
</div>
<div id="installEnterpriseAppiOS" class="panel-collapse panel-body collapse" role="tabpanel" aria-labelledby="installEnterpriseAppiOS">
<label class="wr-input-label" for="appIdentifier">App identifier</label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="appIdentifier" data-key="appIdentifier" placeholder="Enter App Identifier">
</div>
<label class="wr-input-label col-sm-4" for="manifestURL">Manifest URL</label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="manifestURL" data-key="manifestURL" placeholder="Enter manifest URL">
</div>
<label class="wr-input-label col-sm-4" for="bundleId">Bundle ID</label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="bundleId" data-key="bundleId" placeholder="Enter Bundle ID">
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" class="operationDataKeys" id="appRemoval" data-key="appRemoval" checked />
<span class="helper" title="Remove App upon dis-enrollment">Remove App upon dis-enrollment<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
<!--span>Enable if target network is not open or broadcasting</span-->
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" class="operationDataKeys" id="backupData" data-key="backupData" checked />
<span class="helper" title="Prevent backup of App data">Prevent backup of App data<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
<!--span>Enable if target network is not open or broadcasting</span-->
</div>
<a href="javascript:runOperation('{{features.INSTALL_ENTERPRISE_APPLICATION.code}}')" class="btn-operations">Install</a>
</div>
</div>
<div class="panel panel-default operation-data" data-operation="{{features.REMOVE_APPLICATION.code}}">
<div class="panel-heading" role="tab">
<h2 class="sub-title panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#removeApplication" aria-expanded="true" aria-controls="removeApplication" class="collapsed">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-arrow fw-down-arrow fw-stack-1x"></i>
</span>
Uninstall App
</a>
</h2>
</div>
<div id="removeApplication" class="panel-collapse panel-body collapse" role="tabpanel" aria-labelledby="removeApplication">
<label class="wr-input-label col-sm-4" for="bundleId">Bundle ID</label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="bundleId" data-key="bundleId" placeholder="Enter Bundle ID">
</div>
<a href="javascript:runOperation('{{features.REMOVE_APPLICATION.code}}')" class="btn-operations">Uninstall</a>
</div>
</div>
</div>
<!-- /application -->
<!-- wi-fi -->
<div class="wr-hidden-operation panel-body operation-data" data-operation="{{features.WIFI.code}}">
<label class="wr-input-label" title="Identification of the wireless network to connect to">Service Set Identifier<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<!--span>Identification of the wireless network to connect to</span-->
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="ssid" data-key="ssid" placeholder="Enter SSID" />
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" class="operationDataKeys" id="hiddenNetwork" data-key="hiddenNetwork" checked />
<span class="helper" title="Enable if target network is not open or broadcasting">Hidden Network<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
<!--span>Enable if target network is not open or broadcasting</span-->
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" class="operationDataKeys" id="autoJoin" data-key="autoJoin" checked />
<span class="helper" title="Automatically join this wireless network">Auto Join<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
<!--span>Automatically join this wireless network</span-->
</div>
<label class="wr-input-label" title="Configures proxies to be used with this network">Proxy Setup<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<!--span>Configures proxies to be used with this network</span-->
<div class="wr-input-control">
<select class="form-control">
<option>None</option>
</select>
</div>
<label class="wr-input-label" title="Wireless network encryption to use when connecting">Security Type<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<!--span>Wireless network encryption to use when connecting</span-->
<div class="wr-input-control">
<select class="form-control operationDataKeys" id="encryptionType" data-key="encryptionType">
<option data-id="WPA">WPA/WPA2 Personal</option>
</select>
</div>
<label class="wr-input-label" title="Password for the wireless network">Password<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<!--span>Password for the wireless network</span-->
<div class="wr-input-control">
<input type="password" value="" class="operationDataKeys" id="password" data-key="password" placeholder="input text"/>
</div>
<label class="wr-input-label" title="Configures network to appear as legacy or Passport">Network Type<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<!--span>Configures network to appear as legacy or Passport</span-->
<div class="wr-input-control">
<select class="form-control">
<option>Standard</option>
</select>
</div>
<a href="javascript:runOperation('{{features.WIFI.code}}')" class="btn-operations">Configure</a>
</div>
<!-- /wi-fi -->
<!-- mail -->
<div class="wr-hidden-operation panel-body" data-operation="mail">
<label class="wr-input-label" title="The display name of the account">Account Description<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<!--span>Identification of the wireless network to connect to</span-->
<div class="wr-input-control">
<input type="text" value="" placeholder="input text"/>
</div>
<label class="wr-input-label" title="The protocol for accessing the email account">Account Type<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<!--span>Configures proxies to be used with this network</span-->
<div class="wr-input-control">
<div class="cus-col-25">
<select class="form-control">
<option>IMAP</option>
</select>
</div>
<div class="cus-col-50">
<span>Path Prefix</span> <input type="text" value="" placeholder="input text" />
</div>
<br class="c-both" />
</div>
<label class="wr-input-label" title="The display name of the user">User Display Name<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<!--span>Identification of the wireless network to connect to</span-->
<div class="wr-input-control">
<input type="text" value="" placeholder="input text"/>
</div>
<label class="wr-input-label" title="The address of the account">Email Address<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<!--span>Identification of the wireless network to connect to</span-->
<div class="wr-input-control">
<input type="text" value="" placeholder="input text"/>
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" checked />
<span class="helper" title="Messages can be moved from this account to another">Allow user to move messages from this account<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
<!--span>Enable if target network is not open or broadcasting</span-->
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" checked />
<span class="helper" title="Include this account in recent address syncing">Allow Recent Address syncing<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
<!--span>Enable if target network is not open or broadcasting</span-->
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" checked />
<span class="helper" title="Send outgoing mail from this account only from Mail app">Use Only in Mail<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
<!--span>Send outgoing mail from this account only from Mail app</span-->
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" checked />
<span class="helper" title="Support S/MIME for this account">Enable S/MIME<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
<!--span>Support S/MIME for this account</span-->
</div>
<label class="wr-input-label" title="The protocol for accessing the email account">Mail Server and Port<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<!--span>The protocol for accessing the email account</span-->
<div class="wr-input-control">
<div class="cus-col-70">
<input type="text" value="" placeholder="input text"/>
</div>
<div class="cus-col-25">
<span> : </span><input type="text" value="993" placeholder="input text" />
</div>
<br class="c-both" />
</div>
<label class="wr-input-label" title="The username used to connect to the server for incoming mail">Username<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<!--span>The Username used to connect to the server for incoming mail</span-->
<div class="wr-input-control">
<input type="text" value="" placeholder="input text"/>
</div>
<label class="wr-input-label" title="The autyentication method for the incoming mail server">Authentication Type<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<!--span>Wireless network encryption to use when connecting</span-->
<div class="wr-input-control">
<select class="form-control">
<option>Password</option>
</select>
</div>
<label class="wr-input-label" title="The password for the incoming mail server">Password<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></label>
<!--span>The Username used to connect to the server for incoming mail</span-->
<div class="wr-input-control">
<input type="text" value="" placeholder="input text"/>
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" checked />
<span class="helper" title="Retrieve incoming mail through secure socket layer">Use SSL<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
<!--span>Enable if target network is not open or broadcasting</span-->
</div>
</div>
<!-- /mail -->
<!-- general -->
<div class="wr-hidden-operation panel-body operation-data" data-operation="{{features.RESTRICTION.code}}">
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" class="operationDataKeys" id="allowCamera" data-key="allowCamera" checked />
<span class="helper" title="Allow Camera">Allow Camera<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" class="operationDataKeys" id="allowCloudBackup" data-key="allowCloudBackup" checked/>
<span class="helper" title="Allow Cloud Backup">Allow Cloud Backup<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" class="operationDataKeys" id="allowScreenShot" data-key="allowScreenShot" checked/>
<span class="helper" title="Allow Screenshots">Allow Screenshots<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" class="operationDataKeys" id="allowSafari" data-key="allowSafari" checked />
<span class="helper" title="Allow Safari Browser">Allow Safari Browser<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
</div>
<div class="wr-input-control">
<label class="wr-input-control checkbox">
<input type="checkbox" class="operationDataKeys" id="allowAirDrop" data-key="allowAirDrop" checked />
<span class="helper" title="Allow AirDrop">Allow AirDrop<span class="wr-help-tip glyphicon glyphicon-question-sign"></span></span>
</label>
</div>
<a href="javascript:runOperation('{{features.RESTRICTION.code}}')" class="btn-operations">Configure</a>
</div>
<!-- /general -->
<!-- air play -->
<div class="wr-hidden-operation panel-body operation-data" data-operation="{{features.AIR_PLAY.code}}">
<label class="wr-input-label col-sm-4" for="airPlayLocation">Location</label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="airPlayLocation" data-key="location" placeholder="Enter location" />
</div>
<label class="wr-input-label col-sm-4" for="airPlayDeviceName">Device Name</label>
<div class="wr-input-control">
<input type="text" class="form-control operationDataKeys" id="airPlayDeviceName" data-key="deviceName" placeholder="Enter Device Name" />
</div
<label class="wr-input-label col-sm-4" for="airPlayPassword">AirPlay password</label>
<div class="wr-input-control">
<input type="password" class="form-control operationDataKeys" id="airPlayPassword" data-key="password" placeholder="Password" />
</div>
<a href="javascript:runOperation('{{features.AIR_PLAY.code}}')" class="btn-operations">Configure</a>
</div>
<!-- /air play -->
</div>
</div>

@ -1,249 +0,0 @@
<div id="errorOperations" class="operation">
<div class="modal-header">
<h3 class="pull-left modal-title">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-error fw-stack-1x"></i>
</span>
Operation cannot be performed !
</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="fw fw-cancel"></i></button>
</div>
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
<h4>
Please select a device or a list of devices to perform an operation.
</h4>
</div>
<div class="modal-footer">
<div class="buttons">
<a href="javascript:hidePopup()" class="btn-operations">Ok</a>
</div>
</div>
</div>
<div id="errorOperationUnexpected" class="operation">
<div class="modal-header">
<h3 class="pull-left modal-title">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-error fw-stack-1x"></i>
</span>
Operation cannot be performed !
</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="fw fw-cancel"></i></button>
</div>
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
<h4>
Unexpected error occurred. Please Try again later.
</h4>
</div>
<div class="modal-footer">
<div class="buttons">
<a href="javascript:hidePopup()" class="btn-operations">Ok</a>
</div>
</div>
</div>
<div id="operationSuccess" class="operation">
<div class="modal-header">
<h3 class="pull-left modal-title">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-check fw-stack-1x"></i>
</span>
Operation queued successfully !
</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="fw fw-cancel"></i></button>
</div>
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
<h4>
Operation has been queued successfully to be sent to the device.
</h4>
</div>
<div class="modal-footer">
<div class="buttons">
<a href="javascript:hidePopup()" class="btn-operations">Ok</a>
</div>
</div>
</div>
<div id="messageSuccess" class="operation">
<div class="modal-header">
<h3 class="pull-left modal-title">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-check fw-stack-1x"></i>
</span>
Message sent successfully !
</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="fw fw-cancel"></i></button>
</div>
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
<h4>Message has been queued to be sent to the device.</h4>
</div>
<div class="modal-footer">
<div class="buttons">
<a href="javascript:hidePopup()" class="btn-operations">Ok</a>
</div>
</div>
</div>
{{#each features}}
<a href="javascript:operationSelect('{{code}}')" title="{{description}}">
<i class="fw {{icon}}"></i>
<span>{{name}}</span>
</a>
<div class="operation" data-operation-code="{{code}}">
<div class="modal-content clearfix">
<div class="modal-header">
<h3 class="pull-left modal-title">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw {{icon}} fw-stack-1x"></i>
</span>
{{name}}
<br>
</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><i class="fw fw-cancel"></i></button>
</div>
<div class="modal-body add-margin-top-2x add-margin-bottom-2x">
<h4>
{{#equal code "WIPE_DATA"}}
{{#equal deviceType "android"}}
{{#equal ownership "BYOD"}}
Enter PIN code* of the device
<br><br>
<div>
<input id="pin" type="password"
class="form-control modal-input operationDataKeys"
placeholder="[ Required for a BYOD device ]" data-key="pin" />
</div>
{{/equal}}
{{/equal}}
{{/equal}}
{{#equal code "NOTIFICATION"}}
Type your message below.
<br><br>
<div id="notification-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
</div>
<div class="form-group">
<input class="form-control modal-input operationDataKeys"
id="messageTitle" data-key="messageTitle" placeholder="Title here..." />
</div>
<div class="form-group">
<textarea class="form-control modal-input operationDataKeys"
id="messageText" data-key="messageText" placeholder="Message here..."></textarea>
</div>
<br>
{{/equal}}
{{#equal code "CHANGE_LOCK_CODE"}}
Type new lock-code below.
<br><br>
<input type="password" class="form-control modal-input operationDataKeys" id="lockcode"
data-key="lockCode" placeholder="Enter Lockcode"/>
<br>
{{/equal}}
{{#equal code "DEVICE_LOCK"}}
{{#equal deviceType "android"}}
{{#equal ownership "COPE"}}
<label class="wr-input-control checkbox">
<input id="hard-lock" type="checkbox" class="form-control operationDataKeys"
data-key="hard-lock"/>
<span class="helper" title="Once it enables, device will be blocked permanently.">
&nbsp;&nbsp;&nbsp;Enable Permanent Lock
<span class="wr-help-tip glyphicon glyphicon-question-sign"></span>
</span>
</label>
<br><br>
{{/equal}}
Type your message to be shown in the lock screen
<br><br>
<div>
<textarea id="lock-message" class="form-control modal-input operationDataKeys"
data-key="lock-message" placeholder="[ Message content is optional ]"></textarea>
</div>
{{/equal}}
{{/equal}}
{{#equal code "UPGRADE_FIRMWARE"}}
{{#equal deviceType "android"}}
Enter firmware upgrade scheduling information.
<br><br>
<label class="wr-input-control checkbox">
<input id="instant-upgrade" type="checkbox" class="form-control operationDataKeys"
data-key="instant-upgrade"/>
<span class="helper"
title="Once enabled, device firmware upgrade process will start instantly.">
&nbsp;&nbsp;&nbsp;Instant Upgrade
<span class="wr-help-tip glyphicon glyphicon-question-sign"></span>
</span>
</label>
<br><br>
<div class='input-group date' id='dateTimePicker'>
Enter the date and time to schedule firmware upgrade.
<br><br>
<div id="firmware-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
</div>
<input type='text' class="form-control modal-input operationDataKeys"
style="z-index : 900;" name="daterange" id="schedule" data-key="schedule"/>
</div>
<br><br>
<div class='wr-input-control' id='firmwareServerInfo'>
Enter firmware upgrade server URL (ie. http://abc.com or http://abc.com/ota)
(Optional).
<br><br>
<input type='text' class="form-control modal-input operationDataKeys" id="server"
data-key="server"/>
</div>
<script type="text/javascript">
$(function () {
$('.modalpopup-bg').css('z-index', '1000');
$('.modalpopup-container').css('z-index', '1200');
$('input[name="daterange"]').daterangepicker({
singleDatePicker: true,
timePicker: true,
showDropdowns: true,
timePickerIncrement: 1,
locale: {
format: 'MM-DD-YYYY hh:mm a'
}
});
});
$('#instant-upgrade').change(function () {
if ($(this).is(":checked")) {
$('#dateTimePicker').addClass("hidden");
$("#schedule").val('');
} else {
$('#dateTimePicker').removeClass("hidden");
$('input[name="daterange"]').daterangepicker({
singleDatePicker: true,
timePicker: true,
showDropdowns: true,
timePickerIncrement: 1,
locale: {
format: 'MM-DD-YYYY hh:mm a'
}
});
}
});
</script>
<br>
{{/equal}}
{{/equal}}
<br><br>
Do you want to perform this operation on selected device(s) ?
<br>
</h4>
</div>
<div class="modal-footer">
<div class="buttons">
<a href="javascript:runOperation('{{code}}')" class="btn-operations">Yes</a>
<a href="javascript:hidePopup()" class="btn-operations btn-default">No</a>
</div>
</div>
</div>
</div>
{{/each}}
<br class="c-both"/>

@ -34,7 +34,7 @@
</label>
<select id="android-config-notifier" class="form-control" data-default="0">
<option value="1">Local Polling</option>
<option value="2">Google Cloud Messaging ( GCM )</option>
<option value="2">Firebase Cloud Messaging ( FCM )</option>
</select>
</div>
@ -62,16 +62,6 @@
</label>
<input id="android-config-gcm-api-key" type="text" class="form-control" >
</div>
<div class="wr-input-control">
<label class="wr-input-label" for="android-config-gcm-sender-id">
Sender ID*
<span class="helper" title="GCM Sender ID">
<span class="wr-help-tip glyphicon glyphicon-question-sign"></span>
</span>
</label>
<input id="android-config-gcm-sender-id" type="text" class="form-control">
</div>
</div>
<h4>
End User License Agreement ( EULA )

@ -124,8 +124,6 @@ $(document).ready(function () {
$("input#android-config-notifier-frequency").val(config.value / 1000);
} else if (config.name == configParams["GCM_API_KEY"]) {
$("input#android-config-gcm-api-key").val(config.value);
} else if (config.name == configParams["GCM_SENDER_ID"]) {
$("input#android-config-gcm-sender-id").val(config.value);
} else if (config.name == configParams["ANDROID_EULA"]) {
$("#android-eula").val(config.value);
}
@ -159,7 +157,7 @@ $(document).ready(function () {
var notifierType = $("#android-config-notifier").find("option:selected").attr("value");
var notifierFrequency = $("input#android-config-notifier-frequency").val();
var gcmAPIKey = $("input#android-config-gcm-api-key").val();
var gcmSenderId = $("input#android-config-gcm-sender-id").val();
var gcmSenderId = "sender_id";
var androidLicense = tinyMCE.activeEditor.getContent();
var errorMsgWrapper = "#android-config-error-msg";
var errorMsg = "#android-config-error-msg span";
@ -170,10 +168,7 @@ $(document).ready(function () {
$(errorMsg).text("Provided notifier frequency is invalid. ");
$(errorMsgWrapper).removeClass("hidden");
} else if (notifierType == notifierTypeConstants["GCM"] && !gcmAPIKey) {
$(errorMsg).text("GCM API Key is a required field. It cannot be empty.");
$(errorMsgWrapper).removeClass("hidden");
} else if (notifierType == notifierTypeConstants["GCM"] && !gcmSenderId) {
$(errorMsg).text("GCM Sender ID is a required field. It cannot be empty.");
$(errorMsg).text("FCM API Key is a required field. It cannot be empty.");
$(errorMsgWrapper).removeClass("hidden");
} else {

@ -15,6 +15,9 @@
* specific language governing permissions and limitations
* under the License.
*/
var configuredOperations = [];
// Constants to define Android Operation Constants
var androidOperationConstants = {
"PASSCODE_POLICY_OPERATION": "passcode-policy",
@ -60,21 +63,56 @@ var updateGroupedInputVisibility = function (domElement) {
*
* This method will be invoked from the relevant cdmf unit when the edit page gets loaded.
*
* @param configuredOperations selected configurations.
* @param profileFeatureList saved feature list
*/
var polulateProfileOperations = function (configuredOperations) {
var polulateProfileOperations = function (profileFeatureList) {
var selectedOperations = androidOperationModule.populateProfile(profileFeatureList);
$(".wr-advance-operations li.grouped-input").each(function () {
updateGroupedInputVisibility(this);
});
for (var i = 0; i < configuredOperations.length; ++i) {
var configuredOperation = configuredOperations[i];
$(".operation-data").filterByData("operation-code", configuredOperation)
for (var i = 0; i < selectedOperations.length; ++i) {
var selectedOperation = selectedOperations[i];
$(".operation-data").filterByData("operation-code", selectedOperation)
.find(".panel-title .wr-input-control.switch input[type=checkbox]").each(function () {
$(this).click();
});
}
};
/**
* Generates policy profile feature list which will be saved with the profile.
*
* This function will be invoked from the relevant cdmf unit at the time of policy creation.
*
* @returns {Array} profile payloads
*/
var generateProfileFeaturesList = function () {
var profilePayloads = [];
var key;
for (key in policy["profile"]) {
if (policy["profile"].hasOwnProperty(key)) {
profilePayloads.push({
"featureCode": key,
"deviceType": policy["platform"],
"content": policy["profile"][key]
});
}
}
return profilePayloads;
};
/**
* Generates policy profile object which will be saved with the profile.
*
* This function will be invoked from the relevant cdmf unit at the time of policy creation.
*
* @returns {object} generated profile.
*/
var generatePolicyProfile = function () {
return androidOperationModule.generateProfile(configuredOperations);
};
/**
* Checks if provided number is valid against a range.
*
@ -542,30 +580,6 @@ var validatePolicyProfile = function () {
return wizardIsToBeContinued;
};
/**
* Generates policy profile object which will be saved with the profile.
*
* This function will be invoked from the relevant cdmf unit at the time of policy creation.
*
* @returns {Array} profile payloads
*/
var generatePolicyProfile = function () {
var profilePayloads = [];
// traverses key by key in policy["profile"]
var key;
for (key in policy["profile"]) {
if (policy["profile"].hasOwnProperty(key)) {
profilePayloads.push({
"featureCode": key,
"deviceType": policy["platform"],
"content": policy["profile"][key]
});
}
}
return profilePayloads;
};
// Start of HTML embedded invoke methods
var showAdvanceOperation = function (operation, button) {
$(button).addClass('selected');

@ -16,8 +16,6 @@
* under the License.
*/
var configuredOperations = [];
/**
* Method to update the visibility (i.e. disabled or enabled view)
* of grouped input according to the values
@ -47,9 +45,10 @@ var updateGroupedInputVisibility = function (domElement) {
*
* This method will be invoked from the relevant cdmf unit when the edit page gets loaded.
*
* @param selectedConfigurations selected configurations.
* @param profileFeatureList selected configurations.
*/
var polulateProfileOperations = function (selectedConfigurations) {
var polulateProfileOperations = function (profileFeatureList) {
var selectedConfigurations = androidOperationModule.populateProfile(profileFeatureList);
$(".wr-advance-operations li.grouped-input").each(function () {
updateGroupedInputVisibility(this);
});
@ -169,35 +168,6 @@ var slideDownPaneAgainstValueSetForRadioButtons = function (selectElement, paneI
};
// End of HTML embedded invoke methods
// Start of functions related to grid-input-view
/**
* Method to set count id to cloned elements.
* @param {object} addFormContainer
*/
var setId = function (addFormContainer) {
$(addFormContainer).find("[data-add-form-clone]").each(function (i) {
$(this).attr("id", $(this).attr("data-add-form-clone").slice(1) + "-" + (i + 1));
if ($(this).find(".index").length > 0) {
$(this).find(".index").html(i + 1);
}
});
};
/**
* Method to set count id to cloned elements.
* @param {object} addFormContainer
*/
var showHideHelpText = function (addFormContainer) {
var helpText = "[data-help-text=add-form]";
if ($(addFormContainer).find("[data-add-form-clone]").length > 0) {
$(addFormContainer).find(helpText).hide();
} else {
$(addFormContainer).find(helpText).show();
}
};
/**
* This method will display appropriate fields based on wifi type
* @param {object} wifi type select object
@ -229,148 +199,19 @@ var changeAndroidWifiPolicyEAP = function (select, superSelect) {
};
$(document).ready(function () {
// Maintains an array of configured features of the profile
var advanceOperations = ".wr-advance-operations";
$(advanceOperations).on("click", ".wr-input-control.switch", function (event) {
var operationCode = $(this).parents(".operation-data").data("operation-code");
var operation = $(this).parents(".operation-data").data("operation");
var operationDataWrapper = $(this).data("target");
// prevents event bubbling by figuring out what element it's being called from.
if (event.target.tagName == "INPUT") {
var featureConfiguredIcon;
if ($("input[type='checkbox']", this).is(":checked")) {
configuredOperations.push(operationCode);
// when a feature is enabled, if "zero-configured-features" msg is available, hide that.
var zeroConfiguredOperationsErrorMsg = "#policy-profile-main-error-msg";
if (!$(zeroConfiguredOperationsErrorMsg).hasClass("hidden")) {
$(zeroConfiguredOperationsErrorMsg).addClass("hidden");
}
// add configured-state-icon to the feature
featureConfiguredIcon = "#" + operation + "-configured";
if ($(featureConfiguredIcon).hasClass("hidden")) {
$(featureConfiguredIcon).removeClass("hidden");
}
} else {
//splicing the array if operation is present.
var index = $.inArray(operationCode, configuredOperations);
if (index != -1) {
configuredOperations.splice(index, 1);
}
// when a feature is disabled, clearing all its current configured, error or success states
var subErrorMsgWrapper = "#" + operation + "-feature-error-msg";
var subErrorIcon = "#" + operation + "-error";
var subOkIcon = "#" + operation + "-ok";
featureConfiguredIcon = "#" + operation + "-configured";
if (!$(subErrorMsgWrapper).hasClass("hidden")) {
$(subErrorMsgWrapper).addClass("hidden");
}
if (!$(subErrorIcon).hasClass("hidden")) {
$(subErrorIcon).addClass("hidden");
}
if (!$(subOkIcon).hasClass("hidden")) {
$(subOkIcon).addClass("hidden");
}
if (!$(featureConfiguredIcon).hasClass("hidden")) {
$(featureConfiguredIcon).addClass("hidden");
}
// reinitializing input fields into the defaults
$(operationDataWrapper + " input").each(
function () {
if ($(this).is("input:text")) {
$(this).val($(this).data("default"));
} else if ($(this).is("input:password")) {
$(this).val("");
} else if ($(this).is("input:checkbox")) {
$(this).prop("checked", $(this).data("default"));
// if this checkbox is the parent input of a grouped-input
if ($(this).hasClass("parent-input")) {
var groupedInput = $(this).parent().parent().parent();
updateGroupedInputVisibility(groupedInput);
}
}
}
);
// reinitializing select fields into the defaults
$(operationDataWrapper + " select").each(
function () {
var defaultOption = $(this).data("default");
$("option:eq(" + defaultOption + ")", this).prop("selected", "selected");
}
);
// collapsing expanded-panes (upon the selection of html-select-options) if any
$(operationDataWrapper + " .expanded").each(
function () {
if ($(this).hasClass("expanded")) {
$(this).removeClass("expanded");
}
$(this).slideUp();
}
);
// removing all entries of grid-input elements if exist
$(operationDataWrapper + " .grouped-array-input").each(
function () {
var gridInputs = $(this).find("[data-add-form-clone]");
if (gridInputs.length > 0) {
gridInputs.remove();
}
var helpTexts = $(this).find("[data-help-text=add-form]");
if (helpTexts.length > 0) {
helpTexts.show();
}
}
);
}
}
});
// adding support for cloning multiple profiles per feature with cloneable class definitions
$(advanceOperations).on("click", ".multi-view.add.enabled", function () {
// get a copy of .cloneable and create new .cloned div element
var cloned = "<div class='cloned'><hr>" + $(".cloneable", $(this).parent().parent()).html() + "</div>";
// append newly created .cloned div element to panel-body
$(this).parent().parent().append(cloned);
// enable remove action of newly cloned div element
$(".cloned", $(this).parent().parent()).each(
function () {
if ($(".multi-view.remove", this).hasClass("disabled")) {
$(".multi-view.remove", this).removeClass("disabled");
}
if (!$(".multi-view.remove", this).hasClass("enabled")) {
$(".multi-view.remove", this).addClass("enabled");
}
}
);
});
$(advanceOperations).on("click", ".multi-view.remove.enabled", function () {
$(this).parent().remove();
});
// enabling or disabling grouped-input based on the status of a parent check-box
$(advanceOperations).on("click", ".grouped-input", function () {
updateGroupedInputVisibility(this);
});
// add form entry click function for grid inputs
$(advanceOperations).on("click", "[data-click-event=add-form]", function () {
var addFormContainer = $("[data-add-form-container=" + $(this).attr("href") + "]");
var clonedForm = $("[data-add-form=" + $(this).attr("href") + "]").clone().find("[data-add-form-element=clone]").attr("data-add-form-clone", $(this).attr("href"));
// adding class .child-input to capture text-input-array-values
$("input, select", clonedForm).addClass("child-input");
$(addFormContainer).append(clonedForm);
setId(addFormContainer);
showHideHelpText(addFormContainer);
});
// remove form entry click function for grid inputs
$(advanceOperations).on("click", "[data-click-event=remove-form]", function () {
var addFormContainer = $("[data-add-form-container=" + $(this).attr("href") + "]");
$(this).closest("[data-add-form-element=clone]").remove();
setId(addFormContainer);
showHideHelpText(addFormContainer);
});
});

@ -16,6 +16,8 @@
* under the License.
*/
var configuredOperations = [];
var androidOperationConstants = {
"PASSCODE_POLICY_OPERATION": "passcode-policy",
"PASSCODE_POLICY_OPERATION_CODE": "PASSCODE_POLICY",
@ -523,13 +525,13 @@ var validatePolicyProfile = function () {
};
/**
* Generates policy profile object which will be saved with the profile.
* Generates policy profile feature list which will be saved with the profile.
*
* This function will be invoked from the relevant cdmf unit at the time of policy creation.
*
* @returns {Array} profile payloads
*/
var generatePolicyProfile = function () {
var generateProfileFeaturesList = function () {
var profilePayloads = [];
// traverses key by key in policy["profile"]
var key;
@ -546,6 +548,24 @@ var generatePolicyProfile = function () {
return profilePayloads;
};
/**
* Generates policy profile object which will be saved with the profile.
*
* This function will be invoked from the relevant cdmf unit at the time of policy creation.
*
* @returns {object} generated profile.
*/
var generatePolicyProfile = function () {
return androidOperationModule.generateProfile(configuredOperations);
};
/**
* Resets policy profile configurations.
*/
var resetPolicyProfile = function () {
configuredOperations = [];
};
// Start of HTML embedded invoke methods
var showAdvanceOperation = function (operation, button) {
$(button).addClass('selected');

@ -22,8 +22,8 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.DeviceManager;
import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig;
import org.wso2.carbon.device.mgt.common.ProvisioningConfig;
import org.wso2.carbon.device.mgt.common.TaskOperation;
import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
@ -54,7 +54,7 @@ public class AndroidDeviceManagementService implements DeviceManagementService {
}
@Override
public List<TaskOperation> getTasksForPlatform() {
public OperationMonitoringTaskConfig getOperationMonitoringConfig() {
return null;
}

@ -159,7 +159,7 @@ public class AndroidDeviceDAOImpl implements MobileDeviceDAO{
stmt.setString(2, properties.get(AndroidPluginConstants.DEVICE_INFO));
stmt.setString(3, mobileDevice.getSerial());
stmt.setString(4, mobileDevice.getVendor());
stmt.setString(5, mobileDevice.getMobileDeviceId());
stmt.setString(5, properties.get(AndroidPluginConstants.MAC_ADDRESS));
stmt.setString(6, properties.get(AndroidPluginConstants.DEVICE_NAME));
stmt.setString(7, mobileDevice.getLatitude());
stmt.setString(8, mobileDevice.getLongitude());
@ -167,8 +167,8 @@ public class AndroidDeviceDAOImpl implements MobileDeviceDAO{
stmt.setString(10, mobileDevice.getImsi());
stmt.setString(11, mobileDevice.getOsVersion());
stmt.setString(12, mobileDevice.getModel());
stmt.setString(13, mobileDevice.getMobileDeviceId());
stmt.setString(14, mobileDevice.getOsBuildDate());
stmt.setString(13, mobileDevice.getOsBuildDate());
stmt.setString(14, mobileDevice.getMobileDeviceId());
int rows = stmt.executeUpdate();
if (rows > 0) {
status = true;

@ -51,7 +51,7 @@ public class GCMUtil {
private static final Log log = LogFactory.getLog(GCMService.class);
private final static String GCM_ENDPOINT = "https://gcm-http.googleapis.com/gcm/send";
private final static String GCM_ENDPOINT = "https://fcm.googleapis.com/fcm/send";
private static final String GCM_API_KEY = "gcmAPIKey";
private static final int TIME_TO_LIVE = 60;
private static final int HTTP_STATUS_CODE_OK = 200;

@ -37,7 +37,7 @@ public final class AndroidPluginConstants {
public static final String VENDOR = "VENDOR";
public static final String OS_VERSION = "OS_VERSION";
public static final String OS_BUILD_DATE = "OS_BUILD_DATE";
public static final String MAC_ADDRESS = "MAC_ADDRESS";
public static final String MAC_ADDRESS = "MAC";
//Properties related to AD_FEATURE table
public static final String ANDROID_FEATURE_ID = "ID";

@ -351,6 +351,20 @@
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-core</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jaxrs</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>

@ -189,7 +189,7 @@ public final class PluginConstants {
public static final int MODEL_POSITION = 5;
public static final int MAC_ADDRESS_POSITION = 7;
public static final int RESOLUTION_POSITION = 8;
public static final int DEVICE_NAME_POSITION = 9;
public static final int DEVICE_NAME_POSITION = 10;
public static final String SYNCML_DATA_ONE = "1";
public static final String SYNCML_DATA_ZERO = "0";
public static final String OS_VERSION = "OS_VERSION";

@ -54,7 +54,7 @@ import javax.ws.rs.core.Response;
@Extension(properties = {
@ExtensionProperty(name = "name", value = "Windows Configuration Management"),
@ExtensionProperty(name = "context",
value = "/api/device-mgt/windows/v1.0/services/configuration"),
value = "/api/device-mgt/windows/v1.0/configuration"),
})
}
),
@ -63,13 +63,13 @@ import javax.ws.rs.core.Response;
}
)
@Api(value = "Windows Configuration Management",
description = "This carries all the resources related to Windows configurations management functionalities")
description = "This carries all the resources related to Windows configurations management functionalities")
@WebService
@Path("services/configuration")
@Path("/configuration")
@Produces({"application/json", "application/xml"})
@Consumes({"application/json", "application/xml"})
public interface ConfigurationMgtService {
@GET
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
@ -80,9 +80,9 @@ public interface ConfigurationMgtService {
tags = "Windows Configuration Management",
authorizations = {
@Authorization(
value="permission",
scopes = { @AuthorizationScope(scope = "/device-mgt/platform-configurations/view",
description = "View Configurations") }
value = "permission",
scopes = {@AuthorizationScope(scope = "/device-mgt/platform-configurations/view",
description = "View Configurations")}
)
}
)
@ -117,7 +117,12 @@ public interface ConfigurationMgtService {
code = 500,
message = "Internal Server Error. \n Server error occurred while fetching the Windows platform configuration.")
})
PlatformConfiguration getConfiguration() throws WindowsConfigurationException;
Response getConfiguration(@ApiParam(
name = "If-Modified-Since",
value = "Checks if the requested variant was modified, since the specified date-time.\n" +
"Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z.\n" +
"Example: Mon, 05 Jan 2014 15:10:00 +0200",
required = false) @HeaderParam("If-Modified-Since") String ifModifiedSince);
/**
* Update Tenant Configurations for the specific Device type.
@ -136,9 +141,9 @@ public interface ConfigurationMgtService {
tags = "Windows Configuration Management",
authorizations = {
@Authorization(
value="permission",
scopes = { @AuthorizationScope(scope = "/device-mgt/configurations/manage",
description = "Manage Configurations") }
value = "permission",
scopes = {@AuthorizationScope(scope = "/device-mgt/configurations/manage",
description = "Manage Configurations")}
)
}
)
@ -175,11 +180,11 @@ public interface ConfigurationMgtService {
message = "Internal Server Error. \n " +
"Server error occurred while modifying the Windows platform configurations.")
})
Message updateConfiguration
( @ApiParam(
Response updateConfiguration
(@ApiParam(
name = "configuration",
value = "The properties to update the Windows platform configurations.")
PlatformConfiguration configuration) throws WindowsConfigurationException;
PlatformConfiguration configuration) throws WindowsConfigurationException;
@GET
@Path("license")
@ -194,9 +199,9 @@ public interface ConfigurationMgtService {
tags = "Windows Configuration Management",
authorizations = {
@Authorization(
value="permission",
scopes = { @AuthorizationScope(scope = "/device-mgt/devices/enroll/windows",
description = "Enroll Device") }
value = "permission",
scopes = {@AuthorizationScope(scope = "/device-mgt/devices/enroll/windows",
description = "Enroll Device")}
)
}
)
@ -236,7 +241,7 @@ public interface ConfigurationMgtService {
name = "If-Modified-Since",
value = "Checks if the requested variant was modified, since the specified date-time.\n" +
"Provide the value in the following format: EEE, d MMM yyyy HH:mm:ss Z.\n" +
"Example: Mon, 05 Jan 2014 15:10:00 +0200",
"Example: Mon, 05 Jan 2014 15:10:00 +0200.",
required = false)
@HeaderParam("If-Modified-Since") String ifModifiedSince) throws WindowsConfigurationException;

@ -18,13 +18,9 @@
package org.wso2.carbon.device.mgt.mobile.windows.api.services;
import io.swagger.annotations.SwaggerDefinition;
import io.swagger.annotations.Info;
import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.Extension;
import io.swagger.annotations.Tag;
import io.swagger.annotations.Api;
import io.swagger.annotations.*;
import org.wso2.carbon.apimgt.annotations.api.Permission;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsDeviceEnrolmentException;
import javax.jws.WebService;
@ -41,7 +37,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.")
description = "Device management related admin APIs.")
@SwaggerDefinition(
info = @Info(
@ -68,31 +64,313 @@ public interface DeviceManagementAdminService {
@POST
@Path("/lock-devices")
@Permission(name = "Lock Device", permission = "/device-mgt/devices/owning-device/operations/windows/lock")
Response lock(@HeaderParam("Accept") String headerParam, List<String> deviceIds) throws
WindowsDeviceEnrolmentException;
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Adding a Device Lock on Windows devices.",
notes = "Using this API you have the option of Device Windows device.",
response = Activity.class,
tags = "Windows Device Management Administrative Service",
authorizations = {
@Authorization(
value = "permission",
scopes = {@AuthorizationScope(
scope = "/device-mgt/devices/owning-device/operations/windows/lock",
description = "Lock Device")}
)
}
)
@ApiResponses(value = {
@ApiResponse(
code = 201,
message = "Created. \n Successfully scheduled the device lock operation.",
response = Activity.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "URL of the activity instance that refers to the scheduled operation."),
@ResponseHeader(
name = "Content-Type",
description = "Content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified. \n" +
"Used by caches, or in conditional requests.")}),
@ApiResponse(
code = 303,
message = "See Other. \n The source can be retrieved from the URL specified in the location header.",
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 locking the device.")
})
Response lock(@HeaderParam("Accept") String headerParam, @ApiParam(
name = "deviceIDs",
value = "Provide the ID of the AWindows device. Multiple device IDs can be added by " +
"using comma separated values. ",
required = true) List<String> deviceIds) throws WindowsDeviceEnrolmentException;
@POST
@Path("/disenroll-devices")
@Permission(name = "Disenroll Device", permission = "/device-mgt/devices/disenroll/windows")
Response disenroll(@HeaderParam("Accept") String headerParam, List<String> deviceIds) throws
WindowsDeviceEnrolmentException;
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Dis-enrol the windows Devices",
notes = "Dis-enroll on Android devices",
response = Activity.class,
tags = "Windows Device Management Administrative Service.",
authorizations = {
@Authorization(
value = "permission",
scopes = {@AuthorizationScope(
scope = "/device-mgt/devices/disenroll/windows",
description = "Dis-enroll the windows devices ")}
)
}
)
@ApiResponses(value = {
@ApiResponse(
code = 201,
message = "Created. \n Successfully scheduled the Dis-enroll operation.",
response = Activity.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "URL of the activity instance that refers to the scheduled operation."),
@ResponseHeader(
name = "Content-Type",
description = "Content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified the last time.\n" +
"Used by caches, or in conditional requests.")}),
@ApiResponse(
code = 303,
message = "See Other. \n The source can be retrieved from the URL specified in the location header.\n",
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "The Source URL of the document.")}),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error."),
@ApiResponse(
code = 415,
message = "Unsupported media type. \n The format of the requested entity was not supported."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while adding a Dis-enroll operation.")
})
Response disenroll(@HeaderParam("Accept") String headerParam, @ApiParam(
name = "deviceIDs",
value = "Provide the ID of the A Windows device. Multiple device IDs can be added by " +
"using comma separated values. ",
required = true) List<String> deviceIds) throws WindowsDeviceEnrolmentException;
@POST
@Path("/wipe-devices")
@Permission(name = "Wipe Device", permission = "/device-mgt/devices/owning-device/operations/windows/wipe")
Response wipe(@HeaderParam("Accept") String headerParam, List<String> deviceIds) throws
WindowsDeviceEnrolmentException;
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
produces = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Factory Resetting an Windows Device",
notes = "Factory rest or erase all the data stored on the Windows devices" +
"to restore them back to the original system.",
response = Activity.class,
tags = "Windows Device Management Administrative Service",
authorizations = {
@Authorization(
value = "permission",
scopes = {@AuthorizationScope(
scope = "/device-mgt/devices/owning-device/operations/windows/wipe",
description = "DeviceWipe")}
)
}
)
@ApiResponses(value = {
@ApiResponse(
code = 201,
message = "Created. \n Successfully scheduled the Data wipe operation.",
response = Activity.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "URL of the activity instance that refers to the scheduled operation."),
@ResponseHeader(
name = "Content-Type",
description = "Content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified." +
"Used by caches, or in conditional requests.")}),
@ApiResponse(
code = 303,
message = "See Other. \n The source can be retrieved from the URL specified in the location header.\n",
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "The Source URL of the document.")}),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error."),
@ApiResponse(
code = 415,
message = "Unsupported media type. \n The format of the requested entity was not supported."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while adding the Data wipe operation.")})
Response wipe(@HeaderParam("Accept") String headerParam, @ApiParam(
name = "deviceIDs",
value = "Provide the ID of the A Windows device. Multiple device IDs can be added by " +
"using comma separated values. ",
required = true) List<String> deviceIds) throws WindowsDeviceEnrolmentException;
@POST
@Path("/ring-devices")
@Permission(name = "Ring Device", permission = "/device-mgt/devices/owning-device/operations/windows/ring")
Response ring(@HeaderParam("Accept") String headerParam, List<String> deviceIds) throws
WindowsDeviceEnrolmentException;
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Ringing Windows Devices",
notes = "Ring Windows devices.",
response = Activity.class,
tags = "Windows Device Management Administrative Service",
authorizations = {
@Authorization(
value="permission",
scopes = { @AuthorizationScope(
scope = "/device-mgt/devices/owning-device/operations/windows/ring",
description = "Ring Device") }
)
}
)
@ApiResponses(value = {
@ApiResponse(
code = 201,
message = "Created. \n Successfully scheduled the device ring operation.",
response = Activity.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "URL of the activity instance that refers to the scheduled operation."),
@ResponseHeader(
name = "Content-Type",
description = "Content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests.")}),
@ApiResponse(
code = 303,
message = "See Other. \n The source can be retrieved from the URL specified in the location header.",
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "The Source URL of the document.")}),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error."),
@ApiResponse(
code = 415,
message = "Unsupported media type. \n The format of the requested entity was not supported.\n"),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while adding a new device ring operation.")
})
Response ring(@HeaderParam("Accept") String headerParam, @ApiParam(
name = "deviceIDs",
value = "Provide the ID of the A Windows device. Multiple device IDs can be added by " +
"using comma separated values. ",
required = true) List<String> deviceIds) throws WindowsDeviceEnrolmentException;
@POST
@Path("/lock-reset-devices")
@Permission(name = "Lock-Reset Device", permission = "/device-mgt/devices/owning-device/operations/windows/lock-reset")
Response lockReset(@HeaderParam("Accept") String acceptHeader, List<String> deviceIds)
throws WindowsDeviceEnrolmentException;
@ApiOperation(
consumes = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Lock reset on Windows devices",
notes = "Lock reset on Windows devices.Its use to reset the device pass code",
response = Activity.class,
tags = "Windows Device Management Administrative Service",
authorizations = {
@Authorization(
value="permission",
scopes = { @AuthorizationScope(
scope = "/device-mgt/devices/owning-device/operations/windows/lock-reset",
description = "Lock reset") }
)
}
)
@ApiResponses(value = {
@ApiResponse(
code = 201,
message = "Created. \n Successfully scheduled the lock-reset operation.",
response = Activity.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "URL of the activity instance that refers to the scheduled operation."),
@ResponseHeader(
name = "Content-Type",
description = "Content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests.")}),
@ApiResponse(
code = 303,
message = "See Other. \n The source can be retrieved from the URL specified in the location header.\n",
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "The Source URL of the document.")}),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error."),
@ApiResponse(
code = 415,
message = "Unsupported media type. \n The format of the requested entity was not supported."),
@ApiResponse(
code = 500,
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 " +
"using comma separated values. ",
required = true) List<String> deviceIds) throws WindowsDeviceEnrolmentException;
}

@ -1,111 +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.
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.services;
import io.swagger.annotations.SwaggerDefinition;
import io.swagger.annotations.Info;
import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.Extension;
import io.swagger.annotations.Tag;
import io.swagger.annotations.Api;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.license.mgt.License;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsConfigurationException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.Message;
import javax.jws.WebService;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.List;
/**
* Windows Device Management REST-API implementation. All end points supports JSON, XMl with content negotiation.
*/
@Api(value = "Windows Device Management",
description = "This carries all the resources related to Windows device management functionalities")
@SwaggerDefinition(
info = @Info(
version = "1.0.0",
title = "",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "Windows Device Management"),
@ExtensionProperty(name = "context", value = "/api/device-mgt/windows/v1.0/devices"),
})
}
),
tags = {
@Tag(name = "devicemgt_windows", description = "")
}
)
@WebService
@Path("/devices")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public interface DeviceManagementService {
/**
* Get all devices.Returns list of Windows devices registered in MDM.
*
* @return Returns retrieved devices.
* @throws WindowsConfigurationException occurred while retrieving all the devices from DB.
*/
@GET
List<Device> getAllDevices() throws WindowsConfigurationException;
/**
* Fetch Windows device details of a given device Id.
*
* @param deviceId Device Id
* @return Returns retrieved device.
* @throws WindowsConfigurationException occurred while getting device from DB.
*/
@GET
@Path("{id}")
Device getDevice(@PathParam("id") String deviceId) throws WindowsConfigurationException;
/**
* Update Windows device details of given device id.
*
* @param deviceId Device Id.
* @param device Device details to be updated.
* @return Returns the message whether device update or not.
* @throws WindowsConfigurationException occurred while updating the Device Info.
*/
@PUT
@Path("{id}")
Message updateDevice(@PathParam("id") String deviceId, Device device) throws WindowsConfigurationException;
/**
* Fetch the Licence agreement for specific windows platform.
*
* @return Returns License agreement.
* @throws WindowsConfigurationException occurred while getting licence for specific platform and Language.
*/
@GET
@Path("license")
@Produces("application/json")
License getLicense() throws WindowsConfigurationException;
}

@ -1,46 +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.
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.services;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsConfigurationException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.util.Message;
import javax.jws.WebService;
import javax.ws.rs.*;
/**
* Endpoint for Enforce Effective Policy.
*/
@WebService
@Produces({ "application/json", "application/xml"})
@Consumes({"application/json", "application/xml"})
public interface PolicyManagementService {
/**
* Get the applicable effective policy for an enrolled windows device.
*
* @param deviceId Device Id
* @return Returns retrieved devices.
* @throws WindowsConfigurationException occurred while retrieving all the devices from DB.
*/
@GET
@Path("{deviceId}")
Message getEffectivePolicy(@HeaderParam("Accept") String acceptHeader,
@PathParam("deviceId") String deviceId) throws WindowsConfigurationException;
}

@ -18,25 +18,104 @@
package org.wso2.carbon.device.mgt.mobile.windows.api.services.authbst;
import io.swagger.annotations.*;
import org.wso2.carbon.apimgt.annotations.api.Permission;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsDeviceEnrolmentException;
import org.wso2.carbon.device.mgt.mobile.windows.api.services.authbst.beans.Credentials;
import javax.jws.WebService;
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 handling authentication request comes via MDM login page.
*/
@SwaggerDefinition(
info = @Info(
version = "1.0.0",
title = "",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "Windows Binary security token provider"),
@ExtensionProperty(name = "context",
value = "/api/device-mgt/windows/v1.0/federated"),
})
}
),
tags = {
@Tag(name = "devicemgt_windows", description = "")
}
)
@Api(value = "Windows BST Management",
description = "This carries all the resources related to Windows Binary security token management.")
@WebService
@Path("/bst")
@Produces({"application/json", "application/xml"})
@Consumes({"application/json", "application/xml"})
public interface BSTProvider {
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Path("/authentication")
@Permission(name = "Enroll Device", permission = "/device-mgt/devices/enroll/windows")
Response getBST(Credentials credentials) throws WindowsDeviceEnrolmentException;
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
consumes = MediaType.APPLICATION_JSON,
httpMethod = "POST",
value = "Getting Binary security token.",
notes = "Using this API to fetch Binary security token to call window enrollment and policy endpoints.",
tags = "BST Provider",
authorizations = {
@Authorization(
value = "permission",
scopes = {@AuthorizationScope(scope = "/device-mgt/devices/enroll/windows",
description = "Getting Binary security token for Windows enrollment " +
"and policy endpoints.")}
)
}
)
@ApiResponses(
value = {
@ApiResponse(code = 200, message = "Ok. \n Successfully fetching the binary security token.",
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "The URL of the added policy."),
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests.")
}),
@ApiResponse(
code = 303,
message = "See Other. \n The source can be retrieved from the URL specified in the location header.",
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "The Source URL of the document.")}),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error."),
@ApiResponse(
code = 415,
message = "Unsupported media type. \n The format of the requested entity was not supported."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while fetching Binary security token.")
})
Response getBST(Credentials credentials)
throws WindowsDeviceEnrolmentException;
}

@ -18,6 +18,9 @@
package org.wso2.carbon.device.mgt.mobile.windows.api.services.authbst.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;

@ -18,6 +18,8 @@
package org.wso2.carbon.device.mgt.mobile.windows.api.services.discovery;
import io.swagger.annotations.*;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsDeviceEnrolmentException;
import org.wso2.carbon.device.mgt.mobile.windows.api.services.discovery.beans.DiscoveryRequest;
@ -29,6 +31,8 @@ import javax.jws.WebResult;
import javax.jws.WebService;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.ws.BindingType;
import javax.xml.ws.RequestWrapper;
@ -38,23 +42,142 @@ import javax.xml.ws.soap.SOAPBinding;
/**
* Interface for Discovery service related operations.
*/
@SwaggerDefinition(
info = @Info(
version = "1.0.0",
title = "",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "Windows Discovery service provider"),
@ExtensionProperty(name = "context",
value = "/api/device-mgt/windows/v1.0/discovery/post"),
})
}
),
tags = {
@Tag(name = "devicemgt_windows", description = "")
}
)
@Api(value = "Windows Discovery service",
description = "This carries all the resources related to Windows Discovery service.")
@WebService(targetNamespace = PluginConstants.DISCOVERY_SERVICE_TARGET_NAMESPACE,
name = "IDiscoveryService")
@BindingType(value = SOAPBinding.SOAP12HTTP_BINDING)
public interface DiscoveryService {
@POST
@ApiOperation(
httpMethod = "POST",
value = "Discovering the server Enrollment policy and Enrollment service Endpoints.",
notes = "Using this API to discover the Enrollment policy,Enrollment service and " +
"federated login page server endpoints in the server. ",
response = DiscoveryResponse.class,
tags = "Windows Device Enrollment.",
authorizations = {
@Authorization(
value = "permission",
scopes = {@AuthorizationScope(
scope = "/device-mgt/devices/enroll/windows",
description = "Discover the service endpoints.")}
)
}
)
@ApiResponses(value = {
@ApiResponse(
code = 200,
message = "Ok. \n Accepted and getting server endpoints.",
response = DiscoveryResponse.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "URL of the activity instance."),
@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 URLr.",
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 fetching the server endpoints.")
})
@RequestWrapper(localName = "Discover", targetNamespace = PluginConstants.DISCOVERY_SERVICE_TARGET_NAMESPACE)
@WebMethod(operationName = "Discover")
@ResponseWrapper(localName = "DiscoverResponse", targetNamespace = PluginConstants.DISCOVERY_SERVICE_TARGET_NAMESPACE)
void discover(
@WebParam(name = "request", targetNamespace = PluginConstants.DISCOVERY_SERVICE_TARGET_NAMESPACE)
DiscoveryRequest request,
@ApiParam(
name = "DiscoveryRequest",
value = "Discovery service SOAP request.")
DiscoveryRequest request,
@WebParam(mode = WebParam.Mode.OUT, name = "DiscoverResult",
targetNamespace = PluginConstants.DISCOVERY_SERVICE_TARGET_NAMESPACE)
javax.xml.ws.Holder<DiscoveryResponse> response
javax.xml.ws.Holder<DiscoveryResponse> response
) throws WindowsDeviceEnrolmentException;
@ApiOperation(
httpMethod = "GET",
value = "Device ping the server to check whether it is running or not.",
notes = ".",
tags = "Windows Discovery service.",
authorizations = {
@Authorization(
value = "permission",
scopes = {@AuthorizationScope(scope = "/device-mgt/devices/enroll/windows",
description = "Ping the Discovery service")}
)
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Server is already running."),
@ApiResponse(
code = 303,
message = "See Other. \n The source can be retrieved from the URL specified " +
"in the location header.",
responseHeaders = {
@ResponseHeader(name = "Content-Location",
description = "Source URL of the document.")
}),
@ApiResponse(
code = 304,
message = "Not Modified. \n " +
"Empty body because the client already has the latest version of " +
"the requested resource."),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error. You must provide" +
" the device identifier. Additionally, the device identifier can be combined" +
" with either the device type" +
" OR the from and to date."),
@ApiResponse(
code = 404,
message = "Not Found. \n The specified resource does not exist."),
@ApiResponse(
code = 500,
message = "Error occurred while pinging the server.")
})
@GET
@WebMethod
@WebResult()

@ -18,6 +18,9 @@
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;
@ -26,15 +29,21 @@ import java.io.Serializable;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "DiscoveryRequest")
@ApiModel(value = "DiscoveryRequest",
description = "Discover request related information.")
@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;

@ -29,7 +29,6 @@ import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.UnexpectedServerErrorException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsConfigurationException;
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.ConfigurationMgtService;
@ -55,17 +54,17 @@ public class ConfigurationMgtServiceImpl implements ConfigurationMgtService {
* @throws WindowsConfigurationException
*/
@GET
public PlatformConfiguration getConfiguration() throws WindowsConfigurationException {
public Response getConfiguration(@HeaderParam("If-Modified-Since") String ifModifiedSince) {
String msg;
PlatformConfiguration tenantConfiguration;
PlatformConfiguration platformConfiguration;
List<ConfigurationEntry> configs;
try {
tenantConfiguration = WindowsAPIUtils.getDeviceManagementService().
platformConfiguration = WindowsAPIUtils.getDeviceManagementService().
getConfiguration(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_WINDOWS);
if (tenantConfiguration != null) {
configs = tenantConfiguration.getConfiguration();
if (platformConfiguration != null) {
configs = platformConfiguration.getConfiguration();
} else {
tenantConfiguration = new PlatformConfiguration();
platformConfiguration = new PlatformConfiguration();
configs = new ArrayList<>();
}
@ -79,28 +78,29 @@ public class ConfigurationMgtServiceImpl implements ConfigurationMgtService {
entry.setName(PluginConstants.TenantConfigProperties.LICENSE_KEY);
entry.setValue(license.getText());
configs.add(entry);
tenantConfiguration.setConfiguration(configs);
platformConfiguration.setConfiguration(configs);
}
} catch (DeviceManagementException e) {
msg = "Error occurred while retrieving the Windows tenant configuration";
log.error(msg, e);
throw new WindowsConfigurationException(msg, e);
throw new UnexpectedServerErrorException(
new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
}
return tenantConfiguration;
return Response.status(Response.Status.OK).entity(platformConfiguration).build();
}
/**
* Update Tenant Configurations for the specific Device type.
*
* @param configuration Tenant configurations to be updated.
* @param configurations to be updated.
* @return Response message.
* @throws WindowsConfigurationException
*/
@PUT
public Message updateConfiguration(PlatformConfiguration configuration) throws WindowsConfigurationException {
public Response updateConfiguration(PlatformConfiguration windowsPlatformConfiguration) throws WindowsConfigurationException {
String message;
Message responseMsg = new Message();
ConfigurationEntry licenseEntry = null;
PlatformConfiguration configuration = new PlatformConfiguration();
try {
configuration.setType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_WINDOWS);
List<ConfigurationEntry> configs = configuration.getConfiguration();
@ -123,14 +123,15 @@ public class ConfigurationMgtServiceImpl implements ConfigurationMgtService {
configuration.setConfiguration(configs);
WindowsAPIUtils.getDeviceManagementService().saveConfiguration(configuration);
Response.status(Response.Status.CREATED);
responseMsg.setResponseMessage("Windows platform configuration succeeded.");
responseMsg.setResponseCode(Response.Status.CREATED.toString());
} catch (DeviceManagementException e) {
message = "Error occurred while modifying configuration settings of Windows platform.";
log.error(message, e);
throw new WindowsConfigurationException(message, e);
throw new UnexpectedServerErrorException(
new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(message).build());
}
return responseMsg;
return Response.status(Response.Status.OK).
entity("Windows platform configuration has been updated successfully.").build();
}
@GET

@ -1,157 +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.
*/
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.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.license.mgt.License;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsConfigurationException;
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.DeviceManagementService;
import javax.jws.WebService;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
/**
* Windows Device Management REST-API implementation.
* All end points supports JSON, XMl with content negotiation.
*/
@WebService
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public class DeviceManagementServiceImpl implements DeviceManagementService {
private static Log log = LogFactory.getLog(
org.wso2.carbon.device.mgt.mobile.windows.api.services.impl.DeviceManagementServiceImpl.class);
/**
* Get all devices.Returns list of Windows devices registered in MDM.
*
* @return Returns retrieved devices.
* @throws WindowsConfigurationException occurred while retrieving all the devices from DB.
*/
@GET
public List<Device> getAllDevices() throws WindowsConfigurationException {
String msg;
List<Device> devices;
try {
devices = WindowsAPIUtils.getDeviceManagementService().
getAllDevices(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_WINDOWS);
} catch (DeviceManagementException e) {
msg = "Error occurred while fetching the device list.";
log.error(msg, e);
throw new WindowsConfigurationException(msg, e);
}
return devices;
}
/**
* Fetch Windows device details of a given device Id.
*
* @param deviceId Device Id
* @return Returns retrieved device.
* @throws WindowsConfigurationException occurred while getting device from DB.
*/
@GET
@Path("{id}")
public Device getDevice(@PathParam("id") String deviceId) throws WindowsConfigurationException {
String msg;
Device device;
try {
DeviceIdentifier deviceIdentifier = WindowsAPIUtils.convertToDeviceIdentifierObject(deviceId);
device = WindowsAPIUtils.getDeviceManagementService().getDevice(deviceIdentifier);
if (device == null) {
Response.status(Response.Status.NOT_FOUND);
}
} catch (DeviceManagementException e) {
msg = "Error occurred while fetching the device information.";
log.error(msg, e);
throw new WindowsConfigurationException(msg, e);
}
return device;
}
/**
* Update Windows device details of given device id.
*
* @param deviceId Device Id.
* @param device Device details to be updated.
* @return Returns the message whether device update or not.
* @throws WindowsConfigurationException occurred while updating the Device Info.
*/
@PUT
@Path("{id}")
public Message updateDevice(@PathParam("id") String deviceId, Device device) throws WindowsConfigurationException {
String msg;
Message responseMessage = new Message();
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_WINDOWS);
boolean isUpdated;
try {
device.setType(DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_WINDOWS);
isUpdated = WindowsAPIUtils.getDeviceManagementService().updateDeviceInfo(deviceIdentifier, device);
if (isUpdated) {
Response.status(Response.Status.ACCEPTED);
responseMessage.setResponseMessage("Device information has modified successfully.");
} else {
Response.status(Response.Status.NOT_MODIFIED);
responseMessage.setResponseMessage("Device not found for the update.");
}
} catch (DeviceManagementException e) {
msg = "Error occurred while modifying the device information.";
log.error(msg, e);
throw new WindowsConfigurationException(msg, e);
}
return responseMessage;
}
/**
* Fetch the Licence agreement for specific windows platform.
*
* @return Returns License agreement.
* @throws WindowsConfigurationException occurred while getting licence for specific platform and Language.
*/
@GET
@Path("license")
@Produces("application/json")
public License getLicense() throws WindowsConfigurationException {
License license;
try {
license =
WindowsAPIUtils.getDeviceManagementService().getLicense(
DeviceManagementConstants.MobileDeviceTypes.MOBILE_DEVICE_TYPE_WINDOWS,
DeviceManagementConstants.LanguageCodes.LANGUAGE_CODE_ENGLISH_US);
} catch (DeviceManagementException e) {
String msg = "Error occurred while retrieving the license configured for Windows device enrollment";
log.error(msg, e);
throw new WindowsConfigurationException(msg, e);
}
return license;
}
}

@ -1,71 +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.
*/
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.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsConfigurationException;
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.PolicyManagementService;
import org.wso2.carbon.policy.mgt.common.Policy;
import org.wso2.carbon.policy.mgt.common.PolicyManagementException;
import org.wso2.carbon.policy.mgt.core.PolicyManagerService;
import javax.jws.WebService;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@WebService
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
@Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public class PolicyManagementServiceImpl implements PolicyManagementService {
private static Log log = LogFactory.getLog(
org.wso2.carbon.device.mgt.mobile.windows.api.services.impl.PolicyManagementServiceImpl.class);
@GET
@Path("{deviceId}")
public Message getEffectivePolicy(@HeaderParam("Accept") String acceptHeader,
@PathParam("deviceId") String deviceId) throws WindowsConfigurationException {
DeviceIdentifier deviceIdentifier = WindowsAPIUtils.convertToDeviceIdentifierObject(deviceId);
Message responseMessage = new Message();
Policy policy;
try {
PolicyManagerService policyManagerService = WindowsAPIUtils.getPolicyManagerService();
policy = policyManagerService.getEffectivePolicy(deviceIdentifier);
if (policy == null) {
responseMessage.setResponseCode(Response.Status.NO_CONTENT.toString());
responseMessage.setResponseMessage("No effective policy found");
return responseMessage;
} else {
responseMessage.setResponseCode(Response.Status.OK.toString());
responseMessage.setResponseMessage("Effective policy added to operation");
return responseMessage;
}
} catch (PolicyManagementException e) {
String msg = "Error occurred while getting the policy.";
log.error(msg, e);
throw new WindowsConfigurationException(msg, e);
}
}
}

@ -18,8 +18,10 @@
package org.wso2.carbon.device.mgt.mobile.windows.api.services.syncml;
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.common.operation.mgt.Activity;
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;
@ -35,14 +37,85 @@ 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/syncml"),
})
}
),
tags = {
@Tag(name = "devicemgt_windows", description = "")
}
)
@Api(value = "Windows syncml service",
description = "This carries all the resources related to Windows syncml message flow.")
@Path("/devicemanagement")
public interface SyncmlService {
@Path("/request")
@POST
@Consumes({ PluginConstants.SYNCML_MEDIA_TYPE, MediaType.APPLICATION_XML})
@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;
NotificationManagementException, WindowsConfigurationException;
}

@ -235,7 +235,6 @@ public class SyncmlServiceImpl implements SyncmlService {
String devLang;
String vendor;
String macAddress;
String resolution;
String modVersion;
boolean status = false;
String user;
@ -287,7 +286,6 @@ public class SyncmlServiceImpl implements SyncmlService {
vendor = itemList.get(PluginConstants.SyncML.VENDOR_POSITION).getData();
devMod = itemList.get(PluginConstants.SyncML.MODEL_POSITION).getData();
macAddress = itemList.get(PluginConstants.SyncML.MAC_ADDRESS_POSITION).getData();
resolution = itemList.get(PluginConstants.SyncML.RESOLUTION_POSITION).getData();
deviceName = itemList.get(PluginConstants.SyncML.DEVICE_NAME_POSITION).getData();
DeviceIdentifier deviceIdentifier = convertToDeviceIdentifierObject(syncmlDocument.
getHeader().getSource().getLocURI());
@ -320,24 +318,16 @@ public class SyncmlServiceImpl implements SyncmlService {
macAddressProperty.setValue(macAddress);
existingProperties.add(macAddressProperty);
// Device.Property resolutionProperty = new Device.Property();
// resolutionProperty.setName(PluginConstants.SyncML.DEVICE_INFO);
// resolutionProperty.setValue("null");
// existingProperties.add(resolutionProperty);
Device.Property deviceNameProperty = new Device.Property();
deviceNameProperty.setName(PluginConstants.SyncML.DEVICE_NAME);
deviceNameProperty.setValue(deviceName);
existingProperties.add(deviceNameProperty);
Device.Property deviceModelProperty = new Device.Property();
deviceNameProperty.setName(PluginConstants.SyncML.MODEL);
deviceNameProperty.setValue(devMod);
deviceModelProperty.setName(PluginConstants.SyncML.MODEL);
deviceModelProperty.setValue(devMod);
existingProperties.add(deviceModelProperty);
existingDevice.setName(deviceName);
existingDevice.setProperties(existingProperties);
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();

@ -17,6 +17,7 @@
*/
package org.wso2.carbon.device.mgt.mobile.windows.api.services.wstep;
import io.swagger.annotations.*;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WAPProvisioningException;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.exceptions.WindowsDeviceEnrolmentException;
@ -26,6 +27,11 @@ import org.wso2.carbon.device.mgt.mobile.windows.api.services.wstep.beans.Reques
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
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.xml.ws.BindingType;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
@ -35,6 +41,24 @@ import java.io.UnsupportedEncodingException;
/**
* Interface of WSTEP implementation.
*/
@SwaggerDefinition(
info = @Info(
version = "1.0.0",
title = "",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "Windows enrollment service provider"),
@ExtensionProperty(name = "context",
value = "/api/device-mgt/windows/v1.0/deviceenrolment/wstep"),
})
}
),
tags = {
@Tag(name = "devicemgt_windows", description = "")
}
)
@Api(value = "Windows Enrollment service Management",
description = "This carries all the resources related to Windows enrollment service.")
@WebService(targetNamespace = PluginConstants.DEVICE_ENROLLMENT_SERVICE_TARGET_NAMESPACE, name = "wstep")
@BindingType(value = SOAPBinding.SOAP12HTTP_BINDING)
public interface CertificateEnrollmentService {
@ -44,20 +68,73 @@ public interface CertificateEnrollmentService {
@WebMethod(operationName = "RequestSecurityToken")
@ResponseWrapper(localName = "RequestSecurityTokenResponseCollection", targetNamespace =
PluginConstants.WS_TRUST_TARGET_NAMESPACE)
@POST
@ApiOperation(
httpMethod = "POST",
value = "Signing the certificate signing request(CSR) and provide request security token response.",
notes = "Using this API to fetching more information to enroll the Device and " +
"getting pending operations.",
tags = "Windows Device Enrollment Service.",
authorizations = {
@Authorization(
value = "permission",
scopes = {@AuthorizationScope(
scope = "/device-mgt/devices/enroll/windows",
description = "GSigning the certificate signing request(CSR) " +
"and provide request security token response")}
)
}
)
@ApiResponses(value = {
@ApiResponse(
code = 200,
message = "Ok.Successfully signed the CSR.",
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "URL of the activity instance that refers to the scheduled operation."),
@ResponseHeader(
name = "Content-Type",
description = "Content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource was last modified. \n" +
"Used by caches, or in conditional requests.")}),
@ApiResponse(
code = 303,
message = "See Other. \n The source can be retrieved from the URL specified in the location header.",
responseHeaders = {
@ResponseHeader(
name = "Content-Location",
description = "The Source URL of the document.")}),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error."),
@ApiResponse(
code = 415,
message = "Unsupported media type. \n The format of the requested entity was not supported.\n"),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n " +
"Server error occurred while Signing the CSR.")
})
void requestSecurityToken(
@WebParam(name = "TokenType", targetNamespace = PluginConstants.WS_TRUST_TARGET_NAMESPACE)
String tokenType,
String tokenType,
@WebParam(name = "RequestType", targetNamespace = PluginConstants.WS_TRUST_TARGET_NAMESPACE)
String requestType,
String requestType,
@WebParam(name = "BinarySecurityToken", targetNamespace = PluginConstants
.WS_SECURITY_TARGET_NAMESPACE)
String binarySecurityToken,
String binarySecurityToken,
@WebParam(name = "AdditionalContext", targetNamespace = PluginConstants
.SOAP_AUTHORIZATION_TARGET_NAMESPACE)
AdditionalContext additionalContext,
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;
javax.xml.ws.Holder<RequestSecurityTokenResponse> response) throws
WindowsDeviceEnrolmentException, UnsupportedEncodingException, WAPProvisioningException;
}

@ -51,6 +51,7 @@ import org.xml.sax.SAXException;
import javax.annotation.Resource;
import javax.jws.WebService;
import javax.servlet.ServletContext;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@ -233,9 +234,8 @@ public class CertificateEnrollmentServiceImpl implements CertificateEnrollmentSe
signedCertEncodedString = base64Encoder.encodeAsString(signedCertificate.getEncoded());
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
builder = domFactory.newDocumentBuilder();
domFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document document = builder.parse(wapProvisioningFilePath);
NodeList wapParm = document.getElementsByTagName(PluginConstants.CertificateEnrolment.PARM);
Node caCertificatePosition = wapParm.item(PluginConstants.CertificateEnrolment.CA_CERTIFICATE_POSITION);

@ -18,12 +18,18 @@
package org.wso2.carbon.device.mgt.mobile.windows.api.services.xcep;
import io.swagger.annotations.*;
import org.wso2.carbon.device.mgt.mobile.windows.api.common.PluginConstants;
import org.wso2.carbon.device.mgt.mobile.windows.api.services.xcep.beans.*;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
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.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.BindingType;
import javax.xml.ws.Holder;
@ -34,6 +40,25 @@ import javax.xml.ws.soap.SOAPBinding;
/**
* Interface for MS-XCEP implementation.
*/
@SwaggerDefinition(
info = @Info(
version = "1.0.0",
title = "",
extensions = {
@io.swagger.annotations.Extension(properties = {
@ExtensionProperty(name = "name", value = "Windows Enrollment policy service"),
@ExtensionProperty(name = "context",
value = "/api/device-mgt/windows/v1.0/certificatepolicy/xcep"),
})
}
),
tags = {
@Tag(name = "devicemgt_windows", description = "")
}
)
@Api(value = "Windows enrollment policy Management",
description = "This carries all the resources related to Windows enrollment policy.")
@WebService(targetNamespace = PluginConstants.CERTIFICATE_ENROLLMENT_POLICY_SERVICE_TARGET_NAMESPACE,
name = "IPolicy")
@BindingType(value = SOAPBinding.SOAP12HTTP_BINDING)
@ -45,7 +70,64 @@ public interface CertificateEnrollmentPolicyService {
@WebMethod(operationName = "GetPolicies")
@ResponseWrapper(localName = "GetPoliciesResponse", targetNamespace = PluginConstants.
ENROLLMENT_POLICY_TARGET_NAMESPACE, className = PluginConstants.
RESPONSE_WRAPPER_CLASS_NAME) void getPolicies(
RESPONSE_WRAPPER_CLASS_NAME)
@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.")
})
void getPolicies(
@WebParam(name = "client", targetNamespace = PluginConstants.
ENROLLMENT_POLICY_TARGET_NAMESPACE)
Client client,

@ -33,7 +33,12 @@
<jaxrs:server id="DiscoveryService_rest" address="/discovery/get">
<jaxrs:serviceBeans>
<ref bean="discoveryService"/>
<ref bean="swaggerResource"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider"/>
<ref bean="swaggerWriter"/>
</jaxrs:providers>
</jaxrs:server>
<!--Discovery Service POST Endpoint-->
@ -88,43 +93,39 @@
</jaxws:handlers>
</jaxws:endpoint>
<!--WSTEP Endpoint for OnPremise Auth-Policy-->
<jaxws:endpoint
id="CertificateEnrollmentServiceOnPremise"
implementor="org.wso2.carbon.device.mgt.mobile.windows.api.services.wstep.impl.CertificateEnrollmentServiceImpl"
address="/deviceenrolment/wstep/onpremise">
<jaxws:properties>
<entry key="ws-security.ut.validator" value-ref="customvalidatoronpremise"/>
</jaxws:properties>
<jaxws:inInterceptors>
<ref bean="wss4jInInterceptor"/>
</jaxws:inInterceptors>
<jaxws:handlers>
<ref bean="serviceOptionsHandler"/>
</jaxws:handlers>
</jaxws:endpoint>
<!--Syncml Endpoint-->
<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">
<jaxrs:serviceBeans>
<ref bean="bstProviderService"/>
<ref bean="swaggerResource"/>
</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">
<jaxrs:serviceBeans>
<ref bean="deviceMgtAdminService"/>
<ref bean="swaggerResource"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider"/>
<ref bean="swaggerWriter"/>
</jaxrs:providers>
</jaxrs:server>
@ -132,32 +133,12 @@
<jaxrs:server id="configurationService" address="/configuration">
<jaxrs:serviceBeans>
<ref bean="configurationMgtService"/>
<ref bean="swaggerResource"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider"/>
<ref bean="errorHandler"/>
</jaxrs:providers>
</jaxrs:server>
<!--Endpoint for Policy -->
<jaxrs:server id="policyService" address="/policy">
<jaxrs:serviceBeans>
<ref bean="policyManagementService"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider"/>
<ref bean="errorHandler"/>
</jaxrs:providers>
</jaxrs:server>
<!--Endpoint for Devicemanager -->
<jaxrs:server id="deviceManagementService" address="/device">
<jaxrs:serviceBeans>
<ref bean="deviceMgtService"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider"/>
<ref bean="errorHandler"/>
<ref bean="swaggerWriter"/>
</jaxrs:providers>
</jaxrs:server>
@ -186,7 +167,21 @@
</map>
</property>
</bean>
<bean id="swaggerWriter" class="io.swagger.jaxrs.listing.SwaggerSerializers" />
<bean id="swaggerResource" class="io.swagger.jaxrs.listing.ApiListingResource" />
<bean id="swaggerConfig" class="io.swagger.jaxrs.config.BeanConfig">
<property name="resourcePackage" value="org.wso2.carbon.device.mgt.mobile.windows.api.services"/>
<property name="version" value="1.0"/>
<property name="host" value="localhost:9443"/>
<property name="schemes" value="https" />
<property name="basePath" value="/api/device-mgt/windows/v1.0"/>
<property name="title" value="Windows Device Management API Definitions"/>
<property name="contact" value="dev@wso2.org"/>
<property name="license" value="Apache 2.0"/>
<property name="licenseUrl" value="http://www.apache.org/licenses/LICENSE-2.0.html"/>
<property name="scan" value="true"/>
</bean>
<bean id="Syncml_initial_bean"
class="org.wso2.carbon.device.mgt.mobile.windows.api.services.syncml.impl.SyncmlServiceImpl"/>
<bean id="customvalidator"
@ -198,10 +193,6 @@
<bean id="jsonProvider" class="org.wso2.carbon.device.mgt.mobile.windows.api.common.util.GsonMessageBodyHandler"/>
<bean id="configurationMgtService"
class="org.wso2.carbon.device.mgt.mobile.windows.api.services.impl.ConfigurationMgtServiceImpl"/>
<bean id="policyManagementService"
class="org.wso2.carbon.device.mgt.mobile.windows.api.services.impl.PolicyManagementServiceImpl"/>
<bean id="errorHandler" class="org.wso2.carbon.device.mgt.mobile.windows.api.common.util.ErrorHandler"/>
<bean id="deviceMgtService"
class="org.wso2.carbon.device.mgt.mobile.windows.api.services.impl.DeviceManagementServiceImpl"/>
</beans>

@ -43,7 +43,7 @@
</servlet>
<servlet-mapping>
<servlet-name>JAXServlet-windows</servlet-name>
<url-pattern>/services/*</url-pattern>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
@ -66,7 +66,7 @@
</context-param>
<context-param>
<param-name>nonSecuredEndPoints</param-name>
<param-value>/services/discovery/get,/services/discovery/post,/services/certificatepolicy/xcep,
,/services/deviceenrolment/wstep,/services/syncml/devicemanagement/request</param-value>
<param-value>/discovery/get,/discovery/post,/certificatepolicy/xcep,
,/deviceenrolment/wstep,/syncml/devicemanagement/request</param-value>
</context-param>
</web-app>

@ -16,6 +16,8 @@
* under the License.
*/
var configuredOperations = [];
var windowsOperationConstants = {
"PASSCODE_POLICY_OPERATION": "passcode-policy",
"PASSCODE_POLICY_OPERATION_CODE": "PASSCODE_POLICY",
@ -52,21 +54,60 @@ var updateGroupedInputVisibility = function (domElement) {
*
* This method will be invoked from the relevant cdmf unit when the edit page gets loaded.
*
* @param configuredOperations selected configurations.
* @param profileFeatureList saved feature list
*/
var polulateProfileOperations = function (configuredOperations) {
var polulateProfileOperations = function (profileFeatureList) {
var selectedOperations = windowsOperationModule.populateProfile(profileFeatureList);
$(".wr-advance-operations li.grouped-input").each(function () {
updateGroupedInputVisibility(this);
});
for (var i = 0; i < configuredOperations.length; ++i) {
var configuredOperation = configuredOperations[i];
$(".operation-data").filterByData("operation-code", configuredOperation)
for (var i = 0; i < selectedOperations.length; ++i) {
var selectedOperation = selectedOperations[i];
$(".operation-data").filterByData("operation-code", selectedOperation)
.find(".panel-title .wr-input-control.switch input[type=checkbox]").each(function () {
$(this).click();
});
}
};
/**
* Generates policy profile feature list which will be saved with the profile.
*
* This function will be invoked from the relevant cdmf unit at the time of policy creation.
*
* @returns {Array} profile payloads
*/
var generateProfileFeaturesList = function () {
var profilePayloads = [];
// traverses key by key in policy["profile"]
var key;
for (key in policy["profile"]) {
if (policy["profile"].hasOwnProperty(key)) {
if (key == windowsOperationConstants["PASSCODE_POLICY_OPERATION_CODE"]) {
policy["profile"][key].enablePassword = true;
}
profilePayloads.push({
"featureCode": key,
"deviceType": policy["platform"],
"content": policy["profile"][key]
});
}
}
return profilePayloads;
};
/**
* Generates policy profile object which will be saved with the profile.
*
* This function will be invoked from the relevant cdmf unit at the time of policy creation.
*
* @returns {object} generated profile.
*/
var generatePolicyProfile = function () {
return windowsOperationModule.generateProfile(configuredOperations);
};
/**
* Checks if provided number is valid against a range.
*
@ -256,33 +297,6 @@ var validatePolicyProfile = function () {
return wizardIsToBeContinued;
};
/**
* Generates policy profile object which will be saved with the profile.
*
* This function will be invoked from the relevant cdmf unit at the time of policy creation.
*
* @returns {Array} profile payloads
*/
var generatePolicyProfile = function () {
var profilePayloads = [];
// traverses key by key in policy["profile"]
var key;
for (key in policy["profile"]) {
if (key == windowsOperationConstants["PASSCODE_POLICY_OPERATION_CODE"]) {
policy["profile"][key].enablePassword = true;
}
if (policy["profile"].hasOwnProperty(key)) {
profilePayloads.push({
"featureCode": key,
"deviceType": policy["platform"],
"content": policy["profile"][key]
});
}
}
return profilePayloads;
};
// Start of HTML embedded invoke methods
var showAdvanceOperation = function (operation, button) {
$(button).addClass('selected');

@ -16,8 +16,6 @@
* under the License.
*/
var configuredOperations = [];
/**
* Method to update the visibility (i.e. disabled or enabled view)
* of grouped input according to the values
@ -47,9 +45,10 @@ var updateGroupedInputVisibility = function (domElement) {
*
* This method will be invoked from the relevant cdmf unit when the edit page gets loaded.
*
* @param selectedConfigurations selected configurations.
* @param profileFeatureList selected configurations.
*/
var polulateProfileOperations = function (selectedConfigurations) {
var polulateProfileOperations = function (profileFeatureList) {
var selectedConfigurations = windowsOperationModule.populateProfile(profileFeatureList);
$(".wr-advance-operations li.grouped-input").each(function () {
updateGroupedInputVisibility(this);
});
@ -168,208 +167,20 @@ var slideDownPaneAgainstValueSetForRadioButtons = function (selectElement, paneI
};
// End of HTML embedded invoke methods
// Start of functions related to grid-input-view
/**
* Method to set count id to cloned elements.
* @param {object} addFormContainer
*/
var setId = function (addFormContainer) {
$(addFormContainer).find("[data-add-form-clone]").each(function (i) {
$(this).attr("id", $(this).attr("data-add-form-clone").slice(1) + "-" + (i + 1));
if ($(this).find(".index").length > 0) {
$(this).find(".index").html(i + 1);
}
});
};
/**
* Method to set count id to cloned elements.
* @param {object} addFormContainer
*/
var showHideHelpText = function (addFormContainer) {
var helpText = "[data-help-text=add-form]";
if ($(addFormContainer).find("[data-add-form-clone]").length > 0) {
$(addFormContainer).find(helpText).hide();
} else {
$(addFormContainer).find(helpText).show();
}
};
/**
* This method will display appropriate fields based on wifi type
* @param {object} wifi type select object
*/
var changeAndroidWifiPolicy = function (select) {
slideDownPaneAgainstValueSet(select, 'control-wifi-password', ['wep', 'wpa', '802eap']);
slideDownPaneAgainstValueSet(select, 'control-wifi-eap', ['802eap']);
slideDownPaneAgainstValueSet(select, 'control-wifi-phase2', ['802eap']);
slideDownPaneAgainstValueSet(select, 'control-wifi-identity', ['802eap']);
slideDownPaneAgainstValueSet(select, 'control-wifi-anoidentity', ['802eap']);
slideDownPaneAgainstValueSet(select, 'control-wifi-cacert', ['802eap']);
};
/**
* This method will display appropriate fields based on wifi EAP type
* @param {object} wifi eap select object
* @param {object} wifi type select object
*/
var changeAndroidWifiPolicyEAP = function (select, superSelect) {
slideDownPaneAgainstValueSet(select, 'control-wifi-password', ['peap', 'ttls', 'pwd', 'fast', 'leap']);
slideDownPaneAgainstValueSet(select, 'control-wifi-phase2', ['peap', 'ttls', 'fast']);
slideDownPaneAgainstValueSet(select, 'control-wifi-provisioning', ['fast']);
slideDownPaneAgainstValueSet(select, 'control-wifi-identity', ['peap', 'tls', 'ttls', 'pwd', 'fast', 'leap']);
slideDownPaneAgainstValueSet(select, 'control-wifi-anoidentity', ['peap', 'ttls']);
slideDownPaneAgainstValueSet(select, 'control-wifi-cacert', ['peap', 'tls', 'ttls']);
if (superSelect.value != '802eap') {
changeAndroidWifiPolicy(superSelect);
}
};
$(document).ready(function () {
// Maintains an array of configured features of the profile
var advanceOperations = ".wr-advance-operations";
$(advanceOperations).on("click", ".wr-input-control.switch", function (event) {
var operationCode = $(this).parents(".operation-data").data("operation-code");
var operation = $(this).parents(".operation-data").data("operation");
var operationDataWrapper = $(this).data("target");
// prevents event bubbling by figuring out what element it's being called from.
if (event.target.tagName == "INPUT") {
var featureConfiguredIcon;
if ($("input[type='checkbox']", this).is(":checked")) {
configuredOperations.push(operationCode);
// when a feature is enabled, if "zero-configured-features" msg is available, hide that.
var zeroConfiguredOperationsErrorMsg = "#policy-profile-main-error-msg";
if (!$(zeroConfiguredOperationsErrorMsg).hasClass("hidden")) {
$(zeroConfiguredOperationsErrorMsg).addClass("hidden");
}
// add configured-state-icon to the feature
featureConfiguredIcon = "#" + operation + "-configured";
if ($(featureConfiguredIcon).hasClass("hidden")) {
$(featureConfiguredIcon).removeClass("hidden");
}
} else {
//splicing the array if operation is present.
var index = $.inArray(operationCode, configuredOperations);
if (index != -1) {
configuredOperations.splice(index, 1);
}
// when a feature is disabled, clearing all its current configured, error or success states
var subErrorMsgWrapper = "#" + operation + "-feature-error-msg";
var subErrorIcon = "#" + operation + "-error";
var subOkIcon = "#" + operation + "-ok";
featureConfiguredIcon = "#" + operation + "-configured";
if (!$(subErrorMsgWrapper).hasClass("hidden")) {
$(subErrorMsgWrapper).addClass("hidden");
}
if (!$(subErrorIcon).hasClass("hidden")) {
$(subErrorIcon).addClass("hidden");
}
if (!$(subOkIcon).hasClass("hidden")) {
$(subOkIcon).addClass("hidden");
}
if (!$(featureConfiguredIcon).hasClass("hidden")) {
$(featureConfiguredIcon).addClass("hidden");
}
// reinitializing input fields into the defaults
$(operationDataWrapper + " input").each(
function () {
if ($(this).is("input:text")) {
$(this).val($(this).data("default"));
} else if ($(this).is("input:password")) {
$(this).val("");
} else if ($(this).is("input:checkbox")) {
$(this).prop("checked", $(this).data("default"));
// if this checkbox is the parent input of a grouped-input
if ($(this).hasClass("parent-input")) {
var groupedInput = $(this).parent().parent().parent();
updateGroupedInputVisibility(groupedInput);
}
}
}
);
// reinitializing select fields into the defaults
$(operationDataWrapper + " select").each(
function () {
var defaultOption = $(this).data("default");
$("option:eq(" + defaultOption + ")", this).prop("selected", "selected");
}
);
// collapsing expanded-panes (upon the selection of html-select-options) if any
$(operationDataWrapper + " .expanded").each(
function () {
if ($(this).hasClass("expanded")) {
$(this).removeClass("expanded");
}
$(this).slideUp();
}
);
// removing all entries of grid-input elements if exist
$(operationDataWrapper + " .grouped-array-input").each(
function () {
var gridInputs = $(this).find("[data-add-form-clone]");
if (gridInputs.length > 0) {
gridInputs.remove();
}
var helpTexts = $(this).find("[data-help-text=add-form]");
if (helpTexts.length > 0) {
helpTexts.show();
}
}
);
}
}
});
// adding support for cloning multiple profiles per feature with cloneable class definitions
$(advanceOperations).on("click", ".multi-view.add.enabled", function () {
// get a copy of .cloneable and create new .cloned div element
var cloned = "<div class='cloned'><hr>" + $(".cloneable", $(this).parent().parent()).html() + "</div>";
// append newly created .cloned div element to panel-body
$(this).parent().parent().append(cloned);
// enable remove action of newly cloned div element
$(".cloned", $(this).parent().parent()).each(
function () {
if ($(".multi-view.remove", this).hasClass("disabled")) {
$(".multi-view.remove", this).removeClass("disabled");
}
if (!$(".multi-view.remove", this).hasClass("enabled")) {
$(".multi-view.remove", this).addClass("enabled");
}
}
);
});
$(advanceOperations).on("click", ".multi-view.remove.enabled", function () {
$(this).parent().remove();
});
// enabling or disabling grouped-input based on the status of a parent check-box
$(advanceOperations).on("click", ".grouped-input", function () {
updateGroupedInputVisibility(this);
});
// add form entry click function for grid inputs
$(advanceOperations).on("click", "[data-click-event=add-form]", function () {
var addFormContainer = $("[data-add-form-container=" + $(this).attr("href") + "]");
var clonedForm = $("[data-add-form=" + $(this).attr("href") + "]").clone().find("[data-add-form-element=clone]").attr("data-add-form-clone", $(this).attr("href"));
// adding class .child-input to capture text-input-array-values
$("input, select", clonedForm).addClass("child-input");
$(addFormContainer).append(clonedForm);
setId(addFormContainer);
showHideHelpText(addFormContainer);
});
// remove form entry click function for grid inputs
$(advanceOperations).on("click", "[data-click-event=remove-form]", function () {
var addFormContainer = $("[data-add-form-container=" + $(this).attr("href") + "]");
$(this).closest("[data-add-form-element=clone]").remove();
setId(addFormContainer);
showHideHelpText(addFormContainer);
});
});

@ -16,6 +16,8 @@
* under the License.
*/
var configuredOperations = [];
var windowsOperationConstants = {
"PASSCODE_POLICY_OPERATION": "passcode-policy",
"PASSCODE_POLICY_OPERATION_CODE": "PASSCODE_POLICY",
@ -237,21 +239,21 @@ var validatePolicyProfile = function () {
};
/**
* Generates policy profile object which will be saved with the profile.
* Generates policy profile feature list which will be saved with the profile.
*
* This function will be invoked from the relevant cdmf unit at the time of policy creation.
*
* @returns {Array} profile payloads
*/
var generatePolicyProfile = function () {
var generateProfileFeaturesList = function () {
var profilePayloads = [];
// traverses key by key in policy["profile"]
var key;
for (key in policy["profile"]) {
if (key == windowsOperationConstants["PASSCODE_POLICY_OPERATION_CODE"]) {
policy["profile"][key].enablePassword = true;
}
if (policy["profile"].hasOwnProperty(key)) {
if (key == windowsOperationConstants["PASSCODE_POLICY_OPERATION_CODE"]) {
policy["profile"][key].enablePassword = true;
}
profilePayloads.push({
"featureCode": key,
"deviceType": policy["platform"],
@ -259,10 +261,27 @@ var generatePolicyProfile = function () {
});
}
}
return profilePayloads;
};
/**
* Generates policy profile object which will be saved with the profile.
*
* This function will be invoked from the relevant cdmf unit at the time of policy creation.
*
* @returns {object} generated profile.
*/
var generatePolicyProfile = function () {
return windowsOperationModule.generateProfile(configuredOperations);
};
/**
* Resets policy profile configurations.
*/
var resetPolicyProfile = function () {
configuredOperations = [];
};
// Start of HTML embedded invoke methods
var showAdvanceOperation = function (operation, button) {
$(button).addClass('selected');
@ -272,37 +291,6 @@ var showAdvanceOperation = function (operation, button) {
$(hiddenOperation + '[data-operation="' + operation + '"]').siblings().hide();
};
/**
* This method will display appropriate fields based on wifi type
* @param select
*/
var changeAndroidWifiPolicy = function (select) {
slideDownPaneAgainstValueSet(select, 'control-wifi-password', ['wep', 'wpa', '802eap']);
slideDownPaneAgainstValueSet(select, 'control-wifi-eap', ['802eap']);
slideDownPaneAgainstValueSet(select, 'control-wifi-phase2', ['802eap']);
slideDownPaneAgainstValueSet(select, 'control-wifi-identity', ['802eap']);
slideDownPaneAgainstValueSet(select, 'control-wifi-anoidentity', ['802eap']);
slideDownPaneAgainstValueSet(select, 'control-wifi-cacert', ['802eap']);
};
/**
* This method will display appropriate fields based on wifi EAP type
* @param select
* @param superSelect
*/
var changeAndroidWifiPolicyEAP = function (select, superSelect) {
slideDownPaneAgainstValueSet(select, 'control-wifi-password', ['peap', 'ttls', 'pwd', 'fast', 'leap']);
slideDownPaneAgainstValueSet(select, 'control-wifi-phase2', ['peap', 'ttls', 'fast']);
slideDownPaneAgainstValueSet(select, 'control-wifi-provisioning', ['fast']);
slideDownPaneAgainstValueSet(select, 'control-wifi-identity', ['peap', 'tls', 'ttls', 'pwd', 'fast', 'leap']);
slideDownPaneAgainstValueSet(select, 'control-wifi-anoidentity', ['peap', 'ttls']);
slideDownPaneAgainstValueSet(select, 'control-wifi-cacert', ['peap', 'tls', 'ttls']);
if (superSelect.value != '802eap') {
changeAndroidWifiPolicy(superSelect);
}
};
/**
* Method to slide down a provided pane upon provided value set.
*

@ -34,7 +34,7 @@
}
},
"androidAgentApp" : "android-agent.apk",
"windowsConfigRoot" : "%http.ip%/api/device-mgt/windows/v1.0/services/federated/bst/authentication",
"windowsConfigRoot" : "%http.ip%/api/device-mgt/windows/v1.0/federated/bst/authentication",
"ssoConfiguration" : {
"enabled" : false,
"issuer" : "mdm",

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save