Fixed mobile application for user groups.

Ylian Saint-Hilaire committed Jan 4, 2020 at 11:37 UTC 8a31f38241b209ae3d4236daef660251a95286c4
4 files changed +75 -9
package.json
+1 -1
@@ -1,6 +1,6 @@
1 {
2 "name": "meshcentral",
3 - "version": "0.4.6-w",
3 + "version": "0.4.6-x",
4 "keywords": [
5 "Remote Management",
6 "Intel AMT",
sample-config.json
+1 -1
@@ -65,7 +65,7 @@
65 },
66 "__MaxInvalidLogin": "Time in minutes, max amount of bad logins from a source IP in the time before logins are rejected.",
67 "MaxInvalidLogin": { "time": 10, "count": 10, "coolofftime": 10 },
68 - "_plugins": {
68 + "_Plugins": {
69 "enabled": true
70 }
71 },
views/default-mobile.handlebars
+72 -6
@@ -117,6 +117,14 @@
117 float: left;
118 }
119
120 + .m4 {
121 + background: url(../images/images16.png) -128px 0px;
122 + height: 16px;
123 + width: 16px;
124 + border: none;
125 + float: left;
126 + }
127 +
128 .gray {
129 /*filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale");*/ /* Firefox 10+, Firefox on Android */
130 filter: gray; /* IE6-9 */
@@ -614,6 +622,7 @@
622 var authCookieRenewTimer = null;
623 var meshserver = null;
624 var xdr = null;
625 + var usergroups = null;
626 var serverinfo = null;
627 var nodes = [];
628 var meshes = {};
@@ -670,6 +679,7 @@
679 if (authCookieRenewTimer != null) { clearInterval(authCookieRenewTimer); authCookieRenewTimer = null; }
680 } else if (state == 2) {
681 // Fetch list of meshes, nodes, files
682 + meshserver.send({ action: 'usergroups' });
683 meshserver.send({ action: 'meshes' });
684 meshserver.send({ action: 'nodes' });
685 meshserver.send({ action: 'files' });
@@ -755,6 +765,20 @@
765 updateDevices();
766 break;
767 }
768 + case 'usergroups': {
769 + var groupCount = 0;
770 + if (Array.isArray(message.ugroups)) {
771 + usergroups = {};
772 + for (var i in message.ugroups) { groupCount++; usergroups[message.ugroups[i]._id] = message.ugroups[i]; }
773 + if (groupCount == 0) { usergroups = null; }
774 + } else {
775 + usergroups = message.ugroups;
776 + for (var i in message.ugroups) { groupCount++; }
777 + if (groupCount == 0) { usergroups = null; }
778 + }
779 + //masterUpdate(8192);
780 + break;
781 + }
782 case 'files': {
783 filetree = setupBackPointers(message.filetree);
784 updateFiles();
@@ -876,6 +900,34 @@
900 }
901 break;
902 }
903 + case 'createusergroup':
904 + case 'usergroupchange': {
905 + // User group changed
906 + if (usergroups == null) { usergroups = {}; }
907 + var ugroup = usergroups[message.event.ugrpid];
908 + if (ugroup == null) {
909 + // This is a new user group for us
910 + usergroups[message.event.ugrpid] = { _id: message.event.ugrpid, name: message.event.name, desc: message.event.desc, domain: message.event.domain, links: message.event.links };
911 + } else {
912 + // This is an existing user group
913 + ugroup.name = message.event.name;
914 + ugroup.desc = message.event.desc;
915 + ugroup.links = message.event.links;
916 + }
917 + //masterUpdate(8192 + 16384);
918 + break;
919 + }
920 + case 'deleteusergroup': {
921 + // User group removed
922 + if ((usergroups != null) && (usergroups[message.event.ugrpid] != null)) {
923 + delete usergroups[message.event.ugrpid];
924 + var c = 0;
925 + for (var i in usergroups) { c++; }
926 + if (c == 0) { usergroups = null; } // If user groups is empty, set it to null.
927 + //masterUpdate(8192 + 16384);
928 + }
929 + break;
930 + }
931 case 'createmesh': {
932 // A new mesh was created
933 if (message.event.links[userinfo._id] != null) { // Check if this is a mesh create for a mesh we own. If site administrator, we get all messages so need to ignore some.
@@ -1724,11 +1776,11 @@
1776 if (typeof deviceHeaderCount[nodes[i].state] == 'undefined') { deviceHeaderCount[nodes[i].state] = 1; } else { deviceHeaderCount[nodes[i].state]++; }
1777 }
1778
1727 - // Display all empty meshes, we need to do this because users can add devices to these at any time.
1779 + // Display all empty device groups, we need to do this because users can add devices to these at any time.
1780 if (sort == 0) {
1781 for (var i in meshes) {
1782 var mesh = meshes[i];
1731 - if (IsMeshViewable(mesh)) {
1783 + if ((displayedMeshes[mesh._id] == null) && (IsMeshViewable(mesh))) {
1784 if ((current != '') && (r != '')) { r += '</tr></table>'; }
1785 r += '<div><div colspan=3 class=DevSt><span style=float:right>';
1786 //r += getMeshActions(mesh, meshrights);
@@ -3135,16 +3187,23 @@
3187
3188 // Sort the users for this mesh
3189 var count = 1, sortedusers = [];
3138 - for (var i in currentMesh.links) { sortedusers.push({ id: i, name: i.split('/')[2], rights: currentMesh.links[i].rights }); }
3190 + for (var i in currentMesh.links) {
3191 + var uname = i.split('/')[2];
3192 + if (currentMesh.links[i].name) { uname = currentMesh.links[i].name; }
3193 + if (i == userinfo._id) { uname = userinfo.name; }
3194 + if ((usergroups != null) && (usergroups[i] != null)) { uname = usergroups[i].name; }
3195 + sortedusers.push({ id: i, name: uname, rights: currentMesh.links[i].rights });
3196 + }
3197 sortedusers.sort(function (a, b) { if (a.name > b.name) return 1; if (a.name < b.name) return -1; return 0; });
3198
3199 // Display all users for this mesh
3200 for (var i in sortedusers) {
3143 - var trash = '', rights = "Partial Rights", r = sortedusers[i].rights;
3201 + var trash = '', rights = "Partial Rights", r = sortedusers[i].rights, icon = 2;
3202 if (r == 0xFFFFFFFF) rights = "Full Administrator"; else if (r == 0) rights = "No Rights";
3203 if ((i != userinfo._id) && (meshrights == 0xFFFFFFFF || (((meshrights & 2) != 0)))) { trash = '<a onclick=p20deleteUser(event,"' + encodeURIComponent(sortedusers[i].id) + '") style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'; }
3204 + if (sortedusers[i].id.startsWith('ugrp/')) { icon = 4; }
3205 x += '<tr onclick=p20viewuser("' + encodeURIComponent(sortedusers[i].id) + '") style=height:32px;cursor:pointer' + (((count % 2) == 0) ? ';background-color:#DDD' : '') + '><td>';
3147 - x += '<div style=float:right>' + trash + '</div><div style=float:right;padding-right:4px>' + rights + '</div><div class=m2></div><div>&nbsp;' + EscapeHtml(decodeURIComponent(sortedusers[i].name)) + '<div></div></div>';
3206 + x += '<div style=float:right>' + trash + '</div><div style=float:right;padding-right:4px>' + rights + '</div><div class=m' + icon + '></div><div>&nbsp;' + EscapeHtml(decodeURIComponent(sortedusers[i].name)) + '<div></div></div>';
3207 x += '</td></tr>';
3208 ++count;
3209 }
@@ -3296,7 +3355,14 @@
3355 setDialogMode(2, "Device Group User", buttons, p20viewuserEx, x, userid);
3356 }
3357
3299 - function p20viewuserEx(button, userid) { if (button != 2) return; setDialogMode(2, "Remote Mesh User", 3, p20viewuserEx2, format("Confirm removal of user {0}?", userid.split('/')[2]), userid); }
3358 + function p20viewuserEx(button, userid) {
3359 + if (button != 2) return;
3360 + var uname = userid.split('/')[2];
3361 + if (users && users[userid]) { uname = users[userid].name; }
3362 + if (usergroups && usergroups[userid]) { uname = usergroups[userid].name; }
3363 + if (userinfo._id == userid) { uname = userinfo.name; }
3364 + setDialogMode(2, "Remote Mesh User", 3, p20viewuserEx2, format("Confirm removal of user {0}?", uname), userid);
3365 + }
3366 function p20deleteUser(e, userid) { haltEvent(e); p20viewuserEx(2, decodeURIComponent(userid)); }
3367 function p20viewuserEx2(button, userid) { meshserver.send({ action: 'removemeshuser', meshid: currentMesh._id, meshname: currentMesh.name, userid: userid }); }
3368
views/default.handlebars
+1 -1
@@ -1500,8 +1500,8 @@
1500 if (authCookieRenewTimer != null) { clearInterval(authCookieRenewTimer); authCookieRenewTimer = null; }
1501 } else if (state == 2) {
1502 // Fetch list of meshes, nodes, files
1503 - meshserver.send({ action: 'meshes' });
1503 meshserver.send({ action: 'usergroups' });
1504 + meshserver.send({ action: 'meshes' });
1505 meshserver.send({ action: 'nodes', id: '{{currentNode}}' });
1506 if (pluginHandler != null) { meshserver.send({ action: 'plugins' }); }
1507 if ('{{currentNode}}' == '') { meshserver.send({ action: 'files' }); }