Merge pull request #441 from madawas/IOTS-296

Generalizing Policy UI
4.x.x
Madawa Soysa 8 years ago committed by GitHub
commit 20dee2ec44

@ -21,6 +21,7 @@ package org.wso2.carbon.device.mgt.jaxrs.beans;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.policy.mgt.common.DeviceGroupWrapper;
import javax.validation.constraints.Size;
import java.util.List;
@ -75,6 +76,10 @@ public class PolicyWrapper {
required = true)
private List<String> users;
@ApiModelProperty(name = "deviceGroups", value = "Lists out the groups on whose devices the policy is enforced",
required = true)
private List<DeviceGroupWrapper> deviceGroups;
public Profile getProfile() {
return profile;
}
@ -147,4 +152,12 @@ public class PolicyWrapper {
this.users = users;
}
public List<DeviceGroupWrapper> getDeviceGroups() {
return deviceGroups;
}
public void setDeviceGroups(List<DeviceGroupWrapper> deviceGroups) {
this.deviceGroups = deviceGroups;
}
}

@ -122,6 +122,7 @@ public class PolicyManagementServiceImpl implements PolicyManagementService {
policy.setRoles(policyWrapper.getRoles());
policy.setUsers(policyWrapper.getUsers());
policy.setCompliance(policyWrapper.getCompliance());
policy.setDeviceGroups(policyWrapper.getDeviceGroups());
//TODO iterates the device identifiers to create the object. need to implement a proper DAO layer here.
List<Device> devices = new ArrayList<Device>();
List<DeviceIdentifier> deviceIdentifiers = policyWrapper.getDeviceIdentifiers();

@ -79,4 +79,30 @@ var groupModule = {};
);
};
groupModule.getGroups = function () {
var permissions = userModule.getUIPermissions();
if (permissions.LIST_ALL_GROUPS) {
endPoint = deviceServiceEndpoint + "/admin/groups";
} else if (permissions.LIST_GROUPS) {
endPoint = deviceServiceEndpoint + "/groups";
} else {
log.error("Access denied for user: " + carbonUser.username);
return -1;
}
return serviceInvokers.XMLHttp.get(
endPoint, function (responsePayload) {
var data = JSON.parse(responsePayload.responseText);
if(data) {
return data.deviceGroups;
} else {
return [];
}
},
function (responsePayload) {
log.error(responsePayload);
return -1;
}
);
};
}(groupModule));

