Improved MeshCtrl.js
Ylian Saint-Hilaire committed
Apr 1, 2020 at 13:15 UTC
1eeb7646574b583ca4d0586a91c7e22218047db7
5 files changed
+132
-17
meshctrl.js
+87
-4
@@ -3,7 +3,7 @@
3
const crypto = require('crypto');
4
var settings = {};
5
const args = require('minimist')(process.argv.slice(2));
6
-const possibleCommands = ['listusers', 'listdevicegroups', 'listdevices', 'listusersofdevicegroup', 'serverinfo', 'userinfo', 'adduser', 'removeuser', 'adddevicegroup', 'removedevicegroup', 'broadcast', 'showevents', 'addusertodevicegroup', 'removeuserfromdevicegroup', 'sendinviteemail', 'generateinvitelink', 'config'];
6
+const possibleCommands = ['listusers', 'listdevicegroups', 'listdevices', 'listusersofdevicegroup', 'serverinfo', 'userinfo', 'adduser', 'removeuser', 'adddevicegroup', 'removedevicegroup', 'broadcast', 'showevents', 'addusertodevicegroup', 'removeuserfromdevicegroup', 'addusertodevice', 'removeuserfromdevice', 'sendinviteemail', 'generateinvitelink', 'config'];
7
//console.log(args);
8
9
if (args['_'].length == 0) {
@@ -25,6 +25,8 @@ if (args['_'].length == 0) {
25
console.log(" RemoveDeviceGroup - Delete a device group.");
26
console.log(" AddUserToDeviceGroup - Add a user to a device group.");
27
console.log(" RemoveUserFromDeviceGroup - Remove a user from a device group.");
28
+ console.log(" AddUserToDevice - Add a user to a device.");
29
+ console.log(" RemoveUserFromDevice - Remove a user from a device.");
30
console.log(" SendInviteEmail - Send an agent install invitation email.");
31
console.log(" GenerateInviteLink - Create an invitation link.");
32
console.log(" Broadcast - Display a message to all online users.");
@@ -68,6 +70,18 @@ if (args['_'].length == 0) {
70
else { ok = true; }
71
break;
72
}
73
+ case 'addusertodevice': {
74
+ if (args.userid == null) { console.log("Add user to device missing useid, use --userid [userid]"); }
75
+ else if (args.id == null) { console.log("Add user to device missing device id, use --id [deviceid]"); }
76
+ else { ok = true; }
77
+ break;
78
+ }
79
+ case 'removeuserfromdevice': {
80
+ if (args.userid == null) { console.log("Remove user from device missing useid, use --userid [userid]"); }
81
+ else if (args.id == null) { console.log("Remove user from device missing device id, use --id [deviceid]"); }
82
+ else { ok = true; }
83
+ break;
84
+ }
85
case 'adddevicegroup': {
86
if (args.name == null) { console.log("Message group name, use --name [name]"); }
87
else { ok = true; }
@@ -262,6 +276,14 @@ if (args['_'].length == 0) {
276
console.log(" --noterminal - Hide the terminal tab from this user.");
277
console.log(" --nofiles - Hide the files tab from this user.");
278
console.log(" --noamt - Hide the Intel AMT tab from this user.");
279
+ console.log(" --limitedevents - User can only see his own events.");
280
+ console.log(" --chatnotify - Allow chat and notification options.");
281
+ console.log(" --uninstall - Allow remote uninstall of the agent.");
282
+ if (args.limiteddesktop) { meshrights |= 4096; }
283
+ if (args.limitedevents) { meshrights |= 8192; }
284
+ if (args.chatnotify) { meshrights |= 16384; }
285
+ if (args.uninstall) { meshrights |= 32768; }
286
+
287
break;
288
}
289
case 'removeuserfromdevicegroup': {
@@ -272,11 +294,43 @@ if (args['_'].length == 0) {
294
console.log(" --userid [userid] - The user identifier.");
295
break;
296
}
297
+ case 'addusertodevice': {
298
+ console.log("Add a user to a device, Example usages:\r\n");
299
+ console.log(" MeshCtrl AddUserToDevice --id deviceid --userid userid --fullrights");
300
+ console.log(" MeshCtrl AddUserToDevice --id deviceid --userid userid --remotecontrol");
301
+ console.log("\r\nRequired arguments:\r\n");
302
+ console.log(" --id [deviceid] - The device identifier.");
303
+ console.log(" --userid [userid] - The user identifier.");
304
+ console.log("\r\nOptional arguments:\r\n");
305
+ console.log(" --fullrights - Allow full rights over this device.");
306
+ console.log(" --remotecontrol - Allow device remote control operations.");
307
+ console.log(" --agentconsole - Allow agent console operations.");
308
+ console.log(" --serverfiles - Allow access to group server files.");
309
+ console.log(" --wakedevices - Allow device wake operation.");
310
+ console.log(" --notes - Allow editing of device notes.");
311
+ console.log(" --desktopviewonly - Restrict user to view-only remote desktop.");
312
+ console.log(" --limiteddesktop - Limit remote desktop keys.");
313
+ console.log(" --noterminal - Hide the terminal tab from this user.");
314
+ console.log(" --nofiles - Hide the files tab from this user.");
315
+ console.log(" --noamt - Hide the Intel AMT tab from this user.");
316
+ console.log(" --limitedevents - User can only see his own events.");
317
+ console.log(" --chatnotify - Allow chat and notification options.");
318
+ console.log(" --uninstall - Allow remote uninstall of the agent.");
319
+ break;
320
+ }
321
+ case 'removeuserfromdevice': {
322
+ console.log("Remove a user from a device, Example usages:\r\n");
323
+ console.log(" MeshCtrl RemoveuserFromDeviceGroup --id deviceid --userid userid");
324
+ console.log("\r\nRequired arguments:\r\n");
325
+ console.log(" --id [deviceid] - The device identifier.");
326
+ console.log(" --userid [userid] - The user identifier.");
327
+ break;
328
+ }
329
case 'broadcast': {
330
console.log("Display a message to all logged in users, Example usages:\r\n");
331
console.log(" MeshCtrl Broadcast --msg \"This is a test\"");
332
console.log("\r\nRequired arguments:\r\n");
279
- console.log(" --msg [message] - Message to display.");
333
+ console.log(" --msg [message] - Message to display.");
334
break;
335
}
336
default: {
@@ -532,6 +586,9 @@ function serverConnect() {
586
if (args.nofiles) { meshrights |= 1024; }
587
if (args.noamt) { meshrights |= 2048; }
588
if (args.limiteddesktop) { meshrights |= 4096; }
589
+ if (args.limitedevents) { meshrights |= 8192; }
590
+ if (args.chatnotify) { meshrights |= 16384; }
591
+ if (args.uninstall) { meshrights |= 32768; }
592
var op = { action: 'addmeshuser', meshid: args.id, usernames: [args.userid], meshadmin: meshrights, responseid: 'meshctrl' };
593
ws.send(JSON.stringify(op));
594
break;
@@ -541,13 +598,38 @@ function serverConnect() {
598
ws.send(JSON.stringify(op));
599
break;
600
}
601
+ case 'addusertodevice': {
602
+ var meshrights = 0;
603
+ if (args.fullrights) { meshrights = (8 + 16 + 32 + 64 + 128 + 16384 + 32768); }
604
+ if (args.remotecontrol) { meshrights |= 8; }
605
+ if (args.agentconsole) { meshrights |= 16; }
606
+ if (args.serverfiles) { meshrights |= 32; }
607
+ if (args.wakedevices) { meshrights |= 64; }
608
+ if (args.notes) { meshrights |= 128; }
609
+ if (args.desktopviewonly) { meshrights |= 256; }
610
+ if (args.noterminal) { meshrights |= 512; }
611
+ if (args.nofiles) { meshrights |= 1024; }
612
+ if (args.noamt) { meshrights |= 2048; }
613
+ if (args.limiteddesktop) { meshrights |= 4096; }
614
+ if (args.limitedevents) { meshrights |= 8192; }
615
+ if (args.chatnotify) { meshrights |= 16384; }
616
+ if (args.uninstall) { meshrights |= 32768; }
617
+ var op = { action: 'adddeviceuser', nodeid: args.id, usernames: [args.userid], rights: meshrights, responseid: 'meshctrl' };
618
+ ws.send(JSON.stringify(op));
619
+ break;
620
+ }
621
+ case 'removeuserfromdevice': {
622
+ var op = { action: 'adddeviceuser', nodeid: args.id, usernames: [args.userid], rights: 0, responseid: 'meshctrl' };
623
+ ws.send(JSON.stringify(op));
624
+ break;
625
+ }
626
case 'sendinviteemail': {
545
- var op = { action: "inviteAgent", meshid: args.id, email: args.email, name: "", os: "0", responseid: 'meshctrl' }
627
+ var op = { action: 'inviteAgent', meshid: args.id, email: args.email, name: '', os: '0', responseid: 'meshctrl' }
628
ws.send(JSON.stringify(op));
629
break;
630
}
631
case 'generateinvitelink': {
550
- var op = { action: "createInviteLink", meshid: args.id, expire: args.hours, flags: 0, responseid: 'meshctrl' }
632
+ var op = { action: 'createInviteLink', meshid: args.id, expire: args.hours, flags: 0, responseid: 'meshctrl' }
633
ws.send(JSON.stringify(op));
634
break;
635
}
@@ -604,6 +686,7 @@ function serverConnect() {
686
case 'addmeshuser': //
687
case 'removemeshuser': //
688
case 'inviteAgent': //
689
+ case 'adddeviceuser': //
690
case 'userbroadcast': { // BROADCAST
691
if (data.responseid == 'meshctrl') {
692
if (data.meshid) { console.log(data.result, data.meshid); }
meshuser.js
+32
-6
@@ -2392,16 +2392,22 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2392
for (var i in command.usernames) { command.userids.push('user/' + domain.id + '/' + command.usernames[i].toLowerCase()); }
2393
}
2394
2395
- var unknownUsers = [], removedCount = 0, failCount = 0;
2395
+ var unknownUsers = [], successCount = 0, failCount = 0, msgs = [];
2396
for (var i in command.userids) {
2397
// Check if the user exists
2398
var newuserid = command.userids[i], newuser = null;
2399
if (newuserid.startsWith('user/')) { newuser = parent.users[newuserid]; }
2400
else if (newuserid.startsWith('ugrp/')) { newuser = parent.userGroups[newuserid]; }
2401
2402
+ // Search for a user name in that windows domain is the username starts with *\
2403
+ if ((newuser == null) && (newuserid.startsWith('user/' + domain.id + '/*\\')) == true) {
2404
+ var search = newuserid.split('/')[2].substring(1);
2405
+ for (var i in parent.users) { if (i.endsWith(search) && (parent.users[i].domain == domain.id)) { newuser = parent.users[i]; command.userids[i] = newuserid = parent.users[i]._id; break; } }
2406
+ }
2407
+
2408
if (newuser != null) {
2409
// Can't add or modify self
2404
- if (newuserid == obj.user._id) { continue; }
2410
+ if (newuserid == obj.user._id) { errors.push("Can't add self."); continue; }
2411
2412
// Add mesh to user or user group
2413
if (newuser.links == null) { newuser.links = {}; }
@@ -2432,19 +2438,23 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2438
var event = { etype: 'mesh', username: newuser.name, userid: user._id, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, action: 'meshchange', links: mesh.links, msg: 'Added user ' + newuser.name + ' to mesh ' + mesh.name, domain: domain.id, invite: mesh.invite };
2439
if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come.
2440
parent.parent.DispatchEvent(['*', mesh._id, user._id, newuserid], obj, event);
2435
- removedCount++;
2441
+ msgs.push("Added user " + newuser._id.split('/')[2]);
2442
+ successCount++;
2443
} else {
2437
- unknownUsers.push(command.userids[i]);
2444
+ msgs.push("Unknown user " + newuserid._id.split('/')[2]);
2445
+ unknownUsers.push(newuserid);
2446
failCount++;
2447
}
2448
}
2449
2450
+ if ((successCount == 0) && (failCount == 0)) { msgs.push("Nothing done"); }
2451
+
2452
if (unknownUsers.length > 0) {
2453
// Send error back, user not found.
2454
displayNotificationMessage('User' + ((unknownUsers.length > 1) ? 's' : '') + ' ' + EscapeHtml(unknownUsers.join(', ')) + ' not found.', 'Device Group', 'ServerNotify');
2455
}
2456
2447
- if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'addmeshuser', responseid: command.responseid, result: 'ok', removed: removedCount, failed: failCount })); } catch (ex) { } }
2457
+ if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'addmeshuser', responseid: command.responseid, result: msgs.join(', '), success: successCount, failed: failCount })); } catch (ex) { } }
2458
break;
2459
}
2460
case 'adddeviceuser': {
@@ -2456,7 +2466,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2466
else if ((command.rights & 7) != 0) { err = 'Invalid rights'; } // EDITMESH, MANAGEUSERS or MANAGECOMPUTERS rights can't be assigned to a user to device link
2467
else if ((common.validateStrArray(command.usernames, 1, 64) == false) && (common.validateStrArray(command.userids, 1, 128) == false)) { err = 'Invalid usernames'; } // Username is between 1 and 64 characters
2468
else {
2459
- if (command.nodeid.indexOf('/') == -1) { command.nodeid = 'node/' + domain.id + '/' + command.meshid; }
2469
+ if (command.nodeid.indexOf('/') == -1) { command.nodeid = 'node/' + domain.id + '/' + command.nodeid; }
2470
else if ((command.nodeid.split('/').length != 3) || (command.nodeid.split('/')[1] != domain.id)) { err = 'Invalid domain'; } // Invalid domain, operation only valid for current domain
2471
}
2472
} catch (ex) { err = 'Validation exception: ' + ex; }
@@ -2487,6 +2497,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2497
for (var i in command.userids) {
2498
var newuserid = command.userids[i];
2499
var newuser = parent.users[newuserid];
2500
+
2501
+ // Search for a user name in that windows domain is the username starts with *\
2502
+ if ((newuser == null) && (newuserid.startsWith('user/' + domain.id + '/*\\')) == true) {
2503
+ var search = newuserid.split('/')[2].substring(1);
2504
+ for (var i in parent.users) { if (i.endsWith(search) && (parent.users[i].domain == domain.id)) { newuser = parent.users[i]; command.userids[i] = newuserid = newuser._id; break; } }
2505
+ }
2506
+
2507
if (newuser != null) {
2508
// Add this user to the dispatch target list
2509
dispatchTargets.push(newuser._id);
@@ -2537,6 +2554,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2554
if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come.
2555
parent.parent.DispatchEvent(dispatchTargets, obj, event);
2556
}
2557
+
2558
+ if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'adddeviceuser', responseid: command.responseid, result: 'ok' })); } catch (ex) { } }
2559
});
2560
2561
break;
@@ -2569,6 +2588,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2588
var deluserid = command.userid, deluser = null;
2589
if (deluserid.startsWith('user/')) { deluser = parent.users[deluserid]; }
2590
else if (deluserid.startsWith('ugrp/')) { deluser = parent.userGroups[deluserid]; }
2591
+
2592
+ // Search for a user name in that windows domain is the username starts with *\
2593
+ if ((deluser == null) && (deluserid.startsWith('user/' + domain.id + '/*\\')) == true) {
2594
+ var search = deluserid.split('/')[2].substring(1);
2595
+ for (var i in parent.users) { if (i.endsWith(search) && (parent.users[i].domain == domain.id)) { deluser = parent.users[i]; command.userid = deluserid = deluser._id; break; } }
2596
+ }
2597
+
2598
if (deluser != null) {
2599
// Remove mesh from user
2600
if (deluser.links != null && deluser.links[command.meshid] != null) {
package.json
+1
-1
@@ -1,6 +1,6 @@
1
{
2
"name": "meshcentral",
3
- "version": "0.5.0-x",
3
+ "version": "0.5.0-y",
4
"keywords": [
5
"Remote Management",
6
"Intel AMT",
translate/translate.json
+1
-1
@@ -27870,4 +27870,4 @@
27870
]
27871
}
27872
]
27873
-}
27873
+}
\ No newline at end of file
views/default.handlebars
+11
-5
@@ -3125,7 +3125,9 @@
3125
}
3126
3127
// If there is nothing to display, explain the problem
3128
+ var viewNothing = false;
3129
if ((r == '') && (nodes.length > 0) && (Q('SearchInput').value != '')) {
3130
+ viewNothing = true;
3131
if (sort == 3) {
3132
r = '<div style="margin:30px">' + "No devices are included in any groups, click on a device\'s \"Groups\" to add to a group." + '</div>';
3133
} else {
@@ -3172,7 +3174,7 @@
3174
}
3175
}
3176
3175
- if (r != '') {
3177
+ if ((r != '') && (viewNothing == false)) {
3178
r += '</table>';
3179
if (view == 2) {
3180
// This height of 1 div at the end to fix a problem in Linux firefox browsers
@@ -9587,20 +9589,24 @@
9589
if ((user.otpsecret > 0) || (user.otphkeys > 0)) { username += ' <img src="images/key12.png" height=12 width=11 title="' + "2nd factor authentication enabled" + '" style="margin-top:2px" />'; }
9590
if ((user.siteadmin != null) && ((user.siteadmin & 32) != 0) && (user.siteadmin != 0xFFFFFFFF)) { username += ' <img src="images/padlock12.png" height=12 width=8 title="' + "Account is locked" + '" style="margin-top:2px" />'; }
9591
9590
- x += '<tr tabindex=0 onmouseover=userMouseHover(this,1) onmouseout=userMouseHover(this,0) onkeypress="if (event.key==\'Enter\') gotoUser(\'' + encodeURIComponent(user._id) + '\')"><td style=cursor:pointer onclick=gotoUser(\"' + encodeURIComponent(user._id) + '\")>';
9592
+ x += '<tr tabindex=0 onmouseover=userMouseHover(this,1) onmouseout=userMouseHover(this,0) onkeypress="if (event.key==\'Enter\') gotoUser(\'' + encodeURIComponent(user._id) + '\')"><td>';
9593
x += '<div class=bar>';
9594
+ x += '<div class=baricon><input type=checkbox></div><div style=cursor:pointer onclick=gotoUser(\"' + encodeURIComponent(user._id) + '\")>';
9595
x += '<div class=baricon><div class="' + icon + gray + '"></div></div>';
9593
- x += '<div class=g1></div><div class=g2></div>';
9596
+ x += '<div class=g1></div><div class=g2></div><div>';
9597
x += '<div><span>' + username + '</span>' + msg + '</div></div><td style=text-align:center>' + groups + '<td style=text-align:center>' + lastAccess + '<td style=text-align:center>' + permissions;
9598
return x;
9599
}
9600
9601
// Highlights the user being hovered
9602
function userMouseHover(element, over) {
9600
- var e = element.children[0].children[0];
9603
+ var e = element.children[0].children[0].children[1];
9604
e.children[1].classList.remove('g1s');
9605
e.children[2].classList.remove('g2s');
9603
- if (over == 1) { e.children[1].classList.add('g1s'); e.children[2].classList.add('g2s'); }
9606
+ if (over == 1) {
9607
+ e.children[1].classList.add('g1s');
9608
+ e.children[2].classList.add('g2s');
9609
+ }
9610
element.children[0].children[0].style['background-color'] = ((over == 0) ? '#c9c9c9' : '#b9b9b9');
9611
}
9612