More access control improvements, RPi icon.
|
@ -1919,13 +1919,10 @@ function createMeshCore(agent) {
|
|||
switch (cmd) {
|
||||
case 'help': { // Displays available commands
|
||||
var fin = '', f = '', availcommands = 'version,help,info,osinfo,args,print,type,dbkeys,dbget,dbset,dbcompact,eval,parseuri,httpget,nwslist,plugin,wsconnect,wssend,wsclose,notify,ls,ps,kill,amt,netinfo,location,power,wakeonlan,setdebug,smbios,rawsmbios,toast,lock,users,sendcaps,openurl,amtreset,amtccm,amtacm,amtdeactivate,amtpolicy,getscript,getclip,setclip,log,av,cpuinfo,sysinfo,apf,scanwifi,scanamt,wallpaper';
|
||||
if (process.platform == 'win32')
|
||||
{
|
||||
availcommands += ',safemode,wpfhwacceleration';
|
||||
}
|
||||
if (process.platform == 'win32') { availcommands += ',safemode,wpfhwacceleration'; }
|
||||
availcommands = availcommands.split(',').sort();
|
||||
while (availcommands.length > 0) {
|
||||
if (f.length > 100) { fin += (f + ',\r\n'); f = ''; }
|
||||
if (f.length > 90) { fin += (f + ',\r\n'); f = ''; }
|
||||
f += (((f != '') ? ', ' : ' ') + availcommands.shift());
|
||||
}
|
||||
if (f != '') { fin += f; }
|
||||
|
|
|
@ -12,10 +12,10 @@
|
|||
/*jshint node: true */
|
||||
/*jshint strict: false */
|
||||
/*jshint esversion: 6 */
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
const crypto = require("crypto");
|
||||
const common = require("./common.js");
|
||||
const crypto = require('crypto');
|
||||
const common = require('./common.js');
|
||||
|
||||
var HttpInterceptorAuthentications = {};
|
||||
//var RedirInterceptorAuthentications = {};
|
||||
|
@ -28,8 +28,8 @@ module.exports.CreateHttpInterceptor = function (args) {
|
|||
obj.randomValueHex = function (len) { return crypto.randomBytes(Math.ceil(len / 2)).toString('hex').slice(0, len); };
|
||||
|
||||
obj.args = args;
|
||||
obj.amt = { acc: "", mode: 0, count: 0, error: false }; // mode: 0:Header, 1:LengthBody, 2:ChunkedBody, 3:UntilClose
|
||||
obj.ws = { acc: "", mode: 0, count: 0, error: false, authCNonce: obj.randomValueHex(10), authCNonceCount: 1 };
|
||||
obj.amt = { acc: '', mode: 0, count: 0, error: false }; // mode: 0:Header, 1:LengthBody, 2:ChunkedBody, 3:UntilClose
|
||||
obj.ws = { acc: '', mode: 0, count: 0, error: false, authCNonce: obj.randomValueHex(10), authCNonceCount: 1 };
|
||||
obj.blockAmtStorage = false;
|
||||
|
||||
// Private method
|
||||
|
@ -38,7 +38,7 @@ module.exports.CreateHttpInterceptor = function (args) {
|
|||
// Process data coming from Intel AMT
|
||||
obj.processAmtData = function (data) {
|
||||
obj.amt.acc += data; // Add data to accumulator
|
||||
data = "";
|
||||
data = '';
|
||||
var datalen = 0;
|
||||
do {
|
||||
datalen = data.length;
|
||||
|
@ -53,7 +53,7 @@ module.exports.CreateHttpInterceptor = function (args) {
|
|||
if (obj.amt.mode == 0) { // Header Mode
|
||||
// Decode the HTTP header
|
||||
headerend = obj.amt.acc.indexOf('\r\n\r\n');
|
||||
if (headerend < 0) return "";
|
||||
if (headerend < 0) return '';
|
||||
var headerlines = obj.amt.acc.substring(0, headerend).split('\r\n');
|
||||
obj.amt.acc = obj.amt.acc.substring(headerend + 4);
|
||||
obj.amt.directive = headerlines[0].split(' ');
|
||||
|
@ -98,7 +98,7 @@ module.exports.CreateHttpInterceptor = function (args) {
|
|||
} else if (obj.amt.mode == 2) { // Chunked Body Mode
|
||||
// Send data one chunk at a time
|
||||
headerend = obj.amt.acc.indexOf('\r\n');
|
||||
if (headerend < 0) return "";
|
||||
if (headerend < 0) return '';
|
||||
var chunksize = parseInt(obj.amt.acc.substring(0, headerend), 16);
|
||||
if ((chunksize == 0) && (obj.amt.acc.length >= headerend + 4)) {
|
||||
// Send the ending chunk (NOTE: We do not support trailing headers)
|
||||
|
@ -114,16 +114,16 @@ module.exports.CreateHttpInterceptor = function (args) {
|
|||
}
|
||||
} else if (obj.amt.mode == 3) { // Until Close Mode
|
||||
r = obj.amt.acc;
|
||||
obj.amt.acc = "";
|
||||
obj.amt.acc = '';
|
||||
return r;
|
||||
}
|
||||
return "";
|
||||
return '';
|
||||
};
|
||||
|
||||
// Process data coming from the Browser
|
||||
obj.processBrowserData = function (data) {
|
||||
obj.ws.acc += data; // Add data to accumulator
|
||||
data = "";
|
||||
data = '';
|
||||
var datalen = 0;
|
||||
do {
|
||||
datalen = data.length;
|
||||
|
@ -138,7 +138,7 @@ module.exports.CreateHttpInterceptor = function (args) {
|
|||
if (obj.ws.mode == 0) { // Header Mode
|
||||
// Decode the HTTP header
|
||||
headerend = obj.ws.acc.indexOf('\r\n\r\n');
|
||||
if (headerend < 0) return "";
|
||||
if (headerend < 0) return '';
|
||||
var headerlines = obj.ws.acc.substring(0, headerend).split('\r\n');
|
||||
obj.ws.acc = obj.ws.acc.substring(headerend + 4);
|
||||
obj.ws.directive = headerlines[0].split(' ');
|
||||
|
@ -199,7 +199,7 @@ module.exports.CreateHttpInterceptor = function (args) {
|
|||
} else if (obj.amt.mode == 2) { // Chunked Body Mode
|
||||
// Send data one chunk at a time
|
||||
headerend = obj.amt.acc.indexOf('\r\n');
|
||||
if (headerend < 0) return "";
|
||||
if (headerend < 0) return '';
|
||||
var chunksize = parseInt(obj.amt.acc.substring(0, headerend), 16);
|
||||
if (isNaN(chunksize)) { // TODO: Check this path
|
||||
// Chunk is not in this batch, move one
|
||||
|
@ -226,10 +226,10 @@ module.exports.CreateHttpInterceptor = function (args) {
|
|||
}
|
||||
} else if (obj.ws.mode == 3) { // Until Close Mode
|
||||
r = obj.ws.acc;
|
||||
obj.ws.acc = "";
|
||||
obj.ws.acc = '';
|
||||
return r;
|
||||
}
|
||||
return "";
|
||||
return '';
|
||||
};
|
||||
|
||||
// Parse authentication values from the HTTP header
|
||||
|
@ -249,9 +249,9 @@ module.exports.CreateHttpInterceptor = function (args) {
|
|||
|
||||
// Compute the MD5 digest hash for a set of values
|
||||
obj.ComputeDigesthash = function (username, password, realm, method, path, qop, nonce, nc, cnonce) {
|
||||
var ha1 = crypto.createHash('md5').update(username + ":" + realm + ":" + password).digest("hex");
|
||||
var ha2 = crypto.createHash('md5').update(method + ":" + path).digest("hex");
|
||||
return crypto.createHash('md5').update(ha1 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + ha2).digest("hex");
|
||||
var ha1 = crypto.createHash('md5').update(username + ':' + realm + ':' + password).digest('hex');
|
||||
var ha2 = crypto.createHash('md5').update(method + ':' + path).digest('hex');
|
||||
return crypto.createHash('md5').update(ha1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2).digest('hex');
|
||||
};
|
||||
|
||||
return obj;
|
||||
|
@ -266,8 +266,8 @@ module.exports.CreateRedirInterceptor = function (args) {
|
|||
obj.randomValueHex = function (len) { return crypto.randomBytes(Math.ceil(len / 2)).toString('hex').slice(0, len); };
|
||||
|
||||
obj.args = args;
|
||||
obj.amt = { acc: "", mode: 0, count: 0, error: false, direct: false };
|
||||
obj.ws = { acc: "", mode: 0, count: 0, error: false, direct: false, authCNonce: obj.randomValueHex(10), authCNonceCount: 1 };
|
||||
obj.amt = { acc: '', mode: 0, count: 0, error: false, direct: false };
|
||||
obj.ws = { acc: '', mode: 0, count: 0, error: false, direct: false, authCNonce: obj.randomValueHex(10), authCNonceCount: 1 };
|
||||
|
||||
obj.RedirectCommands = { StartRedirectionSession: 0x10, StartRedirectionSessionReply: 0x11, EndRedirectionSession: 0x12, AuthenticateSession: 0x13, AuthenticateSessionReply: 0x14 };
|
||||
obj.StartRedirectionSessionReplyStatus = { SUCCESS: 0, TYPE_UNKNOWN: 1, BUSY: 2, UNSUPPORTED: 3, ERROR: 0xFF };
|
||||
|
@ -280,7 +280,7 @@ module.exports.CreateRedirInterceptor = function (args) {
|
|||
// Process data coming from Intel AMT
|
||||
obj.processAmtData = function (data) {
|
||||
obj.amt.acc += data; // Add data to accumulator
|
||||
data = "";
|
||||
data = '';
|
||||
var datalen = 0;
|
||||
do { datalen = data.length; data += obj.processAmtDataEx(); } while (datalen != data.length); // Process as much data as possible
|
||||
return data;
|
||||
|
@ -298,11 +298,11 @@ module.exports.CreateRedirInterceptor = function (args) {
|
|||
//console.log(obj.amt.acc.charCodeAt(0));
|
||||
switch (obj.amt.acc.charCodeAt(0)) {
|
||||
case obj.RedirectCommands.StartRedirectionSessionReply: {
|
||||
if (obj.amt.acc.length < 4) return "";
|
||||
if (obj.amt.acc.length < 4) return '';
|
||||
if (obj.amt.acc.charCodeAt(1) == obj.StartRedirectionSessionReplyStatus.SUCCESS) {
|
||||
if (obj.amt.acc.length < 13) return "";
|
||||
if (obj.amt.acc.length < 13) return '';
|
||||
var oemlen = obj.amt.acc.charCodeAt(12);
|
||||
if (obj.amt.acc.length < 13 + oemlen) return "";
|
||||
if (obj.amt.acc.length < 13 + oemlen) return '';
|
||||
r = obj.amt.acc.substring(0, 13 + oemlen);
|
||||
obj.amt.acc = obj.amt.acc.substring(13 + oemlen);
|
||||
return r;
|
||||
|
@ -310,9 +310,9 @@ module.exports.CreateRedirInterceptor = function (args) {
|
|||
break;
|
||||
}
|
||||
case obj.RedirectCommands.AuthenticateSessionReply: {
|
||||
if (obj.amt.acc.length < 9) return "";
|
||||
if (obj.amt.acc.length < 9) return '';
|
||||
var l = common.ReadIntX(obj.amt.acc, 5);
|
||||
if (obj.amt.acc.length < 9 + l) return "";
|
||||
if (obj.amt.acc.length < 9 + l) return '';
|
||||
var authstatus = obj.amt.acc.charCodeAt(1);
|
||||
var authType = obj.amt.acc.charCodeAt(4);
|
||||
|
||||
|
@ -337,17 +337,17 @@ module.exports.CreateRedirInterceptor = function (args) {
|
|||
}
|
||||
default: {
|
||||
obj.amt.error = true;
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
return '';
|
||||
};
|
||||
|
||||
// Process data coming from the Browser
|
||||
obj.processBrowserData = function (data) {
|
||||
obj.ws.acc += data; // Add data to accumulator
|
||||
data = "";
|
||||
data = '';
|
||||
var datalen = 0;
|
||||
do { datalen = data.length; data += obj.processBrowserDataEx(); } while (datalen != data.length); // Process as much data as possible
|
||||
return data;
|
||||
|
@ -356,39 +356,39 @@ module.exports.CreateRedirInterceptor = function (args) {
|
|||
// Process data coming from the Browser in the accumulator
|
||||
obj.processBrowserDataEx = function () {
|
||||
var r;
|
||||
if (obj.ws.acc.length == 0) return "";
|
||||
if (obj.ws.acc.length == 0) return '';
|
||||
if (obj.ws.direct == true) {
|
||||
var data = obj.ws.acc;
|
||||
obj.ws.acc = "";
|
||||
obj.ws.acc = '';
|
||||
return data;
|
||||
} else {
|
||||
switch (obj.ws.acc.charCodeAt(0)) {
|
||||
case obj.RedirectCommands.StartRedirectionSession: {
|
||||
if (obj.ws.acc.length < 8) return "";
|
||||
if (obj.ws.acc.length < 8) return '';
|
||||
r = obj.ws.acc.substring(0, 8);
|
||||
obj.ws.acc = obj.ws.acc.substring(8);
|
||||
return r;
|
||||
}
|
||||
case obj.RedirectCommands.EndRedirectionSession: {
|
||||
if (obj.ws.acc.length < 4) return "";
|
||||
if (obj.ws.acc.length < 4) return '';
|
||||
r = obj.ws.acc.substring(0, 4);
|
||||
obj.ws.acc = obj.ws.acc.substring(4);
|
||||
return r;
|
||||
}
|
||||
case obj.RedirectCommands.AuthenticateSession: {
|
||||
if (obj.ws.acc.length < 9) return "";
|
||||
if (obj.ws.acc.length < 9) return '';
|
||||
var l = common.ReadIntX(obj.ws.acc, 5);
|
||||
if (obj.ws.acc.length < 9 + l) return "";
|
||||
if (obj.ws.acc.length < 9 + l) return '';
|
||||
|
||||
var authType = obj.ws.acc.charCodeAt(4);
|
||||
if (authType == obj.AuthenticationType.DIGEST && obj.args.user && obj.args.pass) {
|
||||
var authurl = "/RedirectionService";
|
||||
var authurl = '/RedirectionService';
|
||||
if (obj.amt.digestRealm) {
|
||||
// Replace this authentication digest with a server created one
|
||||
// We have everything we need to authenticate
|
||||
var nc = obj.ws.authCNonceCount;
|
||||
obj.ws.authCNonceCount++;
|
||||
var digest = obj.ComputeDigesthash(obj.args.user, obj.args.pass, obj.amt.digestRealm, "POST", authurl, obj.amt.digestQOP, obj.amt.digestNonce, nc, obj.ws.authCNonce);
|
||||
var digest = obj.ComputeDigesthash(obj.args.user, obj.args.pass, obj.amt.digestRealm, 'POST', authurl, obj.amt.digestQOP, obj.amt.digestNonce, nc, obj.ws.authCNonce);
|
||||
|
||||
// Replace this authentication digest with a server created one
|
||||
// We have everything we need to authenticate
|
||||
|
@ -434,18 +434,18 @@ module.exports.CreateRedirInterceptor = function (args) {
|
|||
}
|
||||
default: {
|
||||
obj.ws.error = true;
|
||||
return "";
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
return '';
|
||||
};
|
||||
|
||||
// Compute the MD5 digest hash for a set of values
|
||||
obj.ComputeDigesthash = function (username, password, realm, method, path, qop, nonce, nc, cnonce) {
|
||||
var ha1 = crypto.createHash('md5').update(username + ":" + realm + ":" + password).digest("hex");
|
||||
var ha2 = crypto.createHash('md5').update(method + ":" + path).digest("hex");
|
||||
return crypto.createHash('md5').update(ha1 + ":" + nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + ha2).digest("hex");
|
||||
var ha1 = crypto.createHash('md5').update(username + ':' + realm + ':' + password).digest('hex');
|
||||
var ha2 = crypto.createHash('md5').update(method + ':' + path).digest('hex');
|
||||
return crypto.createHash('md5').update(ha1 + ':' + nonce + ':' + nc + ':' + cnonce + ':' + qop + ':' + ha2).digest('hex');
|
||||
};
|
||||
|
||||
return obj;
|
||||
|
|
|
@ -80,7 +80,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
|||
var agent = parent.wsagents[command.nodeid];
|
||||
if (agent != null) {
|
||||
// Check if we have permission to send a message to that node
|
||||
rights = user.links[agent.dbMeshKey];
|
||||
rights = user.links[agent.dbMeshKey]; // TODO: Need to include user group / node rights
|
||||
mesh = parent.meshes[agent.dbMeshKey];
|
||||
if ((rights != null) && (mesh != null) || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking
|
||||
if (ws.sessionId) { command.sessionid = ws.sessionId; } // Set the session id, required for responses.
|
||||
|
@ -98,7 +98,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
|
|||
var routing = parent.parent.GetRoutingServerId(command.nodeid, 1); // 1 = MeshAgent routing type
|
||||
if (routing != null) {
|
||||
// Check if we have permission to send a message to that node
|
||||
rights = user.links[routing.meshid];
|
||||
rights = user.links[routing.meshid]; // TODO: Need to include user groups / node rights
|
||||
mesh = parent.meshes[routing.meshid];
|
||||
if (rights != null || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking
|
||||
if (ws.sessionId) { command.fromSessionid = ws.sessionId; } // Set the session id, required for responses.
|
||||
|
|
484
meshuser.js
|
@ -152,7 +152,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
var agent = parent.wsagents[command.nodeid];
|
||||
if (agent != null) {
|
||||
// Check if we have permission to send a message to that node
|
||||
var meshrights = parent.GetMeshRights(user, agent.dbMeshKey);
|
||||
var meshrights = parent.GetMeshRights(user, agent.dbMeshKey); // TODO: We will need to get the rights for this specific node.
|
||||
var mesh = parent.meshes[agent.dbMeshKey];
|
||||
if ((mesh != null) && ((meshrights & MESHRIGHT_REMOTECONTROL) || (meshrights & MESHRIGHT_REMOTEVIEWONLY))) { // 8 is remote control permission, 256 is desktop read only
|
||||
command.sessionid = ws.sessionId; // Set the session id, required for responses
|
||||
|
@ -503,20 +503,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
}
|
||||
case 'powertimeline':
|
||||
{
|
||||
// Perform pre-validation
|
||||
if (common.validateString(command.nodeid, 0, 128) == false) break;
|
||||
var snode = command.nodeid.split('/');
|
||||
if ((snode.length != 3) || (snode[1] != domain.id)) break;
|
||||
|
||||
// Check that we have permissions for this node.
|
||||
db.Get(command.nodeid, function (err, nodes) {
|
||||
if (nodes == null || nodes.length != 1) return;
|
||||
const node = nodes[0];
|
||||
|
||||
if (parent.GetMeshRights(user, node.meshid) != 0) {
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
if (visible == false) return;
|
||||
// Query the database for the power timeline for a given node
|
||||
// The result is a compacted array: [ startPowerState, startTimeUTC, powerState ] + many[ deltaTime, powerState ]
|
||||
db.getPowerTimeline(command.nodeid, function (err, docs) {
|
||||
db.getPowerTimeline(node._id, function (err, docs) {
|
||||
if ((err == null) && (docs != null) && (docs.length > 0)) {
|
||||
var timeline = [], time = null, previousPower;
|
||||
for (i in docs) {
|
||||
|
@ -535,69 +527,50 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
}
|
||||
previousPower = doc.power;
|
||||
}
|
||||
try { ws.send(JSON.stringify({ action: 'powertimeline', nodeid: command.nodeid, timeline: timeline, tag: command.tag })); } catch (ex) { }
|
||||
try { ws.send(JSON.stringify({ action: 'powertimeline', nodeid: node._id, timeline: timeline, tag: command.tag })); } catch (ex) { }
|
||||
} else {
|
||||
// No records found, send current state if we have it
|
||||
var state = parent.parent.GetConnectivityState(command.nodeid);
|
||||
if (state != null) { try { ws.send(JSON.stringify({ action: 'powertimeline', nodeid: command.nodeid, timeline: [state.powerState, Date.now(), state.powerState], tag: command.tag })); } catch (ex) { } }
|
||||
if (state != null) { try { ws.send(JSON.stringify({ action: 'powertimeline', nodeid: node._id, timeline: [state.powerState, Date.now(), state.powerState], tag: command.tag })); } catch (ex) { } }
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'getsysinfo':
|
||||
{
|
||||
// Perform pre-validation
|
||||
if (common.validateString(command.nodeid, 0, 128) == false) break;
|
||||
var snode = command.nodeid.split('/');
|
||||
if ((snode.length != 3) || (snode[1] != domain.id)) break;
|
||||
|
||||
// Check that we have permissions for this node.
|
||||
db.Get(command.nodeid, function (err, nodes) {
|
||||
if (nodes == null || nodes.length != 1) return;
|
||||
const node = nodes[0];
|
||||
|
||||
if (parent.GetMeshRights(user, node.meshid) != 0) {
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
if (visible == false) return;
|
||||
// Query the database system information
|
||||
db.Get('si' + command.nodeid, function (err, docs) {
|
||||
if ((docs != null) && (docs.length > 0)) {
|
||||
var doc = docs[0];
|
||||
doc.action = 'getsysinfo';
|
||||
doc.nodeid = command.nodeid;
|
||||
doc.nodeid = node._id;
|
||||
doc.tag = command.tag;
|
||||
delete doc.type;
|
||||
delete doc.domain;
|
||||
delete doc._id;
|
||||
try { ws.send(JSON.stringify(doc)); } catch (ex) { }
|
||||
} else {
|
||||
try { ws.send(JSON.stringify({ action: 'getsysinfo', nodeid: command.nodeid, tag: command.tag, noinfo: true })); } catch (ex) { }
|
||||
try { ws.send(JSON.stringify({ action: 'getsysinfo', nodeid: node._id, tag: command.tag, noinfo: true })); } catch (ex) { }
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'lastconnect':
|
||||
{
|
||||
// Perform pre-validation
|
||||
if (common.validateString(command.nodeid, 0, 128) == false) return;
|
||||
var snode = command.nodeid.split('/');
|
||||
if ((snode.length != 3) || (snode[1] != domain.id)) break;
|
||||
|
||||
// Check that we have permissions for this node.
|
||||
db.Get(command.nodeid, function (err, nodes) {
|
||||
if (nodes == null || nodes.length != 1) return;
|
||||
const node = nodes[0];
|
||||
|
||||
if (parent.GetMeshRights(user, node.meshid) != 0) {
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
if (visible == false) return;
|
||||
// Query the database for the last time this node connected
|
||||
db.Get('lc' + command.nodeid, function (err, docs) {
|
||||
if ((docs != null) && (docs.length > 0)) {
|
||||
try { ws.send(JSON.stringify({ action: 'lastconnect', nodeid: command.nodeid, time: docs[0].time, addr: docs[0].addr })); } catch (ex) { }
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
@ -963,32 +936,28 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
try { ws.send(JSON.stringify({ action: 'events', events: docs, user: command.user, tag: command.tag })); } catch (ex) { }
|
||||
});
|
||||
}
|
||||
} else if (common.validateString(command.nodeid, 0, 128) == true) { // Device filtered events
|
||||
} else if (command.nodeid != null) { // Device filtered events
|
||||
// Check that the user has access to this nodeid
|
||||
db.Get(command.nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
const node = nodes[0];
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
if (node == null) return;
|
||||
|
||||
var meshrights = parent.GetMeshRights(user, node.meshid);
|
||||
if (meshrights != 0) {
|
||||
// Put a limit on the number of returned entries if present
|
||||
var limit = 10000;
|
||||
if (common.validateInt(command.limit, 1, 60000) == true) { limit = command.limit; }
|
||||
|
||||
if ((meshrights & MESHRIGHT_LIMITEVENTS) != 0) {
|
||||
if ((rights & MESHRIGHT_LIMITEVENTS) != 0) {
|
||||
// Send the list of most recent events for this nodeid that only apply to us, up to 'limit' count
|
||||
db.GetNodeEventsSelfWithLimit(command.nodeid, domain.id, user._id, limit, function (err, docs) {
|
||||
db.GetNodeEventsSelfWithLimit(node._id, domain.id, user._id, limit, function (err, docs) {
|
||||
if (err != null) return;
|
||||
try { ws.send(JSON.stringify({ action: 'events', events: docs, nodeid: command.nodeid, tag: command.tag })); } catch (ex) { }
|
||||
try { ws.send(JSON.stringify({ action: 'events', events: docs, nodeid: node._id, tag: command.tag })); } catch (ex) { }
|
||||
});
|
||||
} else {
|
||||
// Send the list of most recent events for this nodeid, up to 'limit' count
|
||||
db.GetNodeEventsWithLimit(command.nodeid, domain.id, limit, function (err, docs) {
|
||||
db.GetNodeEventsWithLimit(node._id, domain.id, limit, function (err, docs) {
|
||||
if (err != null) return;
|
||||
try { ws.send(JSON.stringify({ action: 'events', events: docs, nodeid: command.nodeid, tag: command.tag })); } catch (ex) { }
|
||||
try { ws.send(JSON.stringify({ action: 'events', events: docs, nodeid: node._id, tag: command.tag })); } catch (ex) { }
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Create a filter for device groups
|
||||
|
@ -997,7 +966,10 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
// All events
|
||||
var exGroupFilter2 = [], filter = [], filter2 = user.subscriptions;
|
||||
|
||||
// Remove MeshID's that we do not have rights to see events for (TODO: user groups)
|
||||
// Add all meshes for groups this user is part of
|
||||
// TODO (UserGroups)
|
||||
|
||||
// Remove MeshID's that we do not have rights to see events for
|
||||
for (var link in obj.user.links) { if (((obj.user.links[link].rights & MESHRIGHT_LIMITEVENTS) != 0) && ((obj.user.links[link].rights != 0xFFFFFFFF))) { exGroupFilter2.push(link); } }
|
||||
for (var i in filter2) { if (exGroupFilter2.indexOf(filter2[i]) == -1) { filter.push(filter2[i]); } }
|
||||
|
||||
|
@ -1198,7 +1170,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Remove user groups??
|
||||
// TODO (UserGroups): Remove user groups??
|
||||
|
||||
db.Remove('ws' + deluser._id); // Remove user web state
|
||||
db.Remove('nt' + deluser._id); // Remove notes for this user
|
||||
|
@ -1507,18 +1479,21 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
if (common.validateString(command.meshid, 1, 1024) == false) { err = 'Invalid group identifier'; } // Check the meshid
|
||||
else if (command.meshid.indexOf('/') == -1) { command.meshid = 'mesh/' + domain.id + '/' + command.meshid; }
|
||||
if (common.validateInt(command.notify) == false) { err = 'Invalid notification flags'; }
|
||||
if (parent.GetMeshRights(user, command.meshid) == 0) err = 'Access denied';
|
||||
if (parent.IsMeshViewable(user, command.meshid) == false) err = 'Access denied';
|
||||
} catch (ex) { err = 'Validation exception: ' + ex; }
|
||||
|
||||
// Handle any errors
|
||||
if (err != null) { if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'changemeshnotify', responseid: command.responseid, result: err })); } catch (ex) { } } break; }
|
||||
|
||||
// Change the notification (TODO: Add user group support, not sure how to do this here)
|
||||
// TODO (UserGroups)
|
||||
if (user.links[command.meshid]) {
|
||||
if (command.notify == 0) {
|
||||
delete user.links[command.meshid].notify;
|
||||
} else {
|
||||
user.links[command.meshid].notify = command.notify;
|
||||
}
|
||||
}
|
||||
|
||||
// Save the user
|
||||
parent.db.SetUser(user);
|
||||
|
@ -1674,20 +1649,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
}
|
||||
}
|
||||
|
||||
// User-to-device chat is not support in LAN-only mode yet. We need the agent to replace the IP address of the server??
|
||||
if (args.lanonly == true) { return; }
|
||||
|
||||
// Setup a user-to-node session
|
||||
if (common.validateString(command.nodeid, 1, 2048)) {
|
||||
if (args.lanonly == true) { return; } // User-to-device chat is not support in LAN-only mode yet. We need the agent to replace the IP address of the server??
|
||||
|
||||
// Get the device
|
||||
db.Get(command.nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
var node = nodes[0];
|
||||
|
||||
// Get the mesh for this device
|
||||
mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
// Check if this user has rights to do this
|
||||
if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_CHATNOTIFY) == 0) return;
|
||||
if ((rights & MESHRIGHT_CHATNOTIFY) == 0) return;
|
||||
|
||||
// Create the server url
|
||||
var httpsPort = ((args.aliasport == null) ? args.port : args.aliasport); // Use HTTPS alias port is specified
|
||||
|
@ -1697,10 +1665,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
|
||||
// Create the notification message
|
||||
routeCommandToNode({ "action": "openUrl", "nodeid": command.nodeid, "userid": user._id, "username": user.name, "url": url });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'serverversion':
|
||||
|
@ -2084,20 +2049,17 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
|
||||
// For each nodeid, change the group
|
||||
for (var i = 0; i < command.nodeids.length; i++) {
|
||||
db.Get(command.nodeids[i], function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
const node = nodes[0];
|
||||
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) {
|
||||
// Check if already in the right mesh
|
||||
if (node.meshid == command.meshid) return;
|
||||
if ((node == null) || (node.meshid == command.meshid)) return;
|
||||
|
||||
// Make sure both source and target mesh are the same type
|
||||
try { if (parent.meshes[node.meshid].mtype != parent.meshes[command.meshid].mtype) return; } catch (e) { return; };
|
||||
|
||||
// Make sure that we have rights on both source and destination mesh
|
||||
const sourceMeshRights = parent.GetMeshRights(user, node.meshid);
|
||||
const targetMeshRights = parent.GetMeshRights(user, command.meshid);
|
||||
if (((sourceMeshRights & MESHRIGHT_MANAGECOMPUTERS) == 0) || ((targetMeshRights & MESHRIGHT_MANAGECOMPUTERS) == 0)) return;
|
||||
if (((rights & MESHRIGHT_MANAGECOMPUTERS) == 0) || ((targetMeshRights & MESHRIGHT_MANAGECOMPUTERS) == 0)) return;
|
||||
|
||||
// Perform the switch, start by saving the node with the new meshid.
|
||||
const oldMeshId = node.meshid;
|
||||
|
@ -2139,22 +2101,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
case 'removedevices':
|
||||
{
|
||||
if (common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
|
||||
|
||||
for (i in command.nodeids) {
|
||||
nodeid = command.nodeids[i];
|
||||
if (common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
if ((nodeid.split('/').length != 3) || (nodeid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
|
||||
|
||||
// Get the device
|
||||
db.Get(nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
var node = nodes[0];
|
||||
|
||||
// Get the mesh for this device
|
||||
mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
// Check if this user has rights to do this
|
||||
if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_MANAGECOMPUTERS) == 0) return;
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) {
|
||||
// Check we have the rights to delete this device
|
||||
if ((rights & MESHRIGHT_MANAGECOMPUTERS) == 0) return;
|
||||
|
||||
// Delete this node including network interface information, events and timeline
|
||||
db.Remove(node._id); // Remove node with that id
|
||||
|
@ -2182,34 +2133,21 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
if ((state.connectivity & 1) != 0) { parent.wsagents[nodeid].close(); } // Disconnect mesh agent
|
||||
if ((state.connectivity & 2) != 0) { parent.parent.mpsserver.close(parent.parent.mpsserver.ciraConnections[nodeid]); } // Disconnect CIRA connection
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'wakedevices':
|
||||
{
|
||||
if (common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
|
||||
// TODO: We can optimize this a lot.
|
||||
// - We should get a full list of all MAC's to wake first.
|
||||
// - We should try to only have one agent per subnet (using Gateway MAC) send a wake-on-lan.
|
||||
if (common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
|
||||
for (i in command.nodeids) {
|
||||
nodeid = command.nodeids[i];
|
||||
var wakeActions = 0;
|
||||
if (common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
|
||||
// Get the device
|
||||
db.Get(nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
var node = nodes[0];
|
||||
|
||||
// Get the mesh for this device
|
||||
mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
|
||||
// Check if this user has rights to do this
|
||||
if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_WAKEDEVICE) != 0) {
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) {
|
||||
// Check we have the rights to delete this device
|
||||
if ((rights & MESHRIGHT_WAKEDEVICE) == 0) return;
|
||||
|
||||
// If this device is connected on MQTT, send a wake action.
|
||||
if (parent.parent.mqttbroker != null) { parent.parent.mqttbroker.publish(node._id, 'powerAction', 'wake'); }
|
||||
|
@ -2217,12 +2155,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
// Get the device interface information
|
||||
db.Get('if' + node._id, function (err, nodeifs) {
|
||||
if ((nodeifs != null) && (nodeifs.length == 1)) {
|
||||
var nodeif = nodeifs[0];
|
||||
var macs = [];
|
||||
var macs = [], nodeif = nodeifs[0];
|
||||
for (var i in nodeif.netif) { if (nodeif.netif[i].mac) { macs.push(nodeif.netif[i].mac); } }
|
||||
|
||||
// Have the server send a wake-on-lan packet (Will not work in WAN-only)
|
||||
if (parent.parent.meshScanner != null) { parent.parent.meshScanner.wakeOnLan(macs); wakeActions++; }
|
||||
if (parent.parent.meshScanner != null) { parent.parent.meshScanner.wakeOnLan(macs); }
|
||||
|
||||
// Get the list of mesh this user as access to
|
||||
var targetMeshes = [];
|
||||
|
@ -2234,51 +2171,33 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
if ((targetMeshes.indexOf(agent.dbMeshKey) >= 0) && (agent.authenticated == 2)) {
|
||||
//console.log('Asking agent ' + agent.dbNodeKey + ' to wake ' + macs.join(','));
|
||||
try { agent.send(JSON.stringify({ action: 'wakeonlan', macs: macs })); } catch (ex) { }
|
||||
wakeActions++;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// Confirm we may be doing something (TODO)
|
||||
try { ws.send(JSON.stringify({ action: 'wakedevices' })); } catch (ex) { }
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'uninstallagent':
|
||||
{
|
||||
if (common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
|
||||
for (i in command.nodeids) {
|
||||
nodeid = command.nodeids[i];
|
||||
if (common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
|
||||
// Get the device
|
||||
db.Get(nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
var node = nodes[0];
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) {
|
||||
// Check we have the rights to delete this device
|
||||
if ((rights & MESHRIGHT_UNINSTALL) == 0) return;
|
||||
|
||||
// Get the mesh for this device
|
||||
mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
// Check if this user has rights to do this
|
||||
if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_UNINSTALL) != 0) {
|
||||
// Send uninstall command to connected agent
|
||||
var agent = parent.wsagents[node._id];
|
||||
const agent = parent.wsagents[node._id];
|
||||
if (agent != null) {
|
||||
//console.log('Asking agent ' + agent.dbNodeKey + ' to uninstall.');
|
||||
try { agent.send(JSON.stringify({ action: 'uninstallagent' })); } catch (ex) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 'poweraction':
|
||||
|
@ -2286,34 +2205,21 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
if (common.validateArray(command.nodeids, 1) == false) break; // Check nodeid's
|
||||
if (common.validateInt(command.actiontype, 2, 4) == false) break; // Check actiontype
|
||||
for (i in command.nodeids) {
|
||||
nodeid = command.nodeids[i];
|
||||
var powerActions = 0;
|
||||
if (common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
|
||||
// Get the device
|
||||
db.Get(nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
var node = nodes[0];
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) {
|
||||
// Check we have the rights to delete this device
|
||||
if ((rights & MESHRIGHT_REMOTECONTROL) == 0) return;
|
||||
|
||||
// Get the mesh for this device
|
||||
mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
// If this device is connected on MQTT, send a power action.
|
||||
if (parent.parent.mqttbroker != null) { parent.parent.mqttbroker.publish(nodeid, 'powerAction', ['', '', 'poweroff', 'reset', 'sleep'][command.actiontype]); }
|
||||
if (parent.parent.mqttbroker != null) { parent.parent.mqttbroker.publish(node._id, 'powerAction', ['', '', 'poweroff', 'reset', 'sleep'][command.actiontype]); }
|
||||
|
||||
// Check if this user has rights to do this
|
||||
if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_REMOTECONTROL) != 0) { // "Remote Control permission"
|
||||
// Get this device
|
||||
var agent = parent.wsagents[node._id];
|
||||
// Get this device and send the power command
|
||||
const agent = parent.wsagents[node._id];
|
||||
if (agent != null) {
|
||||
// Send the power command
|
||||
try { agent.send(JSON.stringify({ action: 'poweraction', actiontype: command.actiontype })); } catch (ex) { }
|
||||
powerActions++;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Confirm we may be doing something (TODO)
|
||||
try { ws.send(JSON.stringify({ action: 'poweraction' })); } catch (ex) { }
|
||||
}
|
||||
|
@ -2325,31 +2231,18 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
if (common.validateString(command.title, 1, 512) == false) break; // Check title
|
||||
if (common.validateString(command.msg, 1, 4096) == false) break; // Check message
|
||||
for (i in command.nodeids) {
|
||||
nodeid = command.nodeids[i];
|
||||
var powerActions = 0;
|
||||
if (common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
|
||||
// Get the device
|
||||
db.Get(nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
var node = nodes[0];
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) {
|
||||
// Check we have the rights to delete this device
|
||||
if ((rights & MESHRIGHT_CHATNOTIFY) == 0) return;
|
||||
|
||||
// Get the mesh for this device
|
||||
mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
// Check if this user has rights to do this
|
||||
if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_CHATNOTIFY) != 0) {
|
||||
// Get this device
|
||||
var agent = parent.wsagents[node._id];
|
||||
// Get this device and send toast command
|
||||
const agent = parent.wsagents[node._id];
|
||||
if (agent != null) {
|
||||
// Send the power command
|
||||
try { agent.send(JSON.stringify({ action: 'toast', title: command.title, msg: command.msg, sessionid: ws.sessionId, username: user.name, userid: user._id })); } catch (ex) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'getnetworkinfo':
|
||||
|
@ -2358,24 +2251,16 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
if ((command.nodeid.split('/').length != 3) || (command.nodeid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
|
||||
|
||||
// Get the device
|
||||
db.Get(command.nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) { try { ws.send(JSON.stringify({ action: 'getnetworkinfo', nodeid: command.nodeid, netif: null })); } catch (ex) { } return; }
|
||||
var node = nodes[0];
|
||||
|
||||
// Get the mesh for this device
|
||||
mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
// Check if this user has rights to do this
|
||||
if (parent.GetMeshRights(user, mesh) == 0) { try { ws.send(JSON.stringify({ action: 'getnetworkinfo', nodeid: command.nodeid, netif: null })); } catch (ex) { } return; }
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
if (visible == false) return;
|
||||
|
||||
// Get network information about this node
|
||||
db.Get('if' + command.nodeid, function (err, netinfos) {
|
||||
if ((netinfos == null) || (netinfos.length != 1)) { try { ws.send(JSON.stringify({ action: 'getnetworkinfo', nodeid: command.nodeid, netif: null })); } catch (ex) { } return; }
|
||||
db.Get('if' + node._id, function (err, netinfos) {
|
||||
if ((netinfos == null) || (netinfos.length != 1)) { try { ws.send(JSON.stringify({ action: 'getnetworkinfo', nodeid: node._id, netif: null })); } catch (ex) { } return; }
|
||||
var netinfo = netinfos[0];
|
||||
try { ws.send(JSON.stringify({ action: 'getnetworkinfo', nodeid: command.nodeid, updateTime: netinfo.updateTime, netif: netinfo.netif })); } catch (ex) { }
|
||||
try { ws.send(JSON.stringify({ action: 'getnetworkinfo', nodeid: node._id, updateTime: netinfo.updateTime, netif: netinfo.netif })); } catch (ex) { }
|
||||
});
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
@ -2383,24 +2268,17 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
{
|
||||
// Argument validation
|
||||
if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
if ((command.nodeid.split('/').length != 3) || (command.nodeid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
|
||||
if ((command.userloc) && (command.userloc.length != 2) && (command.userloc.length != 0)) return;
|
||||
|
||||
// Change the device
|
||||
db.Get(command.nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
var node = nodes[0];
|
||||
|
||||
// Get the mesh for this device
|
||||
mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
// Check if this user has rights to do this
|
||||
if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_MANAGECOMPUTERS) == 0) return;
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
if ((rights & MESHRIGHT_MANAGECOMPUTERS) == 0) return;
|
||||
var mesh = parent.meshes[node.meshid];
|
||||
|
||||
// Ready the node change event
|
||||
var changes = [], event = { etype: 'node', userid: user._id, username: user.name, action: 'changenode', nodeid: node._id, domain: domain.id };
|
||||
change = 0;
|
||||
event.msg = ": ";
|
||||
event.msg = ': ';
|
||||
|
||||
// If we are in WAN-only mode, host is not used
|
||||
if ((args.wanonly == true) && (command.host)) { delete command.host; }
|
||||
|
@ -2443,35 +2321,26 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the node. Another event will come.
|
||||
parent.parent.DispatchEvent(['*', node.meshid, user._id], obj, event);
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'uploadagentcore':
|
||||
{
|
||||
if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
if (common.validateString(command.type, 1, 40) == false) break; // Check path
|
||||
|
||||
// Change the device
|
||||
db.Get(command.nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
var node = nodes[0];
|
||||
|
||||
// Get the mesh for this device
|
||||
mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
// Check if this user has rights to do this
|
||||
if (((parent.GetMeshRights(user, mesh) & MESHRIGHT_AGENTCONSOLE) == 0) && (user.siteadmin != 0xFFFFFFFF)) { return; }
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
if ((node == null) || (((rights & MESHRIGHT_AGENTCONSOLE) == 0) && (user.siteadmin != 0xFFFFFFFF))) return;
|
||||
|
||||
if (command.type == 'default') {
|
||||
// Send the default core to the agent
|
||||
parent.parent.updateMeshCore(function () { parent.sendMeshAgentCore(user, domain, command.nodeid, 'default'); });
|
||||
parent.parent.updateMeshCore(function () { parent.sendMeshAgentCore(user, domain, node._id, 'default'); });
|
||||
} else if (command.type == 'clear') {
|
||||
// Clear the mesh agent core on the mesh agent
|
||||
parent.sendMeshAgentCore(user, domain, command.nodeid, 'clear');
|
||||
parent.sendMeshAgentCore(user, domain, node._id, 'clear');
|
||||
} else if (command.type == 'recovery') {
|
||||
// Send the recovery core to the agent
|
||||
parent.sendMeshAgentCore(user, domain, command.nodeid, 'recovery');
|
||||
parent.sendMeshAgentCore(user, domain, node._id, 'recovery');
|
||||
} else if ((command.type == 'custom') && (common.validateString(command.path, 1, 2048) == true)) {
|
||||
// Send a mesh agent core to the mesh agent
|
||||
var file = parent.getServerFilePath(user, domain, command.path);
|
||||
|
@ -2479,34 +2348,24 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
fs.readFile(file.fullpath, 'utf8', function (err, data) {
|
||||
if (err != null) {
|
||||
data = common.IntToStr(0) + data; // Add the 4 bytes encoding type & flags (Set to 0 for raw)
|
||||
parent.sendMeshAgentCore(user, domain, command.nodeid, 'custom', data);
|
||||
parent.sendMeshAgentCore(user, domain, node._id, 'custom', data);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'agentdisconnect':
|
||||
{
|
||||
if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
if (common.validateInt(command.disconnectMode) == false) return; // Check disconnect mode
|
||||
|
||||
// Change the device
|
||||
db.Get(command.nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
var node = nodes[0];
|
||||
|
||||
// Get the mesh for this device
|
||||
mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
// Check if this user has rights to do this
|
||||
if (((parent.GetMeshRights(user, mesh) & MESHRIGHT_AGENTCONSOLE) == 0) && (user.siteadmin != 0xFFFFFFFF)) return;
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
if ((node == null) || (((rights & MESHRIGHT_AGENTCONSOLE) == 0) && (user.siteadmin != 0xFFFFFFFF))) return;
|
||||
|
||||
// Force mesh agent disconnection
|
||||
parent.forceMeshAgentDisconnect(user, domain, command.nodeid, command.disconnectMode);
|
||||
}
|
||||
parent.forceMeshAgentDisconnect(user, domain, node._id, command.disconnectMode);
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
@ -2552,7 +2411,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
mesh = parent.meshes[command.meshid];
|
||||
if (mesh == null) { err = 'Unknown device group'; } // Check if the group exists
|
||||
else if (mesh.mtype != 2) { err = 'Invalid group type'; } // Check if this is the correct group type
|
||||
else if (parent.GetMeshRights(user, mesh) == 0) { err = 'Not allowed'; } // Check if this user has rights to do this
|
||||
else if (parent.IsMeshViewable(user, mesh) == false) { err = 'Not allowed'; } // Check if this user has rights to do this
|
||||
}
|
||||
}
|
||||
} catch (ex) { err = 'Validation exception: ' + ex; }
|
||||
|
@ -2574,24 +2433,16 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
{
|
||||
// Argument validation
|
||||
if (common.validateString(command.msg, 1, 4096) == false) break; // Check event
|
||||
if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
var splitid = command.nodeid.split('/');
|
||||
if ((splitid.length != 3) || (splitid[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
|
||||
var idtype = splitid[0];
|
||||
if ((idtype != 'node')) return;
|
||||
|
||||
// Check if this user has rights on this id to set notes
|
||||
db.Get(command.nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length == 1)) {
|
||||
if (parent.GetMeshRights(user, nodes[0].meshid) != 0) {
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
if (rights == 0) return;
|
||||
|
||||
// Add an event for this device
|
||||
var targets = ['*', 'server-users', user._id, nodes[0].meshid];
|
||||
var event = { etype: 'node', userid: user._id, username: user.name, nodeid: nodes[0]._id, action: 'manual', msg: decodeURIComponent(command.msg), domain: domain.id };
|
||||
parent.parent.DispatchEvent(targets, obj, event);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
case 'setNotes':
|
||||
|
@ -2604,16 +2455,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
if ((idtype != 'user') && (idtype != 'mesh') && (idtype != 'node')) return;
|
||||
|
||||
if (idtype == 'node') {
|
||||
// Check if this user has rights on this id to set notes
|
||||
db.Get(command.id, function (err, nodes) { // TODO: Make a NodeRights(user) method that also does not do a db call if agent is connected (???)
|
||||
if ((nodes == null) || (nodes.length == 1)) {
|
||||
if ((parent.GetMeshRights(user, nodes[0].meshid) & MESHRIGHT_SETNOTES) != 0) {
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.id, function (node, rights, visible) {
|
||||
if ((rights & MESHRIGHT_SETNOTES) != 0) {
|
||||
// Set the id's notes
|
||||
if (common.validateString(command.notes, 1) == false) {
|
||||
db.Remove('nt' + command.id); // Delete the note for this node
|
||||
db.Remove('nt' + node._id); // Delete the note for this node
|
||||
} else {
|
||||
db.Set({ _id: 'nt' + command.id, type: 'note', value: command.notes }); // Set the note for this node
|
||||
}
|
||||
db.Set({ _id: 'nt' + node._id, type: 'note', value: command.notes }); // Set the note for this node
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -2893,44 +2742,26 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
case 'getClip': {
|
||||
if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
|
||||
// Get the device
|
||||
db.Get(command.nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
var node = nodes[0];
|
||||
|
||||
// Get the mesh for this device
|
||||
mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
// Check if this user has "remote" rights to do this
|
||||
var meshrights = parent.GetMeshRights(user, mesh);
|
||||
if ((meshrights & MESHRIGHT_AGENTCONSOLE) == 0) return;
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
if ((rights & MESHRIGHT_AGENTCONSOLE) == 0) return;
|
||||
|
||||
// Ask for clipboard data from agent
|
||||
var agent = parent.wsagents[node._id];
|
||||
if (agent != null) { try { agent.send(JSON.stringify({ action: 'getClip' })); } catch (ex) { } }
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'setClip': {
|
||||
if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
if (common.validateString(command.data, 1, 65535) == false) break; // Check
|
||||
|
||||
// Get the device
|
||||
db.Get(command.nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
var node = nodes[0];
|
||||
|
||||
// Get the mesh for this device
|
||||
mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
// Check if this user has "remote" rights to do this
|
||||
if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_AGENTCONSOLE) == 0) return;
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
if ((rights & MESHRIGHT_AGENTCONSOLE) == 0) return;
|
||||
|
||||
// Send clipboard data to the agent
|
||||
var agent = parent.wsagents[node._id];
|
||||
if (agent != null) { try { agent.send(JSON.stringify({ action: 'setClip', data: command.data })); } catch (ex) { } }
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
@ -2951,16 +2782,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
if ((idtype != 'user') && (idtype != 'mesh') && (idtype != 'node')) return;
|
||||
|
||||
if (idtype == 'node') {
|
||||
// Get the device
|
||||
db.Get(command.id, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
var node = nodes[0];
|
||||
|
||||
// Get the mesh for this device
|
||||
mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
// Check if this user has rights to do this
|
||||
if (parent.GetMeshRights(user, mesh) == 0) return;
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.id, function (node, rights, visible) {
|
||||
if (visible == false) return;
|
||||
|
||||
// Get the notes about this node
|
||||
db.Get('nt' + command.id, function (err, notes) {
|
||||
|
@ -2969,7 +2793,6 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
ws.send(JSON.stringify({ action: 'getNotes', id: command.id, notes: notes[0].value }));
|
||||
} catch (ex) { }
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (idtype == 'mesh') {
|
||||
// Get the mesh for this device
|
||||
|
@ -3037,6 +2860,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
break;
|
||||
}
|
||||
case 'sendmqttmsg': {
|
||||
if (parent.parent.mqttbroker == null) { err = 'MQTT not supported on this server'; }; // MQTT not available
|
||||
if (common.validateArray(command.nodeids, 1) == false) { err = 'Invalid nodeids'; }; // Check nodeid's
|
||||
if (common.validateString(command.topic, 1, 64) == false) { err = 'Invalid topic'; } // Check the topic
|
||||
if (common.validateString(command.msg, 1, 4096) == false) { err = 'Invalid msg'; } // Check the message
|
||||
|
@ -3047,31 +2871,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
break;
|
||||
}
|
||||
|
||||
// TODO: We can optimize this a lot.
|
||||
// - We should get a full list of all MAC's to wake first.
|
||||
// - We should try to only have one agent per subnet (using Gateway MAC) send a wake-on-lan.
|
||||
// Send the MQTT message
|
||||
for (i in command.nodeids) {
|
||||
nodeid = command.nodeids[i];
|
||||
var wakeActions = 0;
|
||||
if (common.validateString(nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
|
||||
// Get the device
|
||||
db.Get(nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
var node = nodes[0];
|
||||
|
||||
// Get the mesh for this device
|
||||
mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
// Check if this user has rights to do this
|
||||
if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_WAKEDEVICE) != 0) {
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeids[i], function (node, rights, visible) {
|
||||
// If this device is connected on MQTT, send a wake action.
|
||||
if (parent.parent.mqttbroker != null) { parent.parent.mqttbroker.publish(node._id, command.topic, command.msg); }
|
||||
}
|
||||
}
|
||||
if (rights != 0) { parent.parent.mqttbroker.publish(node._id, command.topic, command.msg); }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -3083,19 +2890,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
// Handle any errors
|
||||
if (err != null) { if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'getmqttlogin', responseid: command.responseid, result: err })); } catch (ex) { } } break; }
|
||||
|
||||
var nodeid = command.nodeid;
|
||||
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
|
||||
// Get the device
|
||||
db.Get(nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) { if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'getmqttlogin', responseid: command.responseid, result: 'Invalid node id' })); } catch (ex) { } return; } }
|
||||
var node = nodes[0];
|
||||
|
||||
// Get the device group for this node
|
||||
var mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
// Check if this user has rights to do this
|
||||
if ((parent.GetMeshRights(user, mesh) == 0xFFFFFFFF)) {
|
||||
var token = parent.parent.mqttbroker.generateLogin(mesh._id, node._id);
|
||||
if (rights == 0xFFFFFFFF) {
|
||||
var token = parent.parent.mqttbroker.generateLogin(node.meshid, node._id);
|
||||
var r = { action: 'getmqttlogin', responseid: command.responseid, nodeid: node._id, user: token.user, pass: token.pass };
|
||||
const serverName = parent.getWebServerName(domain);
|
||||
|
||||
|
@ -3108,18 +2907,16 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
|
||||
// Add WS URL
|
||||
var xdomain = (domain.dns == null) ? domain.id : '';
|
||||
if (xdomain != '') xdomain += "/";
|
||||
if (xdomain != '') xdomain += '/';
|
||||
var httpsPort = ((args.aliasport == null) ? args.port : args.aliasport); // Use HTTPS alias port is specified
|
||||
r.wsUrl = "ws" + (args.notls ? '' : 's') + "://" + serverName + ":" + httpsPort + "/" + xdomain + "mqtt.ashx";
|
||||
r.wsUrl = 'ws' + (args.notls ? '' : 's') + '://' + serverName + ':' + httpsPort + '/' + xdomain + 'mqtt.ashx';
|
||||
r.wsTrustedCert = parent.isTrustedCert(domain);
|
||||
|
||||
try { ws.send(JSON.stringify(r)); } catch (ex) { }
|
||||
} else {
|
||||
if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'getmqttlogin', responseid: command.responseid, result: 'Unable to perform this operation' })); } catch (ex) { } }
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'amt': {
|
||||
|
@ -3136,23 +2933,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
} else if (command.mode == 3) {
|
||||
if (parent.parent.apfserver.apfConnections[command.nodeid] == null) break;
|
||||
}
|
||||
var nodeid = command.nodeid;
|
||||
if ((nodeid.split('/').length == 3) && (nodeid.split('/')[1] == domain.id)) { // Validate the domain, operation only valid for current domain
|
||||
// Get the device
|
||||
db.Get(nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) return;
|
||||
var node = nodes[0];
|
||||
|
||||
// Get the mesh for this device
|
||||
var mesh = parent.meshes[node.meshid];
|
||||
if (mesh) {
|
||||
// Check if this user has rights to do this
|
||||
if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_REMOTECONTROL) != 0) { // "Remote Control permission"
|
||||
// Get the node and the rights for this node
|
||||
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
|
||||
if ((rights & MESHRIGHT_REMOTECONTROL) == 0) return;
|
||||
handleAmtCommand(command, node);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'distributeCore': {
|
||||
|
@ -3304,15 +3090,15 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
|
||||
// Read all files recursively
|
||||
try {
|
||||
files.filetree.f[user._id].f = readFilesRec(parent.path.join(parent.filespath, domainx + "/user-" + usersplit[2]));
|
||||
files.filetree.f[user._id].f = readFilesRec(parent.path.join(parent.filespath, domainx + '/user-' + usersplit[2]));
|
||||
} catch (e) {
|
||||
// TODO: We may want to fake this file structure until it's needed.
|
||||
// Got an error, try to create all the folders and try again...
|
||||
try { fs.mkdirSync(parent.filespath); } catch (e) { }
|
||||
try { fs.mkdirSync(parent.path.join(parent.filespath, domainx)); } catch (e) { }
|
||||
try { fs.mkdirSync(parent.path.join(parent.filespath, domainx + "/user-" + usersplit[2])); } catch (e) { }
|
||||
try { fs.mkdirSync(parent.path.join(parent.filespath, domainx + "/user-" + usersplit[2] + "/Public")); } catch (e) { }
|
||||
try { files.filetree.f[user._id].f = readFilesRec(parent.path.join(parent.filespath, domainx + "/user-" + usersplit[2])); } catch (e) { }
|
||||
try { fs.mkdirSync(parent.path.join(parent.filespath, domainx + '/user-' + usersplit[2])); } catch (e) { }
|
||||
try { fs.mkdirSync(parent.path.join(parent.filespath, domainx + '/user-' + usersplit[2] + '/Public')); } catch (e) { }
|
||||
try { files.filetree.f[user._id].f = readFilesRec(parent.path.join(parent.filespath, domainx + '/user-' + usersplit[2])); } catch (e) { }
|
||||
}
|
||||
|
||||
// Add files for each mesh // TODO: Get all meshes including groups!!
|
||||
|
@ -3326,7 +3112,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
|
||||
// Read all files recursively
|
||||
try {
|
||||
files.filetree.f[mesh._id].f = readFilesRec(parent.path.join(parent.filespath, domainx + "/mesh-" + meshsplit[2]));
|
||||
files.filetree.f[mesh._id].f = readFilesRec(parent.path.join(parent.filespath, domainx + '/mesh-' + meshsplit[2]));
|
||||
} catch (e) {
|
||||
files.filetree.f[mesh._id].f = {}; // Got an error, return empty folder. We will create the folder only when needed.
|
||||
}
|
||||
|
@ -3338,7 +3124,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
try { ws.send(JSON.stringify(files)); } catch (ex) { }
|
||||
}
|
||||
|
||||
function EscapeHtml(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<').replace(/"/g, '"').replace(/'/g, '''); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
|
||||
function EscapeHtml(x) { if (typeof x == 'string') return x.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<').replace(/"/g, '"').replace(/'/g, '''); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
|
||||
//function EscapeHtmlBreaks(x) { if (typeof x == "string") return x.replace(/&/g, '&').replace(/>/g, '>').replace(/</g, '<').replace(/"/g, '"').replace(/'/g, ''').replace(/\r/g, '<br />').replace(/\n/g, '').replace(/\t/g, ' '); if (typeof x == "boolean") return x; if (typeof x == "number") return x; }
|
||||
|
||||
// Split a string taking into account the quoats. Used for command line parsing
|
||||
|
@ -3388,13 +3174,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
|||
node.intelamt.tls, tlsoptions, parent.parent, cmd.mode);
|
||||
var amt = new Amt(wsman);
|
||||
switch (cmd.command) {
|
||||
case "Get-GeneralSettings": {
|
||||
amt.Get("AMT_GeneralSettings", function (obj, name, response, status) {
|
||||
case 'Get-GeneralSettings': {
|
||||
amt.Get('AMT_GeneralSettings', function (obj, name, response, status) {
|
||||
if (status == 200) {
|
||||
var resp = { action: 'amt', nodeid: cmd.nodeid, command: 'Get-GeneralSettings', value: response.Body }
|
||||
ws.send(JSON.stringify(resp));
|
||||
} else {
|
||||
ws.send(JSON.stringify({ "error": error }));
|
||||
ws.send(JSON.stringify({ 'error': error }));
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
|
58
mpsserver.js
|
@ -11,7 +11,7 @@
|
|||
/*jshint strict:false */
|
||||
/*jshint -W097 */
|
||||
/*jshint esversion: 6 */
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
// Construct a Intel AMT MPS server object
|
||||
module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||
|
@ -24,9 +24,9 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
var tlsSessionStore = {}; // Store TLS session information for quick resume.
|
||||
var tlsSessionStoreCount = 0; // Number of cached TLS session information in store.
|
||||
const constants = (require('crypto').constants ? require('crypto').constants : require('constants')); // require('constants') is deprecated in Node 11.10, use require('crypto').constants instead.
|
||||
const common = require("./common.js");
|
||||
const net = require("net");
|
||||
const tls = require("tls");
|
||||
const common = require('./common.js');
|
||||
const net = require('net');
|
||||
const tls = require('tls');
|
||||
const MAX_IDLE = 90000; // 90 seconds max idle time, higher than the typical KEEP-ALIVE periode of 60 seconds
|
||||
|
||||
if (obj.args.mpstlsoffload) {
|
||||
|
@ -42,9 +42,9 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
|
||||
obj.server.listen(args.mpsport, function () { console.log("MeshCentral Intel(R) AMT server running on " + certificates.AmtMpsName + ":" + args.mpsport + ((args.mpsaliasport != null) ? (", alias port " + args.mpsaliasport) : "") + "."); }).on("error", function (err) { console.error("ERROR: MeshCentral Intel(R) AMT server port " + args.mpsport + " is not available."); if (args.exactports) { process.exit(); } });
|
||||
obj.server.on('tlsClientError', function (err, tlssocket) { if (args.mpsdebug) { var remoteAddress = tlssocket.remoteAddress; if (tlssocket.remoteFamily == 'IPv6') { remoteAddress = '[' + remoteAddress + ']'; } console.log('MPS:Invalid TLS connection from ' + remoteAddress + ':' + tlssocket.remotePort + '.'); } });
|
||||
obj.parent.updateServerState("mps-port", args.mpsport);
|
||||
obj.parent.updateServerState("mps-name", certificates.AmtMpsName);
|
||||
if (args.mpsaliasport != null) { obj.parent.updateServerState("mps-alias-port", args.mpsaliasport); }
|
||||
obj.parent.updateServerState('mps-port', args.mpsport);
|
||||
obj.parent.updateServerState('mps-name', certificates.AmtMpsName);
|
||||
if (args.mpsaliasport != null) { obj.parent.updateServerState('mps-alias-port', args.mpsaliasport); }
|
||||
|
||||
const APFProtocol = {
|
||||
UNKNOWN: 0,
|
||||
|
@ -202,47 +202,47 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
function onConnection(socket) {
|
||||
connectionCount++;
|
||||
if (obj.args.mpstlsoffload) {
|
||||
socket.tag = { first: true, clientCert: null, accumulator: "", activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
|
||||
socket.tag = { first: true, clientCert: null, accumulator: '', activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
|
||||
} else {
|
||||
socket.tag = { first: true, clientCert: socket.getPeerCertificate(true), accumulator: "", activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
|
||||
socket.tag = { first: true, clientCert: socket.getPeerCertificate(true), accumulator: '', activetunnels: 0, boundPorts: [], socket: socket, host: null, nextchannelid: 4, channels: {}, nextsourceport: 0 };
|
||||
}
|
||||
socket.setEncoding("binary");
|
||||
socket.setEncoding('binary');
|
||||
parent.debug('mps', "New CIRA connection");
|
||||
|
||||
// Setup the CIRA keep alive timer
|
||||
socket.setTimeout(MAX_IDLE);
|
||||
socket.on("timeout", () => { ciraTimeoutCount++; parent.debug('mps', "CIRA timeout, disconnecting."); try { socket.end(); } catch (e) { } });
|
||||
socket.on('timeout', () => { ciraTimeoutCount++; parent.debug('mps', "CIRA timeout, disconnecting."); try { socket.end(); } catch (e) { } });
|
||||
|
||||
socket.addListener("data", function (data) {
|
||||
if (args.mpsdebug) { var buf = Buffer.from(data, "binary"); console.log("MPS <-- (" + buf.length + "):" + buf.toString('hex')); } // Print out received bytes
|
||||
socket.addListener('data', function (data) {
|
||||
if (args.mpsdebug) { var buf = Buffer.from(data, 'binary'); console.log("MPS <-- (" + buf.length + "):" + buf.toString('hex')); } // Print out received bytes
|
||||
socket.tag.accumulator += data;
|
||||
|
||||
// Detect if this is an HTTPS request, if it is, return a simple answer and disconnect. This is useful for debugging access to the MPS port.
|
||||
if (socket.tag.first == true) {
|
||||
if (socket.tag.accumulator.length < 3) return;
|
||||
//if (!socket.tag.clientCert.subject) { console.log("MPS Connection, no client cert: " + socket.remoteAddress); socket.write('HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: close\r\n\r\nMeshCentral2 MPS server.\r\nNo client certificate given.'); socket.end(); return; }
|
||||
if (socket.tag.accumulator.substring(0, 3) == "GET") { if (args.mpsdebug) { console.log("MPS Connection, HTTP GET detected: " + socket.remoteAddress); } socket.write("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n<!DOCTYPE html><html><head><meta charset=\"UTF-8\"></head><body>MeshCentral2 MPS server.<br />Intel® AMT computers should connect here.</body></html>"); socket.end(); return; }
|
||||
if (socket.tag.accumulator.substring(0, 3) == 'GET') { if (args.mpsdebug) { console.log("MPS Connection, HTTP GET detected: " + socket.remoteAddress); } socket.write("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n<!DOCTYPE html><html><head><meta charset=\"UTF-8\"></head><body>MeshCentral2 MPS server.<br />Intel® AMT computers should connect here.</body></html>"); socket.end(); return; }
|
||||
|
||||
// If the MQTT broker is active, look for inbound MQTT connections
|
||||
if (parent.mqttbroker != null) {
|
||||
var chunk = Buffer.from(socket.tag.accumulator, "binary");
|
||||
var chunk = Buffer.from(socket.tag.accumulator, 'binary');
|
||||
var packet_len = 0;
|
||||
if (chunk.readUInt8(0) == 16) { packet_len = getMQTTPacketLength(chunk); }
|
||||
if (chunk.readUInt8(0) == 16 && (socket.tag.accumulator.length < packet_len)) return; // Minimum MQTT detection
|
||||
|
||||
// check if it is MQTT, need more initial packet to probe
|
||||
if (chunk.readUInt8(0) == 16 && ((chunk.slice(4, 8).toString() === "MQTT") || (chunk.slice(5, 9).toString() === "MQTT")
|
||||
|| (chunk.slice(6, 10).toString() === "MQTT") || (chunk.slice(7, 11).toString() === "MQTT"))) {
|
||||
parent.debug("mps", "MQTT connection detected.");
|
||||
if (chunk.readUInt8(0) == 16 && ((chunk.slice(4, 8).toString() === 'MQTT') || (chunk.slice(5, 9).toString() === 'MQTT')
|
||||
|| (chunk.slice(6, 10).toString() === 'MQTT') || (chunk.slice(7, 11).toString() === 'MQTT'))) {
|
||||
parent.debug('mps', "MQTT connection detected.");
|
||||
socket.removeAllListeners("data");
|
||||
socket.removeAllListeners("close");
|
||||
socket.setNoDelay(true);
|
||||
socket.serialtunnel = SerialTunnel();
|
||||
socket.serialtunnel.xtransport = 'mps';
|
||||
socket.serialtunnel.xip = socket.remoteAddress;
|
||||
socket.on("data", function (b) { socket.serialtunnel.updateBuffer(Buffer.from(b, "binary")) });
|
||||
socket.serialtunnel.forwardwrite = function (b) { socket.write(b, "binary") }
|
||||
socket.on("close", function () { socket.serialtunnel.emit("end"); });
|
||||
socket.on('data', function (b) { socket.serialtunnel.updateBuffer(Buffer.from(b, 'binary')) });
|
||||
socket.serialtunnel.forwardwrite = function (b) { socket.write(b, 'binary') }
|
||||
socket.on('close', function () { socket.serialtunnel.emit('end'); });
|
||||
|
||||
// Pass socket wrapper to the MQTT broker
|
||||
parent.mqttbroker.handle(socket.serialtunnel);
|
||||
|
@ -533,7 +533,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
var request = data.substring(5, 5 + requestLen);
|
||||
//var wantResponse = data.charCodeAt(5 + requestLen);
|
||||
|
||||
if (request == "tcpip-forward") {
|
||||
if (request == 'tcpip-forward') {
|
||||
var addrLen = common.ReadInt(data, 6 + requestLen);
|
||||
if (len < 14 + requestLen + addrLen) return 0;
|
||||
var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
|
||||
|
@ -545,7 +545,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
return 14 + requestLen + addrLen;
|
||||
}
|
||||
|
||||
if (request == "cancel-tcpip-forward") {
|
||||
if (request == 'cancel-tcpip-forward') {
|
||||
var addrLen = common.ReadInt(data, 6 + requestLen);
|
||||
if (len < 14 + requestLen + addrLen) return 0;
|
||||
var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
|
||||
|
@ -557,7 +557,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
return 14 + requestLen + addrLen;
|
||||
}
|
||||
|
||||
if (request == "udp-send-to@amt.intel.com") {
|
||||
if (request == 'udp-send-to@amt.intel.com') {
|
||||
var addrLen = common.ReadInt(data, 6 + requestLen);
|
||||
if (len < 26 + requestLen + addrLen) return 0;
|
||||
var addr = data.substring(10 + requestLen, 10 + requestLen + addrLen);
|
||||
|
@ -748,14 +748,14 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
}
|
||||
}
|
||||
|
||||
socket.addListener("close", function () {
|
||||
socket.addListener('close', function () {
|
||||
socketClosedCount++;
|
||||
parent.debug('mps', 'CIRA connection closed');
|
||||
try { delete obj.ciraConnections[socket.tag.nodeid]; } catch (e) { }
|
||||
obj.parent.ClearConnectivityState(socket.tag.meshid, socket.tag.nodeid, 2);
|
||||
});
|
||||
|
||||
socket.addListener("error", function () {
|
||||
socket.addListener('error', function () {
|
||||
socketErrorCount++;
|
||||
//console.log("MPS Error: " + socket.remoteAddress);
|
||||
});
|
||||
|
@ -802,7 +802,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
*/
|
||||
|
||||
function SendChannelOpen(socket, direct, channelid, windowsize, target, targetport, source, sourceport) {
|
||||
var connectionType = ((direct == true) ? "direct-tcpip" : "forwarded-tcpip");
|
||||
var connectionType = ((direct == true) ? 'direct-tcpip' : 'forwarded-tcpip');
|
||||
if ((target == null) || (target == null)) target = ''; // TODO: Reports of target being undefined that causes target.length to fail. This is a hack.
|
||||
Write(socket, String.fromCharCode(APFProtocol.CHANNEL_OPEN) + common.IntToStr(connectionType.length) + connectionType + common.IntToStr(channelid) + common.IntToStr(windowsize) + common.IntToStr(-1) + common.IntToStr(target.length) + target + common.IntToStr(targetport) + common.IntToStr(source.length) + source + common.IntToStr(sourceport));
|
||||
}
|
||||
|
@ -837,11 +837,11 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
|||
function Write(socket, data) {
|
||||
if (args.mpsdebug) {
|
||||
// Print out sent bytes
|
||||
var buf = Buffer.from(data, "binary");
|
||||
var buf = Buffer.from(data, 'binary');
|
||||
console.log('MPS --> (' + buf.length + '):' + buf.toString('hex'));
|
||||
socket.write(buf);
|
||||
} else {
|
||||
socket.write(Buffer.from(data, "binary"));
|
||||
socket.write(Buffer.from(data, 'binary'));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
/*jshint strict:false */
|
||||
/*jshint -W097 */
|
||||
/*jshint esversion: 6 */
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
// Construct a Mesh Multi-Server object. This is used for MeshCentral-to-MeshCentral communication.
|
||||
module.exports.CreateMultiServer = function (parent, args) {
|
||||
|
@ -552,17 +552,13 @@ module.exports.CreateMultiServer = function (parent, args) {
|
|||
if (msg.fromNodeid != null) { msg.nodeid = msg.fromNodeid; delete msg.fromNodeid; }
|
||||
var cmdstr = JSON.stringify(msg);
|
||||
for (userid in obj.parent.webserver.wssessions) { // Find all connected users for this mesh and send the message
|
||||
var user = obj.parent.webserver.users[userid];
|
||||
if (user) {
|
||||
var rights = user.links[msg.meshid];
|
||||
if (rights != null) { // TODO: Look at what rights are needed for message routing
|
||||
if (parent.webserver.GetMeshRights(userid, msg.meshid) != 0) { // TODO: Look at what rights are needed for message routing
|
||||
var sessions = obj.parent.webserver.wssessions[userid];
|
||||
// Send the message to all users on this server
|
||||
for (i in sessions) { sessions[i].send(cmdstr); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "meshcentral",
|
||||
"version": "0.4.6-p",
|
||||
"version": "0.4.6-q",
|
||||
"keywords": [
|
||||
"Remote Management",
|
||||
"Intel AMT",
|
||||
|
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 46 KiB |
|
@ -1155,6 +1155,14 @@ a {
|
|||
border: none;
|
||||
}
|
||||
|
||||
.i7 {
|
||||
background: url(../images/icons50.png) -300px 0px;
|
||||
height: 50px;
|
||||
width: 50px;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.j1 {
|
||||
background: url(../images/icons16.png) 0px 0px;
|
||||
height: 16px;
|
||||
|
@ -1203,6 +1211,14 @@ a {
|
|||
border: none;
|
||||
}
|
||||
|
||||
.j7 {
|
||||
background: url(../images/icons16.png) -96px 0px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.relayIcon16 {
|
||||
background: url(../images/icon-relay.png);
|
||||
height: 16px;
|
||||
|
@ -1339,7 +1355,7 @@ a {
|
|||
float: left;
|
||||
}
|
||||
|
||||
.si0 {
|
||||
.si1 {
|
||||
background: url(../images/icons16.png) 0px 0px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
|
@ -1347,7 +1363,7 @@ a {
|
|||
float: left;
|
||||
}
|
||||
|
||||
.si1 {
|
||||
.si2 {
|
||||
background: url(../images/icons16.png) -16px 0px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
|
@ -1355,7 +1371,7 @@ a {
|
|||
float: left;
|
||||
}
|
||||
|
||||
.si2 {
|
||||
.si3 {
|
||||
background: url(../images/icons16.png) -32px 0px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
|
@ -1363,7 +1379,7 @@ a {
|
|||
float: left;
|
||||
}
|
||||
|
||||
.si3 {
|
||||
.si4 {
|
||||
background: url(../images/icons16.png) -48px 0px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
|
@ -1371,7 +1387,7 @@ a {
|
|||
float: left;
|
||||
}
|
||||
|
||||
.si4 {
|
||||
.si5 {
|
||||
background: url(../images/icons16.png) -64px 0px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
|
@ -1379,7 +1395,7 @@ a {
|
|||
float: left;
|
||||
}
|
||||
|
||||
.si5 {
|
||||
.si6 {
|
||||
background: url(../images/icons16.png) -80px 0px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
|
@ -1387,6 +1403,14 @@ a {
|
|||
float: left;
|
||||
}
|
||||
|
||||
.si7 {
|
||||
background: url(../images/icons16.png) -96px 0px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
border: none;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.mi {
|
||||
background: url(../images/meshicon50.png) 0px 0px;
|
||||
height: 50px;
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
"nl": "0",
|
||||
"xloc": [
|
||||
"default.handlebars->container->masthead->7->notificationCount",
|
||||
"default-mobile.handlebars->9->229",
|
||||
{ "$ref": "#" }
|
||||
"default-mobile.handlebars->9->229"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -5610,7 +5609,7 @@
|
|||
{
|
||||
"en": "free",
|
||||
"fr": "libre",
|
||||
"pt": "Livre",
|
||||
"pt": "livre",
|
||||
"ja": "無料",
|
||||
"cs": "volné",
|
||||
"nl": "vrij",
|
||||
|
|
|
@ -1327,7 +1327,7 @@
|
|||
count++;
|
||||
|
||||
// Mesh rights
|
||||
var meshrights = meshes[i].links[userinfo._id].rights;
|
||||
var meshrights = GetMeshRights(meshes[i]);
|
||||
var rights = "Partial Rights";
|
||||
if (meshrights == 0xFFFFFFFF) rights = "Full Administrator"; else if (meshrights == 0) rights = "No Rights";
|
||||
|
||||
|
@ -1576,8 +1576,7 @@
|
|||
if (desktop && !xxdialogMode && xxcurrentView == 10) {
|
||||
// Check what keys we are allows to send
|
||||
if (currentNode != null) {
|
||||
var mesh = meshes[currentNode.meshid];
|
||||
var meshrights = mesh.links[userinfo._id].rights;
|
||||
var meshrights = GetMeshRights(currentNode.meshid);
|
||||
var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
|
||||
if (inputAllowed == false) return false;
|
||||
var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
|
||||
|
@ -1594,8 +1593,7 @@
|
|||
if (desktop && !xxdialogMode && xxcurrentView == 10) {
|
||||
// Check what keys we are allows to send
|
||||
if (currentNode != null) {
|
||||
var mesh = meshes[currentNode.meshid];
|
||||
var meshrights = mesh.links[userinfo._id].rights;
|
||||
var meshrights = GetMeshRights(currentNode.meshid);
|
||||
var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
|
||||
if (inputAllowed == false) return false;
|
||||
var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
|
||||
|
@ -1612,8 +1610,7 @@
|
|||
if (desktop && !xxdialogMode && xxcurrentView == 10) {
|
||||
// Check what keys we are allows to send
|
||||
if (currentNode != null) {
|
||||
var mesh = meshes[currentNode.meshid];
|
||||
var meshrights = mesh.links[userinfo._id].rights;
|
||||
var meshrights = GetMeshRights(currentNode.meshid);
|
||||
var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
|
||||
if (inputAllowed == false) return false;
|
||||
var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
|
||||
|
@ -1655,9 +1652,7 @@
|
|||
// Go thru the list of nodes and display them
|
||||
for (var i in nodes) {
|
||||
if (nodes[i].v == false) continue;
|
||||
var mesh2 = meshes[nodes[i].meshid], meshlinks = mesh2.links[userinfo._id];
|
||||
if (meshlinks == null) continue;
|
||||
var meshrights = meshlinks.rights;
|
||||
//var meshrights = GetNodeRights(nodes[i]);
|
||||
|
||||
if (sort == 0) {
|
||||
// Mesh header
|
||||
|
@ -1668,7 +1663,7 @@
|
|||
if (meshes[nodes[i].meshid].mtype == 1) { extra = '<span style=color:lightgray>' + ", Intel® AMT only" + '</span>'; }
|
||||
if (current != null) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
|
||||
r += '<div class=DevSt style=padding-top:4px><span style=float:right>';
|
||||
//r += getMeshActions(mesh2, meshrights);
|
||||
//r += getMeshActions(meshes[nodes[i].meshid], meshrights);
|
||||
r += '</span><span id=MxMESH style=cursor:pointer onclick=goForward("' + nodes[i].meshid + '")>' + EscapeHtml(meshes[nodes[i].meshid].name) + '</span>' + extra + '<span id=DevxHeader' + deviceHeaderId + ' style=color:lightgray></span></div>';
|
||||
current = nodes[i].meshid;
|
||||
displayedMeshes[current] = 1;
|
||||
|
@ -1726,10 +1721,8 @@
|
|||
// Display all empty meshes, we need to do this because users can add devices to these at any time.
|
||||
if (sort == 0) {
|
||||
for (var i in meshes) {
|
||||
var mesh = meshes[i], meshlink = mesh.links[userinfo._id];
|
||||
if (meshlink != null) {
|
||||
var meshrights = meshlink.rights;
|
||||
if (displayedMeshes[mesh._id] == null) {
|
||||
var mesh = meshes[i];
|
||||
if (IsMeshViewable(mesh)) {
|
||||
if ((current != '') && (r != '')) { r += '</tr></table>'; }
|
||||
r += '<div><div colspan=3 class=DevSt><span style=float:right>';
|
||||
//r += getMeshActions(mesh, meshrights);
|
||||
|
@ -1742,7 +1735,6 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
QH('xdevices', '<div style="margin-top:50px;text-align:center"><span style="font-size:30px">' + "No devices" + '</span><br /><br />' + "Use the desktop version of this website to add devices." + '</div>');
|
||||
|
@ -1813,11 +1805,6 @@
|
|||
gotoDevice(nodeid, xxcurrentView, true);
|
||||
}
|
||||
|
||||
function getNodeRights(nodeid) {
|
||||
var node = getNodeFromId(nodeid), mesh = meshes[node.meshid];
|
||||
return mesh.links[userinfo._id].rights;
|
||||
}
|
||||
|
||||
var currentDevicePanel = 0;
|
||||
var currentNode;
|
||||
var powerTimelineNode = null;
|
||||
|
@ -1837,7 +1824,7 @@
|
|||
if (node == null) { goBack(); return; }
|
||||
var mesh = meshes[node.meshid];
|
||||
if (mesh == null) { goBack(); return; }
|
||||
var meshrights = mesh.links[userinfo._id].rights;
|
||||
var meshrights = GetMeshRights(mesh);
|
||||
if (!currentNode || currentNode._id != node._id || refresh == true) {
|
||||
currentNode = node;
|
||||
|
||||
|
@ -2008,8 +1995,7 @@
|
|||
}
|
||||
|
||||
function setupDeviceMenu(op, obj) {
|
||||
var meshrights = 0;
|
||||
if (currentNode) { meshrights = meshes[currentNode.meshid].links[userinfo._id].rights; }
|
||||
var meshrights = GetNodeRights(currentNode);
|
||||
if (op != null) { currentDevicePanel = op; }
|
||||
QV('p10general', currentDevicePanel == 0);
|
||||
QV('p10desktop', currentDevicePanel == 1); // Show if we have remote control rights or desktop view only rights
|
||||
|
@ -2027,7 +2013,7 @@
|
|||
|
||||
function deviceActionFunction() {
|
||||
if (xxdialogMode) return;
|
||||
var meshrights = meshes[currentNode.meshid].links[userinfo._id].rights;
|
||||
var meshrights = GetNodeRights(currentNode);
|
||||
var x = "Select an operation to perform on this device." + '<br /><br />';
|
||||
var y = '<select id=d2deviceop style=float:right;width:170px>';
|
||||
if ((meshrights & 64) != 0) { y += '<option value=100>' + "Wake-up" + '</option>'; } // Wake-up permission
|
||||
|
@ -2117,7 +2103,7 @@
|
|||
|
||||
function editDeviceAmtSettings(nodeid, func) {
|
||||
if (xxdialogMode) return;
|
||||
var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = getNodeRights(nodeid);
|
||||
var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = GetNodeRights(node);
|
||||
if ((meshrights & 4) == 0) return;
|
||||
x += addHtmlValue("Username", '<input id=dp10username style=width:170px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
|
||||
x += addHtmlValue("Password", '<input id=dp10password type=password style=width:170px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
|
||||
|
@ -2166,9 +2152,8 @@
|
|||
|
||||
function p10showiconselector() {
|
||||
if (xxdialogMode) return;
|
||||
var mesh = meshes[currentNode.meshid];
|
||||
var meshrights = mesh.links[userinfo._id].rights;
|
||||
if ((meshrights & 4) == 0) return;
|
||||
var rights = GetNodeRights(currentNode);
|
||||
if ((rights & 4) == 0) return;
|
||||
|
||||
var x = '<table align=center><td>';
|
||||
x += '<div style=display:inline-block class=i1 onclick=p10setIcon(1)></div>';
|
||||
|
@ -2245,7 +2230,7 @@
|
|||
var mesh = meshes[currentNode.meshid];
|
||||
var deskState = 0;
|
||||
if (desktop != null) { deskState = desktop.State; }
|
||||
var meshrights = mesh.links[userinfo._id].rights;
|
||||
var meshrights = GetNodeRights(currentNode);
|
||||
|
||||
// Show the right buttons
|
||||
QV('disconnectbutton1', (deskState != 0));
|
||||
|
@ -3096,7 +3081,7 @@
|
|||
if (currentMesh == null) return;
|
||||
QH('p20meshName', EscapeHtml(currentMesh.name));
|
||||
var meshtype = format("Unknown #{0}", currentMesh.mtype);
|
||||
var meshrights = currentMesh.links[userinfo._id].rights;
|
||||
var meshrights = GetMeshRights(currentMesh);
|
||||
if (currentMesh.mtype == 1) meshtype = "Intel® AMT only, no agent";
|
||||
if (currentMesh.mtype == 2) meshtype = "Managed using a software agent";
|
||||
|
||||
|
@ -3229,7 +3214,7 @@
|
|||
}
|
||||
|
||||
function p20validateAddMeshUserDialog() {
|
||||
var meshrights = currentMesh.links[userinfo._id].rights;
|
||||
var meshrights = GetMeshRights(currentMesh);
|
||||
var nc = !Q('p20fulladmin').checked;
|
||||
QE('p20fulladmin', meshrights == 0xFFFFFFFF);
|
||||
QE('p20editmesh', nc && (meshrights == 0xFFFFFFFF));
|
||||
|
@ -3278,7 +3263,7 @@
|
|||
function p20viewuser(userid) {
|
||||
if (xxdialogMode) return;
|
||||
userid = decodeURIComponent(userid);
|
||||
var r = [], cmeshrights = currentMesh.links[userinfo._id].rights, meshrights = currentMesh.links[userid].rights;
|
||||
var r = [], cmeshrights = GetMeshRights(currentMesh), meshrights = GetMeshRights(currentMesh, userid);
|
||||
if (meshrights == 0xFFFFFFFF) r.push("Full Administrator"); else {
|
||||
if ((meshrights & 1) != 0) r.push("Edit Device Group");
|
||||
if ((meshrights & 2) != 0) r.push("Manage Device Group Users");
|
||||
|
@ -3361,6 +3346,49 @@
|
|||
if (((b & 8) || x) && f) f(x, t);
|
||||
}
|
||||
|
||||
//
|
||||
// Access Control Functions
|
||||
// These must match server
|
||||
//
|
||||
|
||||
// Get the right of a user on a given device group
|
||||
function GetMeshRights(mesh, user) {
|
||||
if (mesh == null) { return 0; }
|
||||
if (user == null) { user = userinfo._id; }
|
||||
if (typeof mesh == 'string') { mesh = meshes[mesh] }
|
||||
if ((mesh == null) || (mesh.links == null)) { return 0; }
|
||||
var rights = mesh.links[user];
|
||||
if (rights == null) { return 0; }
|
||||
return rights.rights;
|
||||
}
|
||||
|
||||
// Returns true if the user can view the given device group
|
||||
function IsMeshViewable(mesh, user) {
|
||||
if (mesh == null) { return 0; }
|
||||
if (user == null) { user = userinfo._id; }
|
||||
if (typeof mesh == 'string') { mesh = meshes[mesh] }
|
||||
if ((mesh == null) || (mesh.links == null)) { return false; }
|
||||
var rights = mesh.links[user];
|
||||
if (rights == null) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return the user rights for a given node
|
||||
function GetNodeRights(node, user) {
|
||||
if (node == null) { return 0; }
|
||||
if (user == null) { user = userinfo._id; }
|
||||
if (typeof node == 'string') { node = getNodeFromId(node); if (node == null) { return 0; } }
|
||||
var mesh = meshes[node.meshid];
|
||||
if ((mesh == null) || (mesh.links == null)) { return 0; }
|
||||
var meshlinks = mesh.links[user];
|
||||
if (meshlinks == null) { return 0; }
|
||||
return meshlinks.rights;
|
||||
}
|
||||
|
||||
//
|
||||
// Generic Methods
|
||||
//
|
||||
|
||||
function putstore(name, val) { try { if ((typeof (localStorage) === 'undefined') || (localStorage.getItem(name) == val)) return; if (val == null) { localStorage.removeItem(name); } else { localStorage.setItem(name, val); } } catch (e) { } if (name[0] != '_') { var s = {}; for (var i = 0, len = localStorage.length; i < len; ++i) { var k = localStorage.key(i); if (k[0] != '_') { s[k] = localStorage.getItem(k); } } meshserver.send({ action: 'userWebState', state: JSON.stringify(s) }); } }
|
||||
function getstore(name, val) { try { if (typeof (localStorage) === 'undefined') return val; var v = localStorage.getItem(name); if ((v == null) || (v == null)) return val; return v; } catch (e) { return val; } }
|
||||
function center() { QS('dialog').left = ((((getDocWidth() - 300) / 2)) + 'px'); deskAdjust(); deskAdjust(); /*drawDeviceTimeline();*/ }
|
||||
|
|
|
@ -2587,8 +2587,7 @@
|
|||
if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
|
||||
// Check what keys we are allows to send
|
||||
if (currentNode != null) {
|
||||
var mesh = meshes[currentNode.meshid];
|
||||
var meshrights = mesh.links[userinfo._id].rights;
|
||||
var meshrights = GetMeshRights(currentNode.meshid);
|
||||
var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
|
||||
if (inputAllowed == false) return false;
|
||||
var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
|
||||
|
@ -2647,8 +2646,7 @@
|
|||
if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
|
||||
// Check what keys we are allows to send
|
||||
if (currentNode != null) {
|
||||
var mesh = meshes[currentNode.meshid];
|
||||
var meshrights = mesh.links[userinfo._id].rights;
|
||||
var meshrights = GetMeshRights(currentNode.meshid);
|
||||
var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
|
||||
if (inputAllowed == false) return false;
|
||||
var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
|
||||
|
@ -2682,8 +2680,7 @@
|
|||
if (!xxdialogMode && xxcurrentView == 11 && desktop && Q('DeskControl').checked) {
|
||||
// Check what keys we are allows to send
|
||||
if (currentNode != null) {
|
||||
var mesh = meshes[currentNode.meshid];
|
||||
var meshrights = mesh.links[userinfo._id].rights;
|
||||
var meshrights = GetMeshRights(currentNode.meshid);
|
||||
var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
|
||||
if (inputAllowed == false) return false;
|
||||
var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
|
||||
|
@ -2783,10 +2780,9 @@
|
|||
for (var i in nodes) {
|
||||
var node = nodes[i];
|
||||
if (node.v == false) continue;
|
||||
var mesh2 = meshes[node.meshid], meshlinks = mesh2.links[userinfo._id];
|
||||
if (meshlinks == null) continue;
|
||||
var meshrights = meshlinks.rights;
|
||||
var mesh2 = meshes[node.meshid];
|
||||
if ((view == 3) && (mesh2.mtype == 1)) continue;
|
||||
var meshrights = GetNodeRights(node);
|
||||
if (sort == 0) {
|
||||
// Mesh header
|
||||
if (node.meshid != current) {
|
||||
|
@ -2948,9 +2944,7 @@
|
|||
if ((sort == 0) && (Q('SearchInput').value == '') && (view < 3)) {
|
||||
var deviceHeaderId2 = deviceHeaderId;
|
||||
for (var i in meshes) {
|
||||
var mesh = meshes[i], meshlink = mesh.links[userinfo._id];
|
||||
if (meshlink != null) {
|
||||
var meshrights = meshlink.rights;
|
||||
var mesh = meshes[i], meshrights = GetMeshRights(mesh);
|
||||
if (displayedMeshes[mesh._id] == null) {
|
||||
if ((current != '') && (r != '')) { r += '</tr></table>'; }
|
||||
r += '<table style=width:100%;padding-top:4px cellpadding=0 cellspacing=0><tr><td colspan=3 class=DevSt>';
|
||||
|
@ -2981,7 +2975,6 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (r != '') {
|
||||
r += '</table>';
|
||||
|
@ -3107,8 +3100,8 @@
|
|||
|
||||
function toggleKvmDevice(node) {
|
||||
if (typeof node == 'string') { node = getNodeFromId(node); } // Convert nodeid to node if needed
|
||||
var mesh = meshes[node.meshid], meshrights = mesh.links[userinfo._id].rights;
|
||||
if ((meshrights & 8) || (meshrights & 256)) { // Requires remote control rights or desktop view only rights
|
||||
var rights = GetNodeRights(node);
|
||||
if ((rights & 8) || (rights & 256)) { // Requires remote control rights or desktop view only rights
|
||||
//var conn = 0;
|
||||
//if ((node.conn & 1) != 0) { conn = 1; } else if ((node.conn & 6) != 0) { conn = 2; } // Check what type of connect we can do (Agent vs AMT)
|
||||
if (node.conn & 1) { connectMultiDesktop(node, 1); }
|
||||
|
@ -3133,8 +3126,8 @@
|
|||
for (var i in nodes) {
|
||||
var node = nodes[i], nodeid = nodes[i]._id;
|
||||
if ((multiDesktop[nodeid] == null) && ((multiDesktopFilter.length == 0) || (multiDesktopFilter.indexOf('devid_' + nodeid) >= 0))) {
|
||||
var mesh = meshes[node.meshid], meshrights = mesh.links[userinfo._id].rights;
|
||||
if ((meshrights & 8) || (meshrights & 256)) { // Requires remote control rights or desktop view only rights
|
||||
var rights = GetNodeRights(node);
|
||||
if ((rights & 8) || (rights & 256)) { // Requires remote control rights or desktop view only rights
|
||||
//var conn = 0;
|
||||
//if ((node.conn & 1) != 0) { conn = 1; } else if ((node.conn & 6) != 0) { conn = 2; } // Check what type of connect we can do (Agent vs AMT)
|
||||
if ((node.conn & 1) && (node.v == true)) { count++; }
|
||||
|
@ -3646,9 +3639,8 @@
|
|||
// Display the "Uninstall Agent" option if allowed and we selected connected devices.
|
||||
for (var i in nodeids) {
|
||||
var node = getNodeFromId(nodeids[i]);
|
||||
var mesh = meshes[node.meshid];
|
||||
var meshrights = mesh.links[userinfo._id].rights;
|
||||
if (((node.conn & 1) != 0) && ((meshrights & 32768) != 0)) { addedOptions += '<option value=104>' + "Uninstall Agent" + '</option>'; break; }
|
||||
var rights = GetNodeRights(node);
|
||||
if (((node.conn & 1) != 0) && ((rights & 32768) != 0)) { addedOptions += '<option value=104>' + "Uninstall Agent" + '</option>'; break; }
|
||||
}
|
||||
|
||||
var x = "Select an operation to perform on all selected devices. Actions will be performed only with proper rights." + '<br /><br />';
|
||||
|
@ -3790,19 +3782,18 @@
|
|||
var nodeid = contextelement.children[1].attributes.onclick.value;
|
||||
var node = getNodeFromId(nodeid.substring(12, nodeid.length - 18));
|
||||
var mesh = meshes[node.meshid];
|
||||
var meshlinks = mesh.links[userinfo._id];
|
||||
var meshrights = meshlinks.rights;
|
||||
var consoleRights = ((meshrights & 16) != 0);
|
||||
var rights = GetNodeRights(node);
|
||||
var consoleRights = ((rights & 16) != 0);
|
||||
|
||||
// Check if we have terminal and file access
|
||||
var terminalAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 512) == 0));
|
||||
var fileAccess = ((meshrights == 0xFFFFFFFF) || ((meshrights & 1024) == 0));
|
||||
var terminalAccess = ((rights == 0xFFFFFFFF) || ((rights & 512) == 0));
|
||||
var fileAccess = ((rights == 0xFFFFFFFF) || ((rights & 1024) == 0));
|
||||
|
||||
QV('cxdesktop', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0) || (node.intelamt && (node.intelamt.state == 2))) && ((meshrights & 8) || (meshrights & 256)));
|
||||
QV('cxterminal', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0) || (node.intelamt && (node.intelamt.state == 2))) && (meshrights & 8) && terminalAccess);
|
||||
QV('cxfiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8) && fileAccess);
|
||||
QV('cxevents', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (meshrights & 8));
|
||||
QV('cxconsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8));
|
||||
QV('cxdesktop', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0) || (node.intelamt && (node.intelamt.state == 2))) && ((rights & 8) || (rights & 256)));
|
||||
QV('cxterminal', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0) || (node.intelamt && (node.intelamt.state == 2))) && (rights & 8) && terminalAccess);
|
||||
QV('cxfiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (rights & 8) && fileAccess);
|
||||
QV('cxevents', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (rights & 8));
|
||||
QV('cxconsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (rights & 8));
|
||||
}
|
||||
|
||||
return haltEvent(event);
|
||||
|
@ -4488,11 +4479,6 @@
|
|||
gotoDevice(nodeid, xxcurrentView, true);
|
||||
}
|
||||
|
||||
function getNodeRights(nodeid) {
|
||||
var node = getNodeFromId(nodeid), mesh = meshes[node.meshid];
|
||||
return mesh.links[userinfo._id].rights;
|
||||
}
|
||||
|
||||
var currentNode;
|
||||
var powerTimelineNode = null;
|
||||
var powerTimelineReq = null;
|
||||
|
@ -4515,7 +4501,7 @@
|
|||
//disconnectAllKvmFunction();
|
||||
var node = getNodeFromId(nodeid);
|
||||
var mesh = meshes[node.meshid];
|
||||
var meshrights = mesh.links[userinfo._id].rights;
|
||||
var meshrights = GetNodeRights(node);
|
||||
if (!currentNode || currentNode._id != node._id || refresh == true) {
|
||||
currentNode = node;
|
||||
|
||||
|
@ -4857,13 +4843,13 @@
|
|||
|
||||
function deviceActionFunction() {
|
||||
if (xxdialogMode) return;
|
||||
var meshrights = meshes[currentNode.meshid].links[userinfo._id].rights;
|
||||
var rights = GetNodeRights(currentNode);
|
||||
var x = "Select an operation to perform on this device." + '<br /><br />';
|
||||
var y = '<select id=d2deviceop style=float:right;width:250px>';
|
||||
if ((meshrights & 64) != 0) { y += '<option value=100>' + "Wake-up" + '</option>'; } // Wake-up permission
|
||||
if ((meshrights & 8) != 0) { y += '<option value=4>' + "Sleep" + '</option><option value=3>' + "Reset" + '</option><option value=2>' + "Power off" + '</option>'; } // Remote control permission
|
||||
if ((rights & 64) != 0) { y += '<option value=100>' + "Wake-up" + '</option>'; } // Wake-up permission
|
||||
if ((rights & 8) != 0) { y += '<option value=4>' + "Sleep" + '</option><option value=3>' + "Reset" + '</option><option value=2>' + "Power off" + '</option>'; } // Remote control permission
|
||||
if ((currentNode.conn & 16) != 0) { y += '<option value=103>' + "Send MQTT Message" + '</option>'; }
|
||||
if (((currentNode.conn & 1) != 0) && ((meshrights & 32768) != 0)) { y += '<option value=104>' + "Uninstall Agent" + '</option>'; }
|
||||
if (((currentNode.conn & 1) != 0) && ((rights & 32768) != 0)) { y += '<option value=104>' + "Uninstall Agent" + '</option>'; }
|
||||
y += '</select>';
|
||||
x += addHtmlValue("Operation", y);
|
||||
setDialogMode(2, "Device Action", 3, deviceActionFunctionEx, x);
|
||||
|
@ -4975,7 +4961,7 @@
|
|||
|
||||
function editDeviceAmtSettings(nodeid, func, arg) {
|
||||
if (xxdialogMode) return;
|
||||
var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = getNodeRights(nodeid);
|
||||
var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = GetNodeRights(node);
|
||||
if ((meshrights & 4) == 0) return;
|
||||
x += addHtmlValue("Username", '<input id=dp10username style=width:230px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
|
||||
x += addHtmlValue("Password", '<input id=dp10password type=password style=width:230px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
|
||||
|
@ -5049,7 +5035,7 @@
|
|||
// List all available alternative groups
|
||||
var y = '<select id=p10newGroup style=width:236px>', count = 0;
|
||||
for (var i in meshes) {
|
||||
var meshrights = meshes[i].links[userinfo._id].rights;
|
||||
var meshrights = GetMeshRights(i);
|
||||
if ((meshes[i]._id != targetMeshId) && (meshrights & 4)) { count++; y += '<option value=\'' + meshes[i]._id + '\'>' + meshes[i].name + '</option>'; }
|
||||
}
|
||||
y += '</select>';
|
||||
|
@ -5195,17 +5181,16 @@
|
|||
|
||||
function p10showiconselector() {
|
||||
if (xxdialogMode) return;
|
||||
var mesh = meshes[currentNode.meshid];
|
||||
var meshrights = mesh.links[userinfo._id].rights;
|
||||
if ((meshrights & 4) == 0) return;
|
||||
if ((GetNodeRights(currentNode) & 4) == 0) return;
|
||||
|
||||
var x = '<br><div style=display:inline-block;width:40px></div>';
|
||||
var x = '<br><div style=display:inline-block;width:16px></div>';
|
||||
x += '<div tabindex=0 style=display:inline-block class=i1 onclick=p10setIcon(1) onkeypress="if (event.key==\'Enter\') p10setIcon(1)"></div>';
|
||||
x += '<div tabindex=0 style=display:inline-block class=i2 onclick=p10setIcon(2) onkeypress="if (event.key==\'Enter\') p10setIcon(2)"></div>';
|
||||
x += '<div tabindex=0 style=display:inline-block class=i3 onclick=p10setIcon(3) onkeypress="if (event.key==\'Enter\') p10setIcon(3)"></div>';
|
||||
x += '<div tabindex=0 style=display:inline-block class=i4 onclick=p10setIcon(4) onkeypress="if (event.key==\'Enter\') p10setIcon(4)"></div>';
|
||||
x += '<div tabindex=0 style=display:inline-block class=i5 onclick=p10setIcon(5) onkeypress="if (event.key==\'Enter\') p10setIcon(5)"></div>';
|
||||
x += '<div tabindex=0 style=display:inline-block class=i6 onclick=p10setIcon(6) onkeypress="if (event.key==\'Enter\') p10setIcon(6)"></div><br><br>';
|
||||
x += '<div tabindex=0 style=display:inline-block class=i6 onclick=p10setIcon(6) onkeypress="if (event.key==\'Enter\') p10setIcon(6)"></div>';
|
||||
x += '<div tabindex=0 style=display:inline-block class=i7 onclick=p10setIcon(7) onkeypress="if (event.key==\'Enter\') p10setIcon(7)"></div><br><br>';
|
||||
setDialogMode(2, "Icon Selection", 0, null, x);
|
||||
QV('id_dialogclose', true);
|
||||
}
|
||||
|
@ -5292,14 +5277,14 @@
|
|||
var mesh = meshes[currentNode.meshid];
|
||||
var deskState = 0;
|
||||
if (desktop != null) { deskState = desktop.State; }
|
||||
var meshrights = mesh.links[userinfo._id].rights;
|
||||
var rights = GetNodeRights(currentNode);
|
||||
|
||||
// Show the right buttons
|
||||
QV('disconnectbutton1span', (deskState != 0));
|
||||
QV('connectbutton1span', (deskState == 0) && ((meshrights & 8) || (meshrights & 256)) && (mesh.mtype == 2) && (currentNode.agent.caps & 1));
|
||||
QV('connectbutton1span', (deskState == 0) && ((rights & 8) || (rights & 256)) && (mesh.mtype == 2) && (currentNode.agent.caps & 1));
|
||||
QV('connectbutton1hspan',
|
||||
(deskState == 0) &&
|
||||
(meshrights & 8) &&
|
||||
(rights & 8) &&
|
||||
((mesh.mtype == 1) ||
|
||||
((currentNode.intelamt != null) &&
|
||||
(currentNode.intelamt.state == 2) &&
|
||||
|
@ -5314,7 +5299,7 @@
|
|||
QV('d7meshkvm', (webRtcDesktop) || ((mesh.mtype == 2) && (currentNode.agent.caps & 1) && ((deskState == false) || (desktop.contype == 1))));
|
||||
|
||||
// Enable buttons
|
||||
var inputAllowed = (meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) == 0));
|
||||
var inputAllowed = (rights == 0xFFFFFFFF) || (((rights & 8) != 0) && ((rights & 256) == 0) && ((rights & 4096) == 0));
|
||||
var online = ((currentNode.conn & 1) != 0); // If Agent (1) connected, enable remote desktop
|
||||
QE('connectbutton1', online);
|
||||
var hwonline = ((currentNode.conn & 6) != 0); // If CIRA (2) or AMT (4) connected, enable hardware terminal
|
||||
|
@ -5330,8 +5315,8 @@
|
|||
QE('deskkeys', deskState == 3);
|
||||
|
||||
// Display this only if we have Chat & Notify permissions
|
||||
QV('DeskChatButton', ((meshrights & 16384) != 0) && (browserfullscreen == false) && (inputAllowed) && (mesh.mtype == 2) && online);
|
||||
QV('DeskNotifyButton', ((meshrights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && (currentNode.agent.id < 5) && (inputAllowed) && (mesh.mtype == 2) && online);
|
||||
QV('DeskChatButton', ((rights & 16384) != 0) && (browserfullscreen == false) && (inputAllowed) && (mesh.mtype == 2) && online);
|
||||
QV('DeskNotifyButton', ((rights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && (currentNode.agent.id < 5) && (inputAllowed) && (mesh.mtype == 2) && online);
|
||||
|
||||
QV('DeskToolsButton', (inputAllowed) && (mesh.mtype == 2) && online);
|
||||
QV('DeskOpenWebButton', (browserfullscreen == false) && (inputAllowed) && (mesh.mtype == 2) && online);
|
||||
|
@ -5339,7 +5324,7 @@
|
|||
QV('DeskControlSpan', inputAllowed)
|
||||
QV('deskActionsBtn', (browserfullscreen == false));
|
||||
QV('deskActionsSettings', (browserfullscreen == false));
|
||||
if (meshrights & 8) { Q('DeskControl').checked = (getstore('DeskControl', 1) == 1); } else { Q('DeskControl').checked = false; }
|
||||
if (rights & 8) { Q('DeskControl').checked = (getstore('DeskControl', 1) == 1); } else { Q('DeskControl').checked = false; }
|
||||
if (online == false) QV('DeskTools', false);
|
||||
}
|
||||
|
||||
|
@ -6966,8 +6951,8 @@
|
|||
consoleNode = currentNode;
|
||||
|
||||
var mesh = meshes[consoleNode.meshid];
|
||||
var meshrights = mesh.links[userinfo._id].rights;
|
||||
if ((meshrights & 16) != 0) {
|
||||
var rights = GetNodeRights(currentNode);
|
||||
if ((rights & 16) != 0) {
|
||||
if (consoleNode.consoleText == null) { consoleNode.consoleText = ''; }
|
||||
if (samenode == false) {
|
||||
QH('p15agentConsoleText', consoleNode.consoleText);
|
||||
|
@ -7443,8 +7428,7 @@
|
|||
count++;
|
||||
|
||||
// Mesh rights
|
||||
var meshrights = 0;
|
||||
if (meshes[i].links[userinfo._id]) { meshrights = meshes[i].links[userinfo._id].rights; }
|
||||
var meshrights = GetMeshRights(meshes[i]);
|
||||
var rights = "Partial Rights";
|
||||
if (meshrights == 0xFFFFFFFF) rights = "Full Administrator"; else if (meshrights == 0) rights = "No Rights";
|
||||
|
||||
|
@ -7511,8 +7495,7 @@
|
|||
if (currentMesh == null) return;
|
||||
QH('p20meshName', EscapeHtml(currentMesh.name));
|
||||
var meshtype = format("Unknown #{0}", currentMesh.mtype);
|
||||
var meshrights = 0;
|
||||
try { meshrights = currentMesh.links[userinfo._id].rights; } catch (ex) { }
|
||||
var meshrights = GetMeshRights(currentMesh);
|
||||
if (currentMesh.mtype == 1) meshtype = "Intel® AMT only, no agent";
|
||||
if (currentMesh.mtype == 2) meshtype = "Managed using a software agent";
|
||||
|
||||
|
@ -7580,10 +7563,9 @@
|
|||
if (meshrights & 1) { x += '<br><input type=button value=' + "Notes" + ' title=\"' + "View notes about this device group" + '\" onclick=showNotes(false,"' + encodeURIComponent(currentMesh._id) + '") />'; }
|
||||
|
||||
x += '<br style=clear:both><br>';
|
||||
var currentMeshLinks = currentMesh.links[userinfo._id];
|
||||
if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += '<a href=# onclick="return p20showAddMeshUserDialog()" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Users" + '</a>'; }
|
||||
if (meshrights & 2) { x += '<a href=# onclick="return p20showAddMeshUserDialog()" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Users" + '</a>'; }
|
||||
|
||||
if ((meshrights & 4) != 0) {
|
||||
if (meshrights & 4) {
|
||||
if (currentMesh.mtype == 1) {
|
||||
x += '<a href=# onclick=\'return addCiraDeviceToMesh(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title=\"' + "Add a new Intel® AMT computer that is located on the internet." + '\"><img src=images/icon-installmesh.png border=0 height=12 width=12> ' + "Install CIRA" + '</a>';
|
||||
x += '<a href=# onclick=\'return addDeviceToMesh(\"' + currentMesh._id + '\")\' style=cursor:pointer;margin-right:10px title=\"' + "Add a new Intel® AMT computer that is located on the local network." + '\"><img src=images/icon-installmesh.png border=0 height=12 width=12> ' + "Install local" + '</a>';
|
||||
|
@ -7838,7 +7820,7 @@
|
|||
Q('dp20username').focus();
|
||||
} else {
|
||||
setDialogMode(2, "Edit User Device Group Permissions", 7, p20showAddMeshUserDialogEx, x, userid);
|
||||
var cmeshrights = currentMesh.links[userinfo._id].rights, meshrights = currentMesh.links[userid].rights;
|
||||
var cmeshrights = GetMeshRights(currentMesh), meshrights = GetMeshRights(currentMesh, userid);
|
||||
if (meshrights == 0xFFFFFFFF) {
|
||||
Q('p20fulladmin').checked = true;
|
||||
} else {
|
||||
|
@ -7877,7 +7859,7 @@
|
|||
}
|
||||
|
||||
function p20validateAddMeshUserDialog() {
|
||||
var meshrights = currentMesh.links[userinfo._id].rights;
|
||||
var meshrights = GetMeshRights(currentMesh);
|
||||
var ok = true;
|
||||
if (Q('dp20username')) {
|
||||
var xusers = Q('dp20username').value.split(',');
|
||||
|
@ -7964,7 +7946,7 @@
|
|||
function p20viewuser(userid) {
|
||||
if (xxdialogMode) return;
|
||||
var xuserid = decodeURIComponent(userid);
|
||||
var cmeshrights = currentMesh.links[userinfo._id].rights, meshrights = currentMesh.links[xuserid].rights;
|
||||
var cmeshrights = GetMeshRights(currentMesh), meshrights = GetMeshRights(currentMesh, xuserid);
|
||||
if (((userinfo._id) != xuserid) && (cmeshrights == 0xFFFFFFFF || (((cmeshrights & 2) != 0) && (meshrights != 0xFFFFFFFF)))) {
|
||||
p20showAddMeshUserDialog(userid);
|
||||
} else {
|
||||
|
@ -10063,7 +10045,49 @@
|
|||
if (pname == null) { Q('p43iframe').src = ''; } else { QH('p43title', title); Q('p43iframe').src = '/pluginadmin.ashx?pin=' + pname; go(43); }
|
||||
}
|
||||
|
||||
//
|
||||
// Access Control Functions
|
||||
// These must match server
|
||||
//
|
||||
|
||||
// Get the right of a user on a given device group
|
||||
function GetMeshRights(mesh, user) {
|
||||
if (mesh == null) { return 0; }
|
||||
if (user == null) { user = userinfo._id; }
|
||||
if (typeof mesh == 'string') { mesh = meshes[mesh] }
|
||||
if ((mesh == null) || (mesh.links == null)) { return 0; }
|
||||
var rights = mesh.links[user];
|
||||
if (rights == null) { return 0; }
|
||||
return rights.rights;
|
||||
}
|
||||
|
||||
// Returns true if the user can view the given device group
|
||||
function IsMeshViewable(mesh, user) {
|
||||
if (mesh == null) { return 0; }
|
||||
if (user == null) { user = userinfo._id; }
|
||||
if (typeof mesh == 'string') { mesh = meshes[mesh] }
|
||||
if ((mesh == null) || (mesh.links == null)) { return false; }
|
||||
var rights = mesh.links[user];
|
||||
if (rights == null) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return the user rights for a given node
|
||||
function GetNodeRights(node, user) {
|
||||
if (node == null) { return 0; }
|
||||
if (user == null) { user = userinfo._id; }
|
||||
if (typeof node == 'string') { node = getNodeFromId(node); if (node == null) { return 0; } }
|
||||
var mesh = meshes[node.meshid];
|
||||
if ((mesh == null) || (mesh.links == null)) { return 0; }
|
||||
var meshlinks = mesh.links[user];
|
||||
if (meshlinks == null) { return 0; }
|
||||
return meshlinks.rights;
|
||||
}
|
||||
|
||||
//
|
||||
// Generic methods
|
||||
//
|
||||
|
||||
function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); }
|
||||
function putstore(name, val) {
|
||||
try {
|
||||
|
|
70
webserver.js
|
@ -2065,7 +2065,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
if ((splitpath.length < 3) || (splitpath[0] != 'user' && splitpath[0] != 'mesh') || (splitpath[1] != domain.id)) return null; // Basic validation
|
||||
var objid = splitpath[0] + '/' + splitpath[1] + '/' + splitpath[2];
|
||||
if (splitpath[0] == 'user' && (objid != user._id)) return null; // User validation, only self allowed
|
||||
if (splitpath[0] == 'mesh') { var link = user.links[objid]; if ((link == null) || (link.rights == null) || ((link.rights & 32) == 0)) { return null; } } // Check mesh server file rights
|
||||
if (splitpath[0] == 'mesh') { if ((obj.GetMeshRights(user, objid) & 32) == 0) { return null; } } // Check mesh server file rights
|
||||
if (splitpath[1] != '') { serverpath += '-' + splitpath[1]; } // Add the domain if needed
|
||||
serverpath += ('/' + splitpath[0] + '-' + splitpath[2]);
|
||||
for (var i = 3; i < splitpath.length; i++) { if (obj.common.IsFilenameValid(splitpath[i]) == true) { serverpath += '/' + splitpath[i]; filename = splitpath[i]; } else { return null; } } // Check that each folder is correct
|
||||
|
@ -2265,8 +2265,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
if (!node.intelamt) { console.log('ERR: Not AMT node'); try { ws.close(); } catch (e) { } return; } // Disconnect websocket
|
||||
|
||||
// Check if this user has permission to manage this computer
|
||||
var meshlinks = user.links[node.meshid];
|
||||
if ((!meshlinks) || (!meshlinks.rights) || ((meshlinks.rights & MESHRIGHT_REMOTECONTROL) == 0)) { console.log('ERR: Access denied (2)'); try { ws.close(); } catch (e) { } return; }
|
||||
if ((obj.GetMeshRights(user, node.meshid) & MESHRIGHT_REMOTECONTROL) == 0) { console.log('ERR: Access denied (2)'); try { ws.close(); } catch (e) { } return; }
|
||||
|
||||
// Check what connectivity is available for this node
|
||||
var state = parent.GetConnectivityState(req.query.host);
|
||||
|
@ -2998,9 +2997,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
|
||||
// If required, check if this user has rights to do this
|
||||
if ((obj.parent.config.settings != null) && ((obj.parent.config.settings.lockagentdownload == true) || (domain.lockagentdownload == true))) {
|
||||
var user = obj.users[req.session.userid];
|
||||
if ((user == null) || (mesh.links[user._id] == null) || ((mesh.links[user._id].rights & 1) == 0)) { res.sendStatus(401); return; }
|
||||
if (domain.id != mesh.domain) { res.sendStatus(401); return; }
|
||||
if ((domain.id != mesh.domain) || ((obj.GetMeshRights(req.session.userid, mesh) & 1) == 0)) { res.sendStatus(401); return; }
|
||||
}
|
||||
|
||||
var meshidhex = Buffer.from(req.query.meshid.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
|
||||
|
@ -3168,9 +3165,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
|
||||
// If required, check if this user has rights to do this
|
||||
if ((obj.parent.config.settings != null) && ((obj.parent.config.settings.lockagentdownload == true) || (domain.lockagentdownload == true))) {
|
||||
var user = obj.users[req.session.userid];
|
||||
if ((user == null) || (mesh.links[user._id] == null) || ((mesh.links[user._id].rights & 1) == 0)) { res.sendStatus(401); return; }
|
||||
if (domain.id != mesh.domain) { res.sendStatus(401); return; }
|
||||
if ((domain.id != mesh.domain) || ((obj.GetMeshRights(req.session.userid, mesh) & 1) == 0)) { res.sendStatus(401); return; }
|
||||
}
|
||||
|
||||
var meshidhex = Buffer.from(req.query.meshid.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
|
||||
|
@ -3257,9 +3252,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
|
||||
// If needed, check if this user has rights to do this
|
||||
if ((obj.parent.config.settings != null) && ((obj.parent.config.settings.lockagentdownload == true) || (domain.lockagentdownload == true))) {
|
||||
var user = obj.users[req.session.userid];
|
||||
if ((user == null) || (mesh.links[user._id] == null) || ((mesh.links[user._id].rights & 1) == 0)) { res.sendStatus(401); return; }
|
||||
if (domain.id != mesh.domain) { res.sendStatus(401); return; }
|
||||
if ((domain.id != mesh.domain) || ((obj.GetMeshRights(req.session.userid, mesh) & 1) == 0)) { res.sendStatus(401); return; }
|
||||
}
|
||||
|
||||
var meshidhex = Buffer.from(req.query.id.replace(/\@/g, '+').replace(/\$/g, '/'), 'base64').toString('hex').toUpperCase();
|
||||
|
@ -3297,9 +3290,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
var node = docs[0];
|
||||
|
||||
// Check if we have right to this node
|
||||
var rights = 0;
|
||||
for (var i in user.links) { if (i == node.meshid) { rights = user.links[i].rights; } }
|
||||
if (rights == 0) { res.sendStatus(401); return; }
|
||||
if (obj.GetMeshRights(user, node.meshid) == 0) { res.sendStatus(401); return; }
|
||||
|
||||
// Get the list of power events and send them
|
||||
res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/csv', 'Content-Disposition': 'attachment; filename="powerevents.csv"' });
|
||||
|
@ -3772,8 +3763,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
if (agent == null) return;
|
||||
|
||||
// Check we have agent rights
|
||||
var rights = user.links[agent.dbMeshKey].rights;
|
||||
if ((rights != null) && ((rights & MESHRIGHT_AGENTCONSOLE) != 0) || (user.siteadmin == 0xFFFFFFFF)) { agent.close(disconnectMode); }
|
||||
if (((obj.GetMeshRights(user, agent.dbMeshKey) & MESHRIGHT_AGENTCONSOLE) != 0) || (user.siteadmin == 0xFFFFFFFF)) { agent.close(disconnectMode); }
|
||||
};
|
||||
|
||||
// Send the core module to the mesh agent
|
||||
|
@ -3787,8 +3777,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
if (agent == null) return;
|
||||
|
||||
// Check we have agent rights
|
||||
var rights = user.links[agent.dbMeshKey].rights;
|
||||
if ((rights != null) && ((rights & MESHRIGHT_AGENTCONSOLE) != 0) || (user.siteadmin == 0xFFFFFFFF)) {
|
||||
if (((obj.GetMeshRights(user, agent.dbMeshKey) & MESHRIGHT_AGENTCONSOLE) != 0) || (user.siteadmin == 0xFFFFFFFF)) {
|
||||
if (coretype == 'clear') {
|
||||
// Clear the mesh agent core
|
||||
agent.agentCoreCheck = 1000; // Tell the agent object we are using a custom core.
|
||||
|
@ -3907,6 +3896,32 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Access Control Functions
|
||||
//
|
||||
|
||||
// Return the node and rights for a given nodeid
|
||||
obj.GetNodeWithRights = function (domain, user, nodeid, func) {
|
||||
// Perform user pre-validation
|
||||
if ((user == null) || (nodeid == null)) { func(null, 0, false); return; } // Invalid user
|
||||
if (typeof user == 'string') { user = obj.users[user]; }
|
||||
if ((user == null) || (user.links == null)) { func(null, 0, false); return; } // No rights
|
||||
|
||||
// Perform node pre-validation
|
||||
if (obj.common.validateString(nodeid, 0, 128) == false) { func(null, 0, false); return; } // Invalid nodeid
|
||||
const snode = nodeid.split('/');
|
||||
if ((snode.length != 3) || (snode[0] != 'node')) { func(null, 0, false); return; } // Invalid nodeid
|
||||
if ((domain != null) && (snode[1] != domain.id)) { func(null, 0, false); return; } // Invalid domain
|
||||
|
||||
// Check that we have permissions for this node.
|
||||
db.Get(nodeid, function (err, nodes) {
|
||||
if ((nodes == null) || (nodes.length != 1)) { func(null, 0, false); return; } // No such nodeid
|
||||
var rights = user.links[nodes[0].meshid];
|
||||
if (rights == null) { func(null, 0, false); return; } // No rights to this mesh
|
||||
func(nodes[0], rights.rights, true);
|
||||
});
|
||||
}
|
||||
|
||||
// Returns a list of all meshes that this user has some rights too
|
||||
obj.GetAllMeshWithRights = function (user, rights) {
|
||||
if (typeof user == 'string') { user = obj.users[user]; }
|
||||
|
@ -4076,9 +4091,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
if (typeof command.sessionid != 'string') return;
|
||||
var splitsessionid = command.sessionid.split('/');
|
||||
// Check that we are in the same domain and the user has rights over this node.
|
||||
if ((splitsessionid[0] == 'user') && (splitsessionid[1] == domainid)) {
|
||||
if ((splitsessionid.length == 4) && (splitsessionid[0] == 'user') && (splitsessionid[1] == domainid)) {
|
||||
// Check if this user has rights to get this message
|
||||
//if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 16) == 0)) return; // TODO!!!!!!!!!!!!!!!!!!!!!
|
||||
if (obj.GetMeshRights(splitsessionid[0] + '/' + splitsessionid[1] + '/' + splitsessionid[2], meshid) == 0) return; // TODO: Check if this is ok
|
||||
|
||||
// See if the session is connected. If so, go ahead and send this message to the target node
|
||||
var ws = obj.wssessions2[command.sessionid];
|
||||
|
@ -4101,7 +4116,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
// Check that we are in the same domain and the user has rights over this node.
|
||||
if ((splituserid[0] == 'user') && (splituserid[1] == domainid)) {
|
||||
// Check if this user has rights to get this message
|
||||
//if (mesh.links[user._id] == null || ((mesh.links[user._id].rights & 16) == 0)) return; // TODO!!!!!!!!!!!!!!!!!!!!!
|
||||
if (obj.GetMeshRights(command.userid, meshid) == 0) return; // TODO: Check if this is ok
|
||||
|
||||
// See if the session is connected
|
||||
var sessions = obj.wssessions[command.userid];
|
||||
|
@ -4120,17 +4135,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
|||
} else { // Route this command to the mesh
|
||||
command.nodeid = nodeid;
|
||||
var cmdstr = JSON.stringify(command);
|
||||
for (var userid in obj.wssessions) { // Find all connected users for this mesh and send the message
|
||||
var user = obj.users[userid];
|
||||
if ((user != null) && (user.links != null)) {
|
||||
var rights = user.links[meshid];
|
||||
if (rights != null) { // TODO: Look at what rights are needed for message routing
|
||||
if (obj.GetMeshRights(userid, meshid) == 0) return; // TODO: Check if this is ok
|
||||
|
||||
// Find all connected users for this mesh and send the message
|
||||
for (var userid in obj.wssessions) {
|
||||
var xsessions = obj.wssessions[userid];
|
||||
// Send the message to all users on this server
|
||||
for (i in xsessions) { try { xsessions[i].send(cmdstr); } catch (e) { } }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send the message to all users of other servers
|
||||
if (parent.multiServer != null) {
|
||||
|
|