Added mesh and user notes

Ylian Saint-Hilaire committed Apr 16, 2018 at 11:57 UTC e90878364f85d62f4a3d02e3f5d56b796d4e58fb
4 files changed +90 -36
db.js
+1 -1
@@ -99,7 +99,7 @@ module.exports.CreateDB = function (args, datapath) {
99 obj.StoreEvent = function (ids, source, event) { obj.file.insert(event); }
100 obj.GetEvents = function (ids, domain, func) { if (obj.databaseType == 1) { obj.file.find({ type: 'event', domain: domain, ids: { $in: ids } }, { type: 0, _id: 0, domain: 0, ids: 0, node: 0 }).sort({ time: -1 }).exec(func); } else { obj.file.find({ type: 'event', domain: domain, ids: { $in: ids } }, { type: 0, _id: 0, domain: 0, ids: 0, node: 0 }).sort({ time: -1 }, func) } }
101 obj.GetEventsWithLimit = function (ids, domain, limit, func) { if (obj.databaseType == 1) { obj.file.find({ type: 'event', domain: domain, ids: { $in: ids } }, { type: 0, _id: 0, domain: 0, ids: 0, node: 0 }).sort({ time: -1 }).limit(limit).exec(func); } else { obj.file.find({ type: 'event', domain: domain, ids: { $in: ids } }, { type: 0, _id: 0, domain: 0, ids: 0, node: 0 }).sort({ time: -1 }).limit(limit, func); } }
102 - obj.RemoveMesh = function (id) { obj.file.remove({ mesh: id }, { multi: true }); obj.file.remove({ _id: id }); }
102 + obj.RemoveMesh = function (id) { obj.file.remove({ mesh: id }, { multi: true }); obj.file.remove({ _id: id }); obj.file.remove({ _id: 'nt' + id }); }
103 obj.RemoveAllEvents = function (domain) { obj.file.remove({ type: 'event', domain: domain }, { multi: true }); }
104 obj.MakeSiteAdmin = function (username, domain) { obj.Get('user/' + domain + '/' + username, function (err, docs) { if (docs.length == 1) { docs[0].siteadmin = 0xFFFFFFFF; obj.Set(docs[0]); } }); }
105 obj.DeleteDomain = function (domain, func) { obj.file.remove({ domain: domain }, { multi: true }, func); }
meshuser.js
+77 -25
@@ -1021,49 +1021,101 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
1021 case 'setNotes':
1022 {
1023 // Argument validation
1024 - if (obj.common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
1025 - if ((command.nodeid.split('/').length != 3) || (command.nodeid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
1026 -
1027 - // Check if this user has rights on this nodeid to set notes
1028 - obj.db.Get(command.nodeid, function (err, nodes) { // TODO: Make a NodeRights(user) method that also does not do a db call if agent is connected (???)
1029 - if (nodes.length == 1) {
1030 - var meshlinks = user.links[nodes[0].meshid];
1031 - if ((meshlinks) && (meshlinks.rights) && (meshlinks.rights & obj.parent.MESHRIGHT_SETNOTES != 0)) {
1032 - // Set the node's notes
1033 - if (obj.common.validateString(command.notes, 1) == false) {
1034 - obj.db.Remove('nt' + command.nodeid); // Delete the note for this node
1035 - } else {
1036 - obj.db.Set({ _id: 'nt' + command.nodeid, value: command.notes }); // Set the note for this node
1024 + if (obj.common.validateString(command.id, 1, 1024) == false) break; // Check id
1025 + var splitid = command.id.split('/');
1026 + if ((splitid.length != 3) || (splitid[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
1027 + var idtype = splitid[0];
1028 + if ((idtype != 'user') && (idtype != 'mesh') && (idtype != 'node')) return;
1029 +
1030 + if (idtype == 'node') {
1031 + // Check if this user has rights on this id to set notes
1032 + obj.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 (???)
1033 + if (nodes.length == 1) {
1034 + var meshlinks = user.links[nodes[0].meshid];
1035 + if ((meshlinks) && (meshlinks.rights) && (meshlinks.rights & obj.parent.MESHRIGHT_SETNOTES != 0)) {
1036 + // Set the id's notes
1037 + if (obj.common.validateString(command.notes, 1) == false) {
1038 + obj.db.Remove('nt' + command.id); // Delete the note for this node
1039 + } else {
1040 + obj.db.Set({ _id: 'nt' + command.id, value: command.notes }); // Set the note for this node
1041 + }
1042 }
1043 }
1044 + });
1045 + } else if (idtype == 'mesh') {
1046 + // Get the mesh for this device
1047 + var mesh = obj.parent.meshes[command.id];
1048 + if (mesh) {
1049 + // Check if this user has rights to do this
1050 + if (mesh.links[user._id] == null || (mesh.links[user._id].rights == 0)) { return; }
1051 +
1052 + // Set the id's notes
1053 + if (obj.common.validateString(command.notes, 1) == false) {
1054 + obj.db.Remove('nt' + command.id); // Delete the note for this node
1055 + } else {
1056 + obj.db.Set({ _id: 'nt' + command.id, value: command.notes }); // Set the note for this node
1057 + }
1058 }
1040 - });
1059 + } else if ((idtype == 'user') && ((user.siteadmin & 2) != 0)) {
1060 + // Set the id's notes
1061 + if (obj.common.validateString(command.notes, 1) == false) {
1062 + obj.db.Remove('nt' + command.id); // Delete the note for this node
1063 + } else {
1064 + obj.db.Set({ _id: 'nt' + command.id, value: command.notes }); // Set the note for this node
1065 + }
1066 + }
1067 +
1068 break;
1069 }
1070 case 'getNotes':
1071 {
1072 // Argument validation
1046 - if (obj.common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
1047 - if ((command.nodeid.split('/').length != 3) || (command.nodeid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
1073 + if (obj.common.validateString(command.id, 1, 1024) == false) break; // Check id
1074 + var splitid = command.id.split('/');
1075 + if ((splitid.length != 3) || (splitid[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
1076 + var idtype = splitid[0];
1077 + if ((idtype != 'user') && (idtype != 'mesh') && (idtype != 'node')) return;
1078
1049 - // Get the device
1050 - obj.db.Get(command.nodeid, function (err, nodes) {
1051 - if (nodes.length != 1) { ws.send(JSON.stringify({ action: 'getnetworkinfo', nodeid: command.nodeid, netif: null })); return; }
1052 - var node = nodes[0];
1079 + if (idtype == 'node') {
1080 + // Get the device
1081 + obj.db.Get(command.id, function (err, nodes) {
1082 + if (nodes.length != 1) return;
1083 + var node = nodes[0];
1084
1085 + // Get the mesh for this device
1086 + var mesh = obj.parent.meshes[node.meshid];
1087 + if (mesh) {
1088 + // Check if this user has rights to do this
1089 + if (mesh.links[user._id] == null || (mesh.links[user._id].rights == 0)) { return; }
1090 +
1091 + // Get the notes about this node
1092 + obj.db.Get('nt' + command.id, function (err, notes) {
1093 + if (notes.length != 1) { ws.send(JSON.stringify({ action: 'getNotes', id: command.id, notes: null })); return; }
1094 + ws.send(JSON.stringify({ action: 'getNotes', id: command.id, notes: notes[0].value }));
1095 + });
1096 + }
1097 + });
1098 + } else if (idtype == 'mesh') {
1099 // Get the mesh for this device
1055 - var mesh = obj.parent.meshes[node.meshid];
1100 + var mesh = obj.parent.meshes[command.id];
1101 if (mesh) {
1102 // Check if this user has rights to do this
1103 if (mesh.links[user._id] == null || (mesh.links[user._id].rights == 0)) { return; }
1104
1105 // Get the notes about this node
1061 - obj.db.Get('nt' + command.nodeid, function (err, notes) {
1062 - if (notes.length != 1) { ws.send(JSON.stringify({ action: 'getNotes', nodeid: command.nodeid, notes: null })); return; }
1063 - ws.send(JSON.stringify({ action: 'getNotes', nodeid: command.nodeid, notes: notes[0].value }));
1106 + obj.db.Get('nt' + command.id, function (err, notes) {
1107 + if (notes.length != 1) { ws.send(JSON.stringify({ action: 'getNotes', id: command.id, notes: null })); return; }
1108 + ws.send(JSON.stringify({ action: 'getNotes', id: command.id, notes: notes[0].value }));
1109 });
1110 }
1066 - });
1111 + } else if ((idtype == 'user') && ((user.siteadmin & 2) != 0)) {
1112 + // Get the notes about this node
1113 + obj.db.Get('nt' + command.id, function (err, notes) {
1114 + if (notes.length != 1) { ws.send(JSON.stringify({ action: 'getNotes', id: command.id, notes: null })); return; }
1115 + ws.send(JSON.stringify({ action: 'getNotes', id: command.id, notes: notes[0].value }));
1116 + });
1117 + }
1118 +
1119 break;
1120 }
1121 }
package.json
+1 -1
@@ -1,6 +1,6 @@
1 {
2 "name": "meshcentral",
3 - "version": "0.1.6-k",
3 + "version": "0.1.6-l",
4 "keywords": [
5 "Remote Management",
6 "Intel AMT",
views/default.handlebars
+11 -9
@@ -1092,7 +1092,7 @@
1092 }
1093 case 'getNotes':{
1094 var n = Q('d2devNotes');
1095 - if (n && (message.nodeid == n.attributes['nodeid'].value)) {
1095 + if (n && (message.id == decodeURIComponent(n.attributes['noteid'].value))) {
1096 if (message.notes) { QH('d2devNotes', decodeURIComponent(message.notes)); } else { QH('d2devNotes', ''); }
1097 var ro = n.attributes['ro'].value == 'true';
1098 if (ro == false) { // If we have permissions, set read/write on this note.
@@ -2817,7 +2817,7 @@
2817 x += '</table><br />';
2818 // Show action button, only show if we have permissions 4, 8, 64
2819 if ((meshrights & 76) != 0) { x += '<input type=button value=Actions title="Perform power actions on the device" onclick=deviceActionFunction() />'; }
2820 - x += '<input type=button value=Notes title="View notes about this device" onclick=deviceNotesFunction(' + ((meshrights & 128) == 0) + ',"' + node._id + '") />';
2820 + x += '<input type=button value=Notes title="View notes about this device" onclick=showNotes(' + ((meshrights & 128) == 0) + ',"' + encodeURIComponent(node._id) + '") />';
2821 QH('p10html', x);
2822
2823 // Show node last 7 days timeline
@@ -2898,13 +2898,13 @@
2898 go(panel);
2899 }
2900
2901 - function deviceNotesFunction(readonly, nodeid) {
2901 + function showNotes(readonly, noteid) {
2902 if (xxdialogMode) return;
2903 - setDialogMode(2, "Device Notes", 2, deviceNotesFunctionEx, '<textarea id=d2devNotes ro=' + readonly + ' nodeid=' + nodeid + ' readonly style=background-color:#fcf3cf;width:100%;height:200px;resize:none;overflow-y:scroll></textarea>', nodeid);
2904 - meshserver.send({ action: 'getNotes', nodeid: nodeid });
2903 + setDialogMode(2, "Notes", 2, showNotesEx, '<textarea id=d2devNotes ro=' + readonly + ' noteid=' + noteid + ' readonly style=background-color:#fcf3cf;width:100%;height:200px;resize:none;overflow-y:scroll></textarea><span style=font-size:10px>Notes can be viewed and changed by other administrators.<span>', noteid);
2904 + meshserver.send({ action: 'getNotes', id: decodeURIComponent(noteid) });
2905 }
2906
2907 - function deviceNotesFunctionEx(buttons, tag) { meshserver.send({ action: 'setNotes', nodeid: tag, notes: encodeURIComponent(Q('d2devNotes').value) }); }
2907 + function showNotesEx(buttons, tag) { meshserver.send({ action: 'setNotes', id: decodeURIComponent(tag), notes: encodeURIComponent(Q('d2devNotes').value) }); }
2908
2909 function deviceActionFunction() {
2910 var meshrights = meshes[currentNode.meshid].links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights;
@@ -4452,7 +4452,9 @@
4452 x += addHtmlValue('Type', meshtype);
4453 x += addHtmlValue('Identifier', currentMesh._id.split('/')[2]);
4454
4455 - x += '<br>';
4455 + x += '<br><input type=button value=Notes title="View notes about this mesh" onclick=showNotes(false,"' + encodeURIComponent(currentMesh._id) + '") />';
4456 +
4457 + x += '<br><br>';
4458 var currentMeshLinks = currentMesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()];
4459 if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += '<a onclick=p20showAddMeshUserDialog() style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> Add User</a>'; }
4460
@@ -4550,7 +4552,7 @@
4552 x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshagentconsole>Mesh Agent Console<br>';
4553 x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20meshserverfiles>Server Files<br>';
4554 x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20wakedevices>Wake Devices<br>';
4553 - x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editnotes>Edit Notes<br>';
4555 + x += '<input type=checkbox onchange=p20validateAddMeshUserDialog() id=p20editnotes>Edit Device Notes<br>';
4556 x += '</div>';
4557 setDialogMode(2, "Add User to Mesh", 3, p20showAddMeshUserDialogEx, x);
4558 p20validateAddMeshUserDialog();
@@ -5068,7 +5070,7 @@
5070 x += '</table></div><br />';
5071
5072 // Add action buttons
5071 - //x += '<input type=button value=Notes title="View notes about this user" onclick=userNotesFunction("' + userid + '") />';
5073 + x += '<input type=button value=Notes title="View notes about this user" onclick=showNotes(false,"' + userid + '") />';
5074 if (!self && (activeSessions > 0)) { x += '<input type=button value=Notify title="Send user notification" onclick=showUserAlertDialog(event,"' + userid + '") />'; }
5075
5076 // Setup the panel