diff --git a/meshagent.js b/meshagent.js index 49f85aa9..a9f009fc 100644 --- a/meshagent.js +++ b/meshagent.js @@ -214,7 +214,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { obj.sendBinary(common.ShortToStr(10) + common.ShortToStr(0)); // Command 10, ask mesh agent to clear the core } else { // Update new core - if (parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].amt == true) { + if ((parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId] != null) && (parent.parent.meshAgentsArchitectureNumbers[obj.agentInfo.agentId].amt == true)) { obj.sendBinary(common.ShortToStr(10) + common.ShortToStr(0) + parent.parent.defaultMeshCoreHash + parent.parent.defaultMeshCore); // Command 10, ask mesh agent to set the core (with MEI support) } else { obj.sendBinary(common.ShortToStr(10) + common.ShortToStr(0) + parent.parent.defaultMeshCoreNoMeiHash + parent.parent.defaultMeshCoreNoMei); // Command 10, ask mesh agent to set the core (No MEI) diff --git a/meshcentral.js b/meshcentral.js index b063d688..1796776f 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -1280,6 +1280,10 @@ function CreateMeshCentralServer(config, args) { if (obj.config.settings.autobackup && (typeof obj.config.settings.autobackup.backupintervalhours == 'number')) { setInterval(obj.db.performBackup, obj.config.settings.autobackup.backupintervalhours * 60 * 60 * 1000); } + + // Setup users that can see all device groups + obj.config.settings.managealldevicegroups = []; + for (i in obj.config.domains) { if (Array.isArray(obj.config.domains[i].managealldevicegroups)) { for (var j in obj.config.domains[i].managealldevicegroups) { if (typeof obj.config.domains[i].managealldevicegroups[j] == 'string') { obj.config.settings.managealldevicegroups.push('user/' + i + '/' + obj.config.domains[i].managealldevicegroups[j]); } } } } }); }); }; diff --git a/meshuser.js b/meshuser.js index 6d44848e..dde35c38 100644 --- a/meshuser.js +++ b/meshuser.js @@ -370,7 +370,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use try { ws.send(JSON.stringify({ action: 'serverinfo', serverinfo: serverinfo })); } catch (ex) { } // Send user information to web socket, this is the first thing we send - try { ws.send(JSON.stringify({ action: 'userinfo', userinfo: parent.CloneSafeUser(parent.users[user._id]) })); } catch (ex) { } + try { + var xuserinfo = parent.CloneSafeUser(parent.users[user._id]); + if ((user.siteadmin == 0xFFFFFFFF) && (parent.parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0)) { xuserinfo.manageAllDeviceGroups = true; } + ws.send(JSON.stringify({ action: 'userinfo', userinfo: xuserinfo })); + } catch (ex) { } if (user.siteadmin == 0xFFFFFFFF) { // Send server tracing information diff --git a/package.json b/package.json index a01c828a..cab026e8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.4.9-f", + "version": "0.4.9-h", "keywords": [ "Remote Management", "Intel AMT", diff --git a/sample-config.json b/sample-config.json index 916bf494..f765d410 100644 --- a/sample-config.json +++ b/sample-config.json @@ -81,6 +81,7 @@ "_UserNameIsEmail": true, "_NewAccountEmailDomains": [ "sample.com" ], "_NewAccountsRights": [ "nonewgroups", "notools" ], + "_ManageAllDeviceGroups": [ "admin" ], "Footer": "Twitter", "_CertUrl": "https://192.168.2.106:443/", "_PasswordRequirements": { "min": 8, "max": 128, "upper": 1, "lower": 1, "numeric": 1, "nonalpha": 1, "reset": 90, "force2factor": true, "skip2factor": "127.0.0.1,192.168.2.0/24" }, diff --git a/views/default-mobile.handlebars b/views/default-mobile.handlebars index 3a5ed3da..df0117cd 100644 --- a/views/default-mobile.handlebars +++ b/views/default-mobile.handlebars @@ -936,7 +936,7 @@ } case 'createmesh': { // A new mesh was created - if (message.event.links[userinfo._id] != null) { // Check if this is a mesh create for a mesh we own. If site administrator, we get all messages so need to ignore some. + if ((meshes[message.event.meshid] == null) && ((userinfo.manageAllDeviceGroups) || (message.event.links[userinfo._id] != null))) { // Check if this is a mesh create for a mesh we own. If site administrator, we get all messages so need to ignore some. meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links }; updateMeshes(); updateDevices(); @@ -3445,6 +3445,9 @@ if (typeof mesh == 'string') { mesh = meshes[mesh] } if ((mesh == null) || (mesh.links == null)) { return 0; } + // Check if user user + if (userinfo.manageAllDeviceGroups) return 0xFFFFFFFF; + // Check direct link permission var rights = 0, r = mesh.links[userid]; if (r != null) { @@ -3478,6 +3481,9 @@ if ((mesh == null) || (mesh.links == null)) { return false; } if (mesh.links[userid] != null) { return true; } // User has visilibity thru a direct link + // Check if user user + if (userinfo.manageAllDeviceGroups) return true; + // Check permissions thru user groups var user = null; if (userid == userinfo._id) { user = userinfo; } else { if (users != null) { user = users[userid]; } } diff --git a/views/default.handlebars b/views/default.handlebars index 1acbe725..946d87fa 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -2326,7 +2326,7 @@ } case 'createmesh': { // A new mesh was created - if ((meshes[message.event.meshid] == null) && (message.event.links[userinfo._id] != null)) { // Check if this is a mesh create for a mesh we own. If site administrator, we get all messages so need to ignore some. + if ((meshes[message.event.meshid] == null) && ((userinfo.manageAllDeviceGroups) || (message.event.links[userinfo._id] != null))) { // Check if this is a mesh create for a mesh we own. If site administrator, we get all messages so need to ignore some. meshes[message.event.meshid] = { _id: message.event.meshid, name: message.event.name, mtype: message.event.mtype, desc: message.event.desc, links: message.event.links }; masterUpdate(4 + 128 + 8192 + 16384); meshserver.send({ action: 'files' }); @@ -2399,8 +2399,6 @@ if (xxcurrentView >= 20 && xxcurrentView < 30 && currentMesh._id == message.event.meshid) { setDialogMode(0); go(2); } // If we are looking at a node in the deleted mesh, move back to "My Devices" if (xxcurrentView >= 10 && xxcurrentView < 20 && currentNode && currentNode.meshid == message.event.meshid) { setDialogMode(0); go(1); } - - console.log('deletemesh', meshes); break; } case 'addnode': { @@ -10958,6 +10956,9 @@ if (typeof mesh == 'string') { mesh = meshes[mesh] } if ((mesh == null) || (mesh.links == null)) { return 0; } + // Check if user user + if (userinfo.manageAllDeviceGroups) return 0xFFFFFFFF; + // Check direct link permission var rights = 0, r = mesh.links[userid]; if (r != null) { @@ -10991,6 +10992,9 @@ if ((mesh == null) || (mesh.links == null)) { return false; } if (mesh.links[userid] != null) { return true; } // User has visilibity thru a direct link + // Check if user user + if (userinfo.manageAllDeviceGroups) return true; + // Check permissions thru user groups var user = null; if (userid == userinfo._id) { user = userinfo; } else { if (users != null) { user = users[userid]; } } diff --git a/webserver.js b/webserver.js index ad9a53b1..e4abcc63 100644 --- a/webserver.js +++ b/webserver.js @@ -4031,7 +4031,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.GetAllMeshWithRights = function (user, rights) { if (typeof user == 'string') { user = obj.users[user]; } if ((user == null) || (user.links == null)) { return []; } + var r = []; + if ((user.siteadmin == 0xFFFFFFFF) && (parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0)) { + // This is a super user that can see all device groups for a given domain + var meshStartStr = 'mesh/' + user.domain + '/'; + for (var i in obj.meshes) { if ((obj.meshes[i]._id.startsWith(meshStartStr)) && (obj.meshes[i].deleted == null)) { r.push(obj.meshes[i]); } } + return r; + } for (var i in user.links) { if (i.startsWith('mesh/')) { // Grant access to a device group thru a direct link @@ -4062,6 +4069,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (typeof user == 'string') { user = obj.users[user]; } if ((user == null) || (user.links == null)) { return []; } var r = []; + if ((user.siteadmin == 0xFFFFFFFF) && (parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0)) { + // This is a super user that can see all device groups for a given domain + var meshStartStr = 'mesh/' + user.domain + '/'; + for (var i in obj.meshes) { if ((obj.meshes[i]._id.startsWith(meshStartStr)) && (obj.meshes[i].deleted == null)) { r.push(obj.meshes[i]._id); } } + return r; + } for (var i in user.links) { if (i.startsWith('mesh/')) { // Grant access to a device group thru a direct link @@ -4099,6 +4112,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { meshid = mesh._id; } else return 0; + // Check if this is a super user that can see all device groups for a given domain + if ((user.siteadmin == 0xFFFFFFFF) && (parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0) && (meshid.startsWith('mesh/' + user.domain + '/'))) { return 0xFFFFFFFF; } + // Check direct user to device group permissions var rights = 0; r = user.links[meshid]; @@ -4140,6 +4156,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { meshid = mesh._id; } else return false; + // Check if this is a super user that can see all device groups for a given domain + if ((user.siteadmin == 0xFFFFFFFF) && (parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0) && (meshid.startsWith('mesh/' + user.domain + '/'))) { return true; } + // Check direct user to device group permissions if (user.links[meshid] != null) { return true; } // If the user has a direct link, stop here.