@ -34,6 +34,7 @@
</a>
</li>
<li>
<!--suppress HtmlUnknownTarget -->
<a href="{{@app.context}}/policies">
Policies
</a>
@ -41,18 +42,24 @@
{{/zone}}
{{#zone "navbarActions"}}
{{#if managePermitted}}
<li>
<a href="{{@app.context}}/policy/add" class="cu-btn">
<span class="icon fw-stack">
<i class="fw fw-add fw-stack-1x"></i>
<i class="fw fw-ring fw-stack-2x"></i>
</span>
Add Policy
</a>
</li>
{{#if permissions.ADD_ADMIN_POLICY}}
{{#equal noPolicy false}}
<li>
<!--suppress HtmlUnknownTarget -->
<a href="{{@app.context}}/policy/add" class="cu-btn">
<span class="icon fw-stack">
<i class="fw fw-add fw-stack-1x"></i>
<i class="fw fw-ring fw-stack-2x"></i>
</span>
Add New Policy
</a>
</li>
{{/equal}}
{{/if}}
{{#if permissions.CHANGE_POLICY_PRIORITY}}
{{#equal noPolicy false}}
<li>
<!--suppress HtmlUnknownTarget -->
<a href="{{@app.context}}/policy/priority" class="cu-btn">
<span class="icon fw-stack">
<i class="fw fw-throttling-policy fw-stack-1x"></i>
@ -75,44 +82,37 @@
{{/zone}}
{{#zone "content"}}
{{#equal isUpdated true}}
<input type="hidden" id="is-updated" value="UPDATED">
{{/equal}}
{{#equal noPolicy true}}
<div id="ast-container" class="ast-container list-view">
<div class="ctrl-info-panel col-centered text-center wr-login">
<h2>You don't have any policy at the moment.</h2>
<br/>
{{#if managePermitted}}
<p class="text-center">
<a href="{{@app.context}}/policy/add" class="wr-btn">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-add fw-stack-1x"></i>
</span>
<h3 class="text-muted">
<i class="fw fw-policy fw-3x"></i>
</h3>
<h3 class="text-muted">You do not have any device policy at the moment</h3>
{{#if permissions.ADD_ADMIN_POLICY}}
<h3>
<!--suppress HtmlUnknownTarget -->
<a href="{{@app.context}}/policy/add" class="btn-operations btn-default">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-add fw-stack-1x"></i>
</span>
Add New Policy
</a>
</p>
</h3>
{{/if}}
</div>
</div>
{{/equal}}
{{#equal noPolicy false}}
{{#equal isUpdated true}}
<input type="hidden" id="is-updated" name="country" value="UPDATED">
{{/equal}}
<div id="loading-content" class="col-centered">
<i class="fw fw-settings fw-spin fw-2x"></i>
Loading policies . . .
<br>
</div>
<div id="policy-listing-status" class="raw hidden">
<ul style="list-style-type: none;">
<li class="message message-info">
<h4>
<i class="icon fw fw-info"></i>
<a id="policy-listing-status-msg">{{policyListingStatusMsg}}</a>
</h4>
</li>
</ul>
</div>
<table class="table table-striped table-hover list-table display responsive nowrap data-table grid-view hidden"
id="policy-grid">
<thead>
@ -141,10 +141,9 @@
<tr class="bulk-action-row">
<th colspan="9">
<ul class="tiles">
{{#if managePermitted}}
{{#if removePermitted}}
<li class="square">
<a href="#" data-click-event="remove-form"
class="btn square-element policy-remove-link"
<a href="#" data-click-event="remove-form" class="btn square-element policy-remove-link"
data-toggle="modal" data-target="#modalDemo">
<span class="icon fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
@ -155,8 +154,7 @@
</li>
{{/if}}
<li class="square">
<a href="#" data-click-event="remove-form"
class="btn square-element policy-publish-link"
<a href="#" data-click-event="remove-form" class="btn square-element policy-publish-link"
data-toggle="modal" data-target="#modalDemo">
<span class="icon fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
@ -166,8 +164,7 @@
</a>
</li>
<li class="square">
<a href="#" data-click-event="remove-form"
class="btn square-element policy-unpublish-link"
<a href="#" data-click-event="remove-form" class="btn square-element policy-unpublish-link"
data-toggle="modal" data-target="#modalDemo">
<span class="icon fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
@ -185,56 +182,73 @@
{{#each policyListToView}}
<tr data-type="selectable" data-id="{{id}}" data-status="{{status}}">
<td class="remove-padding icon-only content-fill viewEnabledIcon"
data-url="{{@app.context}}/policy/view?id={{id}}&type={{platform}}"
data-id="{{id}}">
<div class="thumbnail icon">
<img src="{{icon}}"/>
data-url="{{@app.context}}/policy/view?id={{id}}" data-id="{{id}}">
<div class="thumbnail icon" style="padding-top: 30px; padding-bottom: 30px;">
<i class="fw fw-{{deviceTypeIcon}}" style="font-size: 59px"></i>
</div>
</td>
<td class="fade-edge" data-search="{{name}}" data-display="{{name}}">
<td class="fade-edge"
data-search="{{name}}"
data-display="{{name}}">
<h4>{{name}}</h4>
<div>({{platform}})</div>
{{#equal status "Active/Updated"}}
<i class="fw fw-warning icon-success"></i> Active/Updated</span>
<span><i class="fw fw-warning icon-success"></i> Active/Updated</span>
{{/equal}}
{{#equal status "Active"}}
<i class="fw fw-ok icon-success"></i> Active</span>
<span><i class="fw fw-ok icon-success"></i> Active</span>
{{/equal}}
{{#equal status "Inactive/Updated"}}
<i class="fw fw-warning icon-warning"></i> Inactive/Updated</span>
<span><i class="fw fw-warning icon-warning"></i> Inactive/Updated</span>
{{/equal}}
{{#equal status "Inactive"}}
<i class="fw fw-error icon-danger"></i> Inactive</span>
<span><i class="fw fw-error icon-danger"></i> Inactive</span>
{{/equal}}
</td>
<td class="fade-edge remove-padding-top" data-search="{{platform}}"
data-display="{{platform}}"></td>
<td class="fade-edge remove-padding-top" data-search="{{ownershipType}}"
<td class="fade-edge remove-padding-top"
data-search="{{platform}}"
data-display="{{platform}}">
</td>
<td class="fade-edge remove-padding-top"
data-search="{{ownershipType}}"
data-display="{{ownershipType}}"
data-grid-label="Ownership">{{ownershipType}}</td>
<td id="policy-roles" class="fade-edge remove-padding-top" data-search="{{roles}}"
data-grid-label="Ownership">
{{ownershipType}}
</td>
<td id="policy-roles" class="fade-edge remove-padding-top"
data-search="{{roles}}"
data-display="{{roles}}"
data-grid-label="Role(s)">{{roles}}</td>
<td id="policy-users" class="fade-edge remove-padding-top" data-search="{{users}}"
data-display="{{users}}" data-grid-label="User(s)">{{users}}</td>
<td class="fade-edge remove-padding-top" data-search="{{compliance}}"
data-display="{{compliance}}" data-grid-label="Compliance">{{compliance}}</td>
<td id="policy-status" class="fade-edge remove-padding-top" data-search="{{status}}"
data-grid-label="Role(s)">
{{roles}}
</td>
<td id="policy-users" class="fade-edge remove-padding-top"
data-search="{{users}}"
data-display="{{users}}"
data-grid-label="User(s)">
{{users}}
</td>
<td class="fade-edge remove-padding-top"
data-search="{{compliance}}"
data-display="{{compliance}}"
data-grid-label="Compliance">
{{compliance}}
</td>
<td id="policy-status" class="fade-edge remove-padding-top"
data-search="{{status}}"
data-display="{{status}}">
</td>
<td class="text-right content-fill text-left-on-grid-view no-wrap">
<a href="{{@app.context}}/policy/edit?id={{id}}&type={{platform}}"
<!--suppress HtmlUnknownTarget -->
<a href="{{@app.context}}/policy/edit?id={{id}}"
data-id="{{id}}"
data-click-event="remove-form"
class="btn padding-reduce-on-grid-view policy-update-link">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-edit fw-stack-1x"></i>
</span>
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-edit fw-stack-1x"></i>
</span>
<span class="hidden-xs hidden-on-grid-view">Re-Configure</span>
</a>
</td>
</tr>
{{/each}}

@ -6,12 +6,12 @@
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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
* "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.
*/
@ -37,27 +37,23 @@ function onRequest(context) {
var policyCount = policyListToView.length;
if (policyCount == 0) {
page["policyListingStatusMsg"] = "No policy is available to be displayed.";
page["saveNewPrioritiesButtonEnabled"] = false;
page["noPolicy"] = true;
} else if (policyCount == 1) {
page["saveNewPrioritiesButtonEnabled"] = false;
page["noPolicy"] = false;
page["isUpdated"] = response["updated"];
} else {
page["saveNewPrioritiesButtonEnabled"] = true;
page["noPolicy"] = false;
page["isUpdated"] = response["updated"];
}
} else {
// here, response["status"] == "error"
page["policyListToView"] = [];
page["policyListingStatusMsg"] = "An unexpected error occurred @ backend. Please try again later.";
page["saveNewPrioritiesButtonEnabled"] = false;
page["policyListingStatusMsg"] = "An unexpected error occurred. Please try again later.";
page["noPolicy"] = true;
}
if (userModule.isAuthorized("/permission/admin/device-mgt/policies/manage")) {
page.managePermitted = true;
if (userModule.isAuthorized("/permission/admin/device-mgt/policies/remove")) {
page["removePermitted"] = true;
}
if (userModule.isAuthorized("/permission/admin/device-mgt/policies/update")) {
page["editPermitted"] = true;
}
page.permissions = userModule.getUIPermissions();
return page;
}
}

@ -1,30 +1,30 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
* Copyright (c) 2015-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
* 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
* "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.
*/
/* sorting function */
var sortUpdateBtn = "#sortUpdateBtn";
var sortedIDs;
var dataTableSelection = '.DTTT_selected';
// var sortedIDs;
// var dataTableSelection = ".DTTT_selected";
var settings = {
"sorting": false
};
$('#policy-grid').datatables_extended(settings);
$(".icon .text").res_text(0.2);
// $(".icon .text").res_text(0.2);
var saveNewPrioritiesButton = "#save-new-priorities-button";
var saveNewPrioritiesButtonEnabled = Boolean($(saveNewPrioritiesButton).data("enabled"));
@ -41,25 +41,6 @@ function InitiateViewOption() {
$(location).attr('href', $(this).data("url"));
}
var addSortableIndexNumbers = function () {
$(".wr-sortable .list-group-item").not(".ui-sortable-placeholder").each(function (i) {
$(".wr-sort-index", this).html(i + 1);
});
};
var sortElements = function () {
addSortableIndexNumbers();
var sortableElem = ".wr-sortable";
$(sortableElem).sortable({
beforeStop: function () {
sortedIDs = $(this).sortable("toArray");
addSortableIndexNumbers();
$(sortUpdateBtn).prop("disabled", false);
}
});
$(sortableElem).disableSelection();
};
/**
* Modal related stuff are as follows.
*/
@ -129,31 +110,29 @@ function getSelectedPolicies() {
}
$(document).ready(function () {
sortElements();
$("#loading-content").remove();
var policyRoles = $("#policy-roles").text();
var policyUsers = $("#policy-users").text();
/**
* ********************************************
* Click functions related to Policy Listing
* ********************************************
*/
if (!policyRoles) {
$("#policy-roles").hide();
}
if (!policyUsers) {
$("#policy-users").hide();
}
// [1] logic for running apply-changes-for-devices use-case
if ($("#policy-listing-status-msg").text()) {
$("#policy-listing-status").removeClass("hidden");
}
var applyChangesButtonId = "#appbar-btn-apply-changes";
// Click functions related to Policy Listing
var isUpdated = $('#is-updated').val();
var isUpdated = $("#is-updated").val();
if (!isUpdated) {
$('#appbar-btn-apply-changes').addClass('hidden');
// if no updated policies found, hide button from app bar
$(applyChangesButtonId).addClass("hidden");
} else {
// if updated policies found, show button from app bar
$(applyChangesButtonId).removeClass("hidden");
}
$("#appbar-btn-apply-changes").click(function () {
var applyPolicyChangesAPI = "/devicemgt_admin/policies/apply-changes";
// click-event function for applyChangesButton
$(applyChangesButtonId).click(function () {
var serviceURL = "/api/device-mgt/v1.0/policies/apply-changes";
modalDialog.header('Do you really want to apply changes to all policies?');
modalDialog.footer('<div class="buttons"><a href="#" id="change-policy-yes-link" class="btn-operations">Yes' +
'</a><a href="#" id="change-policy-cancel-link" class="btn-operations btn-default">No</a></div>');
@ -161,20 +140,23 @@ $(document).ready(function () {
$("a#change-policy-yes-link").click(function () {
invokerUtil.put(
applyPolicyChangesAPI,
serviceURL,
null,
// on success
function () {
modalDialog.header('Done. Changes applied successfully.');
modalDialog.footer('<div class="buttons"><a href="#" id="change-policy-success-link" ' +
'class="btn-operations">Ok</a></div>');
$("a#change-policy-success-link").click(function () {
modalDialog.hide();
location.reload();
});
function (data, textStatus, jqXHR) {
if (jqXHR.status == 200) {
modalDialog.header('Done. Changes applied successfully.');
modalDialog.footer('<div class="buttons"><a href="#" id="change-policy-success-link" ' +
'class="btn-operations">Ok</a></div>');
$("a#change-policy-success-link").click(function () {
modalDialog.hide();
location.reload();
});
}
},
// on error
function () {
function (jqXHR) {
console.log(stringify(jqXHR.data));
modalDialog.header('An unexpected error occurred. Please try again later.');
modalDialog.footer('<div class="buttons"><a href="#" id="change-policy-error-link" ' +
'class="btn-operations">Ok</a></div>');
@ -191,61 +173,26 @@ $(document).ready(function () {
});
});
$(sortUpdateBtn).click(function () {
$(sortUpdateBtn).prop("disabled", true);
var newPolicyPriorityList = [];
var policy;
var i;
for (i = 0; i < sortedIDs.length; i++) {
policy = {};
policy.id = parseInt(sortedIDs[i]);
policy.priority = i + 1;
newPolicyPriorityList.push(policy);
}
var updatePolicyAPI = "/devicemgt_admin/policies/priorities";
invokerUtil.put(
updatePolicyAPI,
newPolicyPriorityList,
function () {
modalDialog.header('Done. New Policy priorities were successfully updated.');
modalDialog.footer('<a href="#" id="save-policy-priorities-success-link" class="btn-operations">Ok' +
'</a>');
modalDialog.show();
$("a#save-policy-priorities-success-link").click(function () {
modalDialog.hide();
});
},
function () {
modalDialog.header('An unexpected error occurred. Please try again later.');
modalDialog.content(html("Message From Server : " + data["statusText"]));
modalDialog.footer('<div class="buttons"><a href="#" id="save-policy-priorities-error-link" ' +
'class="btn-operations">Ok</a></div>');
modalDialog.showAsError();
$("a#save-policy-priorities-error-link").click(function () {
modalDialog.hide();
});
}
);
});
// [2] logic for un-publishing a selected set of Active, Active/Updated policies
$(".policy-unpublish-link").click(function () {
var policyList = getSelectedPolicies();
var statusList = getSelectedPolicyStates();
if (($.inArray('Inactive/Updated', statusList) > -1) || ($.inArray('Inactive', statusList) > -1)) {
modalDialog.header('Operation cannot be performed !');
modalDialog.content('You cannot select already inactive policies. Please deselect inactive policies and ' +
'try again.');
modalDialog.footer('<div class="buttons"><a href="javascript:modalDialog.hide()" ' +
'class="btn-operations">Ok</a></div>');
if (($.inArray("Inactive/Updated", statusList) > -1) || ($.inArray("Inactive", statusList) > -1)) {
// if policies found in Inactive or Inactive/Updated states with in the selection,
// pop-up an error saying
// "You cannot select already inactive policies. Please deselect inactive policies and try again."
modalDialog.header('Action cannot be performed !');
modalDialog.content('You cannot select already inactive policies to be unpublished. Please deselect ' +
'inactive policies and try again.');
modalDialog.footer('<div class="buttons"><a href="javascript:modalDialog.hide()" class="btn-operations">Ok</a>' +
'</div>');
modalDialog.showAsAWarning();
} else {
var serviceURL = "/devicemgt_admin/policies/inactivate";
if (policyList == 0) {
modalDialog.header('Operation cannot be performed !');
modalDialog.content('Please select a policy or a list of policies to unpublish.');
var serviceURL = "/api/device-mgt/v1.0/policies/deactivate-policy";
if (policyList.length == 0) {
modalDialog.header('Action cannot be performed !');
modalDialog.content('Please select a policy or a list of policies to un-publish.');
modalDialog.footer('<div class="buttons"><a href="javascript:modalDialog.hide()" ' +
'class="btn-operations">Ok</a></div>');
modalDialog.showAsAWarning();
@ -257,22 +204,26 @@ $(document).ready(function () {
modalDialog.show();
}
// on-click function for policy un-publishing "yes" button
$("a#unpublish-policy-yes-link").click(function () {
invokerUtil.put(
invokerUtil.post(
serviceURL,
policyList,
// on success
function () {
modalDialog.header('Done. Selected policy was successfully unpublished.');
modalDialog.footer('<div class="buttons"><a href="#" id="unpublish-policy-success-link" ' +
'class="btn-operations">Ok</a></div>');
$("a#unpublish-policy-success-link").click(function () {
modalDialog.hide();
location.reload();
});
function (data, textStatus, jqXHR) {
if (jqXHR.status == 200 && data) {
modalDialog.header('Done. Selected policy was successfully unpublished.');
modalDialog.footer('<div class="buttons"><a href="#" id="unpublish-policy-success-link" ' +
'class="btn-operations">Ok</a></div>');
$("a#unpublish-policy-success-link").click(function () {
modalDialog.hide();
location.reload();
});
}
},
// on error
function () {
function (jqXHR) {
console.log(stringify(jqXHR.data));
modalDialog.header('An unexpected error occurred. Please try again later.');
modalDialog.footer('<div class="buttons"><a href="#" id="unpublish-policy-error-link" ' +
'class="btn-operations">Ok</a></div>');
@ -284,30 +235,35 @@ $(document).ready(function () {
);
});
// on-click function for policy un-publishing "cancel" button
$("a#unpublish-policy-cancel-link").click(function () {
modalDialog.hide();
});
}
});
// [3] logic for publishing a selected set of Inactive, Inactive/Updated policies
$(".policy-publish-link").click(function () {
var policyList = getSelectedPolicies();
var statusList = getSelectedPolicyStates();
if (($.inArray('Active/Updated', statusList) > -1) || ($.inArray('Active', statusList) > -1)) {
modalDialog.header('Operation cannot be performed !');
if (($.inArray("Active/Updated", statusList) > -1) || ($.inArray("Active", statusList) > -1)) {
// if policies found in Active or Active/Updated states with in the selection,
// pop-up an error saying
// "You cannot select already active policies. Please deselect active policies and try again."
modalDialog.header('Action cannot be performed !');
modalDialog.content('You cannot select already active policies. Please deselect active policies and try ' +
'again.');
modalDialog.footer('<div class="buttons"><a href="javascript:modalDialog.hide()" class="btn-operations">' +
'Ok</a></div>');
modalDialog.showAsAWarning();
} else {
var serviceURL = "/devicemgt_admin/policies/activate";
if (policyList == 0) {
modalDialog.header('Operation cannot be performed !');
var serviceURL = "/api/device-mgt/v1.0/policies/activate-policy";
if (policyList.length == 0) {
modalDialog.header('Action cannot be performed !');
modalDialog.content('Please select a policy or a list of policies to publish.');
modalDialog.footer('<div class="buttons"><a href="javascript:modalDialog.hide()" class="btn-operations">' +
'Ok</a></div>');
modalDialog.footer('<div class="buttons"><a href="javascript:modalDialog.hide()" ' +
'class="btn-operations">Ok</a></div>');
modalDialog.showAsAWarning();
} else {
modalDialog.header('Do you really want to publish the selected policy(s)?');
@ -316,23 +272,26 @@ $(document).ready(function () {
'class="btn-operations btn-default">No</a></div>');
modalDialog.show();
}
// on-click function for policy removing "yes" button
$("a#publish-policy-yes-link").click(function () {
invokerUtil.put(
invokerUtil.post(
serviceURL,
policyList,
// on success
function () {
modalDialog.header('Done. Selected policy was successfully published.');
modalDialog.footer('<div class="buttons"><a href="#" id="publish-policy-success-link" ' +
'class="btn-operations">Ok</a></div>');
$("a#publish-policy-success-link").click(function () {
modalDialog.hide();
location.reload();
});
function (data, textStatus, jqXHR) {
if (jqXHR.status == 200 && data) {
modalDialog.header('Done. Selected policy was successfully published.');
modalDialog.footer('<div class="buttons"><a href="#" id="publish-policy-success-link" ' +
'class="btn-operations">Ok</a></div>');
$("a#publish-policy-success-link").click(function () {
modalDialog.hide();
location.reload();
});
}
},
// on error
function () {
function (jqXHR) {
console.log(stringify(jqXHR.data));
modalDialog.header('An unexpected error occurred. Please try again later.');
modalDialog.footer('<div class="buttons"><a href="#" id="publish-policy-error-link" ' +
'class="btn-operations">Ok</a></div>');
@ -344,66 +303,64 @@ $(document).ready(function () {
);
});
// on-click function for policy removing "cancel" button
$("a#publish-policy-cancel-link").click(function () {
modalDialog.hide();
});
}
});
// [4] logic for removing a selected set of policies
$(".policy-remove-link").click(function () {
var policyList = getSelectedPolicies();
var deletePolicyAPI = "/devicemgt_admin/policies/bulk-remove";
if (policyList == 0) {
modalDialog.header('Operation cannot be performed !');
modalDialog.content('Please select a policy or a list of policies to remove.');
var statusList = getSelectedPolicyStates();
if (($.inArray("Active/Updated", statusList) > -1) || ($.inArray("Active", statusList) > -1)) {
// if policies found in Active or Active/Updated states with in the selection,
// pop-up an error saying
// "You cannot remove already active policies. Please deselect active policies and try again."
modalDialog.header('Action cannot be performed !');
modalDialog.content('You cannot select already active policies. Please deselect active policies and try ' +
'again.');
modalDialog.footer('<div class="buttons"><a href="javascript:modalDialog.hide()" class="btn-operations">' +
'Ok</a></div>');
modalDialog.showAsAWarning();
} else {
modalDialog.header('Do you really want to remove the selected policy(s)?');
modalDialog.footer('<div class="buttons"><a href="#" id="remove-policy-yes-link" class=' +
'"btn-operations">Remove</a> <a href="#" id="remove-policy-cancel-link" ' +
'class="btn-operations btn-default">Cancel</a></div>');
modalDialog.show();
}
var serviceURL = "/api/device-mgt/v1.0/policies/remove-policy";
if (policyList.length == 0) {
modalDialog.header('Action cannot be performed !');
modalDialog.content('Please select a policy or a list of policies to remove.');
modalDialog.footer('<div class="buttons"><a href="javascript:modalDialog.hide()" ' +
'class="btn-operations">Ok</a></div>');
modalDialog.showAsAWarning();
} else {
modalDialog.header('Do you really want to remove the selected policy(s)?');
modalDialog.footer('<div class="buttons"><a href="#" id="remove-policy-yes-link" class=' +
'"btn-operations">Remove</a> <a href="#" id="remove-policy-cancel-link" ' +
'class="btn-operations btn-default">Cancel</a></div>');
modalDialog.show();
}
$("a#remove-policy-yes-link").click(function () {
invokerUtil.post(
deletePolicyAPI,
policyList,
// on success
function (data) {
data = JSON.parse(data);
if (data.errorMessage) {
modalDialog.header('Cannot Remove Policies.');
modalDialog.footer('<div class="buttons"><a href="#" id="remove-policy-error-devices" ' +
'class="btn-operations">Ok</a></div>');
modalDialog.showAsError();
$("a#remove-policy-error-devices").click(function () {
modalDialog.hide();
});
} else {
modalDialog.header('Done. Selected policy was successfully removed.');
modalDialog.footer('<div class="buttons"><a href="#" id="remove-policy-success-link" ' +
'class="btn-operations">Ok</a></div>');
$("a#remove-policy-success-link").click(function () {
var thisTable = $(".DTTT_selected").closest('.dataTables_wrapper').find('.dataTable').dataTable();
thisTable.api().rows('.DTTT_selected').remove().draw(false);
modalDialog.hide();
});
}
},
// on error
function (data) {
if (JSON.parse(data.responseText).errorMessage) {
modalDialog.header('Cannot Remove Policies.');
modalDialog.footer('<div class="buttons"><a href="#" id="remove-policy-error-devices" ' +
'class="btn-operations">Ok</a></div>');
modalDialog.showAsError();
$("a#remove-policy-error-devices").click(function () {
modalDialog.hide();
});
} else {
// on-click function for policy removing "yes" button
$("a#remove-policy-yes-link").click(function () {
invokerUtil.post(
serviceURL,
policyList,
// on success
function (data, textStatus, jqXHR) {
if (jqXHR.status == 200 && data) {
modalDialog.header('Done. Selected policy was successfully removed.');
modalDialog.footer('<div class="buttons"><a href="#" id="remove-policy-success-link" ' +
'class="btn-operations">Ok</a></div>');
$("a#remove-policy-success-link").click(function () {
modalDialog.hide();
location.reload();
});
}
},
// on error
function (jqXHR) {
console.log(stringify(jqXHR.data));
modalDialog.header('An unexpected error occurred. Please try again later.');
modalDialog.footer('<div class="buttons"><a href="#" id="remove-policy-error-link" ' +
'class="btn-operations">Ok</a></div>');
@ -412,15 +369,19 @@ $(document).ready(function () {
modalDialog.hide();
});
}
}
);
});
);
});
$("a#remove-policy-cancel-link").click(function () {
modalDialog.hide();
});
// on-click function for policy removing "cancel" button
$("a#remove-policy-cancel-link").click(function () {
modalDialog.hide();
});
}
});
$("#loading-content").remove();
if ($("#policy-listing-status-msg").text()) {
$("#policy-listing-status").removeClass("hidden");
}
$("#policy-grid").removeClass("hidden");
$(".icon .text").res_text(0.2);
});
});

@ -1,5 +1,5 @@
{
"version": "1.0.0",
"version": "1.0.0",
"uri": "/policy/add/{deviceType}",
"layout": "cdmf.layout.default"
"layout": "cdmf.layout.default"
}

@ -0,0 +1,14 @@
{{#zone "topCss"}}
{{css "css/codemirror.css"}}
{{/zone}}
<div class="wr-input-control">
<div class="cus-col-100">
<textarea id="policy-definition-input" placeholder="Enter the policy"></textarea>
</div>
<br class="c-both"/>
</div>
{{#zone "bottomJs"}}
{{js "js/codemirror.js"}}
{{js "js/sql.js"}}
{{js "js/editor.js"}}
{{/zone}}

@ -0,0 +1,37 @@
/*
* 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.
*/
window.queryEditor = CodeMirror.fromTextArea(document.getElementById('policy-definition-input'), {
mode: MIME_TYPE_SIDDHI_QL,
indentWithTabs: true,
smartIndent: true,
lineNumbers: true,
matchBrackets: true,
autofocus: true,
extraKeys: {
"Shift-2": function (cm) {
insertStr(cm, cm.getCursor(), '@');
CodeMirror.showHint(cm, getAnnotationHints);
},
"Ctrl-Space": "autocomplete"
}
});
var validatePolicyProfile = function () {
return true;
};

@ -33,12 +33,26 @@
callback(template);
}
};
$.isResourceExists = function (location, callback) {
$.ajax({
url: location,
type: 'HEAD',
success: function () {
callback(true);
},
error: function () {
callback(false);
}
});
};
$.registerPartial = function (name, location, callback) {
$.get(location, function (data) {
Handlebars.registerPartial( name, data);
console.log("Partial " + name + " has been registered");
callback();
});
$.get(location, function (data) {
Handlebars.registerPartial(name, data);
console.log("Partial " + name + " has been registered");
callback();
});
};
})();

@ -1,74 +1,315 @@
{{!
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 "content"}}
{{#if isAuthorized}}
<span id="logged-in-user" class="hidden" data-username="{{user.username}}" data-domain="{{user.domain}}"
data-tenant-id="{{user.tenantId}}"></span>
<div class="row">
<div class="col-md-12">
<div class="container col-centered wr-content policy-platform">
<div class="wr-steps hidden">
<div class="col-md-3 col-xs-3">
<div class="itm-wiz itm-wiz-current" data-step="policy-platform">
<div class="wiz-no">1</div>
<div class="wiz-lbl hidden-xs"><span>Select a platform</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-profile">
<div class="wiz-no">2</div>
<div class="wiz-lbl hidden-xs"><span>Configure profile</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-criteria">
<div class="wiz-no">3</div>
<div class="wiz-lbl hidden-xs"><span>Assign to groups</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-naming">
<div class="wiz-no">4</div>
<div class="wiz-lbl hidden-xs"><span>Publish to devices</span></div>
</div>
<br class="c-both"/>
</div>
</div>
<div class="col-centered policy-message hidden">
<div class="wr-form">
<h1 id="policy-platform-page-wizard-title" class="page-sub-title">ADD POLICY</h1>
<h1 id="policy-message-page-wizard-title" class="page-sub-title">Policy creation is
successful.</h1>
<br>Please click <b>"Add Another Policy"</b>, if you wish to add another policy or click
<b>"View policy list"</b> to complete the process and go back to the policy list.
<hr>
<div id="policy-platform-wizard-steps" class="row wr-wizard">
<div class="col-md-3 col-xs-3">
<div class="itm-wiz itm-wiz-current" data-step="policy-platform">
<div class="wiz-no">1</div>
<div class="wiz-lbl hidden-xs"><span>Select a platform</span></div>
<button class="wr-btn wizard-stepper" data-current="policy-message"
data-direct="{{@app.context}}/policies/">
View policy list
</button>
<!--suppress HtmlUnknownTarget -->
<a href="{{@app.context}}/policy/add" class="cu-btn-inner">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-add fw-stack-1x"></i>
</span>
Add another policy
</a>
</div>
</div>
<div class="col-centered wr-content policy-naming hidden">
<div class="wr-form">
<h1 id="policy-naming-page-wizard-title" class="page-sub-title">ADD POLICY</h1>
<hr>
<div id="policy-naming-wizard-steps" class="row wr-wizard"></div>
<hr>
<div class="row">
<div class="col-lg-12">
<h4 class="hidden-xs">Step 4: Publish to devices</h4>
<br>
<div id="policy-naming-main-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-profile">
<div class="wiz-no">2</div>
<div class="wiz-lbl hidden-xs"><span>Configure profile</span></div>
<div class="clearfix">
<label class="wr-input-label">Set a Name for your Policy *</label>
<br/>
<label class="wr-input-label">
(Policy name should be 1-to-30 characters long)
</label>
<div id="policyNameField" class="wr-input-control">
<div class="cus-col-50 form-group wr-input-control">
<!--suppress HtmlFormInputWithoutLabel -->
<input id="policy-name-input" class="form-control" type="text" value=""/>
<label class="error nameEmpty hidden" for="summary">Policy name is required
&
Should be be 1-to-30
characters long.</label>
</div>
<br class="c-both"/>
</div>
<br class="c-both"/>
<label class="wr-input-label">
Add a description
</label>
<div class="wr-input-control">
<div class="cus-col-50">
<textarea id="policy-description-input" class="form-control" rows="10"
placeholder="[ Summary about the policy ]"></textarea>
</div>
<br class="c-both"/>
</div>
</div>
<div class="wr-input-control wr-btn-grp">
<a href="javascript:void(0)" class="wr-btn wizard-stepper" data-is-back-btn="true"
data-current="policy-naming" data-next="policy-criteria">Back</a>
<a href="javascript:void(0)" class="wr-btn wizard-stepper"
data-current="policy-naming-publish" data-next="policy-message"
data-validate="true">Publish</a>
<a href="javascript:void(0)" class="wr-btn wizard-stepper"
data-current="policy-naming"
data-next="policy-message" data-validate="true">Save</a>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-criteria">
<div class="wiz-no">3</div>
<div class="wiz-lbl hidden-xs"><span>Assign</span></div>
</div>
</div>
</div>
<div class="col-centered wr-content policy-criteria hidden">
<div class="wr-form">
<h1 id="policy-criteria-page-wizard-title" class="page-sub-title">ADD POLICY</h1>
<hr>
<div id="policy-criteria-wizard-steps" class="row wr-wizard"></div>
<hr>
<div class="row">
<div class="col-lg-12">
<h4 class="hidden-xs">Step 3: Assign to groups</h4>
<br>
<div id="policy-criteria-main-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
</div>
<div>
<label class="wr-input-label">
Set device ownership type
</label>
<div class="wr-input-control">
<div class="cus-col-50">
<!--suppress HtmlFormInputWithoutLabel -->
<select id="ownership-input" class="form-control">
<option value="ANY" selected>ANY</option>
<option value="BYOD">BYOD (Bring Your Own Device)</option>
<option value="COPE">COPE (Corporate-Owned, Personally Enabled)</option>
</select>
</div>
<br class="c-both"/>
</div>
<div class="wr-input-control">
{{#if isAuthorizedViewRoles}}
<label class="wr-input-control radio light">
<input id="user-roles-radio-btn" type="radio"
name="select-users-radio-btn"
class="select-users-radio" checked/>
<span class="helper">Set user role(s)</span>
</label>
{{/if}}
{{#if isAuthorizedViewUsers}}
<label class="wr-input-control radio light" rel="assetfilter">
<input id="users-radio-btn" type="radio" name="select-users-radio-btn"
class="select-users-radio"/>
<span class="helper">Set user(s)</span>
</label>
{{/if}}
</div>
{{#if isAuthorizedViewRoles}}
<div id="user-roles-select-field" class="select-users">
<div class="wr-input-control">
<div class="cus-col-50">
<!--suppress HtmlFormInputWithoutLabel -->
<select id="user-roles-input" class="form-control select2"
multiple="multiple">
<option value="ANY" selected>ANY</option>
{{#each roles}}
<option>{{this}}</option>
{{/each}}
</select>
</div>
<br class="c-both"/>
</div>
</div>
{{/if}}
{{#if isAuthorizedViewUsers}}
<div id="users-select-field" class="select-users">
<div class="wr-input-control">
<div class="cus-col-50">
<!--suppress HtmlFormInputWithoutLabel -->
<select id="users-input" class="form-control select2"
multiple="multiple">
</select>
</div>
<br class="c-both"/>
</div>
</div>
{{/if}}
{{#if isAuthorizedViewGroups}}
<label class="wr-input-label">
Select Groups
</label>
<div id="groups-select-field" class="select-users">
<div class="wr-input-control">
<div class="cus-col-50">
<!--suppress HtmlFormInputWithoutLabel -->
<select id="groups-input" class="form-control select2"
multiple="multiple">
<option value="NONE" selected>NONE</option>
{{#each groups}}
<option>{{this.name}}</option>
{{/each}}
</select>
</div>
<br class="c-both"/>
</div>
</div>
{{/if}}
<br>
<label class="wr-input-label" title="">
Set an action upon non-compliance
</label>
<div class="wr-input-control">
<div class="cus-col-50">
<!--suppress HtmlFormInputWithoutLabel -->
<select id="action-input" class="form-control">
<option data-action="enforce" selected>Enforce</option>
<option data-action="warn">Warn</option>
<option data-action="monitor">Monitor</option>
</select>
</div>
<br class="c-both"/>
</div>
</div>
<div class="wr-input-control wr-btn-grp">
<a href="javascript:void(0)" class="wr-btn wizard-stepper" data-is-back-btn="true"
data-current="policy-criteria" data-next="policy-profile">Back</a>
<a href="javascript:void(0)" class="wr-btn wizard-stepper"
data-current="policy-criteria" data-next="policy-naming" data-validate="true">Continue</a>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-naming">
<div class="wiz-no">4</div>
<div class="wiz-lbl hidden-xs"><span>Publish to devices</span></div>
</div>
</div>
</div>
<div class="col-centered wr-content policy-profile hidden">
<div class="wr-form">
<h1 id="policy-profile-page-wizard-title" class="page-sub-title">ADD POLICY</h1>
<hr>
<div id="policy-profile-wizard-steps" class="row wr-wizard"></div>
<hr>
<div class="row">
<div class="col-lg-12">
<h4 class="hidden-xs">Step 2: Configure profile</h4>
<br>
<div id="policy-profile-main-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
</div>
<div class="wr-advance-operations">
<div class='wr-advance-operations-init'>
<br/>
<i class='fw fw-settings fw-spin fw-2x'></i>
Loading Platform Features . . .
<br/>
<br/>
</div>
<div id="device-type-policy-operations" class="hidden">
</div>
<div id="generic-policy-operations" class="hidden">
{{unit "cdmf.unit.device.type.generic.policy-wizard"}}
</div>
</div>
<div class="wr-input-control wr-btn-grp">
<a href="javascript:void(0)" class="wr-btn wizard-stepper" data-is-back-btn="true"
data-current="policy-profile" data-next="policy-platform">Back</a>
<a href="javascript:void(0)" class="wr-btn wizard-stepper"
data-current="policy-profile"
data-next="policy-criteria" data-validate="true">Continue</a>
</div>
<br class="c-both"/>
</div>
</div>
</div>
</div>
<div id="loading-content" class="col-centered">
<br><br>
<i class="fw fw-settings fw-spin fw-2x"></i>
Loading policy creation wizard . . .
<br><br>
</div>
<div class=" col-centered wr-content policy-platform hidden">
<div class="wr-form">
<h1 id="policy-platform-page-wizard-title" class="page-sub-title">ADD POLICY</h1>
<hr>
<div id="policy-platform-wizard-steps" class="row wr-wizard"></div>
<hr>
<!--<div id="policy-platform-main-error-msg" class="alert alert-danger hidden" role="alert">-->
<!--<i class="icon fw fw-error"></i><span></span>-->
<!--</div>-->
<div class="row">
<div class="col-lg-12">
<h4>Step 1: Select a platform</h4>
<h4 class="hidden-xs"> Step 1: Select a platform</h4>
<br>
<div id="policy-platform-main-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
</div>
<div class="row wr-tile-buttons-list">
<div class="wr-input-control">
<ul class="tile-buttons row">
{{#each types}}
<li class="col-lg-4"
style="margin-top: 5px;margin-bottom: 5px;">
<a href="{{@app.context}}/policy/add/{{name}}"
class="wizard-stepper">
<img src="{{icon}}" width="50px"
height="50px"><br><br>
<li class="col-xs-12 col-sm-12 col-md-4 col-lg-4"
style="margin-top: 5px; margin-bottom: 5px;">
<a href="javascript:void(0)"
class="{{name}}-platform wizard-stepper"
data-current="policy-platform"
data-next="policy-profile"
data-platform="{{name}}"
data-validate="false">
<img src="{{icon}}" width="50px" height="50px"><br><br>
<b>{{label}}</b>
</a>
</li>
@ -83,12 +324,8 @@
<!-- content -->
</div>
</div>
{{else}}
<h1 class="page-sub-title">
Permission Denied
</h1>
<br>
You not authorized to enter Policy Management Section.
<br>
{{/if}}
{{/zone}}
{{#zone "bottomJs"}}
{{js "/js/policy-create.js"}}
{{/zone}}

@ -23,12 +23,15 @@ function onRequest(context) {
var utility = require("/app/modules/utility.js").utility;
var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
var groupModule = require("/app/modules/business-controllers/group.js")["groupModule"];
var types = {};
types.isAuthorized = userModule.isAuthorized("/permission/admin/device-mgt/policies/manage");
types.isAuthorizedViewUsers = userModule.isAuthorized("/permission/admin/device-mgt/roles/view");
types.isAuthorizedViewRoles = userModule.isAuthorized("/permission/admin/device-mgt/users/view");
types.isAuthorizedViewGroups = userModule.isAuthorized("/permission/admin/device-mgt/groups/view");
types["types"] = [];
var typesListResponse = deviceModule.getDeviceTypes();
if (typesListResponse["status"] == "success") {
for (var type in typesListResponse["content"]["deviceTypes"]) {
@ -48,5 +51,14 @@ function onRequest(context) {
}
}
}
var user = userModule.getCarbonUser();
types["user"] = {username: user.username, domain: user.domain, tenantId: user.tenantId};
var roles = userModule.getRoles();
if (roles["status"] == "success") {
types["roles"] = roles["content"];
}
types["groups"] = groupModule.getGroups();
return types;
}

@ -0,0 +1,580 @@
/*
*
* 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 stepForwardFrom = {};
var stepBackFrom = {};
var policy = {};
var configuredOperations = [];
var validateInline = {};
var clearInline = {};
var validateStep = {};
var enableInlineError = function (inputField, errorMsg, errorSign) {
var fieldIdentifier = "#" + inputField;
var errorMsgIdentifier = "#" + inputField + " ." + errorMsg;
var errorSignIdentifier = "#" + inputField + " ." + errorSign;
if (inputField) {
$(fieldIdentifier).addClass(" has-error has-feedback");
}
if (errorMsg) {
$(errorMsgIdentifier).removeClass(" hidden");
}
if (errorSign) {
$(errorSignIdentifier).removeClass(" hidden");
}
};
var disableInlineError = function (inputField, errorMsg, errorSign) {
var fieldIdentifier = "#" + inputField;
var errorMsgIdentifier = "#" + inputField + " ." + errorMsg;
var errorSignIdentifier = "#" + inputField + " ." + errorSign;
if (inputField) {
$(fieldIdentifier).removeClass(" has-error has-feedback");
}
if (errorMsg) {
$(errorMsgIdentifier).addClass(" hidden");
}
if (errorSign) {
$(errorSignIdentifier).addClass(" hidden");
}
};
function loadGroups(callback) {
invokerUtil.get(
"/api/device-mgt/v1.0/groups",
function (data) {
data = JSON.parse(data);
callback(data.deviceGroups);
});
}
var createDeviceGroupWrapper = function (selectedGroups) {
var groupObjects = [];
loadGroups(function (deviceGroups) {
var tenantId = $("#logged-in-user").data("tenant-id");
for (var index in deviceGroups) {
if(deviceGroups.hasOwnProperty(index)) {
var deviceGroupWrapper = {};
if (selectedGroups.indexOf(deviceGroups[index].name) > -1) {
deviceGroupWrapper.id = deviceGroups[index].id;
deviceGroupWrapper.name = deviceGroups[index].name;
deviceGroupWrapper.owner = deviceGroups[index].owner;
deviceGroupWrapper.tenantId = tenantId;
groupObjects.push(deviceGroupWrapper);
}
}
}
});
return groupObjects;
};
/**
*clear inline validation messages.
*/
clearInline["policy-name"] = function () {
disableInlineError("policyNameField", "nameEmpty", "nameError");
};
/**
* Validate if provided policy name is valid against RegEx configures.
*/
validateInline["policy-name"] = function () {
var policyName = $("input#policy-name-input").val();
if (policyName && inputIsValidAgainstLength(policyName, 1, 30)) {
disableInlineError("policyNameField", "nameEmpty", "nameError");
} else {
enableInlineError("policyNameField", "nameEmpty", "nameError");
}
};
$("#policy-name-input").focus(function(){
clearInline["policy-name"]();
}).blur(function(){
validateInline["policy-name"]();
});
stepForwardFrom["policy-platform"] = function (actionButton) {
$("#device-type-policy-operations").html("").addClass("hidden");
$("#generic-policy-operations").addClass("hidden");
policy["platform"] = $(actionButton).data("platform");
policy["platformId"] = $(actionButton).data("platform-type");
// updating next-page wizard title with selected platform
$("#policy-profile-page-wizard-title").text("ADD " + policy["platform"] + " POLICY");
var deviceType = policy["platform"];
var policyOperationsTemplateSrc = context + '/public/cdmf.unit.device.type.' + deviceType +
'.policy-wizard/templates/' + deviceType + '-policy-operations.hbs';
var policyOperationsScriptSrc = context + '/public/cdmf.unit.device.type.' + deviceType +
'.policy-wizard/js/' + deviceType + '-policy-operations.js';
var policyOperationsStylesSrc = context + '/public/cdmf.unit.device.type.' + deviceType +
'.policy-wizard/css/' + deviceType + '-policy-operations.css';
var policyOperationsTemplateCacheKey = deviceType + '-policy-operations';
$.isResourceExists(policyOperationsTemplateSrc, function (status) {
if (status) {
$.template(policyOperationsTemplateCacheKey, policyOperationsTemplateSrc, function (template) {
var content = template();
$("#device-type-policy-operations").html(content).removeClass("hidden");
// $("#device-type-policy-operations").removeClass("hidden");
$(".policy-platform").addClass("hidden");
});
$.isResourceExists(policyOperationsScriptSrc, function (status) {
if (status) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = policyOperationsScriptSrc;
$(".wr-advance-operations").prepend(script);
}
});
$.isResourceExists(policyOperationsStylesSrc, function (status) {
if (status) {
var style = document.createElement('link');
style.type = 'text/css';
style.rel = 'stylesheet';
style.href = policyOperationsStylesSrc;
$(".wr-advance-operations").prepend(style);
}
});
} else {
$("#generic-policy-operations").removeClass("hidden");
}
$(".wr-advance-operations-init").addClass("hidden");
});
};
stepForwardFrom["policy-profile"] = function () {
policy["profile"] = operationModule.generateProfile(policy["platform"], configuredOperations);
// updating next-page wizard title with selected platform
$("#policy-criteria-page-wizard-title").text("ADD " + policy["platform"] + " POLICY");
};
stepBackFrom["policy-profile"] = function () {
// reinitialize configuredOperations
configuredOperations = [];
};
stepForwardFrom["policy-criteria"] = function () {
$("input[type='radio'].select-users-radio").each(function () {
if ($(this).is(':radio')) {
if ($(this).is(":checked")) {
if ($(this).attr("id") == "users-radio-btn") {
policy["selectedUsers"] = $("#users-input").val();
policy["selectedUserRoles"] = null;
} else if ($(this).attr("id") == "user-roles-radio-btn") {
policy["selectedUsers"] = null;
policy["selectedUserRoles"] = $("#user-roles-input").val();
}
}
}
});
policy["selectedGroups"] = $("#groups-input").val();
if (policy["selectedGroups"].length > 1 || policy["selectedGroups"][0] !== "NONE") {
policy["selectedGroups"] = createDeviceGroupWrapper(policy["selectedGroups"]);
}
policy["selectedNonCompliantAction"] = $("#action-input").find(":selected").data("action");
policy["selectedOwnership"] = $("#ownership-input").val();
//updating next-page wizard title with selected platform
$("#policy-naming-page-wizard-title").text("ADD " + policy["platform"] + " POLICY");
};
/**
* Checks if provided input is valid against provided length range.
*
* @param input Alphanumeric or non-alphanumeric input
* @param minLength Minimum Required Length
* @param maxLength Maximum Required Length
* @returns {boolean} Returns true if input matches the provided minimum length and maximum length
*/
var inputIsValidAgainstLength = function (input, minLength, maxLength) {
var length = input.length;
return (length == minLength || (length > minLength && length < maxLength) || length == maxLength);
};
validateStep["policy-criteria"] = function () {
var validationStatus = {};
var selectedAssignees;
var selectedField = "Role(s)";
$("input[type='radio'].select-users-radio").each(function () {
if ($(this).is(":checked")) {
if ($(this).attr("id") == "users-radio-btn") {
selectedAssignees = $("#users-input").val();
selectedField = "User(s)";
} else if ($(this).attr("id") == "user-roles-radio-btn") {
selectedAssignees = $("#user-roles-input").val();
}
return false;
}
});
if (selectedAssignees) {
validationStatus["error"] = false;
} else {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] = selectedField + " is a required field. It cannot be empty";
}
var wizardIsToBeContinued;
if (validationStatus["error"]) {
wizardIsToBeContinued = false;
var mainErrorMsgWrapper = "#policy-criteria-main-error-msg";
var mainErrorMsg = mainErrorMsgWrapper + " span";
$(mainErrorMsg).text(validationStatus["mainErrorMsg"]);
$(mainErrorMsgWrapper).removeClass("hidden");
} else {
wizardIsToBeContinued = true;
}
return wizardIsToBeContinued;
};
validateStep["policy-naming"] = function () {
var validationStatus = {};
// taking values of inputs to be validated
var policyName = $("input#policy-name-input").val();
// starting validation process and updating validationStatus
if (!policyName) {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] = "Policy name is empty. You cannot proceed.";
} else if (!inputIsValidAgainstLength(policyName, 1, 30)) {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] =
"Policy name exceeds maximum allowed length.";
} else {
validationStatus["error"] = false;
}
// ending validation process
// start taking specific actions upon validation
var wizardIsToBeContinued;
if (validationStatus["error"]) {
wizardIsToBeContinued = false;
var mainErrorMsgWrapper = "#policy-naming-main-error-msg";
var mainErrorMsg = mainErrorMsgWrapper + " span";
$(mainErrorMsg).text(validationStatus["mainErrorMsg"]);
$(mainErrorMsgWrapper).removeClass("hidden");
} else {
wizardIsToBeContinued = true;
}
return wizardIsToBeContinued;
};
validateStep["policy-platform"] = function () {
return false;
};
validateStep["policy-naming-publish"] = function () {
var validationStatus = {};
// taking values of inputs to be validated
var policyName = $("input#policy-name-input").val();
// starting validation process and updating validationStatus
if (!policyName) {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] = "Policy name is empty. You cannot proceed.";
} else if (!inputIsValidAgainstLength(policyName, 1, 30)) {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] =
"Policy name exceeds maximum allowed length.";
} else {
validationStatus["error"] = false;
}
// ending validation process
// start taking specific actions upon validation
var wizardIsToBeContinued;
if (validationStatus["error"]) {
wizardIsToBeContinued = false;
var mainErrorMsgWrapper = "#policy-naming-main-error-msg";
var mainErrorMsg = mainErrorMsgWrapper + " span";
$(mainErrorMsg).text(validationStatus["mainErrorMsg"]);
$(mainErrorMsgWrapper).removeClass("hidden");
} else {
wizardIsToBeContinued = true;
}
return wizardIsToBeContinued;
};
stepForwardFrom["policy-naming-publish"] = function () {
policy["policyName"] = $("#policy-name-input").val();
policy["description"] = $("#policy-description-input").val();
//All data is collected. Policy can now be updated.
savePolicy(policy, true, "/api/device-mgt/v1.0/policies/");
};
stepForwardFrom["policy-naming"] = function () {
policy["policyName"] = $("#policy-name-input").val();
policy["description"] = $("#policy-description-input").val();
//All data is collected. Policy can now be updated.
savePolicy(policy, false, "/api/device-mgt/v1.0/policies/");
};
var savePolicy = function (policy, isActive, serviceURL) {
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]
});
}
}
$.each(profilePayloads, function (i, item) {
$.each(item.content, function (key, value) {
//cannot add a true check since it will catch value = false as well
if (value === null || value === undefined || value === "") {
item.content[key] = null;
}
});
});
var payload = {
"policyName": policy["policyName"],
"description": policy["description"],
"compliance": policy["selectedNonCompliantAction"],
"ownershipType": policy["selectedOwnership"],
"active": isActive,
"profile": {
"profileName": policy["policyName"],
"deviceType": policy["platform"],
"profileFeaturesList": profilePayloads
}
};
if (policy["selectedUsers"]) {
payload["users"] = policy["selectedUsers"];
} else if (policy["selectedUserRoles"]) {
payload["roles"] = policy["selectedUserRoles"];
} else {
payload["users"] = [];
payload["roles"] = [];
}
if(policy["selectedGroups"]) {
payload["deviceGroups"] = policy["selectedGroups"];
}
invokerUtil.post(
serviceURL,
payload,
function () {
$(".add-policy").addClass("hidden");
$(".policy-naming").addClass("hidden");
$(".policy-message").removeClass("hidden");
},
function (data) {
}
);
};
function formatRepo(user) {
if (user.loading) {
return user.text;
}
if (!user.username) {
return;
}
var markup = '<div class="clearfix">' +
'<div clas="col-sm-8">' +
'<div class="clearfix">' +
'<div class="col-sm-3">' + user.username + '</div>';
if (user.firstname) {
markup += '<div class="col-sm-3"><i class="fa fa-code-fork"></i> ' + user.firstname + '</div>';
}
if (user.emailAddress) {
markup += '<div class="col-sm-2"><i class="fa fa-star"></i> ' + user.emailAddress + '</div></div>';
}
markup += '</div></div>';
return markup;
}
function formatRepoSelection(user) {
return user.username || user.text;
}
// End of functions related to grid-input-view
$(document).ready(function () {
$("#users-input").select2({
multiple: true,
tags: false,
ajax: {
url: context + "/api/invoker/execute/",
method: "POST",
dataType: 'json',
delay: 250,
id: function (user) {
return user.username;
},
data: function (params) {
var postData = {};
postData.requestMethod = "GET";
postData.requestURL = "/api/device-mgt/v1.0/users/search/usernames?filter=" + params.term;
postData.requestPayload = null;
return JSON.stringify(postData);
},
processResults: function (data) {
var newData = [];
$.each(data, function (index, value) {
value.id = value.username;
newData.push(value);
});
return {
results: newData
};
},
cache: true
},
escapeMarkup: function (markup) {
return markup;
}, // let our custom formatter work
minimumInputLength: 1,
templateResult: formatRepo, // omitted for brevity, see the source of this page
templateSelection: formatRepoSelection // omitted for brevity, see the source of this page
});
$("#loading-content").remove();
$(".policy-platform").removeClass("hidden");
// Adding initial state of wizard-steps.
$("#policy-platform-wizard-steps").html($(".wr-steps").html());
$("select.select2[multiple=multiple]").select2({
"tags": false
});
$("#users-select-field").hide();
$("#user-roles-select-field").show();
$("input[type='radio'].select-users-radio").change(function () {
if ($("#users-radio-btn").is(":checked")) {
$("#user-roles-select-field").hide();
$("#users-select-field").show();
}
if ($("#user-roles-radio-btn").is(":checked")) {
$("#users-select-field").hide();
$("#user-roles-select-field").show();
}
});
// Support for special input type "ANY" on user(s) & user-role(s) selection
$("#user-roles-input").select2({
"tags": false
}).on("select2:select", function (e) {
if (e.params.data.id == "ANY") {
$(this).val("ANY").trigger("change");
} else {
$("option[value=ANY]", this).prop("selected", false).parent().trigger("change");
}
});
$("#groups-input").select2({
"tags": false
}).on("select2:select", function (e) {
if (e.params.data.id == "NONE") {
$(this).val("NONE").trigger("change");
} else {
$("option[value=NONE]", this).prop("selected", false).parent().trigger("change");
}
});
//Policy wizard stepper
$(".wizard-stepper").click(function () {
// button clicked here can be either a continue button or a back button.
var currentStep = $(this).data("current");
var validationIsRequired = $(this).data("validate");
var wizardIsToBeContinued;
if (validationIsRequired) {
if (currentStep == "policy-profile") {
wizardIsToBeContinued = validatePolicyProfile();
} else {
wizardIsToBeContinued = validateStep[currentStep]();
}
} else {
wizardIsToBeContinued = true;
}
if (wizardIsToBeContinued) {
// When moving back and forth, following code segment will
// remove if there are any visible error-messages.
var errorMsgWrappers = ".alert.alert-danger";
$(errorMsgWrappers).each(
function () {
if (!$(this).hasClass("hidden")) {
$(this).addClass("hidden");
}
}
);
var nextStep = $(this).data("next");
var isBackBtn = $(this).data("is-back-btn");
// if current button is a continuation...
if (!isBackBtn) {
// initiate stepForwardFrom[*] functions to gather form data.
if (stepForwardFrom[currentStep]) {
stepForwardFrom[currentStep](this);
}
} else {
// initiate stepBackFrom[*] functions to rollback.
if (stepBackFrom[currentStep]) {
stepBackFrom[currentStep]();
}
}
// following step occurs only at the last stage of the wizard.
if (!nextStep) {
window.location.href = $(this).data("direct");
}
// updating next wizard step as current.
$(".itm-wiz").each(function () {
var step = $(this).data("step");
if (step == nextStep) {
$(this).addClass("itm-wiz-current");
} else {
$(this).removeClass("itm-wiz-current");
}
});
// adding next update of wizard-steps.
$("#" + nextStep + "-wizard-steps").html($(".wr-steps").html());
// hiding current section of the wizard and showing next section.
$("." + currentStep).addClass("hidden");
$("." + nextStep).removeClass("hidden");
}
});
});

@ -1,5 +1,7 @@
{{#zone "content"}}
{{#if isAuthorized }}
<span id="logged-in-user" class="hidden" data-username="{{user.username}}" data-domain="{{user.domain}}"
data-tenant-id="{{user.tenantId}}"></span>
<div class="row">
<div class="col-md-12">
@ -35,10 +37,10 @@
<b>"View policy list"</b> to complete the process and go back to the policy list.
<hr>
<button class="wr-btn wizard-stepper" data-current="policy-message"
data-direct="/emm/policies/">
data-direct="{{@app.context}}/policies/">
View policy list
</button>
<a href="/emm/policies/add-policy" class="cu-btn-inner">
<a href="{{@app.context}}/policies/add" class="cu-btn-inner">
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-add fw-stack-1x"></i>
@ -135,46 +137,72 @@
<br class="c-both"/>
</div>
<div class="wr-input-control">
<label class="wr-input-control radio light">
<input id="user-roles-radio-btn" type="radio" name="select-users-radio-btn"
class="select-users-radio" checked/>
<span class="helper">Set user role(s)</span>
</label>
<label class="wr-input-control radio light" rel="assetfilter">
<input id="users-radio-btn" type="radio" name="select-users-radio-btn"
class="select-users-radio"/>
<span class="helper">Set user(s)</span>
</label>
{{#if isAuthorizedViewRoles}}
<label class="wr-input-control radio light">
<input id="user-roles-radio-btn" type="radio"
name="select-users-radio-btn"
class="select-users-radio" checked/>
<span class="helper">Set user role(s)</span>
</label>
{{/if}}
{{#if isAuthorizedViewUsers}}
<label class="wr-input-control radio light" rel="assetfilter">
<input id="users-radio-btn" type="radio" name="select-users-radio-btn"
class="select-users-radio"/>
<span class="helper">Set user(s)</span>
</label>
{{/if}}
</div>
<div id="user-roles-select-field" class="select-users">
<div class="wr-input-control">
<div class="cus-col-50">
<select id="user-roles-input" class="form-control select2"
multiple="multiple">
<option value="ANY" selected>ANY</option>
{{#each roles}}
<option>{{this}}</option>
{{/each}}
</select>
{{#if isAuthorizedViewRoles}}
<div id="user-roles-select-field" class="select-users">
<div class="wr-input-control">
<div class="cus-col-50">
<!--suppress HtmlFormInputWithoutLabel -->
<select id="user-roles-input" class="form-control select2"
multiple="multiple">
<option value="ANY" selected>ANY</option>
{{#each roles}}
<option>{{this}}</option>
{{/each}}
</select>
</div>
<br class="c-both"/>
</div>
<br class="c-both"/>
</div>
</div>
<div id="users-select-field" class="select-users">
<div class="wr-input-control">
<div class="cus-col-50">
<select id="users-input" class="form-control select2"
multiple="multiple">
<option value="ANY" selected>ANY</option>
{{#each users}}
<option>{{username}}</option>
{{/each}}
</select>
{{/if}}
{{#if isAuthorizedViewUsers}}
<div id="users-select-field" class="select-users">
<div class="wr-input-control">
<div class="cus-col-50">
<!--suppress HtmlFormInputWithoutLabel -->
<select id="users-input" class="form-control select2"
multiple="multiple">
</select>
</div>
<br class="c-both"/>
</div>
<br class="c-both"/>
</div>
</div>
<br>
{{/if}}
{{#if isAuthorizedViewGroups}}
<label class="wr-input-label">
Select Groups
</label>
<div id="groups-select-field" class="select-users">
<div class="wr-input-control">
<div class="cus-col-50">
<!--suppress HtmlFormInputWithoutLabel -->
<select id="groups-input" class="form-control select2"
multiple="multiple">
<option value="NONE" selected>NONE</option>
{{#each groups}}
<option>{{this.name}}</option>
{{/each}}
</select>
</div>
<br class="c-both"/>
</div>
</div>
{{/if}}
<label class="wr-input-label" title="">
Set an action upon non-compliance
</label>
@ -218,13 +246,17 @@
<i class="icon fw fw-error"></i><span></span>
</div>
<div class="wr-advance-operations">
<div class="wr-advance-operations-init">
<br>
<i class="fw fw-settings fw-spin fw-2x"></i>
Loading platform features . . .
<br>
<br>
<div class='wr-advance-operations-init'>
<br/>
<i class='fw fw-settings fw-spin fw-2x'></i>
Loading Platform Features . . .
<br/>
<br/>
</div>
<div id="device-type-policy-operations" class="hidden">
</div>
<div id="generic-policy-operations" class="hidden">
{{unit "cdmf.unit.device.type.generic.policy-wizard"}}
</div>
</div>
<div class="wr-input-control wr-btn-grp">
@ -252,15 +284,5 @@
{{/if}}
{{/zone}}
{{#zone "bottomJs"}}
<!--suppress HtmlUnknownTarget -->
<script id="hidden-operations-ios" src="{{@unit.publicUri}}/templates/hidden-operations-ios.hbs"
type="text/x-handlebars-template"></script>
<!--suppress HtmlUnknownTarget -->
<script id="hidden-operations-android" src="{{@unit.publicUri}}/templates/hidden-operations-android.hbs"
type="text/x-handlebars-template"></script>
<!--suppress HtmlUnknownTarget -->
<script id="hidden-operations-windows" src="{{@unit.publicUri}}/templates/hidden-operations-windows.hbs"
type="text/x-handlebars-template"></script>
{{js "js/edit.js"}}
{{js "js/policy-edit.js"}}
{{/zone}}

@ -18,19 +18,29 @@
function onRequest(context) {
var log = new Log("policy-view-edit-unit backend js");
log.debug("calling policy-view-edit-unit");
var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
var groupModule = require("/app/modules/business-controllers/group.js")["groupModule"];
var rolesResult = userModule.getRoles();
if (rolesResult.status == "success") {
viewModel.roles = rolesResult.content;
context.roles = rolesResult.content;
}
var usersResult = userModule.getUsers();
if (usersResult.status == "success") {
viewModel.users = usersResult.content;
context.users = usersResult.content;
}
viewModel.isAuthorized = userModule.isAuthorized("/permission/admin/device-mgt/policies/manage");
return viewModel;
context["groups"] = groupModule.getGroups();
var user = userModule.getCarbonUser();
context["user"] = {username: user.username, domain: user.domain, tenantId: user.tenantId};
context.isAuthorized = userModule.isAuthorized("/permission/admin/device-mgt/policies/manage");
context.isAuthorizedViewUsers = userModule.isAuthorized("/permission/admin/device-mgt/roles/view");
context.isAuthorizedViewRoles = userModule.isAuthorized("/permission/admin/device-mgt/users/view");
context.isAuthorizedViewGroups = userModule.isAuthorized("/permission/admin/device-mgt/groups/view");
return context;
}

@ -0,0 +1,613 @@
/*
* 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 validateStep = {};
var skipStep = {};
var stepForwardFrom = {};
var stepBackFrom = {};
var configuredOperations = [];
var policy = {};
var currentlyEffected = {};
var validateInline = {};
var clearInline = {};
var enableInlineError = function (inputField, errorMsg, errorSign) {
var fieldIdentifier = "#" + inputField;
var errorMsgIdentifier = "#" + inputField + " ." + errorMsg;
var errorSignIdentifier = "#" + inputField + " ." + errorSign;
if (inputField) {
$(fieldIdentifier).addClass(" has-error has-feedback");
}
if (errorMsg) {
$(errorMsgIdentifier).removeClass(" hidden");
}
if (errorSign) {
$(errorSignIdentifier).removeClass(" hidden");
}
};
var disableInlineError = function (inputField, errorMsg, errorSign) {
var fieldIdentifier = "#" + inputField;
var errorMsgIdentifier = "#" + inputField + " ." + errorMsg;
var errorSignIdentifier = "#" + inputField + " ." + errorSign;
if (inputField) {
$(fieldIdentifier).removeClass(" has-error has-feedback");
}
if (errorMsg) {
$(errorMsgIdentifier).addClass(" hidden");
}
if (errorSign) {
$(errorSignIdentifier).addClass(" hidden");
}
};
function loadGroups(callback) {
invokerUtil.get(
"/api/device-mgt/v1.0/groups",
function (data) {
data = JSON.parse(data);
callback(data.deviceGroups);
});
}
var createDeviceGroupWrapper = function (selectedGroups) {
var groupObjects = [];
loadGroups(function (deviceGroups) {
var tenantId = $("#logged-in-user").data("tenant-id");
for (var index in deviceGroups) {
if(deviceGroups.hasOwnProperty(index)) {
var deviceGroupWrapper = {};
if (selectedGroups.indexOf(deviceGroups[index].name) > -1) {
deviceGroupWrapper.id = deviceGroups[index].id;
deviceGroupWrapper.name = deviceGroups[index].name;
deviceGroupWrapper.owner = deviceGroups[index].owner;
deviceGroupWrapper.tenantId = tenantId;
groupObjects.push(deviceGroupWrapper);
}
}
}
});
return groupObjects;
};
/**
*clear inline validation messages.
*/
clearInline["policy-name"] = function () {
disableInlineError("policy-name-field", "nameEmpty", "nameError");
};
/**
* Validate if provided policy name is valid against RegEx configures.
*/
validateInline["policy-name"] = function () {
var policyName = $("input#policy-name-input").val();
if (policyName && inputIsValidAgainstLength(policyName, 1, 30)) {
disableInlineError("policy-name-field", "nameEmpty", "nameError");
} else {
enableInlineError("policy-name-field", "nameEmpty", "nameError");
}
};
$("#policy-name-input").focus(function () {
clearInline["policy-name"]();
}).blur(function () {
validateInline["policy-name"]();
});
skipStep["policy-platform"] = function (policyPayloadObj) {
policy["name"] = policyPayloadObj["policyName"];
policy["platform"] = policyPayloadObj["profile"]["deviceType"];
var userRoleInput = $("#user-roles-input");
var ownershipInput = $("#ownership-input");
var userInput = $("#users-input");
var groupsInput = $("#groups-input");
var actionInput = $("#action-input");
var policyNameInput = $("#policy-name-input");
var policyDescriptionInput = $("#policy-description-input");
currentlyEffected["roles"] = policyPayloadObj.roles;
currentlyEffected["users"] = policyPayloadObj.users;
currentlyEffected["groups"] = policyPayloadObj.deviceGroups;
if (currentlyEffected["roles"].length > 0) {
$("#user-roles-radio-btn").prop("checked", true);
$("#user-roles-select-field").show();
$("#users-select-field").hide();
userRoleInput.val(currentlyEffected["roles"]).trigger("change");
} else if (currentlyEffected["users"].length > 0) {
$("#users-radio-btn").prop("checked", true);
$("#users-select-field").show();
$("#user-roles-select-field").hide();
userInput.val(currentlyEffected["users"]).trigger("change");
}
if(currentlyEffected["groups"].length > 0) {
groupsInput.val(currentlyEffected["groups"]).trigger("change");
}
ownershipInput.val(policyPayloadObj.ownershipType);
actionInput.val(policyPayloadObj.compliance);
policyNameInput.val(policyPayloadObj["policyName"]);
policyDescriptionInput.val(policyPayloadObj["description"]);
// updating next-page wizard title with selected platform
$("#policy-profile-page-wizard-title").text("EDIT " + policy["platform"] + " POLICY - " + policy["name"]);
var deviceType = policy["platform"];
var policyOperationsTemplateSrc = context + '/public/cdmf.unit.device.type.' + deviceType +
'.policy-edit/templates/' + deviceType + '-policy-edit.hbs';
var policyOperationsScriptSrc = context + '/public/cdmf.unit.device.type.' + deviceType +
'.policy-edit/js/' + deviceType + '-policy-edit.js';
var policyOperationsStylesSrc = context + '/public/cdmf.unit.device.type.' + deviceType +
'.policy-edit/css/' + deviceType + '-policy-edit.css';
var policyOperationsTemplateCacheKey = deviceType + '-policy-operations';
$.isResourceExists(policyOperationsTemplateSrc, function (status) {
if (status) {
$.template(policyOperationsTemplateCacheKey, policyOperationsTemplateSrc, function (template) {
var content = template();
$("#device-type-policy-operations").html(content).removeClass("hidden");
$(".policy-platform").addClass("hidden");
$.isResourceExists(policyOperationsScriptSrc, function (status) {
if (status) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = policyOperationsScriptSrc;
$(".wr-advance-operations").prepend(script);
var configuredOperations = operationModule.
populateProfile(policy["platform"], policyPayloadObj["profile"]["profileFeaturesList"]);
polulateProfileOperations(configuredOperations);
}
});
});
$.isResourceExists(policyOperationsStylesSrc, function (status) {
if (status) {
var style = document.createElement('link');
style.type = 'text/css';
style.rel = 'stylesheet';
style.href = policyOperationsStylesSrc;
$(".wr-advance-operations").prepend(style);
}
});
} else {
$("#generic-policy-operations").removeClass("hidden");
}
$(".wr-advance-operations-init").addClass("hidden");
});
};
stepForwardFrom["policy-profile"] = function () {
policy["profile"] = operationModule.generateProfile(policy["platform"], configuredOperations);
// updating next-page wizard title with selected platform
$("#policy-criteria-page-wizard-title").text("EDIT " + policy["platform"] + " POLICY - " + policy["name"]);
};
stepForwardFrom["policy-criteria"] = function () {
$("input[type='radio'].select-users-radio").each(function () {
if ($(this).is(':radio')) {
if ($(this).is(":checked")) {
if ($(this).attr("id") == "users-radio-btn") {
policy["selectedUsers"] = $("#users-input").val();
policy["selectedUserRoles"] = null;
} else if ($(this).attr("id") == "user-roles-radio-btn") {
policy["selectedUsers"] = null;
policy["selectedUserRoles"] = $("#user-roles-input").val();
}
}
}
});
policy["selectedGroups"] = $("#groups-input").val();
if (policy["selectedGroups"].length > 1 || policy["selectedGroups"][0] !== "NONE") {
policy["selectedGroups"] = createDeviceGroupWrapper(policy["selectedGroups"]);
}
policy["selectedNonCompliantAction"] = $("#action-input").find(":selected").data("action");
policy["selectedOwnership"] = $("#ownership-input").val();
// updating next-page wizard title with selected platform
$("#policy-naming-page-wizard-title").text("EDIT " + policy["platform"] + " POLICY - " + policy["name"]);
};
/**
* Checks if provided input is valid against provided length range.
*
* @param input Alphanumeric or non-alphanumeric input
* @param minLength Minimum Required Length
* @param maxLength Maximum Required Length
* @returns {boolean} Returns true if input matches the provided minimum length and maximum length
*/
var inputIsValidAgainstLength = function (input, minLength, maxLength) {
var length = input.length;
return (length == minLength || (length > minLength && length < maxLength) || length == maxLength);
};
validateStep["policy-criteria"] = function () {
var validationStatus = {};
var selectedAssignees;
var selectedField = "Role(s)";
$("input[type='radio'].select-users-radio").each(function () {
if ($(this).is(":checked")) {
if ($(this).attr("id") == "users-radio-btn") {
selectedAssignees = $("#users-input").val();
selectedField = "User(s)";
} else if ($(this).attr("id") == "user-roles-radio-btn") {
selectedAssignees = $("#user-roles-input").val();
}
return false;
}
});
if (selectedAssignees) {
validationStatus["error"] = false;
} else {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] = selectedField + " is a required field. It cannot be empty";
}
var wizardIsToBeContinued;
if (validationStatus["error"]) {
wizardIsToBeContinued = false;
var mainErrorMsgWrapper = "#policy-criteria-main-error-msg";
var mainErrorMsg = mainErrorMsgWrapper + " span";
$(mainErrorMsg).text(validationStatus["mainErrorMsg"]);
$(mainErrorMsgWrapper).removeClass("hidden");
} else {
wizardIsToBeContinued = true;
}
return wizardIsToBeContinued;
};
validateStep["policy-naming"] = function () {
var validationStatus = {};
// taking values of inputs to be validated
var policyName = $("input#policy-name-input").val();
// starting validation process and updating validationStatus
if (!policyName) {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] = "Policy name is empty. You cannot proceed.";
} else if (!inputIsValidAgainstLength(policyName, 1, 30)) {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] =
"Policy name exceeds maximum allowed length.";
} else {
validationStatus["error"] = false;
}
// ending validation process
// start taking specific actions upon validation
var wizardIsToBeContinued;
if (validationStatus["error"]) {
wizardIsToBeContinued = false;
var mainErrorMsgWrapper = "#policy-naming-main-error-msg";
var mainErrorMsg = mainErrorMsgWrapper + " span";
$(mainErrorMsg).text(validationStatus["mainErrorMsg"]);
$(mainErrorMsgWrapper).removeClass("hidden");
} else {
wizardIsToBeContinued = true;
}
return wizardIsToBeContinued;
};
validateStep["policy-naming-publish"] = function () {
var validationStatus = {};
// taking values of inputs to be validated
var policyName = $("input#policy-name-input").val();
// starting validation process and updating validationStatus
if (!policyName) {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] = "Policy name is empty. You cannot proceed.";
} else if (!inputIsValidAgainstLength(policyName, 1, 30)) {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] =
"Policy name exceeds maximum allowed length.";
} else {
validationStatus["error"] = false;
}
// ending validation process
// start taking specific actions upon validation
var wizardIsToBeContinued;
if (validationStatus["error"]) {
wizardIsToBeContinued = false;
var mainErrorMsgWrapper = "#policy-naming-main-error-msg";
var mainErrorMsg = mainErrorMsgWrapper + " span";
$(mainErrorMsg).text(validationStatus["mainErrorMsg"]);
$(mainErrorMsgWrapper).removeClass("hidden");
} else {
wizardIsToBeContinued = true;
}
return wizardIsToBeContinued;
};
stepForwardFrom["policy-naming-publish"] = function () {
policy["policyName"] = $("#policy-name-input").val();
policy["description"] = $("#policy-description-input").val();
//All data is collected. Policy can now be updated.
updatePolicy(policy, "publish");
};
stepForwardFrom["policy-naming"] = function () {
policy["policyName"] = $("#policy-name-input").val();
policy["description"] = $("#policy-description-input").val();
//All data is collected. Policy can now be updated.
updatePolicy(policy, "save");
};
// End of functions related to grid-input-view
/**
* This method will return query parameter value given its name.
* @param name Query parameter name
* @returns {string} Query parameter value
*/
var getParameterByName = function (name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
};
var updatePolicy = function (policy, state) {
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]
});
}
}
$.each(profilePayloads, function (i, item) {
$.each(item.content, function (key, value) {
if (value === null || value === undefined || value === "") {
item.content[key] = null;
}
});
});
var payload = {
"policyName": policy["policyName"],
"description": policy["description"],
"compliance": policy["selectedNonCompliantAction"],
"ownershipType": policy["selectedOwnership"],
"profile": {
"profileName": policy["policyName"],
"deviceType": policy["platform"],
"profileFeaturesList": profilePayloads
}
};
if (policy["selectedUsers"]) {
payload["users"] = policy["selectedUsers"];
payload["roles"] = [];
} else if (policy["selectedUserRoles"]) {
payload["users"] = [];
payload["roles"] = policy["selectedUserRoles"];
} else {
payload["users"] = [];
payload["roles"] = [];
}
if(policy["selectedGroups"]) {
payload["deviceGroups"] = policy["selectedGroups"];
}
var serviceURL = "/api/device-mgt/v1.0/policies/" + getParameterByName("id");
invokerUtil.put(
serviceURL,
payload,
// on success
function (data, textStatus, jqXHR) {
if (jqXHR.status == 200) {
var policyList = [];
policyList.push(getParameterByName("id"));
if (state == "save") {
serviceURL = "/api/device-mgt/v1.0/policies/deactivate-policy";
invokerUtil.post(
serviceURL,
policyList,
// on success
function (data, textStatus, jqXHR) {
if (jqXHR.status == 200) {
$(".add-policy").addClass("hidden");
$(".policy-message").removeClass("hidden");
}
},
// on error
function (jqXHR) {
console.log("error in saving policy. Received error code : " + jqXHR.status);
}
);
} else if (state == "publish") {
serviceURL = "/api/device-mgt/v1.0/policies/activate-policy";
invokerUtil.post(
serviceURL,
policyList,
// on success
function (data, textStatus, jqXHR) {
if (jqXHR.status == 200) {
$(".add-policy").addClass("hidden");
$(".policy-naming").addClass("hidden");
$(".policy-message").removeClass("hidden");
}
},
// on error
function (jqXHR) {
console.log("error in publishing policy. Received error code : " + jqXHR.status);
}
);
}
}
},
// on error
function (jqXHR) {
console.log("error in updating policy. Received error code : " + jqXHR.status);
}
);
};
$(document).ready(function () {
// Adding initial state of wizard-steps.
invokerUtil.get(
"/api/device-mgt/v1.0/policies/" + getParameterByName("id"),
// on success
function (data, textStatus, jqXHR) {
if (jqXHR.status == 200 && data) {
var policy = JSON.parse(data);
skipStep["policy-platform"](policy);
}
},
// on error
function (jqXHR) {
console.log(jqXHR);
// should be redirected to an error page
}
);
$("input[type='radio'].select-users-radio").change(function () {
if ($("#users-radio-btn").is(":checked")) {
$("#user-roles-select-field").hide();
$("#users-select-field").show();
}
if ($("#user-roles-radio-btn").is(":checked")) {
$("#users-select-field").hide();
$("#user-roles-select-field").show();
}
});
// Support for special input type "ANY" on user(s) & user-role(s) selection
$("#user-roles-input").select2({
"tags": false
}).on("select2:select", function (e) {
if (e.params.data.id == "ANY") {
$(this).val("ANY").trigger("change");
} else {
$("option[value=ANY]", this).prop("selected", false).parent().trigger("change");
}
});
$("#groups-input").select2({
"tags": false
}).on("select2:select", function (e) {
if (e.params.data.id == "NONE") {
$(this).val("NONE").trigger("change");
} else {
$("option[value=NONE]", this).prop("selected", false).parent().trigger("change");
}
});
$("#users-input").select2({
"tags": false
}).on("select2:select", function (e) {
if (e.params.data.id == "ANY") {
$(this).val("ANY").trigger("change");
} else {
$("option[value=ANY]", this).prop("selected", false).parent().trigger("change");
}
});
$("#policy-profile-wizard-steps").html($(".wr-steps").html());
$(".wizard-stepper").click(function () {
// button clicked here can be either a continue button or a back button.
var currentStep = $(this).data("current");
var validationIsRequired = $(this).data("validate");
var wizardIsToBeContinued;
if (validationIsRequired) {
if (currentStep == "policy-profile") {
wizardIsToBeContinued = validatePolicyProfile();
} else {
wizardIsToBeContinued = validateStep[currentStep]();
}
} else {
wizardIsToBeContinued = true;
}
if (wizardIsToBeContinued) {
// When moving back and forth, following code segment will
// remove if there are any visible error-messages.
var errorMsgWrappers = ".alert.alert-danger";
$(errorMsgWrappers).each(
function () {
if (!$(this).hasClass("hidden")) {
$(this).addClass("hidden");
}
}
);
var nextStep = $(this).data("next");
var isBackBtn = $(this).data("is-back-btn");
// if current button is a continuation...
if (!isBackBtn) {
// initiate stepForwardFrom[*] functions to gather form data.
if (stepForwardFrom[currentStep]) {
stepForwardFrom[currentStep](this);
}
} else {
// initiate stepBackFrom[*] functions to rollback.
if (stepBackFrom[currentStep]) {
stepBackFrom[currentStep]();
}
}
// following step occurs only at the last stage of the wizard.
if (!nextStep) {
window.location.href = $(this).data("direct");
}
// updating next wizard step as current.
$(".itm-wiz").each(function () {
var step = $(this).data("step");
if (step == nextStep) {
$(this).addClass("itm-wiz-current");
} else {
$(this).removeClass("itm-wiz-current");
}
});
// adding next update of wizard-steps.
$("#" + nextStep + "-wizard-steps").html($(".wr-steps").html());
// hiding current section of the wizard and showing next section.
$("." + currentStep).addClass("hidden");
$("." + nextStep).removeClass("hidden");
}
});
});

@ -1,17 +1,16 @@
/*
* 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
* 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
* "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.
*/
@ -21,60 +20,120 @@ var stepForwardFrom = {};
var stepBackFrom = {};
var policy = {};
var configuredOperations = [];
var deviceTypeLabel;
var validateInline = {};
var clearInline = {};
/**
* Method to update the visibility of grouped input.
* @param domElement HTML grouped-input element with class name "grouped-input"
*/
var updateGroupedInputVisibility = function (domElement) {
if ($(".parent-input:first", domElement).is(":checked")) {
if ($(".grouped-child-input:first", domElement).hasClass("disabled")) {
$(".grouped-child-input:first", domElement).removeClass("disabled");
}
$(".child-input", domElement).each(function () {
$(this).prop('disabled', false);
});
} else {
if (!$(".grouped-child-input:first", domElement).hasClass("disabled")) {
$(".grouped-child-input:first", domElement).addClass("disabled");
}
$(".child-input", domElement).each(function () {
$(this).prop('disabled', true);
});
var enableInlineError = function (inputField, errorMsg, errorSign) {
var fieldIdentifier = "#" + inputField;
var errorMsgIdentifier = "#" + inputField + " ." + errorMsg;
var errorSignIdentifier = "#" + inputField + " ." + errorSign;
if (inputField) {
$(fieldIdentifier).addClass(" has-error has-feedback");
}
if (errorMsg) {
$(errorMsgIdentifier).removeClass(" hidden");
}
if (errorSign) {
$(errorSignIdentifier).removeClass(" hidden");
}
};
var disableInlineError = function (inputField, errorMsg, errorSign) {
var fieldIdentifier = "#" + inputField;
var errorMsgIdentifier = "#" + inputField + " ." + errorMsg;
var errorSignIdentifier = "#" + inputField + " ." + errorSign;
if (inputField) {
$(fieldIdentifier).removeClass(" has-error has-feedback");
}
if (errorMsg) {
$(errorMsgIdentifier).addClass(" hidden");
}
if (errorSign) {
$(errorSignIdentifier).addClass(" hidden");
}
};
/**
* Checks if provided number is valid against a range.
*
* @param numberInput Number Input
* @param min Minimum Limit
* @param max Maximum Limit
* @returns {boolean} Returns true if input is within the specified range
*clear inline validation messages.
*/
var inputIsValidAgainstRange = function (numberInput, min, max) {
return (numberInput == min || (numberInput > min && numberInput < max) || numberInput == max);
clearInline["policy-name"] = function () {
disableInlineError("policyNameField", "nameEmpty", "nameError");
};
/**
* Checks if provided input is valid against RegEx input.
*
* @param regExp Regular expression
* @param input Input string to check
* @returns {boolean} Returns true if input matches RegEx
* Validate if provided policy name is valid against RegEx configures.
*/
var inputIsValidAgainstRegExp = function (regExp, input) {
return regExp.test(input);
validateInline["policy-name"] = function () {
var policyName = $("input#policy-name-input").val();
if (policyName && inputIsValidAgainstLength(policyName, 1, 30)) {
disableInlineError("policyNameField", "nameEmpty", "nameError");
} else {
enableInlineError("policyNameField", "nameEmpty", "nameError");
}
};
validateStep["policy-profile"] = function () {
return true;
$("#policy-name-input").focus(function(){
clearInline["policy-name"]();
}).blur(function(){
validateInline["policy-name"]();
});
stepForwardFrom["policy-platform"] = function (actionButton) {
policy["platform"] = $(actionButton).data("platform");
policy["platformId"] = $(actionButton).data("platform-type");
// updating next-page wizard title with selected platform
$("#policy-profile-page-wizard-title").text("ADD " + policy["platform"] + " POLICY");
var deviceType = policy["platform"];
var policyOperationsTemplateSrc = context + '/public/cdmf.unit.device.type.' + deviceType +
'.policy-wizard/templates/' + deviceType + '-policy-operations.hbs';
var policyOperationsScriptSrc = context + '/public/cdmf.unit.device.type.' + deviceType +
'.policy-wizard/js/' + deviceType + '-policy-operations.js';
var policyOperationsStylesSrc = context + '/public/cdmf.unit.device.type.' + deviceType +
'.policy-wizard/css/' + deviceType + '-policy-operations.css';
var policyOperationsTemplateCacheKey = deviceType + '-policy-operations';
$.isResourceExists(policyOperationsTemplateSrc, function (status) {
if (status) {
$.template(policyOperationsTemplateCacheKey, policyOperationsTemplateSrc, function (template) {
var content = template();
$(".wr-advance-operations").html(content);
$(".policy-platform").addClass("hidden");
});
}
});
$.isResourceExists(policyOperationsScriptSrc, function (status) {
if (status) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = policyOperationsScriptSrc;
$(".wr-advance-operations").prepend(script);
}
});
$.isResourceExists(policyOperationsStylesSrc, function (status) {
if (status) {
var style = document.createElement('link');
style.type = 'text/css';
style.rel = 'stylesheet';
style.href = policyOperationsStylesSrc;
$(".wr-advance-operations").prepend(style);
}
});
};
stepForwardFrom["policy-profile"] = function () {
policy["profile"] = operationModule.generateProfile(policy["platform"], configuredOperations);
// updating next-page wizard title with selected platform
$("#policy-criteria-page-wizard-title").text("ADD " + deviceTypeLabel + " POLICY");
$("#policy-criteria-page-wizard-title").text("ADD " + policy["platform"] + " POLICY");
};
stepBackFrom["policy-profile"] = function () {
@ -84,15 +143,13 @@ stepBackFrom["policy-profile"] = function () {
// so that, the wrong content would not be shown at the first glance, in case
// the user selects a different platform
$(".wr-advance-operations").html(
"<div class='wr-advance-operations-init'>" +
"<br>" +
"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" +
"<i class='fw fw-settings fw-spin fw-2x'></i>" +
"&nbsp;&nbsp;&nbsp;&nbsp;" +
"Loading Platform Features . . ." +
"<br>" +
"<br>" +
"</div>"
"<div class='wr-advance-operations-init'>" +
"<br>" +
"<i class='fw fw-settings fw-spin fw-2x'></i>" +
"Loading Platform Features . . ." +
"<br>" +
"<br>" +
"</div>"
);
};
@ -102,18 +159,18 @@ stepForwardFrom["policy-criteria"] = function () {
if ($(this).is(":checked")) {
if ($(this).attr("id") == "users-radio-btn") {
policy["selectedUsers"] = $("#users-input").val();
policy["selectedUserRoles"] = null;
} else if ($(this).attr("id") == "user-roles-radio-btn") {
policy["selectedUsers"] = null;
policy["selectedUserRoles"] = $("#user-roles-input").val();
} else if ($(this).attr("id") == "groups-radio-btn") {
policy["selectedUserGroups"] = $("#groups-input").val();
}
}
}
});
policy["selectedNonCompliantAction"] = $("#action-input").find(":selected").data("action");
policy["selectedOwnership"] = $("#ownership-input").val();
// updating next-page wizard title with selected platform
$("#policy-naming-page-wizard-title").text("ADD " + deviceTypeLabel + " POLICY");
//updating next-page wizard title with selected platform
$("#policy-naming-page-wizard-title").text("ADD " + policy["platform"] + " POLICY");
};
/**
@ -129,6 +186,44 @@ var inputIsValidAgainstLength = function (input, minLength, maxLength) {
return (length == minLength || (length > minLength && length < maxLength) || length == maxLength);
};
validateStep["policy-criteria"] = function () {
var validationStatus = {};
var selectedAssignees;
var selectedField = "Role(s)";
$("input[type='radio'].select-users-radio").each(function () {
if ($(this).is(":checked")) {
if ($(this).attr("id") == "users-radio-btn") {
selectedAssignees = $("#users-input").val();
selectedField = "User(s)";
} else if ($(this).attr("id") == "user-roles-radio-btn") {
selectedAssignees = $("#user-roles-input").val();
}
return false;
}
});
if (selectedAssignees) {
validationStatus["error"] = false;
} else {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] = selectedField + " is a required field. It cannot be empty";
}
var wizardIsToBeContinued;
if (validationStatus["error"]) {
wizardIsToBeContinued = false;
var mainErrorMsgWrapper = "#policy-criteria-main-error-msg";
var mainErrorMsg = mainErrorMsgWrapper + " span";
$(mainErrorMsg).text(validationStatus["mainErrorMsg"]);
$(mainErrorMsgWrapper).removeClass("hidden");
} else {
wizardIsToBeContinued = true;
}
return wizardIsToBeContinued;
};
validateStep["policy-naming"] = function () {
var validationStatus = {};
@ -141,7 +236,7 @@ validateStep["policy-naming"] = function () {
} else if (!inputIsValidAgainstLength(policyName, 1, 30)) {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] =
"Policy name exceeds maximum allowed length. Please check.";
"Policy name exceeds maximum allowed length.";
} else {
validationStatus["error"] = false;
}
@ -162,6 +257,10 @@ validateStep["policy-naming"] = function () {
return wizardIsToBeContinued;
};
validateStep["policy-platform"] = function () {
return false;
};
validateStep["policy-naming-publish"] = function () {
var validationStatus = {};
@ -174,7 +273,7 @@ validateStep["policy-naming-publish"] = function () {
} else if (!inputIsValidAgainstLength(policyName, 1, 30)) {
validationStatus["error"] = true;
validationStatus["mainErrorMsg"] =
"Policy name exceeds maximum allowed length. Please check.";
"Policy name exceeds maximum allowed length.";
} else {
validationStatus["error"] = false;
}
@ -199,34 +298,48 @@ stepForwardFrom["policy-naming-publish"] = function () {
policy["policyName"] = $("#policy-name-input").val();
policy["description"] = $("#policy-description-input").val();
//All data is collected. Policy can now be updated.
savePolicy(policy, "publish");
savePolicy(policy, true, "/api/device-mgt/v1.0/policies/");
};
stepForwardFrom["policy-naming"] = function () {
policy["policyName"] = $("#policy-name-input").val();
policy["description"] = $("#policy-description-input").val();
//All data is collected. Policy can now be updated.
savePolicy(policy, "save");
savePolicy(policy, false, "/api/device-mgt/v1.0/policies/");
};
var savePolicy = function (policy, state) {
var profilePayloads = [{
"featureCode": "CONFIG",
"deviceTypeId": policy["platformId"],
"content": {"policyDefinition": window.queryEditor.getValue()}
}];
var savePolicy = function (policy, isActive, serviceURL) {
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]
});
}
}
$.each(profilePayloads, function (i, item) {
$.each(item.content, function (key, value) {
//cannot add a true check since it will catch value = false as well
if (value === null || value === undefined || value === "") {
item.content[key] = null;
}
});
});
var payload = {
"policyName": policy["policyName"],
"description": policy["description"],
"compliance": policy["selectedNonCompliantAction"],
"ownershipType": "ANY",
"active": (state != "save"),
"ownershipType": policy["selectedOwnership"],
"active": isActive,
"profile": {
"profileName": policy["policyName"],
"deviceType": {
"id": policy["platformId"],
"name": policy["platform"]
},
"deviceType": policy["platform"],
"profileFeaturesList": profilePayloads
}
};
@ -241,101 +354,29 @@ var savePolicy = function (policy, state) {
}
invokerUtil.post(
"/api/device-mgt/v1.0/policies",
payload,
function (response) {
response = JSON.parse(response);
if (response["statusCode"] == 201) {
$(".add-policy").addClass("hidden");
$(".policy-naming").addClass("hidden");
$(".policy-message").removeClass("hidden");
if (state == "publish") {
publishToDevice();
}
}
},
function (err) {
console.log(err);
}
);
};
function publishToDevice() {
var payload = {
"policyName": policy["policyName"],
"description": policy["description"],
"compliance": policy["selectedNonCompliantAction"],
"ownershipType": "ANY",
"deviceId": getParameterByName('deviceId'),
"profile": {
"profileName": policy["policyName"],
"deviceType": {
"id": policy["platformId"],
"name": policy["platform"]
},
"policyDefinition": window.queryEditor.getValue(),
"policyDescription": policy["description"]
}
};
var successCallback = function (data, status) {
console.log("Data: " + data + "\nStatus: " + status);
};
var data = {
url: "/devicemgt/api/policies/add",
type: "POST",
contentType: "application/json",
accept: "application/json",
success: successCallback,
data: JSON.stringify(payload)
};
$.ajax(data).fail(function (jqXHR) {
console.log("Error: " + jqXHR);
});
}
// 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);
serviceURL,
payload,
function () {
$(".add-policy").addClass("hidden");
$(".policy-naming").addClass("hidden");
$(".policy-message").removeClass("hidden");
},
function (data) {
}
});
};
/**
* 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();
}
);
};
function formatRepo(user) {
if (user.loading) {
return user.text
return user.text;
}
if (!user.username) {
return;
}
var markup = '<div class="clearfix">' +
'<div clas="col-sm-8">' +
'<div class="clearfix">' +
'<div class="col-sm-3">' + user.username + '</div>';
'<div clas="col-sm-8">' +
'<div class="clearfix">' +
'<div class="col-sm-3">' + user.username + '</div>';
if (user.firstname) {
markup += '<div class="col-sm-3"><i class="fa fa-code-fork"></i> ' + user.firstname + '</div>';
}
@ -350,170 +391,74 @@ function formatRepoSelection(user) {
return user.username || user.text;
}
function formatGroupRepo(group) {
if (group.loading) {
return group.text
}
if (!group.name) {
return;
}
var markup = '<div class="clearfix">' +
'<div clas="col-sm-8">' +
'<div class="clearfix">' +
'<div class="col-sm-3">' + group.name + '</div>';
if (group.name) {
markup += '<div class="col-sm-3"><i class="fa fa-code-fork"></i> ' + group.name + '</div>';
}
if (group.owner) {
markup += '<div class="col-sm-2"><i class="fa fa-star"></i> ' + group.owner + '</div></div>';
}
markup += '</div></div>';
return markup;
}
function formatGroupRepoSelection(group) {
return group.name || group.text;
}
// End of functions related to grid-input-view
$(document).ready(function () {
window.queryEditor = CodeMirror.fromTextArea(document.getElementById('policy-definition-input'), {
mode: MIME_TYPE_SIDDHI_QL,
indentWithTabs: true,
smartIndent: true,
lineNumbers: true,
matchBrackets: true,
autofocus: true,
extraKeys: {
"Shift-2": function (cm) {
insertStr(cm, cm.getCursor(), '@');
CodeMirror.showHint(cm, getAnnotationHints);
$("#users-input").select2({
multiple: true,
tags: false,
ajax: {
url: context + "/api/invoker/execute/",
method: "POST",
dataType: 'json',
delay: 250,
id: function (user) {
return user.username;
},
"Ctrl-Space": "autocomplete"
}
data: function (params) {
var postData = {};
postData.requestMethod = "GET";
postData.requestURL = "/api/device-mgt/v1.0/users/search/usernames?filter=" + params.term;
postData.requestPayload = null;
return JSON.stringify(postData);
},
processResults: function (data) {
var newData = [];
$.each(data, function (index, value) {
value.id = value.username;
newData.push(value);
});
return {
results: newData
};
},
cache: true
},
escapeMarkup: function (markup) {
return markup;
}, // let our custom formatter work
minimumInputLength: 1,
templateResult: formatRepo, // omitted for brevity, see the source of this page
templateSelection: formatRepoSelection // omitted for brevity, see the source of this page
});
$("#users-input").select2({
multiple: true,
tags: true,
ajax: {
url: window.location.origin + "/devicemgt/api/invoker/execute/",
method: "POST",
dataType: 'json',
delay: 250,
id: function (user) {
return user.username;
},
data: function (params) {
var postData = {};
postData.actionMethod = "GET";
postData.actionUrl = "/devicemgt_admin/users";
postData.actionPayload = JSON.stringify({
q: params.term, // search term
page: params.page
});
return JSON.stringify(postData);
},
processResults: function (data, page) {
var newData = [];
$.each(data.responseContent, function (index, value) {
value.id = value.username;
newData.push(value);
});
return {
results: newData
};
},
cache: true
},
escapeMarkup: function (markup) {
return markup;
}, // let our custom formatter work
minimumInputLength: 1,
templateResult: formatRepo, // omitted for brevity, see the source of this page
templateSelection: formatRepoSelection // omitted for brevity, see the source of this page
});
$("#groups-input").select2({
multiple: true,
tags: true,
ajax: {
url: window.location.origin + "/devicemgt/api/invoker/execute/",
method: "POST",
dataType: 'json',
delay: 250,
id: function (group) {
return group.name;
},
data: function (params) {
var postData = {};
postData.actionMethod = "GET";
var username = $("#platform").data("username");
postData.actionUrl = "/devicemgt_admin/groups/user/" + username +
"/search?groupName=" + params.term;
return JSON.stringify(postData);
},
processResults: function (data, page) {
var newData = [];
$.each(data, function (index, value) {
value.id = value.name;
newData.push(value);
});
return {
results: newData
};
},
cache: true
},
escapeMarkup: function (markup) {
return markup;
}, // let our custom formatter work
minimumInputLength: 1,
templateResult: formatGroupRepo, // omitted for brevity, see the source of this page
templateSelection: formatGroupRepoSelection // omitted for brevity, see the source of this page
});
$("#loading-content").remove();
$(".policy-platform").removeClass("hidden");
// Adding initial state of wizard-steps.
$("#policy-profile-wizard-steps").html($(".wr-steps").html());
policy["platform"] = $("#platform").data("platform");
policy["platformId"] = $("#platform").data("platform-id");
deviceTypeLabel = $("#platform").data("platform-label");
// updating next-page wizard title with selected platform
$("#policy-profile-page-wizard-title").text("ADD " + deviceTypeLabel + " POLICY");
$("#policy-platform-wizard-steps").html($(".wr-steps").html());
$("select.select2[multiple=multiple]").select2({
"tags": true
"tags": false
});
$("#users-select-field").hide();
$("#groups-select-field").hide();
$("#user-roles-select-field").show();
$("input[type='radio'].select-users-radio").change(function () {
if ($("#user-roles-radio-btn").is(":checked")) {
$("#user-roles-select-field").show();
$("#users-select-field").hide();
$("#groups-select-field").hide();
}
if ($("#users-radio-btn").is(":checked")) {
$("#user-roles-select-field").hide();
$("#users-select-field").show();
$("#groups-select-field").hide();
}
if ($("#groups-radio-btn").is(":checked")) {
$("#user-roles-select-field").hide();
if ($("#user-roles-radio-btn").is(":checked")) {
$("#users-select-field").hide();
$("#groups-select-field").show();
$("#user-roles-select-field").show();
}
});
// Support for special input type "ANY" on user(s) & user-role(s) selection
$("#user-roles-input").select2({
"tags": true
"tags": false
}).on("select2:select", function (e) {
if (e.params.data.id == "ANY") {
$(this).val("ANY").trigger("change");
@ -522,152 +467,7 @@ $(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);
});
//Policy wizard stepper
$(".wizard-stepper").click(function () {
// button clicked here can be either a continue button or a back button.
var currentStep = $(this).data("current");
@ -685,11 +485,11 @@ $(document).ready(function () {
// remove if there are any visible error-messages.
var errorMsgWrappers = ".alert.alert-danger";
$(errorMsgWrappers).each(
function () {
if (!$(this).hasClass("hidden")) {
$(this).addClass("hidden");
}
function () {
if (!$(this).hasClass("hidden")) {
$(this).addClass("hidden");
}
}
);
var nextStep = $(this).data("next");
@ -728,16 +528,7 @@ $(document).ready(function () {
// hiding current section of the wizard and showing next section.
$("." + currentStep).addClass("hidden");
if (nextStep !== "policy-message") {
$("." + nextStep).removeClass("hidden");
}
$("." + nextStep).removeClass("hidden");
}
});
});
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
});

@ -1,47 +1,13 @@
{{#zone "topCss"}}
{{css "css/codemirror.css"}}
{{/zone}}
<span id="platform" class="hidden" data-platform="{{type.name}}" data-platform-id="{{type.id}}"
data-platform-label="{{type.label}}" data-username="{{username}}"></span>
<span id="platform" class="hidden" data-platform="{{type.name}}" data-platform-label="{{type.label}}"
data-username="{{username}}"></span>
<div class="row">
<div class="col-md-12">
<div class="wr-steps hidden">
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-platform">
<div class="wiz-no">1</div>
<div class="wiz-lbl hidden-xs"><span>Select a platform</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz itm-wiz-current" data-step="policy-profile">
<div class="wiz-no">2</div>
<div class="wiz-lbl hidden-xs"><span>Configure profile</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-criteria">
<div class="wiz-no">3</div>
<div class="wiz-lbl hidden-xs"><span>Assign</span></div>
</div>
<br class="c-both"/>
</div>
<div class="col-md-3 col-xs-3">
<div class="itm-wiz" data-step="policy-naming">
<div class="wiz-no">4</div>
<div class="wiz-lbl hidden-xs"><span>Publish to devices</span></div>
</div>
<br class="c-both"/>
</div>
</div>
<div class="container col-centered wr-content policy-message hidden">
<div class="wr-form">
<h1 id="policy-message-page-wizard-title" class="page-sub-title">Policy creation is
successful.</h1>
successful.</h1>
<br>Please click <b>"Add Another Policy"</b>, if you wish to add another policy or
click
click
<b>"View policy list"</b> to complete the process and go back to the policy list.
<hr>
<button class="wr-btn wizard-stepper" data-current="policy-message"
@ -247,18 +213,11 @@
<div class="col-lg-12">
<h4>Step 2: Configure profile</h4>
<br>
<label class="wr-input-label">
Set device specific configuration instructions
</label>
<div class="wr-advance-operations">
<div class="wr-input-control">
<div class="cus-col-100">
<textarea id="policy-definition-input" placeholder="Enter the policy"
style="width: 100%;" required></textarea>
</div>
<br class="c-both"/>
</div>
{{unit "cdmf.unit.device.type.generic.policy-wizard"}}
</div>
<div class="wr-input-control wr-btn-grp">
<a href="javascript:window.history.back()"
@ -281,7 +240,5 @@
</div>
</div>
{{#zone "bottomJs"}}
{{js "js/codemirror.js"}}
{{js "js/sql.js"}}
{{js "js/policy-create.js"}}
{{/zone}}

@ -17,7 +17,7 @@
*/
function onRequest(context) {
//var log = new Log("wizard.js");
// var log = new Log("wizard.js");
var constants = require("/app/modules/constants.js");
var DTYPE_CONF_DEVICE_TYPE_KEY = "deviceType";
var DTYPE_CONF_DEVICE_TYPE_LABEL_KEY = "label";
@ -32,15 +32,11 @@ function onRequest(context) {
var deviceType = context.uriParams.deviceType;
var typesListResponse = userModule.getPlatforms();
if (typesListResponse["status"] == "success") {
for (var type in typesListResponse["content"]) {
if (deviceType == typesListResponse["content"][type]["name"]) {
wizardPage["type"] = typesListResponse["content"][type];
var deviceTypeLabel = deviceType;
var configs = utility.getDeviceTypeConfig(deviceType);
if (configs && configs[DTYPE_CONF_DEVICE_TYPE_KEY][DTYPE_CONF_DEVICE_TYPE_LABEL_KEY]) {
deviceTypeLabel = configs[DTYPE_CONF_DEVICE_TYPE_KEY][DTYPE_CONF_DEVICE_TYPE_LABEL_KEY];
}
wizardPage["type"]["label"] = deviceTypeLabel;
wizardPage["type"] = {};
for (var type in typesListResponse["content"]["deviceTypes"]) {
if (deviceType == typesListResponse["content"]["deviceTypes"][type]) {
wizardPage["type"]["name"] = deviceType;
wizardPage["type"]["label"] = deviceType;
}
}
}

Loading…
Cancel
Save