merged with upstream

revert-70aa11f8
ayyoob 8 years ago
commit 3b56668af0

@ -309,8 +309,12 @@ public class RequestValidationUtil {
public static void validateRoleDetails(RoleInfo roleInfo) { public static void validateRoleDetails(RoleInfo roleInfo) {
if (roleInfo == null) { if (roleInfo == null) {
throw new InputValidationException( throw new InputValidationException(
new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage("Request body is incorrect or" + new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage("Request body is "
" empty").build()); + "empty").build());
} else if (roleInfo.getRoleName() == null) {
throw new InputValidationException(
new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage("Request body is "
+ "incorrect").build());
} }
} }

@ -368,24 +368,31 @@ public class GenericOperationDAOImpl implements OperationDAO {
// sql = sql + " OFFSET ?"; // sql = sql + " OFFSET ?";
// } // }
String sql = "SELECT dte.ENROLMENT_ID, oor.OPERATION_ID, oor.OP_RES_ID, oor.OPERATION_TYPE, " + String sql = "SELECT feom.ENROLMENT_ID, feom.OPERATION_ID, feom.CREATED_TIMESTAMP, o.TYPE AS OPERATION_TYPE, " +
"oor.OPERATION_CODE, oor.OPERATION_RESPONSE, dte.DEVICE_TYPE, dte.DEVICE_IDENTIFICATION, " + "o.OPERATION_CODE, orsp.OPERATION_RESPONSE, orsp.LATEST_RECEIVED_TIMESTAMP AS RECEIVED_TIMESTAMP, " +
"oor.RECEIVED_TIMESTAMP, eom.UPDATED_TIMESTAMP, eom.STATUS FROM (SELECT d.DEVICE_IDENTIFICATION, " + "orsp.ID AS OP_RES_ID, feom.STATUS, feom.UPDATED_TIMESTAMP, feom.DEVICE_IDENTIFICATION, " +
"t.NAME AS DEVICE_TYPE, e.ID AS ENROLMENT_ID FROM DM_DEVICE d INNER JOIN DM_DEVICE_TYPE t " + "feom.DEVICE_TYPE FROM (SELECT eom.ENROLMENT_ID, eom.OPERATION_ID, eom.STATUS, eom.CREATED_TIMESTAMP, " +
"ON d.DEVICE_TYPE_ID = t.ID INNER JOIN DM_ENROLMENT e ON d.ID = e.DEVICE_ID WHERE " + "eom.UPDATED_TIMESTAMP, fe.DEVICE_IDENTIFICATION, fe.DEVICE_TYPE FROM " +
"e.TENANT_ID = ?) dte INNER JOIN (SELECT o.ID AS OPERATION_ID, o.TYPE AS OPERATION_TYPE, " + "(SELECT ENROLMENT_ID, OPERATION_ID, STATUS, CREATED_TIMESTAMP, UPDATED_TIMESTAMP " +
"o.OPERATION_CODE, r.ID AS OP_RES_ID, r.OPERATION_RESPONSE, r.RECEIVED_TIMESTAMP, " + "FROM DM_ENROLMENT_OP_MAPPING WHERE UPDATED_TIMESTAMP > ? ORDER BY OPERATION_ID LIMIT ? OFFSET ?) eom " +
"r.ENROLMENT_ID FROM DM_OPERATION o INNER JOIN DM_DEVICE_OPERATION_RESPONSE r ON " + "LEFT OUTER JOIN (SELECT e.ID AS ENROLMENT_ID, d.ID AS DEVICE_ID, d.DEVICE_IDENTIFICATION, " +
"o.ID = r.OPERATION_ID) oor ON oor.ENROLMENT_ID=dte.ENROLMENT_ID LEFT OUTER JOIN " + "t.NAME AS DEVICE_TYPE FROM DM_ENROLMENT e LEFT OUTER JOIN DM_DEVICE d ON e.DEVICE_ID = d.ID " +
"(SELECT ENROLMENT_ID, OPERATION_ID, STATUS, UPDATED_TIMESTAMP FROM DM_ENROLMENT_OP_MAPPING " + "LEFT OUTER JOIN DM_DEVICE_TYPE t ON d.DEVICE_TYPE_ID = t.ID WHERE d.TENANT_ID = ? AND " +
"WHERE UPDATED_TIMESTAMP > ? LIMIT ? OFFSET ?) eom ON eom.ENROLMENT_ID=oor.ENROLMENT_ID AND " + "e.TENANT_ID = ?) fe ON fe.ENROLMENT_ID = eom.ENROLMENT_ID) feom LEFT OUTER JOIN DM_OPERATION o " +
"oor.OPERATION_ID=eom.OPERATION_ID ORDER BY oor.OPERATION_ID"; "ON feom.OPERATION_ID = o.ID LEFT OUTER JOIN (SELECT ID, ENROLMENT_ID, OPERATION_ID, " +
"OPERATION_RESPONSE, MAX(RECEIVED_TIMESTAMP) LATEST_RECEIVED_TIMESTAMP " +
"FROM DM_DEVICE_OPERATION_RESPONSE GROUP BY ENROLMENT_ID , OPERATION_ID) orsp " +
"ON o.ID = orsp.OPERATION_ID AND feom.ENROLMENT_ID = orsp.ENROLMENT_ID GROUP BY feom.ENROLMENT_ID";
stmt = conn.prepareStatement(sql); stmt = conn.prepareStatement(sql);
stmt.setInt(1, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
stmt.setLong(2, timestamp); stmt.setLong(1, timestamp);
stmt.setInt(3, limit); stmt.setInt(2, limit);
stmt.setInt(4, offset); stmt.setInt(3, offset);
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
stmt.setInt(4, tenantId);
stmt.setInt(5, tenantId);
rs = stmt.executeQuery(); rs = stmt.executeQuery();
int operationId = 0; int operationId = 0;

@ -42,7 +42,7 @@ var userModule = function () {
privateMethods.getCarbonUser = function () { privateMethods.getCarbonUser = function () {
var carbon = require("carbon"); var carbon = require("carbon");
var carbonUser = session.get(constants["USER_SESSION_KEY"]); var carbonUser = session.get(constants["USER_SESSION_KEY"]);
var utility = require("/modules/utility.js")["utility"]; var utility = require("/app/modules/utility.js")["utility"];
if (!carbonUser) { if (!carbonUser) {
log.error("User object was not found in the session"); log.error("User object was not found in the session");
throw constants["ERRORS"]["USER_NOT_FOUND"]; throw constants["ERRORS"]["USER_NOT_FOUND"];
@ -174,7 +174,11 @@ var userModule = function () {
utility.startTenantFlow(carbonUser); utility.startTenantFlow(carbonUser);
var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] + "/users/" + var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] + "/users/" +
encodeURIComponent(username) + "/roles"; encodeURIComponent(username) + "/roles";
return privateMethods.callBackend(url, constants["HTTP_GET"]); var response = privateMethods.callBackend(url, constants["HTTP_GET"]);
if (response.status == "success") {
response.content = parse(response.content).roles;
}
return response;
} catch (e) { } catch (e) {
throw e; throw e;
} finally { } finally {
@ -267,27 +271,27 @@ var userModule = function () {
* @deprecated moved this device module under getDeviceTypes. * @deprecated moved this device module under getDeviceTypes.
*/ */
//TODO Move this piece of logic out of user.js to somewhere else appropriate. //TODO Move this piece of logic out of user.js to somewhere else appropriate.
//publicMethods.getPlatforms = function () { publicMethods.getPlatforms = function () {
// var carbonUser = session.get(constants["USER_SESSION_KEY"]); var carbonUser = session.get(constants["USER_SESSION_KEY"]);
// var utility = require("/app/modules/utility.js")["utility"]; var utility = require("/app/modules/utility.js")["utility"];
// if (!carbonUser) { if (!carbonUser) {
// log.error("User object was not found in the session"); log.error("User object was not found in the session");
// throw constants["ERRORS"]["USER_NOT_FOUND"]; throw constants["ERRORS"]["USER_NOT_FOUND"];
// } }
// try { try {
// utility.startTenantFlow(carbonUser); utility.startTenantFlow(carbonUser);
// var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] + "/device-types"; var url = devicemgtProps["httpsURL"] + devicemgtProps["backendRestEndpoints"]["deviceMgt"] + "/admin/device-types";
// var response = privateMethods.callBackend(url, constants["HTTP_GET"]); var response = privateMethods.callBackend(url, constants["HTTP_GET"]);
// if (response.status == "success") { if (response.status == "success") {
// response.content = parse(response.content); response.content = parse(response.content);
// } }
// return response; return response;
// } catch (e) { } catch (e) {
// throw e; throw e;
// } finally { } finally {
// utility.endTenantFlow(); utility.endTenantFlow();
// } }
//}; };
/** /**
* Get role * Get role

@ -19,7 +19,6 @@
{{unit "cdmf.unit.lib.service-invoker-utility"}} {{unit "cdmf.unit.lib.service-invoker-utility"}}
{{unit "cdmf.unit.lib.handlebars"}} {{unit "cdmf.unit.lib.handlebars"}}
{{unit deviceViewUnitName}}
{{#zone "breadcrumbs"}} {{#zone "breadcrumbs"}}
<li> <li>
@ -40,6 +39,7 @@
{{/zone}} {{/zone}}
{{#zone "content"}} {{#zone "content"}}
{{unit deviceViewUnitName}}
{{unit "cdmf.unit.lib.data-table"}} {{unit "cdmf.unit.lib.data-table"}}
{{unit "cdmf.unit.device.operation-mod"}} {{unit "cdmf.unit.device.operation-mod"}}
{{unit "cdmf.unit.device.view"}} {{unit "cdmf.unit.device.view"}}

@ -56,9 +56,9 @@
</label> </label>
<div class="wr-input-control"> <div class="wr-input-control">
<select id="userStore" class="form-control select"> <select id="userStore" class="form-control select">
<option>PRIMARY</option> <option value="PRIMARY">PRIMARY</option>
{{#each userStores}} {{#each userStores}}
<option>{{this}}</option> <option value="{{this}}">{{this}}</option>
{{/each}} {{/each}}
</select> </select>
</div> </div>
@ -113,15 +113,17 @@
<div id="user-created-msg" class="container col-centered wr-content hidden"> <div id="user-created-msg" class="container col-centered wr-content hidden">
<div class="wr-form"> <div class="wr-form">
<p class="page-sub-title">User was added successfully.</p> <p class="page-sub-title">User was added successfully.</p>
<br> <p>
An invitation mail will be sent to this user to initiate device enrollment. An invitation mail will be sent to this user to initiate device enrollment.
Below QR code can also be used to enroll a device. Below QR code can also be used to enroll a device.
</p>
<div class="panel panel-default"> <div class="panel panel-default">
<div id="qr-code-modal" class="hidden" data-enrollment-url="{{enrollmentURL}}"></div>
<div class="panel-body"> <div class="panel-body">
<div class="qr-code col-lg-5 col-md-6 col-centered"></div> <div class="qr-code col-lg-5 col-md-6 col-centered"></div>
</div> </div>
</div> </div>
<br>Please click <b>"Add Another User"</b>, if you wish to add another user or click <br>Please click <b>"Add Another User"</b>, if you wish to add another user or click
<b>"View User List"</b> to complete the process and go back to the user list. <b>"View User List"</b> to complete the process and go back to the user list.
<hr/> <hr/>

@ -39,6 +39,7 @@ function onRequest() {
page["firstnameRegExViolationErrorMsg"] = devicemgtProps["userValidationConfig"]["firstnameRegExViolationErrorMsg"]; page["firstnameRegExViolationErrorMsg"] = devicemgtProps["userValidationConfig"]["firstnameRegExViolationErrorMsg"];
page["lastnameJSRegEx"] = devicemgtProps["userValidationConfig"]["lastnameJSRegEx"]; page["lastnameJSRegEx"] = devicemgtProps["userValidationConfig"]["lastnameJSRegEx"];
page["lastnameRegExViolationErrorMsg"] = devicemgtProps["userValidationConfig"]["lastnameRegExViolationErrorMsg"]; page["lastnameRegExViolationErrorMsg"] = devicemgtProps["userValidationConfig"]["lastnameRegExViolationErrorMsg"];
page["enrollmentURL"] = devicemgtProps["generalConfig"]["host"] + devicemgtProps["enrollmentDir"];
return page; return page;
} }

@ -161,6 +161,18 @@ function emailIsValid(email) {
return regExp.test(email); return regExp.test(email);
} }
/*
* QR-code generation function.
*/
function generateQRCode(qrCodeClass) {
var enrollmentURL = $("#qr-code-modal").data("enrollment-url");
$(qrCodeClass).qrcode({
text: enrollmentURL,
width: 200,
height: 200
});
}
$("#userStore").change( $("#userStore").change(
function () { function () {
var str = ""; var str = "";

@ -15,7 +15,7 @@
specific language governing permissions and limitations specific language governing permissions and limitations
under the License. under the License.
}} }}
{{unit "cdmf.unit.ui.title" pageTitle="User Management"}} {{unit "cdmf.unit.ui.title" pageTitle="User Management | Edit User"}}
{{#zone "breadcrumbs"}} {{#zone "breadcrumbs"}}
<li> <li>
@ -51,6 +51,15 @@
<div id="user-create-error-msg" class="alert alert-danger hidden" role="alert"> <div id="user-create-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span> <i class="icon fw fw-error"></i><span></span>
</div> </div>
<label class="wr-input-label" title="Select the domain of the user store from the drop-down given below. The domain of the default user store is PRIMARY">
User Store Domain
<span class="wr-help-tip glyphicon glyphicon-question-sign"></span>
</label>
<div class="wr-input-control">
<select id="userStore" class="form-control select" disabled>
<option value="{{userStore}}" selected>{{userStore}}</option>
</select>
</div>
<label class="wr-input-label"> <label class="wr-input-label">
User Name <br> User Name <br>
</label> </label>
@ -59,8 +68,6 @@
data-errormsg="{{usernameRegExViolationErrorMsg}}" class="form-control" data-errormsg="{{usernameRegExViolationErrorMsg}}" class="form-control"
value="{{editUser.username}}" disabled/> value="{{editUser.username}}" disabled/>
</div> </div>
<label class="wr-input-label">First Name *</label> <label class="wr-input-label">First Name *</label>
<div id="firstNameField" class="form-group wr-input-control"> <div id="firstNameField" class="form-group wr-input-control">
<input type="text" id="firstname" data-regex="{{firstnameJSRegEx}}" <input type="text" id="firstname" data-regex="{{firstnameJSRegEx}}"
@ -95,12 +102,9 @@
<span class="wr-help-tip glyphicon glyphicon-question-sign"></span> <span class="wr-help-tip glyphicon glyphicon-question-sign"></span>
</label> </label>
<div class="wr-input-control"> <div class="wr-input-control">
<select id="roles" class="form-control select2" multiple="multiple" selectedVals=" <select id="roles" class="form-control select2" multiple="multiple"
{{#each usersRoles}} selectedVals="{{#each rolesByUsername}} {{this}}, {{/each}}">
{{this}}, {{#each rolesByUserStore}}
{{/each}}
">
{{#each userRoles}}
<option>{{this}}</option> <option>{{this}}</option>
{{/each}} {{/each}}
</select> </select>

@ -16,14 +16,16 @@
* under the License. * under the License.
*/ */
function onRequest(context) { function onRequest() {
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
var userModule = require("/app/modules/business-controllers/user.js")["userModule"]; var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
var userName = request.getParameter("username"); var userName = request.getParameter("username");
var user = userModule.getUser(userName)["content"]; var user = userModule.getUser(userName)["content"];
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
if (user) { if (user) {
var title; var title;
if (user.firstname || user.lastname) { if (user.firstname && user.lastname) {
title = user.firstname + " " + user.lastname; title = user.firstname + " " + user.lastname;
} else { } else {
title = user.username; title = user.username;
@ -34,6 +36,8 @@ function onRequest(context) {
if (userName.indexOf("/") > -1) { if (userName.indexOf("/") > -1) {
userStore = userName.substr(0, userName.indexOf('/')); userStore = userName.substr(0, userName.indexOf('/'));
} }
page["userStore"] = userStore;
var response = userModule.getUser(userName); var response = userModule.getUser(userName);
if (response["status"] == "success") { if (response["status"] == "success") {
@ -41,28 +45,27 @@ function onRequest(context) {
} }
response = userModule.getRolesByUsername(userName); response = userModule.getRolesByUsername(userName);
var rolesByUsername;
if (response["status"] == "success") { if (response["status"] == "success") {
page["usersRoles"] = response["content"]; rolesByUsername = response["content"];
} }
response = userModule.getRolesByUserStore(userStore); response = userModule.getRolesByUserStore(userStore);
var rolesByUserStore;
if (response["status"] == "success") { if (response["status"] == "success") {
var roleVals = response["content"]; rolesByUserStore = response["content"];
var filteredRoles = [];
var prefix = "Application";
for (i = 0; i < roleVals.length; i++) {
if(roleVals[i].indexOf(prefix) < 0){
filteredRoles.push(roleVals[i]);
}
}
page["userRoles"] = filteredRoles;
} }
page["rolesByUsername"] = rolesByUsername;
page["rolesByUserStore"] = rolesByUserStore;
} }
page["usernameJSRegEx"] = devicemgtProps.userValidationConfig.usernameJSRegEx;
page["usernameRegExViolationErrorMsg"] = devicemgtProps.userValidationConfig.usernameRegExViolationErrorMsg; page["usernameJSRegEx"] = devicemgtProps["userValidationConfig"]["usernameJSRegEx"];
page["firstnameJSRegEx"] = devicemgtProps.userValidationConfig.firstnameJSRegEx; page["usernameRegExViolationErrorMsg"] = devicemgtProps["userValidationConfig"]["usernameRegExViolationErrorMsg"];
page["firstnameRegExViolationErrorMsg"] = devicemgtProps.userValidationConfig.firstnameRegExViolationErrorMsg; page["firstnameJSRegEx"] = devicemgtProps["userValidationConfig"]["firstnameJSRegEx"];
page["lastnameJSRegEx"] = devicemgtProps.userValidationConfig.lastnameJSRegEx; page["firstnameRegExViolationErrorMsg"] = devicemgtProps["userValidationConfig"]["firstnameRegExViolationErrorMsg"];
page["lastnameRegExViolationErrorMsg"] = devicemgtProps.userValidationConfig.lastnameRegExViolationErrorMsg; page["lastnameJSRegEx"] = devicemgtProps["userValidationConfig"]["lastnameJSRegEx"];
page["lastnameRegExViolationErrorMsg"] = devicemgtProps["userValidationConfig"]["lastnameRegExViolationErrorMsg"];
return page; return page;
} }

@ -32,6 +32,8 @@ function inputIsValid(regExp, inputString) {
var validateInline = {}; var validateInline = {};
var clearInline = {}; var clearInline = {};
var deviceMgtBasePath = "/api/device-mgt/v1.0";
var enableInlineError = function (inputField, errorMsg, errorSign) { var enableInlineError = function (inputField, errorMsg, errorSign) {
var fieldIdentifier = "#" + inputField; var fieldIdentifier = "#" + inputField;
var errorMsgIdentifier = "#" + inputField + " ." + errorMsg; var errorMsgIdentifier = "#" + inputField + " ." + errorMsg;
@ -180,7 +182,8 @@ $(document).ready(function () {
var usernameInput = $("input#username"); var usernameInput = $("input#username");
var firstnameInput = $("input#firstname"); var firstnameInput = $("input#firstname");
var lastnameInput = $("input#lastname"); var lastnameInput = $("input#lastname");
var charLimit = parseInt($("input#username").attr("limit")); // var charLimit = parseInt($("input#username").attr("limit"));
var domain = $("#userStore").val();
var username = usernameInput.val().trim(); var username = usernameInput.val().trim();
var firstname = firstnameInput.val(); var firstname = firstnameInput.val();
var lastname = lastnameInput.val(); var lastname = lastnameInput.val();
@ -215,7 +218,7 @@ $(document).ready(function () {
} else { } else {
var addUserFormData = {}; var addUserFormData = {};
addUserFormData.username = username; addUserFormData.username = domain + "/" + username;
addUserFormData.firstname = firstname; addUserFormData.firstname = firstname;
addUserFormData.lastname = lastname; addUserFormData.lastname = lastname;
addUserFormData.emailAddress = emailAddress; addUserFormData.emailAddress = emailAddress;
@ -225,14 +228,13 @@ $(document).ready(function () {
} }
addUserFormData.roles = roles; addUserFormData.roles = roles;
var addUserAPI = "/devicemgt_admin/users?username=" + username; var addUserAPI = deviceMgtBasePath + "/users/" + username;
invokerUtil.put( invokerUtil.put(
addUserAPI, addUserAPI,
addUserFormData, addUserFormData,
function (data) { function (data, textStatus, jqXHR) {
data = JSON.parse(data); if (jqXHR.status == 201) {
if (data["statusCode"] == 201) {
// Clearing user input fields. // Clearing user input fields.
$("input#username").val(""); $("input#username").val("");
$("input#firstname").val(""); $("input#firstname").val("");
@ -243,13 +245,14 @@ $(document).ready(function () {
$("#user-create-form").addClass("hidden"); $("#user-create-form").addClass("hidden");
$("#user-created-msg").removeClass("hidden"); $("#user-created-msg").removeClass("hidden");
} }
}, function (data) { }, function (jqXHR) {
if (data["statusCode"] == 409) { var payload = JSON.parse(jqXHR.responseText);
if (jqXHR.status == 409) {
$(errorMsg).text("User : " + username + " doesn't exists. You cannot proceed."); $(errorMsg).text("User : " + username + " doesn't exists. You cannot proceed.");
} else if (data["statusCode"] == 500) { } else if (jqXHR.status == 500) {
$(errorMsg).text("An unexpected error occurred @ backend server. Please try again later."); $(errorMsg).text("An unexpected error occurred at backend server. Please try again later.");
} else { } else {
$(errorMsg).text(data.errorMessage); $(errorMsg).text(payload.message);
} }
$(errorMsgWrapper).removeClass("hidden"); $(errorMsgWrapper).removeClass("hidden");
} }

@ -16,6 +16,18 @@
* under the License. * under the License.
*/ */
/**
* Checks if provided input is valid against RegEx input.
*
* @param regExp Regular expression
* @param inputString Input string to check
* @returns {boolean} Returns true if input matches RegEx
*/
function inputIsValid(regExp, inputString) {
regExp = new RegExp(regExp);
return regExp.test(inputString);
}
$(function () { $(function () {
var sortableElem = '.wr-sortable'; var sortableElem = '.wr-sortable';
$(sortableElem).sortable({ $(sortableElem).sortable({
@ -116,9 +128,8 @@ $("a.invite-user-link").click(function () {
* when a user clicks on "Remove" link * when a user clicks on "Remove" link
* on User Listing page in WSO2 MDM Console. * on User Listing page in WSO2 MDM Console.
*/ */
function removeUser(uname, uid) { function removeUser(uname) {
var username = uname; var username = uname;
var userid = uid;
var removeUserAPI = apiBasePath + "/users/" + username; var removeUserAPI = apiBasePath + "/users/" + username;
$(modalPopupContent).html($('#remove-user-modal-content').html()); $(modalPopupContent).html($('#remove-user-modal-content').html());
showPopup(); showPopup();
@ -127,7 +138,7 @@ function removeUser(uname, uid) {
invokerUtil.delete( invokerUtil.delete(
removeUserAPI, removeUserAPI,
function () { function () {
$("#" + userid).remove(); $("#role-" + username).remove();
// get new user-list-count // get new user-list-count
var newUserListCount = $(".user-list > span").length; var newUserListCount = $(".user-list > span").length;
// update user-listing-status-msg with new user-count // update user-listing-status-msg with new user-count
@ -264,12 +275,12 @@ function loadUsers(searchParam) {
}; };
return JSON.stringify( json ); return JSON.stringify( json );
}; }
var fnCreatedRow = function( nRow, aData, iDataIndex ) { var fnCreatedRow = function( nRow, aData, iDataIndex ) {
$(nRow).attr('data-type', 'selectable'); $(nRow).attr('data-type', 'selectable');
$(nRow).attr('data-username', aData["filter"]); $(nRow).attr('data-username', aData["filter"]);
}; }
var columns = [ var columns = [
{ {
@ -302,19 +313,19 @@ function loadUsers(searchParam) {
class: "text-right content-fill text-left-on-grid-view no-wrap", class: "text-right content-fill text-left-on-grid-view no-wrap",
data: null, data: null,
render: function ( data, type, row, meta ) { render: function ( data, type, row, meta ) {
return '<a href="/emm/users/edit-user?username=' + data.username + '" data-username="' + data.username + return '<a href="/emm/user/edit?username=' + data.filter + '" data-username="' + data.filter +
'" data-click-event="edit-form" class="btn padding-reduce-on-grid-view edit-user-link"> ' + '" data-click-event="edit-form" class="btn padding-reduce-on-grid-view edit-user-link"> ' +
'<span class="fw-stack"> <i class="fw fw-ring fw-stack-2x"></i> <i class="fw fw-edit fw-stack-1x"></i>' + '<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">Edit</span> </a>' + ' </span> <span class="hidden-xs hidden-on-grid-view">Edit</span> </a>' +
'<a href="#" data-username="' + data.username + '" data-userid=' + data.username + '<a href="#" data-username="' + data.filter + '" data-userid=' + data.filter +
' data-click-event="remove-form" onclick="javascript:removeUser(\'' + data.username + '\', \'' + ' data-click-event="remove-form" onclick="javascript:removeUser(\'' + data.filter + '\')" ' +
data.username + '\')" class="btn padding-reduce-on-grid-view remove-user-link">' + 'class="btn padding-reduce-on-grid-view remove-user-link">' +
'<span class="fw-stack"> <i class="fw fw-ring fw-stack-2x"></i> <i class="fw fw-delete fw-stack-1x">' + '<span class="fw-stack"> <i class="fw fw-ring fw-stack-2x"></i> <i class="fw fw-delete fw-stack-1x">' +
'</i> </span> <span class="hidden-xs hidden-on-grid-view">Remove</span> </a>' + '</i> </span> <span class="hidden-xs hidden-on-grid-view">Remove</span> </a>' +
'<a href="#" data-username="' + data.username + '" data-userid="' + data.username + '<a href="#" data-username="' + data.filter + '" data-userid="' + data.filter +
'" data-click-event="edit-form" onclick="javascript:resetPassword(\'' + data.username + '" data-click-event="edit-form" onclick="javascript:resetPassword(\'' + data.filter +
'\')" class="btn padding-reduce-on-grid-view remove-user-link"> <span class="fw-stack"> <i class="fw fw-ring fw-stack-2x">' + '\')" class="btn padding-reduce-on-grid-view remove-user-link"> <span class="fw-stack"> <i class="fw fw-ring fw-stack-2x">' +
'</i> <i class="fw fw-key fw-stack-1x"></i> <span class="fw-stack fw-move-right fw-move-bottom"> <i class="fw fw-circle fw-stack-2x fw-stroke fw-inverse"><' + '</i> <i class="fw fw-key fw-stack-1x"></i> <span class="fw-stack fw-move-right fw-move-bottom"> <i class="fw fw-circle fw-stack-2x fw-stroke fw-inverse"><' +
'/i> <i class="fw fw-circle fw-stack-2x"></i> <i class="fw fw-refresh fw-stack-1x fw-inverse">' + '/i> <i class="fw fw-circle fw-stack-2x"></i> <i class="fw fw-refresh fw-stack-1x fw-inverse">' +

@ -15,6 +15,7 @@
specific language governing permissions and limitations specific language governing permissions and limitations
under the License. under the License.
}} }}
{{#zone "contentTitle"}} {{#zone "contentTitle"}}
<div class="row wr-device-board"> <div class="row wr-device-board">
<div class="col-lg-12 wr-secondary-bar"> <div class="col-lg-12 wr-secondary-bar">
@ -32,6 +33,7 @@
</div> </div>
{{/zone}} {{/zone}}
{{#zone "content"}}
<div class="row no-gutter add-padding-5x add-margin-top-5x" <div class="row no-gutter add-padding-5x add-margin-top-5x"
style="border: 1px solid #e4e4e4;"> style="border: 1px solid #e4e4e4;">
<div class="media"> <div class="media">
@ -193,7 +195,7 @@
</div> </div>
{{/defineZone}} {{/defineZone}}
</div> </div>
{{/zone}}
{{#zone "bottomJs"}} {{#zone "bottomJs"}}
{{js "js/device-view.js"}} {{js "js/device-view.js"}}
<script id="policy-view" src="{{@unit.publicUri}}/templates/policy-compliance.hbs" <script id="policy-view" src="{{@unit.publicUri}}/templates/policy-compliance.hbs"

@ -15,8 +15,9 @@
specific language governing permissions and limitations specific language governing permissions and limitations
under the License. under the License.
}} }}
<span id="permission" data-permission="{{permissions}}"></span> {{#zone "content"}}
<div class="row"> <span id="permission" data-permission="{{permissions}}"></span>
<div class="row">
<div class="col-md-12"> <div class="col-md-12">
<!-- content --> <!-- content -->
<div id="config-save-form" class="container col-centered wr-content"> <div id="config-save-form" class="container col-centered wr-content">
@ -27,8 +28,7 @@
<div class="wr-advance-operations"> <div class="wr-advance-operations">
<div class="row no-gutter"> <div class="row no-gutter">
<div class="wr-hidden-operations-nav col-lg-4"> <div class="wr-hidden-operations-nav col-lg-4">
<a id="unReadNotifications" href="javascript:void(0)" <a id="unReadNotifications" href="javascript:void(0)" onclick="showAdvanceOperation('unread', this)" class="selected">
onclick="showAdvanceOperation('unread', this)" class="selected">
<span class="wr-hidden-operations-icon fw-stack"> <span class="wr-hidden-operations-icon fw-stack">
<i class="fw fw-mail fw-stack-2x"></i> <i class="fw fw-mail fw-stack-2x"></i>
</span> </span>
@ -52,10 +52,11 @@
</div> </div>
<!-- /content --> <!-- /content -->
</div> </div>
</div> </div>
{{/zone}}
{{#zone "bottomJs"}} {{#zone "bottomJs"}}
<script id="notification-listing" data-current-user="{{currentUser.username}}" <script id="notification-listing" data-current-user="{{currentUser.username}}"
data-image-resource="{{self.publicURL}}/images/" src="{{self.publicURL}}/templates/notification-listing.hbs" data-image-resource="{{@unit.publicUri}}/images/" src="{{@unit.publicUri}}/templates/notification-listing.hbs"
type="text/x-handlebars-template"></script> type="text/x-handlebars-template"></script>
{{js "js/notification-listing.js"}} {{js "js/notification-listing.js"}}
{{/zone}} {{/zone}}

@ -16,15 +16,16 @@
* under the License. * under the License.
*/ */
function onRequest(context){ function onRequest(context) {
var userModule = require("/app/modules/business-controllers/user.js")["userModule"]; var userModule = require("/app/modules/business-controllers/user.js")["userModule"];
var constants = require("/app/modules/constants.js"); var constants = require("/app/modules/constants.js");
var viewModel = {};
var permissions = []; var permissions = [];
if(userModule.isAuthorized("/permission/admin/device-mgt/emm-admin/notifications/list")){ if (userModule.isAuthorized("/permission/admin/device-mgt/emm-admin/notifications/list")) {
permissions.push("LIST_NOTIFICATIONS"); permissions.push("LIST_NOTIFICATIONS");
} }
var currentUser = session.get(constants.USER_SESSION_KEY); var currentUser = session.get(constants.USER_SESSION_KEY);
context.permissions = stringify(permissions); viewModel.permissions = stringify(permissions);
context.currentUser = currentUser; viewModel.currentUser = currentUser;
return context; return viewModel;
} }

@ -91,8 +91,8 @@ function loadNotifications(){
var successCallback = function (data) { var successCallback = function (data) {
var viewModel = {}; var viewModel = {};
data = JSON.parse(data); data = JSON.parse(data);
viewModel.notifications = data; viewModel.notifications = data.notifications;
if(data.length > 0){ if(data.count > 0){
var content = template(viewModel); var content = template(viewModel);
$("#ast-container").html(content); $("#ast-container").html(content);
$('#unread-notifications').datatables_extended(); $('#unread-notifications').datatables_extended();

@ -16,10 +16,10 @@
<tbody> <tbody>
{{#each notifications}} {{#each notifications}}
{{#equal "NEW" status }} {{#equal "NEW" status }}
<tr data-type="selectable" data-id="{{notificationId}}"> <tr data-type="selectable" data-id="{{id}}">
<td data-display="{{description}}" data-grid-label="Description">{{description}}</td> <td data-display="{{description}}" data-grid-label="Description">{{description}}</td>
<td style="text-align: center;"> <td style="text-align: center;">
<a href="#" data-id="{{notificationId}}" data-url="device/{{deviceIdentifier.type}}/{{deviceIdentifier.id}}" class="new-notification" data-click-event="remove-form"> <a href="device?type={{deviceIdentifier.type}}&id={{deviceIdentifier.id}}" data-id="{{id}}" data-url="device?type={{deviceIdentifier.type}}&id={{deviceIdentifier.id}}" class="new-notification" data-click-event="remove-form">
<span class="fw-stack"> <span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i> <i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-view fw-stack-1x"></i> <i class="fw fw-view fw-stack-1x"></i>
@ -54,10 +54,10 @@
</thead> </thead>
<tbody> <tbody>
{{#each notifications}} {{#each notifications}}
<tr data-type="selectable" data-id="{{notificationId}}"> <tr data-type="selectable" data-id="{{id}}">
<td data-display="{{description}}" data-grid-label="Description">{{description}}</td> <td data-display="{{description}}" data-grid-label="Description">{{description}}</td>
<td style="text-align: center;"> <td style="text-align: center;">
<a href="device/{{deviceIdentifier.type}}/{{deviceIdentifier.id}}" data-click-event="remove-form"> <a href="device?type={{deviceIdentifier.type}}&id={{deviceIdentifier.id}}" data-click-event="remove-form">
<span class="fw-stack"> <span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i> <i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-view fw-stack-1x"></i> <i class="fw fw-view fw-stack-1x"></i>

@ -0,0 +1,83 @@
/**
* Checks if provided input is valid against RegEx input.
*
* @param regExp Regular expression
* @param inputString Input string to check
* @returns {boolean} Returns true if input matches RegEx
*/
function inputIsValid(regExp, inputString) {
regExp = new RegExp(regExp);
return regExp.test(inputString);
}
$(document).ready(function () {
var modalPopup = ".wr-modalpopup";
// var modalPopupContainer = modalPopup + " .modalpopup-container";
var modalPopupContent = modalPopup + " .modalpopup-content";
$("#change-password").click(function () {
$(modalPopupContent).html($('#change-password-window').html());
showPopup();
$("a#change-password-yes-link").click(function () {
var oldPassword = $("#old-password").val();
var newPassword = $("#new-password").val();
var confirmedPassword = $("#confirmed-password").val();
var user = $("#user").val();
var errorMsgWrapper = "#notification-error-msg";
var errorMsg = "#notification-error-msg span";
if (!oldPassword) {
$(errorMsg).text("Old password is a required field. It cannot be empty.");
$(errorMsgWrapper).removeClass("hidden");
} else if (!newPassword) {
$(errorMsg).text("New password is a required field. It cannot be empty.");
$(errorMsgWrapper).removeClass("hidden");
} else if (!confirmedPassword) {
$(errorMsg).text("Retyping the new password is required.");
$(errorMsgWrapper).removeClass("hidden");
} else if (confirmedPassword != newPassword) {
$(errorMsg).text("New password doesn't match the confirmation.");
$(errorMsgWrapper).removeClass("hidden");
} else if (!inputIsValid(/^[\S]{5,30}$/, confirmedPassword)) {
$(errorMsg).text("Password should be minimum 5 characters long, should not include any whitespaces.");
$(errorMsgWrapper).removeClass("hidden");
} else {
var changePasswordFormData = {};
//changePasswordFormData.username = user;
changePasswordFormData.newPassword = unescape((confirmedPassword));
changePasswordFormData.oldPassword = unescape((oldPassword));
var changePasswordAPI = "/api/device-mgt/v1.0/users" + user + "/credentials";
invokerUtil.put(
changePasswordAPI,
changePasswordFormData,
function (data, textStatus, jqXHR) {
if (jqXHR.status == 200 && data) {
$(modalPopupContent).html($('#change-password-success-content').html());
$("#change-password-success-link").click(function () {
hidePopup();
});
}
}, function (jqXHR) {
if (jqXHR.status == 400) {
$(errorMsg).text("Old password does not match with the provided value.");
$(errorMsgWrapper).removeClass("hidden");
} else {
$(errorMsg).text("An unexpected error occurred. Please try again later.");
$(errorMsgWrapper).removeClass("hidden");
}
}
);
}
});
$("a#change-password-cancel-link").click(function () {
hidePopup();
});
});
});

@ -17,6 +17,70 @@
}} }}
{{#zone "userMenu-items"}} {{#zone "userMenu-items"}}
<li> <li>
<a href="{{@app.context}}/logout">Logout</a> <a href="javascript:void(0)" id="change-password">Change password</a>
</li> </li>
<li>
<a href="{{@app.context}}/logout">Sign out</a>
</li>
<div id="change-password-window" class="hide">
<input type="hidden" id="user" value="{{username}}">
<div class="content">
<div class="row">
<div class="col-lg-5 col-md-6 col-centered">
<h4>
<span class="fw-stack">
<i class="fw fw-ring fw-stack-2x"></i>
<i class="fw fw-key fw-stack-1x"></i>
</span>
Change Password
<br><br>
</h4>
<div id="notification-error-msg" class="alert alert-danger hidden" role="alert">
<i class="icon fw fw-error"></i><span></span>
</div>
<h3>
Enter old password *
<br><br>
<div>
<input type="password" class="form-control modal-input operationDataKeys" id="old-password" data-key="message"/>
</div>
<br>
Enter new password *
<br><br>
<div>
<input type="password" class="form-control modal-input operationDataKeys" id="new-password" data-key="message"/>
</div>
<br>
Retype new password *
<br><br>
<div>
<input type="password" class="form-control modal-input operationDataKeys" id="confirmed-password" data-key="message"/>
</div>
<br>
</h3>
<div class="buttons">
<a href="#" id="change-password-yes-link" class="btn-operations">Update</a>
<a href="#" id="change-password-cancel-link" class="btn-operations">Cancel</a>
</div>
</div>
</div>
</div>
</div>
<div id="change-password-success-content" class="hide">
<div class="content">
<div class="row">
<div class="col-lg-5 col-md-6 col-centered">
<h3>Password change is successful.</h3>
<div class="buttons">
<a href="#" id="change-password-success-link" class="btn-operations">Ok</a>
</div>
</div>
</div>
</div>
</div>
{{/zone}}
{{#zone "bottomJs"}}
<script src="{{@unit.publicUri}}/js/user-menu.js"></script>
{{/zone}} {{/zone}}

@ -0,0 +1,4 @@
function onRequest() {
var constants = require("/app/modules/constants.js");
return session.get(constants["USER_SESSION_KEY"]);
}

@ -50,6 +50,10 @@
{ {
"url": "/api/data-tables/invoker", "url": "/api/data-tables/invoker",
"path": "/api/data-tables-invoker-api.jag" "path": "/api/data-tables-invoker-api.jag"
},
{
"url": "/api/operation/*",
"path": "/api/operation-api.jag"
} }
] ]
} }
Loading…
Cancel
Save