diff --git a/meshagent.js b/meshagent.js index a196020c..34088dfe 100644 --- a/meshagent.js +++ b/meshagent.js @@ -104,11 +104,25 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { if (cmdid == 11) { // MeshCommand_CoreModuleHash if (msg.length == 4) { ChangeAgentCoreInfo({ "caps": 0 }); } // If the agent indicated that no core is running, clear the core information string. // Mesh core hash, sent by agent with the hash of the current mesh core. - if (obj.agentCoreCheck == 1000) return; // If we are using a custom core, don't try to update it. + + // If we are using a custom core, don't try to update it. + if (obj.agentCoreCheck == 1000) { + obj.send(obj.common.ShortToStr(16) + obj.common.ShortToStr(0)); // MeshCommand_CoreOk. Indicates to the agent that the core is ok. Start it if it's not already started. + agentCoreIsStable(); + return; + } // Get the current meshcore hash const agentMeshCoreHash = (msg.length == 52) ? msg.substring(4, 52) : null; + // If the agent indicates this is a custom core, we are done. TODO: Speed up this compare. + if (Buffer.from(agentMeshCoreHash, 'binary').toString('hex') == '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000') { + obj.agentCoreCheck = 0; + obj.send(obj.common.ShortToStr(16) + obj.common.ShortToStr(0)); // MeshCommand_CoreOk. Indicates to the agent that the core is ok. Start it if it's not already started. + agentCoreIsStable(); + return; + } + // We need to check if the core is current. First, figure out what core we need. var corename = obj.parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].core; if (obj.agentCoreCheck == 1001) { corename = obj.parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].rcore; } // Use the recovery core. diff --git a/meshuser.js b/meshuser.js index 204ab0b4..126a5144 100644 --- a/meshuser.js +++ b/meshuser.js @@ -1160,43 +1160,49 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } case 'changeDeviceMesh': { - if (obj.common.validateString(command.nodeid, 1, 256) == false) break; // Check nodeid string - if (obj.common.validateString(command.meshid, 1, 256) == false) break; // Check meshid string + if (obj.common.validateStrArray(command.nodeids, 1, 256) == false) break; // Check nodeid strings + if (obj.common.validateString(command.meshid, 1, 256) == false) break; // Check target meshid string - obj.db.Get(command.nodeid, function (err, nodes) { - if (nodes.length != 1) return; - var node = nodes[0]; + // For each nodeid, change the group + for (var i = 0; i < command.nodeids.length; i++) { + obj.db.Get(command.nodeids[i], function (err, nodes) { + if (nodes.length != 1) return; + var node = nodes[0]; - // Check if already in the right mesh - if (node.meshid == command.meshid) return; + // Check if already in the right mesh + if (node.meshid == command.meshid) return; - // Make sure that we have rights on both source and destination mesh - var sourceMeshRights = user.links[node.meshid].rights; - var targetMeshRights = user.links[command.meshid].rights; - if (((sourceMeshRights & 4) == 0) || ((targetMeshRights & 4) == 0)) return; + // Make sure both source and target mesh are the same type + try { if (obj.parent.meshes[node.meshid].mtype != obj.parent.meshes[command.meshid].mtype) return; } catch (e) { return; }; - // Perform the switch, start by saving the node with the new meshid. - var oldMeshId = node.meshid; - node.meshid = command.meshid; - obj.db.Set(node); + // Make sure that we have rights on both source and destination mesh + var sourceMeshRights = user.links[node.meshid].rights; + var targetMeshRights = user.links[command.meshid].rights; + if (((sourceMeshRights & 4) == 0) || ((targetMeshRights & 4) == 0)) return; - // If the device is connected on this server, switch it now. - var agentSession = obj.parent.wsagents[command.nodeid]; - if (agentSession != null) { agentSession.dbMeshKey = command.meshid; agentSession.meshid = command.meshid.split('/')[2]; } + // Perform the switch, start by saving the node with the new meshid. + var oldMeshId = node.meshid; + node.meshid = command.meshid; + obj.db.Set(node); - // Add the connection state - var state = obj.parent.parent.GetConnectivityState(node._id); - if (state) { - node.conn = state.connectivity; - node.pwr = state.powerState; - if ((state.connectivity & 1) != 0) { var agent = obj.parent.wsagents[node._id]; if (agent != null) { node.agct = agent.connectTime; } } - if ((state.connectivity & 2) != 0) { var cira = obj.parent.parent.mpsserver.ciraConnections[node._id]; if (cira != null) { node.cict = cira.tag.connectTime; } } - } + // If the device is connected on this server, switch it now. + var agentSession = obj.parent.wsagents[node._id]; + if (agentSession != null) { agentSession.dbMeshKey = command.meshid; agentSession.meshid = command.meshid.split('/')[2]; } - // Event the node change - var newMesh = obj.parent.meshes[command.meshid]; - obj.parent.parent.DispatchEvent(['*', oldMeshId, command.meshid], obj, { etype: 'node', username: user.name, action: 'nodemeshchange', nodeid: node._id, node: node, oldMeshId: oldMeshId, newMeshId: command.meshid, msg: 'Moved device ' + node.name + ' to group ' + newMesh.name, domain: domain.id }); - }); + // Add the connection state + var state = obj.parent.parent.GetConnectivityState(node._id); + if (state) { + node.conn = state.connectivity; + node.pwr = state.powerState; + if ((state.connectivity & 1) != 0) { var agent = obj.parent.wsagents[node._id]; if (agent != null) { node.agct = agent.connectTime; } } + if ((state.connectivity & 2) != 0) { var cira = obj.parent.parent.mpsserver.ciraConnections[node._id]; if (cira != null) { node.cict = cira.tag.connectTime; } } + } + + // Event the node change + var newMesh = obj.parent.meshes[command.meshid]; + obj.parent.parent.DispatchEvent(['*', oldMeshId, command.meshid], obj, { etype: 'node', username: user.name, action: 'nodemeshchange', nodeid: node._id, node: node, oldMeshId: oldMeshId, newMeshId: command.meshid, msg: 'Moved device ' + node.name + ' to group ' + newMesh.name, domain: domain.id }); + }); + } break; } case 'removedevices': diff --git a/views/default-min.handlebars b/views/default-min.handlebars index 166d2525..943f58d4 100644 --- a/views/default-min.handlebars +++ b/views/default-min.handlebars @@ -1 +1 @@ - MeshCentral
{{{title}}}
{{{title2}}}

{{{logoutControl}}}

 

\ No newline at end of file + MeshCentral
{{{title}}}
{{{title2}}}

{{{logoutControl}}}

 

\ No newline at end of file diff --git a/views/default.handlebars b/views/default.handlebars index 5b370df2..35f39172 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -2624,7 +2624,7 @@ function groupActionFunction() { var x = "Select an operation to perform on all selected devices. Actions will be performed only with proper rights.

"; - x += addHtmlValue('Operation', ''); + x += addHtmlValue('Operation', ''); setDialogMode(2, "Group Action", 3, groupActionFunctionEx, x); } @@ -2646,6 +2646,9 @@ x += "Confirm"; setDialogMode(2, "Delete Nodes", 3, groupActionFunctionDelEx, x); QE('idx_dlgOkButton', false); + } else if (op == 102) { + // Move computers to a different group + p10showChangeGroupDialog(getCheckedDevices()); } else { // Power operation meshserver.send({ action: 'poweraction', nodeids: getCheckedDevices(), actiontype: op }); @@ -3529,7 +3532,7 @@ x = '
'; if ((meshrights & 4) != 0) { // TODO: Show change group only if there is another mesh of the same type. - x += ' Change Group'; + x += ' Change Group'; x += ' Delete Device'; } x += '
'; @@ -3795,30 +3798,30 @@ } } - function p10showChangeGroupDialog(nodeid) { - var node = getNodeFromId(nodeid); - if (xxdialogMode || (node == null)) return; - var mesh1 = meshes[node.meshid]; + function p10showChangeGroupDialog(nodeids) { + if (xxdialogMode) return; + var targetMeshId = null; + if (nodeids.length == 1) { try { targetMeshId = meshes[getNodeFromId(nodeids[0])]._id; } catch (ex) { } } // List all available alternative groups var y = ""; if (count > 0) { - var x = "Select a new group for this device

"; + var x = (nodeids.length == 1) ? "Select a new group for this device

" : "Select a new group for selected devices

"; x += addHtmlValue('New Device Group', y); - setDialogMode(2, "Change Group", 3, p10showChangeGroupDialogEx, x, nodeid); + setDialogMode(2, "Change Group", 3, p10showChangeGroupDialogEx, x, nodeids); } else { setDialogMode(2, "Change Group", 1, null, "No other device group of same type exists."); } } - function p10showChangeGroupDialogEx(b, nodeid) { - meshserver.send({ action: 'changeDeviceMesh', nodeid: nodeid, meshid: Q('p10newGroup').value }); + function p10showChangeGroupDialogEx(b, nodeids) { + meshserver.send({ action: 'changeDeviceMesh', nodeids: nodeids, meshid: Q('p10newGroup').value }); } function p10showDeleteNodeDialog(nodeid) {