Added device group edit in MeshCtrl.js.

Ylian Saint-Hilaire committed Jul 24, 2020 at 12:32 UTC 39295112ad38f8176f5362a66b80490bada759a7
2 files changed +122 -41
meshctrl.js
+58 -1
@@ -7,7 +7,7 @@ try { require('ws'); } catch (ex) { console.log('Missing module "ws", type "npm
7 var settings = {};
8 const crypto = require('crypto');
9 const args = require('minimist')(process.argv.slice(2));
10 -const possibleCommands = ['listusers', 'listusersessions', 'listdevicegroups', 'listdevices', 'listusersofdevicegroup', 'serverinfo', 'userinfo', 'adduser', 'removeuser', 'adddevicegroup', 'removedevicegroup', 'broadcast', 'showevents', 'addusertodevicegroup', 'removeuserfromdevicegroup', 'addusertodevice', 'removeuserfromdevice', 'sendinviteemail', 'generateinvitelink', 'config', 'movetodevicegroup', 'deviceinfo', 'addusergroup', 'listusergroups', 'removeusergroup', 'runcommand', 'shell', 'upload', 'download'];
10 +const possibleCommands = ['listusers', 'listusersessions', 'listdevicegroups', 'listdevices', 'listusersofdevicegroup', 'serverinfo', 'userinfo', 'adduser', 'removeuser', 'adddevicegroup', 'removedevicegroup', 'editdevicegroup', 'broadcast', 'showevents', 'addusertodevicegroup', 'removeuserfromdevicegroup', 'addusertodevice', 'removeuserfromdevice', 'sendinviteemail', 'generateinvitelink', 'config', 'movetodevicegroup', 'deviceinfo', 'addusergroup', 'listusergroups', 'removeusergroup', 'runcommand', 'shell', 'upload', 'download'];
11 if (args.proxy != null) { try { require('https-proxy-agent'); } catch (ex) { console.log('Missing module "https-proxy-agent", type "npm install https-proxy-agent" to install it.'); return; } }
12
13 if (args['_'].length == 0) {
@@ -32,6 +32,7 @@ if (args['_'].length == 0) {
32 console.log(" RemoveUserGroup - Delete a user group.");
33 console.log(" AddDeviceGroup - Create a new device group.");
34 console.log(" RemoveDeviceGroup - Delete a device group.");
35 + console.log(" EditDeviceGroup - Change a device group values.");
36 console.log(" MoveToDeviceGroup - Move a device to a different device group.");
37 console.log(" AddUserToDeviceGroup - Add a user to a device group.");
38 console.log(" RemoveUserFromDeviceGroup - Remove a user from a device group.");
@@ -109,6 +110,7 @@ if (args['_'].length == 0) {
110 else { ok = true; }
111 break;
112 }
113 + case 'editdevicegroup':
114 case 'removedevicegroup': {
115 if ((args.id == null) && (args.group == null)) { console.log(winRemoveSingleQuotes("Device group identifier missing, use --id '[groupid]' or --group [groupname]")); }
116 else { ok = true; }
@@ -360,6 +362,35 @@ if (args['_'].length == 0) {
362 console.log(" --group [groupname] - Device group name (or --id).");
363 break;
364 }
365 + case 'editdevicegroup': {
366 + console.log("Edit a device group, Example usages:\r\n");
367 + console.log(" MeshCtrl EditDeviceGroup --id 'groupid' --name 'NewName'");
368 + console.log("\r\nRequired arguments:\r\n");
369 + if (process.platform == 'win32') {
370 + console.log(" --id [groupid] - Device group identifier (or --group).");
371 + } else {
372 + console.log(" --id '[groupid]' - Device group identifier (or --group).");
373 + }
374 + console.log(" --group [groupname] - Device group name (or --id).");
375 + console.log("\r\nOptional arguments:\r\n");
376 + console.log(" --name [name] - Set new device group name.");
377 + console.log(" --desc [name] - Set new device group description, blank to clear.");
378 + console.log(" --flags [number] - Set device group flags, sum of the values below, 0 for none.");
379 + console.log(" 1 = Auto remove device on disconnect.");
380 + console.log(" 2 = Sync hostname.");
381 + console.log(" --consent [number] - Set device group consent options, sum of the values below, 0 for none.");
382 + console.log(" 1 = Desktop notify user.");
383 + console.log(" 2 = Terminal notify user.");
384 + console.log(" 4 = Files notify user.");
385 + console.log(" 8 = Desktop prompt for user consent.");
386 + console.log(" 16 = Terminal prompt for user consent.");
387 + console.log(" 32 = Files prompt for user consent.");
388 + console.log(" 64 = Desktop show connection toolbar.");
389 + console.log(" --invitecodes [aa,bb] - Comma seperated list of invite codes, blank to clear.");
390 + console.log(" --backgroundonly - When used with invitecodes, set agent to only install in background.");
391 + console.log(" --interactiveonly - When used with invitecodes, set agent to only run on demand.");
392 + break;
393 + }
394 case 'movetodevicegroup': {
395 console.log("Move a device to a new device group, Example usages:\r\n");
396 console.log(winRemoveSingleQuotes(" MeshCtrl MoveToDeviceGroup --devid 'deviceid' --id 'groupid'"));
@@ -814,6 +845,31 @@ function serverConnect() {
845 ws.send(JSON.stringify(op));
846 break;
847 }
848 + case 'editdevicegroup': {
849 + var op = { action: 'editmesh', responseid: 'meshctrl' };
850 + if (args.id) { op.meshid = args.id; } else if (args.group) { op.meshidname = args.group; }
851 + if ((typeof args.name == 'string') && (args.name != '')) { op.meshname = args.name; }
852 + if (args.desc === true) { op.desc = ""; } else if (typeof args.desc == 'string') { op.desc = args.desc; }
853 + if (args.invitecodes === true) { op.invite = "*"; } else if (typeof args.invitecodes == 'string') {
854 + var invitecodes = args.invitecodes.split(','), invitecodes2 = [];
855 + for (var i in invitecodes) { if (invitecodes[i].length > 0) { invitecodes2.push(invitecodes[i]); } }
856 + if (invitecodes2.length > 0) {
857 + op.invite = { codes: invitecodes2, flags: 0 };
858 + if (args.backgroundonly === true) { op.invite.flags = 2; }
859 + else if (args.interactiveonly === true) { op.invite.flags = 1; }
860 + }
861 + }
862 + if (args.flags != null) {
863 + var flags = parseInt(args.flags);
864 + if (typeof flags == 'number') { op.flags = flags; }
865 + }
866 + if (args.consent != null) {
867 + var consent = parseInt(args.consent);
868 + if (typeof consent == 'number') { op.consent = consent; }
869 + }
870 + ws.send(JSON.stringify(op));
871 + break;
872 + }
873 case 'movetodevicegroup': {
874 var op = { action: 'changeDeviceMesh', responseid: 'meshctrl', nodeids: [ args.devid ] };
875 if (args.id) { op.meshid = args.id; } else if (args.group) { op.meshname = args.group; }
@@ -1000,6 +1056,7 @@ function serverConnect() {
1056 case 'deleteuser': // REMOVEUSER
1057 case 'createmesh': // ADDDEVICEGROUP
1058 case 'deletemesh': // REMOVEDEVICEGROUP
1059 + case 'editmesh': // EDITDEVICEGROUP
1060 case 'changeDeviceMesh':
1061 case 'addmeshuser': //
1062 case 'removemeshuser': //
meshuser.js
+64 -40
@@ -2590,6 +2590,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2590 }
2591 case 'deletemesh':
2592 {
2593 + // Delete a mesh and all computers within it
2594 var err = null;
2595
2596 // Resolve the device group name if needed
@@ -2602,8 +2603,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2603 }
2604 }
2605
2606 + // Validate input
2607 try {
2606 - // Delete a mesh and all computers within it
2608 if (common.validateString(command.meshid, 1, 1024) == false) { err = 'Invalid group identifier'; } // Check the meshid
2609 else if (command.meshid.indexOf('/') == -1) { command.meshid = 'mesh/' + domain.id + '/' + command.meshid; }
2610 } catch (ex) { err = 'Validation exception: ' + ex; }
@@ -2682,54 +2683,77 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2683 case 'editmesh':
2684 {
2685 // Change the name or description of a device group (mesh)
2685 - if (common.validateString(command.meshid, 1, 1024) == false) break; // Check the meshid
2686 - mesh = parent.meshes[command.meshid];
2687 - change = '';
2686 + var err = null;
2687
2689 - if (mesh) {
2690 - // Check if this user has rights to do this
2691 - if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_EDITMESH) == 0) return;
2692 - if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
2688 + // Resolve the device group name if needed
2689 + if ((typeof command.meshidname == 'string') && (command.meshid == null)) {
2690 + for (var i in parent.meshes) {
2691 + var m = parent.meshes[i];
2692 + if ((m.mtype == 2) && (m.name == command.meshidname) && parent.IsMeshViewable(user, m)) {
2693 + if (command.meshid == null) { command.meshid = m._id; } else { err = 'Duplicate device groups found'; }
2694 + }
2695 + }
2696 + }
2697 +
2698 + // Validate input
2699 + try {
2700 + if (common.validateString(command.meshid, 1, 1024) == false) { err = 'Invalid group identifier'; } // Check the meshid
2701 + else if (command.meshid.indexOf('/') == -1) { command.meshid = 'mesh/' + domain.id + '/' + command.meshid; }
2702 + if (err == null) {
2703 + mesh = parent.meshes[command.meshid];
2704 + if (mesh == null) { err = 'Invalid group identifier '; }
2705 + }
2706 + } catch (ex) { err = 'Validation exception: ' + ex; }
2707
2694 - if ((common.validateString(command.meshname, 1, 64) == true) && (command.meshname != mesh.name)) { change = 'Group name changed from "' + mesh.name + '" to "' + command.meshname + '"'; mesh.name = command.meshname; }
2695 - if ((common.validateString(command.desc, 0, 1024) == true) && (command.desc != mesh.desc)) { if (change != '') change += ' and description changed'; else change += 'Group "' + mesh.name + '" description changed'; mesh.desc = command.desc; }
2696 - if ((common.validateInt(command.flags) == true) && (command.flags != mesh.flags)) { if (change != '') change += ' and flags changed'; else change += 'Group "' + mesh.name + '" flags changed'; mesh.flags = command.flags; }
2697 - if ((common.validateInt(command.consent) == true) && (command.consent != mesh.consent)) { if (change != '') change += ' and consent changed'; else change += 'Group "' + mesh.name + '" consent changed'; mesh.consent = command.consent; }
2708 + // Handle any errors
2709 + if (err != null) { if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'editmesh', responseid: command.responseid, result: err })); } catch (ex) { } } break; }
2710 +
2711 + change = '';
2712
2699 - // See if we need to change device group invitation codes
2700 - if (mesh.mtype == 2) {
2701 - if (command.invite === '*') {
2702 - // Clear invite codes
2703 - if (mesh.invite != null) { delete mesh.invite; }
2704 - if (change != '') { change += ' and invite code changed'; } else { change += 'Group "' + mesh.name + '" invite code changed'; }
2705 - } else if (typeof command.invite === 'object') {
2706 - // Set invite codes
2707 - if ((mesh.invite == null) || (mesh.invite.codes != command.invite.codes) || (mesh.invite.flags != command.invite.flags)) {
2708 - // Check if an invite code is not already in use.
2709 - var dup = null;
2710 - for (var i in command.invite.codes) {
2711 - for (var j in parent.meshes) {
2712 - if ((j != command.meshid) && (parent.meshes[j].domain == domain.id) && (parent.meshes[j].invite != null) && (parent.meshes[j].invite.codes.indexOf(command.invite.codes[i]) >= 0)) { dup = command.invite.codes[i]; break; }
2713 - }
2714 - }
2715 - if (dup != null) {
2716 - // A duplicate was found, don't allow this change.
2717 - displayNotificationMessage('Error, invite code \"' + dup + '\" already in use.', 'Invite Codes');
2718 - return;
2713 + // Check if this user has rights to do this
2714 + if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_EDITMESH) == 0) return;
2715 + if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
2716 +
2717 + if ((common.validateString(command.meshname, 1, 64) == true) && (command.meshname != mesh.name)) { change = 'Group name changed from "' + mesh.name + '" to "' + command.meshname + '"'; mesh.name = command.meshname; }
2718 + if ((common.validateString(command.desc, 0, 1024) == true) && (command.desc != mesh.desc)) { if (change != '') change += ' and description changed'; else change += 'Group "' + mesh.name + '" description changed'; mesh.desc = command.desc; }
2719 + if ((common.validateInt(command.flags) == true) && (command.flags != mesh.flags)) { if (change != '') change += ' and flags changed'; else change += 'Group "' + mesh.name + '" flags changed'; mesh.flags = command.flags; }
2720 + if ((common.validateInt(command.consent) == true) && (command.consent != mesh.consent)) { if (change != '') change += ' and consent changed'; else change += 'Group "' + mesh.name + '" consent changed'; mesh.consent = command.consent; }
2721 +
2722 + // See if we need to change device group invitation codes
2723 + if (mesh.mtype == 2) {
2724 + if (command.invite === '*') {
2725 + // Clear invite codes
2726 + if (mesh.invite != null) { delete mesh.invite; }
2727 + if (change != '') { change += ' and invite code changed'; } else { change += 'Group "' + mesh.name + '" invite code changed'; }
2728 + } else if ((typeof command.invite == 'object') && (Array.isArray(command.invite.codes)) && (typeof command.invite.flags == 'number')) {
2729 + // Set invite codes
2730 + if ((mesh.invite == null) || (mesh.invite.codes != command.invite.codes) || (mesh.invite.flags != command.invite.flags)) {
2731 + // Check if an invite code is not already in use.
2732 + var dup = null;
2733 + for (var i in command.invite.codes) {
2734 + for (var j in parent.meshes) {
2735 + if ((j != command.meshid) && (parent.meshes[j].domain == domain.id) && (parent.meshes[j].invite != null) && (parent.meshes[j].invite.codes.indexOf(command.invite.codes[i]) >= 0)) { dup = command.invite.codes[i]; break; }
2736 }
2720 - mesh.invite = { codes: command.invite.codes, flags: command.invite.flags };
2721 - if (change != '') { change += ' and invite code changed'; } else { change += 'Group "' + mesh.name + '" invite code changed'; }
2737 }
2738 + if (dup != null) {
2739 + // A duplicate was found, don't allow this change.
2740 + displayNotificationMessage('Error, invite code \"' + dup + '\" already in use.', 'Invite Codes');
2741 + return;
2742 + }
2743 + mesh.invite = { codes: command.invite.codes, flags: command.invite.flags };
2744 + if (change != '') { change += ' and invite code changed'; } else { change += 'Group "' + mesh.name + '" invite code changed'; }
2745 }
2746 }
2747 + }
2748
2726 - if (change != '') {
2727 - db.Set(mesh);
2728 - var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, flags: mesh.flags, consent: mesh.consent, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id, invite: mesh.invite };
2729 - 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.
2730 - parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(mesh, [user._id]), obj, event);
2731 - }
2749 + if (change != '') {
2750 + db.Set(mesh);
2751 + var event = { etype: 'mesh', userid: user._id, username: user.name, meshid: mesh._id, name: mesh.name, mtype: mesh.mtype, desc: mesh.desc, flags: mesh.flags, consent: mesh.consent, action: 'meshchange', links: mesh.links, msg: change, domain: domain.id, invite: mesh.invite };
2752 + 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.
2753 + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(mesh, [user._id]), obj, event);
2754 }
2755 +
2756 + if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'editmesh', responseid: command.responseid, result: 'ok' })); } catch (ex) { } }
2757 break;
2758 }
2759 case 'addmeshuser':