From 3a161502b029c01f31467bd9d8be7c5e9f0267a3 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Wed, 18 Sep 2019 12:05:33 -0700 Subject: [PATCH] Added View Self Events only device group permission. --- db.js | 2 ++ meshagent.js | 5 +++-- meshuser.js | 44 ++++++++++++++++++++++++++++++++-------- views/default.handlebars | 5 +++++ 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/db.js b/db.js index 3b79e88e..0cf07475 100644 --- a/db.js +++ b/db.js @@ -567,6 +567,7 @@ module.exports.CreateDB = function (parent, func) { obj.GetUserEvents = function (ids, domain, username, func) { obj.eventsfile.find({ domain: domain, $or: [{ ids: { $in: ids } }, { username: username }] }).project({ type: 0, _id: 0, domain: 0, ids: 0, node: 0 }).sort({ time: -1 }).toArray(func); }; obj.GetUserEventsWithLimit = function (ids, domain, username, limit, func) { obj.eventsfile.find({ domain: domain, $or: [{ ids: { $in: ids } }, { username: username }] }).project({ type: 0, _id: 0, domain: 0, ids: 0, node: 0 }).sort({ time: -1 }).limit(limit).toArray(func); }; obj.GetNodeEventsWithLimit = function (nodeid, domain, limit, func) { obj.eventsfile.find({ domain: domain, nodeid: nodeid }).project({ type: 0, etype: 0, _id: 0, domain: 0, ids: 0, node: 0, nodeid: 0 }).sort({ time: -1 }).limit(limit).toArray(func); }; + obj.GetNodeEventsSelfWithLimit = function (nodeid, domain, userid, limit, func) { obj.eventsfile.find({ domain: domain, nodeid: nodeid, userid: { $in: [userid, null] } }).project({ type: 0, etype: 0, _id: 0, domain: 0, ids: 0, node: 0, nodeid: 0 }).sort({ time: -1 }).limit(limit).toArray(func); }; obj.RemoveAllEvents = function (domain) { obj.eventsfile.deleteMany({ domain: domain }, { multi: true }); }; obj.RemoveAllNodeEvents = function (domain, nodeid) { obj.eventsfile.deleteMany({ domain: domain, nodeid: nodeid }, { multi: true }); }; @@ -669,6 +670,7 @@ module.exports.CreateDB = function (parent, func) { } }; obj.GetNodeEventsWithLimit = function (nodeid, domain, limit, func) { if (obj.databaseType == 1) { obj.eventsfile.find({ domain: domain, nodeid: nodeid }, { type: 0, etype: 0, _id: 0, domain: 0, ids: 0, node: 0, nodeid: 0 }).sort({ time: -1 }).limit(limit).exec(func); } else { obj.eventsfile.find({ domain: domain, nodeid: nodeid }, { type: 0, etype: 0, _id: 0, domain: 0, ids: 0, node: 0, nodeid: 0 }).sort({ time: -1 }).limit(limit, func); } }; + obj.GetNodeEventsSelfWithLimit = function (nodeid, domain, userid, limit, func) { if (obj.databaseType == 1) { obj.eventsfile.find({ domain: domain, nodeid: nodeid, userid: { $in: [userid, null] } }, { type: 0, etype: 0, _id: 0, domain: 0, ids: 0, node: 0, nodeid: 0 }).sort({ time: -1 }).limit(limit).exec(func); } else { obj.eventsfile.find({ domain: domain, nodeid: nodeid }, { type: 0, etype: 0, _id: 0, domain: 0, ids: 0, node: 0, nodeid: 0 }).sort({ time: -1 }).limit(limit, func); } }; obj.RemoveAllEvents = function (domain) { obj.eventsfile.remove({ domain: domain }, { multi: true }); }; obj.RemoveAllNodeEvents = function (domain, nodeid) { obj.eventsfile.remove({ domain: domain, nodeid: nodeid }, { multi: true }); }; diff --git a/meshagent.js b/meshagent.js index 5a66e5a4..02014634 100644 --- a/meshagent.js +++ b/meshagent.js @@ -1206,12 +1206,13 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) { // Log a value in the event log if ((typeof command.msg == 'string') && (command.msg.length < 4096)) { var event = { etype: 'node', action: 'agentlog', nodeid: obj.dbNodeKey, domain: domain.id, msg: command.msg }; + var targets = ['*', obj.dbMeshKey]; if (typeof command.userid == 'string') { var loguser = parent.users[command.userid]; - if (loguser) { event.userid = command.userid; event.username = loguser.name; } + if (loguser) { event.userid = command.userid; event.username = loguser.name; targets.push(command.userid); } } if ((typeof command.sessionid == 'string') && (command.sessionid.length < 500)) { event.sessionid = command.sessionid; } - parent.parent.DispatchEvent(['*', obj.dbMeshKey], obj, event); + parent.parent.DispatchEvent(targets, obj, event); } break; } diff --git a/meshuser.js b/meshuser.js index 0dfced2e..24586937 100644 --- a/meshuser.js +++ b/meshuser.js @@ -819,18 +819,44 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use }); } } else if (common.validateString(command.nodeid, 0, 128) == true) { // Device filtered events - // TODO: Check that the user has access to this nodeid - var limit = 10000; - if (common.validateInt(command.limit, 1, 60000) == true) { limit = command.limit; } + // Check that the user has access to this nodeid + if (obj.user.links == null) return; + db.Get(command.nodeid, function (err, nodes) { + if (nodes.length != 1) return; + const node = nodes[0]; - // Send the list of most recent events for this session, up to 'limit' count - db.GetNodeEventsWithLimit(command.nodeid, 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) { } + var meshlink = obj.user.links[node.meshid]; + if ((meshlink != null) && (meshlink.rights != 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 ((meshlink.rights & 8192) != 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) { + if (err != null) return; + try { ws.send(JSON.stringify({ action: 'events', events: docs, nodeid: command.nodeid, 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) { + if (err != null) return; + try { ws.send(JSON.stringify({ action: 'events', events: docs, nodeid: command.nodeid, tag: command.tag })); } catch (ex) { } + }); + } + } }); } else { + // Create a filter for device groups + if (obj.user.links == null) return; + // All events - var filter = user.subscriptions; + var exGroupFilter2 = [], filter = [], filter2 = user.subscriptions; + + // 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 & 8192) != 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]); } } + if ((command.limit == null) || (typeof command.limit != 'number')) { // Send the list of all events for this session db.GetEvents(filter, domain.id, function (err, docs) { @@ -2192,7 +2218,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (node2.intelamt && node2.intelamt.pass) delete node2.intelamt.pass; // Remove the Intel AMT password before eventing this. event.node = node2; 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], obj, event); + parent.parent.DispatchEvent(['*', node.meshid, user._id], obj, event); } } }); diff --git a/views/default.handlebars b/views/default.handlebars index 6f764a2c..224f92dc 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -7027,6 +7027,7 @@ x += '
'; x += '
'; x += '
'; + x += '
'; x += ''; if (userid == null) { setDialogMode(2, "Add Users to Device Group", 3, p20showAddMeshUserDialogEx, x); @@ -7052,6 +7053,7 @@ if (meshrights & 32) { Q('p20meshserverfiles').checked = true; } if (meshrights & 64) { Q('p20wakedevices').checked = true; } if (meshrights & 128) { Q('p20editnotes').checked = true; } + if (meshrights & 8192) { Q('p20limitevents').checked = true; } } } p20validateAddMeshUserDialog(); @@ -7105,6 +7107,7 @@ QE('p20meshserverfiles', !Q('p20fulladmin').checked); QE('p20wakedevices', !Q('p20fulladmin').checked); QE('p20editnotes', !Q('p20fulladmin').checked); + QE('p20limitevents', !Q('p20fulladmin').checked); QE('p20remoteview', !Q('p20fulladmin').checked && Q('p20remotecontrol').checked); QE('p20remotelimitedinput', !Q('p20fulladmin').checked && Q('p20remotecontrol').checked && !Q('p20remoteview').checked); QE('p20noterminal', !Q('p20fulladmin').checked && Q('p20remotecontrol').checked); @@ -7131,6 +7134,7 @@ if (Q('p20nofiles').checked == true) meshadmin += 1024; if (Q('p20noamt').checked == true) meshadmin += 2048; if (Q('p20remotelimitedinput').checked == true) meshadmin += 4096; + if (Q('p20limitevents').checked == true) meshadmin += 8192; } if (t == null) { @@ -7165,6 +7169,7 @@ if (((meshrights & 8) != 0) && (meshrights & 1024) != 0) r += ', No Files'; if (((meshrights & 8) != 0) && (meshrights & 2048) != 0) r += ', No Intel® AMT'; if (((meshrights & 8) != 0) && ((meshrights & 4096) != 0) && ((meshrights & 256) == 0)) r += ', Limited Input'; + if ((meshrights & 8192) != 0) r += ', Self Events Only'; } r = r.substring(2); if (r == '') { r = 'No Rights'; }