mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-24 22:25:52 -05:00
Added support for device groups
This commit is contained in:
parent
024023247d
commit
a6e0fbef72
@ -130,5 +130,6 @@ module.exports.objKeysToLower = function (obj) {
|
|||||||
// Validation methods
|
// Validation methods
|
||||||
module.exports.validateString = function(str, minlen, maxlen) { return ((str != null) && (typeof str == 'string') && ((minlen == null) || (str.length >= minlen)) && ((maxlen == null) || (str.length <= maxlen))); }
|
module.exports.validateString = function(str, minlen, maxlen) { return ((str != null) && (typeof str == 'string') && ((minlen == null) || (str.length >= minlen)) && ((maxlen == null) || (str.length <= maxlen))); }
|
||||||
module.exports.validateInt = function(int, minval, maxval) { return ((int != null) && (typeof int == 'number') && ((minval == null) || (int >= minval)) && ((maxval == null) || (int <= maxval))); }
|
module.exports.validateInt = function(int, minval, maxval) { return ((int != null) && (typeof int == 'number') && ((minval == null) || (int >= minval)) && ((maxval == null) || (int <= maxval))); }
|
||||||
module.exports.validateArray = function(array, minlen, maxlen) { return ((array != null) && Array.isArray(array) && ((minlen == null) || (array.length >= minlen)) && ((maxlen == null) || (array.length <= maxlen))); }
|
module.exports.validateArray = function (array, minlen, maxlen) { return ((array != null) && Array.isArray(array) && ((minlen == null) || (array.length >= minlen)) && ((maxlen == null) || (array.length <= maxlen))); }
|
||||||
|
module.exports.validateStrArray = function (array, minlen, maxlen) { if (((array != null) && Array.isArray(array)) == false) return false; for (var i in array) { if ((typeof array[i] != 'string') && ((minlen == null) || (array[i].length >= minlen)) && ((maxlen == null) || (array[i].length <= maxlen))) return false; } return true; }
|
||||||
module.exports.validateObject = function(obj) { return ((obj != null) && (typeof obj == 'object')); }
|
module.exports.validateObject = function(obj) { return ((obj != null) && (typeof obj == 'object')); }
|
||||||
|
@ -976,6 +976,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
|
|||||||
if ((command.intelamt.user != null) && (command.intelamt.pass != undefined) && ((command.intelamt.user != node.intelamt.user) || (command.intelamt.pass != node.intelamt.pass))) { change = 1; node.intelamt.user = command.intelamt.user; node.intelamt.pass = command.intelamt.pass; changes.push('Intel AMT credentials'); }
|
if ((command.intelamt.user != null) && (command.intelamt.pass != undefined) && ((command.intelamt.user != node.intelamt.user) || (command.intelamt.pass != node.intelamt.pass))) { change = 1; node.intelamt.user = command.intelamt.user; node.intelamt.pass = command.intelamt.pass; changes.push('Intel AMT credentials'); }
|
||||||
if (command.intelamt.tls && (command.intelamt.tls != node.intelamt.tls)) { change = 1; node.intelamt.tls = command.intelamt.tls; changes.push('Intel AMT TLS'); }
|
if (command.intelamt.tls && (command.intelamt.tls != node.intelamt.tls)) { change = 1; node.intelamt.tls = command.intelamt.tls; changes.push('Intel AMT TLS'); }
|
||||||
}
|
}
|
||||||
|
if (command.tags) { // Node grouping tag, this is a array of strings that can't be empty and can't contain a comma
|
||||||
|
var ok = true;
|
||||||
|
if (obj.common.validateString(command.tags, 0, 4096) == true) { command.tags = command.tags.split(','); }
|
||||||
|
if (obj.common.validateStrArray(command.tags, 1, 256) == true) { var groupTags = command.tags; for (var i in groupTags) { groupTags[i] = groupTags[i].trim(); if ((groupTags[i] == '') || (groupTags[i].indexOf(',') >= 0)) { ok = false; } } }
|
||||||
|
if (ok == true) { groupTags.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); }); node.tags = groupTags; change = 1; }
|
||||||
|
} else if ((command.tags === '') && node.tags) { delete node.tags; change = 1; }
|
||||||
|
|
||||||
if (change == 1) {
|
if (change == 1) {
|
||||||
// Save the node
|
// Save the node
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "meshcentral",
|
"name": "meshcentral",
|
||||||
"version": "0.1.7-a",
|
"version": "0.1.7-b",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Remote Management",
|
"Remote Management",
|
||||||
"Intel AMT",
|
"Intel AMT",
|
||||||
|
@ -155,6 +155,7 @@
|
|||||||
<option>Mesh</option>
|
<option>Mesh</option>
|
||||||
<option>Power</option>
|
<option>Power</option>
|
||||||
<option>Device</option>
|
<option>Device</option>
|
||||||
|
<option>Group</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -1284,6 +1285,7 @@
|
|||||||
node.iploc = message.event.node.iploc;
|
node.iploc = message.event.node.iploc;
|
||||||
node.wifiloc = message.event.node.wifiloc;
|
node.wifiloc = message.event.node.wifiloc;
|
||||||
node.gpsloc = message.event.node.gpsloc;
|
node.gpsloc = message.event.node.gpsloc;
|
||||||
|
node.tags = message.event.node.tags;
|
||||||
node.userloc = message.event.node.userloc;
|
node.userloc = message.event.node.userloc;
|
||||||
if (message.event.node.agent != null) {
|
if (message.event.node.agent != null) {
|
||||||
if (node.agent == null) node.agent = {};
|
if (node.agent == null) node.agent = {};
|
||||||
@ -1476,17 +1478,16 @@
|
|||||||
var deviceHeaders = {};
|
var deviceHeaders = {};
|
||||||
var oldviewmode = 0;
|
var oldviewmode = 0;
|
||||||
function updateDevices() {
|
function updateDevices() {
|
||||||
var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, view = Q('viewselect').value;
|
var r = '', c = 0, current = null, count = 0, displayedMeshes = {}, view = Q('viewselect').value, groups = {}, groupCount = {};
|
||||||
QV('xdevices', view < 4);
|
QV('xdevices', view < 4);
|
||||||
QV('xdevicesmap', view == 4);
|
QV('xdevicesmap', view == 4);
|
||||||
QV('devListToolbar', view < 3);
|
QV('devListToolbar', view < 3);
|
||||||
QV('kvmListToolbar', view == 3);
|
QV('kvmListToolbar', view == 3);
|
||||||
QV('devMapToolbar', view == 4);
|
QV('devMapToolbar', view == 4);
|
||||||
QV('devListToolbarSort', view < 4);
|
|
||||||
QV('devListToolbarSize', view == 3);
|
QV('devListToolbarSize', view == 3);
|
||||||
QV('NoMeshesPanel', meshcount == 0);
|
QV('NoMeshesPanel', meshcount == 0);
|
||||||
QV('devListToolbarView', (meshcount != 0) && (nodes.length > 0));
|
QV('devListToolbarView', (meshcount != 0) && (nodes.length > 0));
|
||||||
QV('devListToolbarSort', (meshcount != 0) && (nodes.length > 0));
|
QV('devListToolbarSort', (meshcount != 0) && (nodes.length > 0) && (view < 4));
|
||||||
if ((meshcount == 0) || (nodes.length == 0)) { view = 1; }
|
if ((meshcount == 0) || (nodes.length == 0)) { view = 1; }
|
||||||
if (view == 4) {
|
if (view == 4) {
|
||||||
setTimeout( function() { if (xxmap.map != null) { xxmap.map.updateSize(); } }, 200);
|
setTimeout( function() { if (xxmap.map != null) { xxmap.map.updateSize(); } }, 200);
|
||||||
@ -1572,10 +1573,41 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we are displaying devices by group, put the device in the right group.
|
||||||
|
if ((sort == 3) && (r != '')) {
|
||||||
|
if (nodes[i].tags) {
|
||||||
|
for (var j in nodes[i].tags) {
|
||||||
|
var tag = nodes[i].tags[j];
|
||||||
|
if (groups[tag] == null) { groups[tag] = r; groupCount[tag] = 1; } else { groups[tag] += r; groupCount[tag] += 1; }
|
||||||
|
if (view == 3) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r = '';
|
||||||
|
}
|
||||||
|
|
||||||
deviceHeaderTotal++;
|
deviceHeaderTotal++;
|
||||||
if (typeof deviceHeaderCount[nodes[i].state] == 'undefined') { deviceHeaderCount[nodes[i].state] = 1; } else { deviceHeaderCount[nodes[i].state]++; }
|
if (typeof deviceHeaderCount[nodes[i].state] == 'undefined') { deviceHeaderCount[nodes[i].state] = 1; } else { deviceHeaderCount[nodes[i].state]++; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If displaying devices by groups, sort the group names and display the devices.
|
||||||
|
if (sort == 3) {
|
||||||
|
var groupNames = [];
|
||||||
|
for (var i in groups) { groupNames.push(i); }
|
||||||
|
groupNames.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); });
|
||||||
|
for (var j in groupNames) {
|
||||||
|
var i = groupNames[j]; r += '<div class=DevSt style=width:100%;padding-top:4px><span>' + i + '</span><span class="devHeaderx">, ' + groupCount[i] + ' device' + ((groupCount[i] > 1)?'s':'') + '</span></div>' + groups[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is nothing to display, explain the problem
|
||||||
|
if (r == '') {
|
||||||
|
if ((Q('SearchInput').value == '') && (sort == 3)) {
|
||||||
|
r = '<div style="margin:30px">No devices are included in any groups, click on a device\'s \"Groups\" to add to a group.</div>';
|
||||||
|
} else {
|
||||||
|
r = '<div style="margin:30px">No devices matching this search.</div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((view == 1) && (c == 2)) r += '<td><div style=width:301px></div></td>'; // Adds device padding
|
if ((view == 1) && (c == 2)) r += '<td><div style=width:301px></div></td>'; // Adds device padding
|
||||||
|
|
||||||
// Display all empty meshes, we need to do this because users can add devices to these at any time.
|
// Display all empty meshes, we need to do this because users can add devices to these at any time.
|
||||||
@ -1654,7 +1686,7 @@
|
|||||||
multiDesktop[id] = desktop;
|
multiDesktop[id] = desktop;
|
||||||
desktop = desktopNode = currentNode = null;
|
desktop = desktopNode = currentNode = null;
|
||||||
// Setup a replacement desktop
|
// Setup a replacement desktop
|
||||||
QH('DeskParent', '<canvas id="Desk" width="640" height="200" style="width:100%;-ms-touch-action:none;margin-left:0px" oncontextmenu="return false" onmousedown="dmousedown(event)" onmouseup="dmouseup(event)" onmousemove="dmousemove(event)"></canvas>');
|
QH('DeskParent', '<canvas id="Desk" width="640" height="200" style="width:100%;-ms-touch-action:none;margin-left:0px" oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></canvas>');
|
||||||
} else {
|
} else {
|
||||||
// This is a new device, create a canvas for it.
|
// This is a new device, create a canvas for it.
|
||||||
var c = document.createElement('canvas');
|
var c = document.createElement('canvas');
|
||||||
@ -1664,7 +1696,7 @@
|
|||||||
c.setAttribute('oncontextmenu', 'return false');
|
c.setAttribute('oncontextmenu', 'return false');
|
||||||
c.setAttribute('style', 'background-color:black;width:' + vsize.x + 'px;height:' + vsize.y + 'px');
|
c.setAttribute('style', 'background-color:black;width:' + vsize.x + 'px;height:' + vsize.y + 'px');
|
||||||
c.setAttribute('onclick', 'toggleKvmDevice(\'' + id + '\')');
|
c.setAttribute('onclick', 'toggleKvmDevice(\'' + id + '\')');
|
||||||
Q('xkvmid_' + shortid).appendChild(c);
|
try { Q('xkvmid_' + shortid).appendChild(c); } catch (ex) {}
|
||||||
// Check if we need to auto-connect
|
// Check if we need to auto-connect
|
||||||
if (Q('autoConnectDesktopCheckbox').checked == true) { setTimeout(function() { connectMultiDesktop(node, 1); }, 100); }
|
if (Q('autoConnectDesktopCheckbox').checked == true) { setTimeout(function() { connectMultiDesktop(node, 1); }, 100); }
|
||||||
}
|
}
|
||||||
@ -2037,13 +2069,18 @@
|
|||||||
setDialogMode(2, "Group Action", 3, groupActionFunctionEx, x);
|
setDialogMode(2, "Group Action", 3, groupActionFunctionEx, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the list of checked devices, removes any duplicates.
|
||||||
|
function getCheckedDevices() {
|
||||||
|
var nodeids = [], elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
|
||||||
|
for (var i in elements) { if (elements[i].checked) { if (elements[i].value) { var nid = elements[i].value.substring(6); if (nodeids.indexOf(nid) == -1) { nodeids.push(nid); } } } }
|
||||||
|
return nodeids;
|
||||||
|
}
|
||||||
|
|
||||||
function groupActionFunctionEx() {
|
function groupActionFunctionEx() {
|
||||||
var op = Q('d2groupop').value;
|
var op = Q('d2groupop').value;
|
||||||
if (op == 100) {
|
if (op == 100) {
|
||||||
// Group wake
|
// Group wake
|
||||||
var nodeids = [], elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
|
meshserver.send({ action: 'wakedevices', nodeids: getCheckedDevices() });
|
||||||
for (var i in elements) { if (elements[i].checked) { nodeids.push(elements[i].value.substring(6)); } }
|
|
||||||
meshserver.send({ action: 'wakedevices', nodeids: nodeids });
|
|
||||||
} else if (op == 101) {
|
} else if (op == 101) {
|
||||||
// Group delete, ask for confirmation
|
// Group delete, ask for confirmation
|
||||||
var x = "Confirm delete selected devices(s)?<br /><br />";
|
var x = "Confirm delete selected devices(s)?<br /><br />";
|
||||||
@ -2052,19 +2089,12 @@
|
|||||||
QE('idx_dlgOkButton', false);
|
QE('idx_dlgOkButton', false);
|
||||||
} else {
|
} else {
|
||||||
// Power operation
|
// Power operation
|
||||||
var nodeids = [], elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
|
meshserver.send({ action: 'poweraction', nodeids: getCheckedDevices(), actiontype: op });
|
||||||
for (var i in elements) { if (elements[i].checked) { nodeids.push(elements[i].value.substring(6)); } }
|
|
||||||
meshserver.send({ action: 'poweraction', nodeids: nodeids, actiontype: op });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function d2groupActionFunctionDelEx() { QE('idx_dlgOkButton', Q('d2check').checked); }
|
function d2groupActionFunctionDelEx() { QE('idx_dlgOkButton', Q('d2check').checked); }
|
||||||
|
function groupActionFunctionDelEx() { meshserver.send({ action: 'removedevices', nodeids: getCheckedDevices() }); }
|
||||||
function groupActionFunctionDelEx() {
|
|
||||||
var nodeids = [], elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
|
|
||||||
for (var i in elements) { if (elements[i].checked) { nodeids.push(elements[i].value.substring(6)); } }
|
|
||||||
meshserver.send({ action: 'removedevices', nodeids: nodeids });
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSortSelectChange(skipsave) {
|
function onSortSelectChange(skipsave) {
|
||||||
sort = document.getElementById("sortselect").selectedIndex;
|
sort = document.getElementById("sortselect").selectedIndex;
|
||||||
@ -2858,6 +2888,11 @@
|
|||||||
x += addDeviceAttribute('Connectivity', cstate.join(', '));
|
x += addDeviceAttribute('Connectivity', cstate.join(', '));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Node grouping tags
|
||||||
|
var groupingTags = '<i>None</i>';
|
||||||
|
if (node.tags != null) { groupingTags = ''; for (var i in node.tags) { groupingTags += '<span style="background-color:lightgray;padding:3px;margin-right:4px;border-radius:5px">' + node.tags[i] + '</span>'; } }
|
||||||
|
x += addDeviceAttribute('Groups', '<span onclick=showEditNodeValueDialog(3) style=cursor:pointer>' + groupingTags + '</span>');
|
||||||
|
|
||||||
x += '</table><br />';
|
x += '</table><br />';
|
||||||
// Show action button, only show if we have permissions 4, 8, 64
|
// Show action button, only show if we have permissions 4, 8, 64
|
||||||
if ((meshrights & 76) != 0) { x += '<input type=button value=Actions title="Perform power actions on the device" onclick=deviceActionFunction() />'; }
|
if ((meshrights & 76) != 0) { x += '<input type=button value=Actions title="Perform power actions on the device" onclick=deviceActionFunction() />'; }
|
||||||
@ -3233,14 +3268,16 @@
|
|||||||
meshserver.send({ action: 'changedevice', nodeid: currentNode._id, icon: icon });
|
meshserver.send({ action: 'changedevice', nodeid: currentNode._id, icon: icon });
|
||||||
}
|
}
|
||||||
|
|
||||||
var showEditNodeValueDialog_modes = ['Device Name', 'Hostname', 'Description'];
|
var showEditNodeValueDialog_modes = ['Device Name', 'Hostname', 'Description', 'Groups'];
|
||||||
var showEditNodeValueDialog_modes2 = ['name', 'host', 'desc'];
|
var showEditNodeValueDialog_modes2 = ['name', 'host', 'desc', 'tags'];
|
||||||
|
var showEditNodeValueDialog_modes3 = ['', '', '', 'Group1, Group2, Group3'];
|
||||||
function showEditNodeValueDialog(mode) {
|
function showEditNodeValueDialog(mode) {
|
||||||
if (xxdialogMode) return;
|
if (xxdialogMode) return;
|
||||||
var x = addHtmlValue(showEditNodeValueDialog_modes[mode], '<input id=dp10devicevalue style=width:230px maxlength=64 onchange=p10editdevicevalueValidate(' + mode + ',event) onkeyup=p10editdevicevalueValidate(' + mode + ',event) />');
|
var x = addHtmlValue(showEditNodeValueDialog_modes[mode], '<input id=dp10devicevalue style=width:230px maxlength=64 placeholder="' + showEditNodeValueDialog_modes3[mode] + '" onchange=p10editdevicevalueValidate(' + mode + ',event) onkeyup=p10editdevicevalueValidate(' + mode + ',event) />');
|
||||||
setDialogMode(2, "Edit Device", 3, showEditNodeValueDialogEx, x, mode);
|
setDialogMode(2, "Edit Device", 3, showEditNodeValueDialogEx, x, mode);
|
||||||
var v = currentNode[showEditNodeValueDialog_modes2[mode]];
|
var v = currentNode[showEditNodeValueDialog_modes2[mode]];
|
||||||
if (v == null) v = '';
|
if (v == null) v = '';
|
||||||
|
if (Array.isArray(v)) { v = v.join(', '); }
|
||||||
Q('dp10devicevalue').value = v;
|
Q('dp10devicevalue').value = v;
|
||||||
p10editdevicevalueValidate();
|
p10editdevicevalueValidate();
|
||||||
Q('dp10devicevalue').focus();
|
Q('dp10devicevalue').focus();
|
||||||
|
Loading…
Reference in New Issue
Block a user