From 5a81c84d67df3bd705b5d159b9ce2dbb05d71c1c Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Wed, 30 Mar 2022 07:14:14 -0700 Subject: [PATCH] Improved uicustomevent security and events, #3823 --- meshuser.js | 32 +++++++++++++++++++++++++------- views/default.handlebars | 8 ++++++-- webserver.js | 12 ++++++++++++ 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/meshuser.js b/meshuser.js index e09c1bd0..2ce36c26 100644 --- a/meshuser.js +++ b/meshuser.js @@ -4244,13 +4244,31 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use break; } case 'uicustomevent': { - // Event the custom UI action - var message = { etype: 'user', userid: user._id, username: user.name, action: 'uicustomevent', domain: domain.id, uisection: command.section, element: command.element }; - if (command.selectedDevices != null) { message.selectedDevices = command.selectedDevices; } - if (command.src != null) { message.src = command.src; } - if (command.values != null) { message.values = command.values; } - if (typeof command.logmsg == 'string') { message.msg = command.logmsg; } else { message.nolog = 1; } - parent.parent.DispatchEvent(['*', user._id], obj, message); + if ((command.src != null) && (Array.isArray(command.src.selectedDevices))) { + // Contains a list of nodeid's, check that we have permissions for them. + parent.GetNodesWithRights(domain, user, command.src.selectedDevices, function (nodes) { + var nodeids = []; + for (var i in nodes) { nodeids.push(i); } + if (nodeids.length == 0) return; + + // Event the custom UI action + var message = { etype: 'user', userid: user._id, username: user.name, action: 'uicustomevent', domain: domain.id, uisection: command.section, element: command.element }; + if (nodeids.length == 1) { message.nodeid = nodeids[0]; } + if (command.selectedDevices != null) { message.selectedDevices = command.selectedDevices; } + if (command.src != null) { message.src = command.src; } + if (command.values != null) { message.values = command.values; } + if (typeof command.logmsg == 'string') { message.msg = command.logmsg; } else { message.nolog = 1; } + parent.parent.DispatchEvent(['*', user._id], obj, message); + }); + } else { + // Event the custom UI action + var message = { etype: 'user', userid: user._id, username: user.name, action: 'uicustomevent', domain: domain.id, uisection: command.section, element: command.element }; + if (command.selectedDevices != null) { message.selectedDevices = command.selectedDevices; } + if (command.src != null) { message.src = command.src; } + if (command.values != null) { message.values = command.values; } + if (typeof command.logmsg == 'string') { message.msg = command.logmsg; } else { message.nolog = 1; } + parent.parent.DispatchEvent(['*', user._id], obj, message); + } break; } case 'serverBackup': { diff --git a/views/default.handlebars b/views/default.handlebars index a2193e3b..727b1ee3 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -10597,8 +10597,12 @@ if (xevent) { var x = '
'; for (var i in xevent) { - if ((i == 'h') || (i == '_id') || (i == 'ids') || (i == 'domain') || (xevent[i] == null) || (typeof xevent[i] == 'object')) continue; - x += addHtmlValue3(EscapeHtml(i), EscapeHtml(xevent[i])); + if ((i == 'h') || (i == '_id') || (i == 'ids') || (i == 'domain') || (xevent[i] == null)) continue; + if (typeof xevent[i] == 'object') { + x += addHtmlValue3(EscapeHtml(i), EscapeHtml(JSON.stringify(xevent[i]))); + } else { + x += addHtmlValue3(EscapeHtml(i), EscapeHtml(xevent[i])); + } } x += '
'; setDialogMode(2, "Event Details", 9, null, x); diff --git a/webserver.js b/webserver.js index 27133b4f..12974a6b 100644 --- a/webserver.js +++ b/webserver.js @@ -7158,6 +7158,18 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF return rights; } + + // Return the node and rights for a array of nodeids + obj.GetNodesWithRights = function (domain, user, nodeids, func) { + var rc = nodeids.length, r = {}; + for (var i in nodeids) { + obj.GetNodeWithRights(domain, user, nodeids[i], function (node, rights, visible) { + if ((node != null) && (visible == true)) { r[node._id] = { node: node, rights: rights }; if (--rc == 0) { func(r); } } + }); + } + } + + // Return the node and rights for a given nodeid obj.GetNodeWithRights = function (domain, user, nodeid, func) { // Perform user pre-validation