Started work on local device group.

Ylian Saint-Hilaire committed Apr 27, 2021 at 13:39 UTC 8529ab86c44e230c85533ffa2d0444ad81e55d1e
3 files changed +90 -24
meshuser.js
+34 -2
@@ -2975,7 +2975,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2975 // Create mesh
2976 else if (common.validateString(command.meshname, 1, 128) == false) { err = 'Invalid group name'; } // Meshname is between 1 and 64 characters
2977 else if ((command.desc != null) && (common.validateString(command.desc, 0, 1024) == false)) { err = 'Invalid group description'; } // Mesh description is between 0 and 1024 characters
2978 - else if ((command.meshtype !== 1) && (command.meshtype !== 2)) { err = 'Invalid group type'; }
2978 + else if ((command.meshtype < 1) && (command.meshtype > 3)) { err = 'Invalid group type'; } // Device group types are 1 = AMT, 2 = Agent, 3 = Local
2979 + else if ((parent.args.wanonly == true) && (command.meshtype == 3)) { err = 'Invalid group type'; } // Local device group type is not allowed in WAN mode
2980 } catch (ex) { err = 'Validation exception: ' + ex; }
2981
2982 // Handle any errors
@@ -3615,6 +3616,37 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
3616 if (agent.dbMeshKey == command.meshid) { agent.sendUpdatedIntelAmtPolicy(amtpolicy); }
3617 }
3618 }
3619 + break;
3620 + }
3621 + case 'addlocaldevice':
3622 + {
3623 + if (args.wanonly == true) return; // This is a WAN-only server, local Intel AMT computers can't be added
3624 + if (common.validateString(command.meshid, 1, 1024) == false) break; // Check meshid
3625 + if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
3626 + if (common.validateString(command.devicename, 1, 256) == false) break; // Check device name
3627 + if (common.validateString(command.hostname, 1, 256) == false) break; // Check hostname
3628 + if ((command.type != 4) && (command.type != 6) && (command.type != 29)) break; // Check device type
3629 +
3630 + // Get the mesh
3631 + mesh = parent.meshes[command.meshid];
3632 + if (mesh) {
3633 + if (mesh.mtype != 3) return; // This operation is only allowed for mesh type 3, local device agentless mesh.
3634 +
3635 + // Check if this user has rights to do this
3636 + if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_MANAGECOMPUTERS) == 0) return;
3637 +
3638 + // Create a new nodeid
3639 + parent.crypto.randomBytes(48, function (err, buf) {
3640 + // Create the new node
3641 + nodeid = 'node/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
3642 + var device = { type: 'node', _id: nodeid, meshid: command.meshid, name: command.devicename, host: command.hostname, domain: domain.id, mtype: 3, agent: { id: command.type, caps: 0 } };
3643 + db.Set(device);
3644 +
3645 + // Event the new node
3646 + parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(command.meshid, [nodeid]), obj, { etype: 'node', userid: user._id, username: user.name, action: 'addnode', node: parent.CloneSafeNode(device), msgid: 84, msgArgs: [command.devicename, mesh.name], msg: 'Added device ' + command.devicename + ' to device group ' + mesh.name, domain: domain.id });
3647 + });
3648 + }
3649 +
3650 break;
3651 }
3652 case 'addamtdevice':
@@ -3642,7 +3674,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
3674
3675 // Create a new nodeid
3676 parent.crypto.randomBytes(48, function (err, buf) {
3645 - // create the new node
3677 + // Create the new node
3678 nodeid = 'node/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
3679 var device = { type: 'node', _id: nodeid, meshid: command.meshid, name: command.devicename, host: command.hostname, domain: domain.id, intelamt: { user: command.amtusername, pass: command.amtpassword, tls: command.amttls } };
3680 db.Set(device);
views/default-mobile.handlebars
+3 -3
@@ -3397,7 +3397,7 @@
3397
3398 x += '</table><br />';
3399 // Show action button, only show if we have permissions 4, 8, 64
3400 - if ((meshrights & (4 + 8 + 64)) != 0) { x += '<input type=button value="' + "Actions" + '" onclick=deviceActionFunction() />'; }
3400 + if (((meshrights & (4 + 8 + 64)) != 0) && (node.mtype != 3)) { x += '<input type=button value="' + "Actions" + '" onclick=deviceActionFunction() />'; }
3401 x += '<input type=button value=Notes onclick=showNotes(' + ((meshrights & 128) == 0) + ',"' + encodeURIComponent(node._id) + '") />';
3402 //if ((connectivity & 1) && (meshrights & 8) && (node.agent.id < 5)) { x += '<input type=button value=Toast onclick=deviceToastFunction() />'; }
3403
@@ -3496,8 +3496,8 @@
3496 ) { menus.push({ n: "Terminal", f: 'setupDeviceMenu(5)' }); }
3497
3498 if ((currentDevicePanel != 2) && (currentNode != null) && (meshrights & 8) && ((meshrights == 0xFFFFFFFF) || ((meshrights & 1024) == 0)) && ((currentNode.mtype == 2) && (currentNode.agent.caps & 4))) { menus.push({ n: "Files", f: 'setupDeviceMenu(2)' }); }
3499 - if ((currentDevicePanel != 3) && (currentNode != null)) { menus.push({ n: "Details", f: 'setupDeviceMenu(3)' }); }
3500 - if ((currentDevicePanel != 4) && (currentNode != null) && (meshrights & 0x00000010)) { menus.push({ n: "Console", f: 'setupDeviceMenu(4)' }); }
3499 + if ((currentDevicePanel != 3) && (currentNode != null) && (currentNode.mtype != 3)) { menus.push({ n: "Details", f: 'setupDeviceMenu(3)' }); }
3500 + if ((currentDevicePanel != 4) && (currentNode != null) && (meshrights & 0x00000010) && (currentNode.mtype == 2)) { menus.push({ n: "Console", f: 'setupDeviceMenu(4)' }); }
3501 updateFooterMenu(menus);
3502 updateCurrentUrl();
3503 if (currentDevicePanel == 1) { deskAdjust(); }
views/default.handlebars
+53 -19
@@ -3695,6 +3695,7 @@
3695 var extra = '';
3696 if (view == 2) { r += '<tr><td colspan=5>'; }
3697 if (meshes[node.meshid] && (meshes[node.meshid].mtype == 1)) { extra = '<span class=devHeaderx>' + ", Intel&reg; AMT only" + '</span>'; }
3698 + if (meshes[node.meshid] && (meshes[node.meshid].mtype == 3)) { extra = '<span class=devHeaderx>' + ", Local Devices" + '</span>'; }
3699 if ((view == 1) && (current != null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
3700 if (view == 2) { r += '<div>'; }
3701 r += '<div class=DevSt style=width:100%;padding-top:4px><span style=float:right>';
@@ -3849,13 +3850,16 @@
3850 r += getMeshActions(mesh, meshrights);
3851 r += '</span></td></tr><tr>';
3852 if (mesh.mtype == 1) {
3852 - r += '<td><div style=padding:10px><i>' + "No Intel&reg; AMT devices in this mesh";
3853 + r += '<td><div style=padding:10px><i>' + "No Intel&reg; AMT devices in this device group";
3854 if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addDeviceToMesh("' + mesh._id + '")\'>' + "add one" + '</a>'; }
3855 } else if (mesh.mtype == 2) {
3856 r += '<td>';
3857 r += '<div id=DevxCol' + deviceHeaderId2 + ((collapsed === true)?' style=display:none':'') + '>'; // Open collapse div
3857 - r += '<div style=padding:10px><i>' + "No devices in this group";
3858 + r += '<div style=padding:10px><i>' + "No devices in this device group";
3859 if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addAgentToMesh("' + mesh._id + '")\'>' + "add one" + '</a>'; }
3860 + } else if (mesh.mtype == 3) {
3861 + r += '<td><div style=padding:10px><i>' + "No local devices in this device group";
3862 + if ((meshrights & 4) != 0) { r += ', <a href=# style=cursor:pointer onclick=\'return addLocalDeviceToMesh("' + mesh._id + '")\'>' + "add one" + '</a>'; }
3863 }
3864 r += '.</i></div></td>';
3865 r += '</div>'; // End collapsing area
@@ -4418,16 +4422,41 @@
4422 r += ' <a href=# style=cursor:pointer;font-size:small title="' + "Perform Intel&reg; AMT activation and configuration." + '" onclick=\'return showAmtSetup("' + mesh._id + '")\'>' + "Setup" + '</a>';
4423 }
4424 }
4421 - if (mesh.mtype == 2) {
4425 + if (mesh.mtype == 2) { // Agent device group
4426 r += ' <a href=# style=cursor:pointer;font-size:small title="' + "Add a new computer to this device group by installing the mesh agent." + '" onclick=\'return addAgentToMesh("' + mesh._id + '")\'>' + "Add Agent" + '</a>';
4427 if ((features & 2) == 0) { r += ' <a href=# style=cursor:pointer;font-size:small title="' + "Invite someone to install the mesh agent on this device group." + '" onclick=\'return inviteAgentToMesh("' + mesh._id + '")\'>' + "Invite" + '</a>'; }
4428 }
4429 + if ((mesh.mtype == 3) && ((features & 1) == 0)) { // Local device group & if not WAN-Only
4430 + r += ' <a href=# style=cursor:pointer;font-size:small title="' + "Add device located on the local network." + '" onclick=\'return addLocalDeviceToMesh("' + mesh._id + '")\'>' + "Add Device" + '</a>';
4431 + }
4432 //if (mesh.amt && (mesh.amt.type > 2)) { // ACM activation or Full Automatic
4433 // r += ' <a href=# style=cursor:pointer;font-size:small title="' + "Switch Intel AMT to Admin Control Mode (ACM)." + '" onclick=\'return showAmtAcmSetup()\'>' + "ACM" + '</a>';
4434 //}
4435 return r;
4436 }
4437
4438 + function addLocalDeviceToMesh(meshid) {
4439 + if (xxdialogMode) return false;
4440 + var mesh = meshes[meshid];
4441 + var x = format("Add a local device to device group \"{0}\".", EscapeHtml(mesh.name)) + '<br /><br />';
4442 + x += addHtmlValue("Device Name", '<input id=dp1devicename style=width:230px maxlength=32 autocomplete=off onchange=validateLocalDeviceToMesh() onkeyup=validateLocalDeviceToMesh() />');
4443 + x += addHtmlValue("Hostname", '<input id=dp1hostname style=width:230px maxlength=32 autocomplete=off placeholder="' + "Same as device name" + '" onchange=validateLocalDeviceToMesh() onkeyup=validateLocalDeviceToMesh() />');
4444 + x += addHtmlValue("Type", '<select id=dp1type style=width:236px><option value=4>' + "Windows (RDP)" + '</option><option value=6>' + "Linux (SSH/SCP/VNC)" + '</option><option value=29>' + "macOS (SSH/SCP/VNC)" + '</option></select>');
4445 + setDialogMode(2, "Add local device", 3, addLocalDeviceToMeshEx, x, meshid);
4446 + validateLocalDeviceToMesh();
4447 + Q('dp1devicename').focus();
4448 + }
4449 +
4450 + function validateLocalDeviceToMesh() {
4451 + QE('idx_dlgOkButton', Q('dp1devicename').value.length > 0);
4452 + }
4453 +
4454 + function addLocalDeviceToMeshEx(button, meshid) {
4455 + var host = Q('dp1hostname').value;
4456 + if (host == '') host = Q('dp1devicename').value;
4457 + meshserver.send({ action: 'addlocaldevice', meshid: meshid, devicename: Q('dp1devicename').value, hostname: host, type: Q('dp1type').value });
4458 + }
4459 +
4460 function addDeviceToMesh(meshid) {
4461 if (xxdialogMode) return false;
4462 var mesh = meshes[meshid];
@@ -6284,7 +6313,7 @@
6313 if (node.users && node.conn && (node.users.length > 0) && (node.conn & 1)) { x += addDeviceAttribute(((node.users.length > 1)?'Active Users':'Active User'), EscapeHtml(node.users.join(', '))); }
6314
6315 // Display device user consent
6287 - if ((node.agent != null) && (node.agent.id != 14)) {
6316 + if ((node.agent != null) && (node.agent.id != 14) && (node.mtype != 3)) {
6317 var meshFeatures = [];
6318 var consent = 0;
6319 if (node.consent) { consent = node.consent; }
@@ -6323,7 +6352,7 @@
6352
6353 x += '</table><br />';
6354 // Show action button, only show if we have permissions 4, 8, 64
6326 - if ((meshrights & (4 + 8 + 64)) != 0) { x += '<input type=button value="' + "Actions" + '" title="' + "Perform power actions on the device" + '" onclick=deviceActionFunction() />'; }
6355 + if (((meshrights & (4 + 8 + 64)) != 0) && (node.mtype != 3)) { x += '<input type=button value="' + "Actions" + '" title="' + "Perform power actions on the device" + '" onclick=deviceActionFunction() />'; }
6356 x += '<input type=button value="' + "Notes" + '" title="' + "View notes about this device" + '" onclick=showNotes(' + ((meshrights & 128) == 0) + ',"' + encodeURIComponentEx(node._id) + '") />';
6357 x += '<input type=button value="' + "Log Event" + '" title="' + "Write an event for this device" + '" onclick=writeDeviceEvent("' + encodeURIComponentEx(node._id) + '") />';
6358 if ((meshrights & 8) && ((connectivity & 1) || ((node.pmt == 1) && ((features2 & 2) != 0)))) { x += '<input type=button value="' + "Message" + '" title="' + "Display a text message on the remote device" + '" onclick=deviceMessageFunction() />'; }
@@ -6364,7 +6393,7 @@
6393 x += '&nbsp;<a href=# onclick=p10showDeleteNodeDialog("' + node._id + '") title="' + "Remove this device" + '">' + "Delete Device" + '</a>';
6394 }
6395 x += '</div><div class="p10html3left">';
6367 - if (node.agent) x += '<a href=# onclick=p10showNodeNetInfoDialog("' + node._id + '") title="' + "Show device network interface information" + '">' + "Interfaces" + '</a>&nbsp;';
6396 + if ((node.agent) && (node.mtype != 3)) x += '<a href=# onclick=p10showNodeNetInfoDialog("' + node._id + '") title="' + "Show device network interface information" + '">' + "Interfaces" + '</a>&nbsp;';
6397 if ((features & 0x00008000) && (xxmap != null)) x += '<a href=# onclick=p10showNodeLocationDialog("' + node._id + '") title="' + "Show device locations information" + '">' + "Location" + '</a>&nbsp;';
6398 if ((userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.siteadmin & 128) == 0)) { // Check if we should view tools
6399 if ((terminalAccess) && ((meshrights & 8) != 0) && (node.agent != null) && (node.agent.id != 14)) x += '<a href=# onclick=p10showMeshCmdDialog(1,"' + node._id + '") title="' + "Traffic router used to connect to a device thru this server" + '.">' + "MeshCmd" + '</a>&nbsp;';
@@ -6445,7 +6474,7 @@
6474 if (consoleRights) { setupConsole(); } else { if (panel == 15) { panel = 10; } }
6475
6476 // Show or hide the tabs
6448 - // mesh.mtype: 1 = Intel AMT only, 2 = Mesh Agent
6477 + // mesh.mtype: 1 = Intel AMT only, 2 = Mesh Agent, 3 = Local Device
6478 // node.agent.caps (bitmask): 1 = Desktop, 2 = Terminal, 4 = Files, 8 = Console
6479 QV('MainDevDesktop', desktopAccess && ((((node.agent == null) && ((typeof node.intelamt.sku !== 'number') || ((node.intelamt.sku & 8) != 0)))
6480 || ((node.agent != null) && ((node.agent.caps == null) || ((node.agent.caps & 1) != 0) || (node.intelamt && (node.intelamt.state == 2)))))
@@ -6453,6 +6482,7 @@
6482 );
6483 QV('MainDevTerminal', (((node.agent == null) && (node.intelamt != null)) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0) || (node.intelamt && (node.intelamt.state == 2))) && (meshrights & 8) && terminalAccess);
6484 QV('MainDevFiles', (node.agent != null) && (node.agent.caps != null) && ((node.agent.caps & 4) != 0) && (meshrights & 8) && fileAccess);
6485 + QV('MainDevInfo', (node.mtype != 3));
6486 QV('MainDevAmt', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (meshrights & 8) && amtAccess);
6487 QV('MainDevConsole', (consoleRights && ((node.agent != null) && (node.agent.caps != null) && ((node.agent.caps & 8) != 0))) && (meshrights & 8));
6488 QV('MainDevPlugins', false);
@@ -10354,9 +10384,10 @@
10384 if ((features & 0x00040000) && (count2factoraAuths() == 0)) { setDialogMode(2, "Account Security", 1, null, "Unable to access this feature until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" tab and look at the \"Account Security\" section."); return false; }
10385
10386 // We are allowed, let's prompt to information
10357 - var x = "Create a new device group using the options below." + '<br /><br />';
10387 + var x = "Create a new device group using the options below." + '<br /><br />', localGroupType = '';
10388 x += addHtmlValue("Name", '<input id=dp2meshname style=width:230px maxlength=128 onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate(event,1) />');
10359 - x += addHtmlValue("Type", '<div style=width:230px;margin:0;padding:0><select id=dp2meshtype style=width:100% onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate(event,2) ><option value=2>' + "Manage using a software agent" + '</option><option value=1>' + "Intel&reg; AMT only, no agent" + '</option></select></div>');
10389 + if ((features & 1) == 0) { localGroupType += '<option value=3>' + "Local devices, no agent" + '</option>'; }
10390 + x += addHtmlValue("Type", '<div style=width:230px;margin:0;padding:0><select id=dp2meshtype style=width:100% onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate(event,2) ><option value=2>' + "Manage using a software agent" + '</option><option value=1>' + "Intel&reg; AMT only, no agent" + '</option>' + localGroupType + '</select></div>');
10391 x += addHtmlValue("Description", '<div style=width:230px;margin:0;padding:0><textarea id=dp2meshdesc maxlength=1024 style=width:100%;resize:none></textarea></div>');
10392 setDialogMode(2, "New Device Group", 3, account_createMeshEx, x);
10393 account_validateMeshCreate();
@@ -10585,6 +10616,7 @@
10616 var meshtype = format("Unknown #{0}", currentMesh.mtype);
10617 if (currentMesh.mtype == 1) meshtype = "Intel&reg; AMT only, no agent";
10618 if (currentMesh.mtype == 2) meshtype = "Managed using a software agent";
10619 + if (currentMesh.mtype == 3) meshtype = "Local devices, no agent";
10620
10621 var x = '';
10622 if ((args.hide & 8) != 0) { x += addHtmlValue("Name", mname); } // If title bar is hidden, display the mesh name here
@@ -10635,15 +10667,17 @@
10667 x += addHtmlValue("User Consent", addLinkConditional(meshFeatures, 'p20editmeshconsent(1)', meshrights & 1));
10668 }
10669
10638 - if ((userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.siteadmin & 1024) == 0)) {
10639 - // Display user notification
10640 - var meshNotify = 0, meshNotifyStr = [];
10641 - if (userinfo.links && userinfo.links[currentMesh._id] && userinfo.links[currentMesh._id].notify) { meshNotify = userinfo.links[currentMesh._id].notify; }
10642 - if (meshNotify & 2) { meshNotifyStr.push("Connect"); }
10643 - if (meshNotify & 4) { meshNotifyStr.push("Disconnect"); }
10644 - if (meshNotify & 8) { meshNotifyStr.push("Intel&reg; AMT"); }
10645 - if (meshNotifyStr.length == 0) { meshNotifyStr.push('<i>' + "None" + '</i>'); }
10646 - x += addHtmlValue("Notifications", addLink(meshNotifyStr.join(', '), 'p20editMeshNotify()'));
10670 + if (currentMesh.mtype != 3) {
10671 + if ((userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.siteadmin & 1024) == 0)) {
10672 + // Display user notification
10673 + var meshNotify = 0, meshNotifyStr = [];
10674 + if (userinfo.links && userinfo.links[currentMesh._id] && userinfo.links[currentMesh._id].notify) { meshNotify = userinfo.links[currentMesh._id].notify; }
10675 + if (meshNotify & 2) { meshNotifyStr.push("Connect"); }
10676 + if (meshNotify & 4) { meshNotifyStr.push("Disconnect"); }
10677 + if (meshNotify & 8) { meshNotifyStr.push("Intel&reg; AMT"); }
10678 + if (meshNotifyStr.length == 0) { meshNotifyStr.push('<i>' + "None" + '</i>'); }
10679 + x += addHtmlValue("Notifications", addLink(meshNotifyStr.join(', '), 'p20editMeshNotify()'));
10680 + }
10681 }
10682
10683 // Display invitation codes
@@ -10654,7 +10688,7 @@
10688 }
10689
10690 // If the Intel AMT manager is active on the server, show the Intel AMT policy edit box.
10657 - if ((features2 & 1) != 0) {
10691 + if ((currentMesh.mtype != 3) && ((features2 & 1) != 0)) {
10692 // Intel AMT setup
10693 var intelAmtPolicy = "No Policy";
10694 if (currentMesh.amt) {