Updated user management and MeshAgent

Ylian Saint-Hilaire committed Apr 17, 2018 at 19:00 UTC b6b2706d1966bf13391a038ffbe7083c360f64de
15 files changed +79 -44
agents/MeshCmd-signed.exe
Binary files a/agents/MeshCmd-signed.exe and b/agents/MeshCmd-signed.exe differ
agents/MeshCmd64-signed.exe
Binary files a/agents/MeshCmd64-signed.exe and b/agents/MeshCmd64-signed.exe differ
agents/MeshService-signed.exe
Binary files a/agents/MeshService-signed.exe and b/agents/MeshService-signed.exe differ
agents/MeshService.exe
Binary files a/agents/MeshService.exe and b/agents/MeshService.exe differ
agents/MeshService64-signed.exe
Binary files a/agents/MeshService64-signed.exe and b/agents/MeshService64-signed.exe differ
agents/MeshService64.exe
Binary files a/agents/MeshService64.exe and b/agents/MeshService64.exe differ
agents/meshcore.js
+2 -2
@@ -583,7 +583,7 @@ function createMeshCore(agent) {
583 if (this.desktop.kvm.connectionCount == 0) { this.httprequest.desktop.kvm.end(); }
584 };
585 if (this.httprequest.desktop.kvm.hasOwnProperty("connectionCount")) { this.httprequest.desktop.kvm.connectionCount++; } else { this.httprequest.desktop.kvm.connectionCount = 1; }
586 - this.pipe(this.httprequest.desktop.kvm, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
586 + this.pipe(this.httprequest.desktop.kvm, { dataTypeSkip: 1, end: false }); // 0 = Binary, 1 = Text. (****************)
587 this.httprequest.desktop.kvm.pipe(this, { dataTypeSkip: 1 }); // 0 = Binary, 1 = Text.
588 this.removeAllListeners('data');
589 this.on('data', onTunnelControlData);
@@ -789,7 +789,7 @@ function createMeshCore(agent) {
789 } else if (ws.httprequest.protocol == 2) { // Desktop
790 // Switch the user input from websocket to webrtc at this point.
791 ws.unpipe(ws.httprequest.desktop.kvm);
792 - try { ws.webrtc.rtcchannel.pipe(ws.httprequest.desktop.kvm, { dataTypeSkip: 1 }); } catch (e) { sendConsoleText('EX2'); } // 0 = Binary, 1 = Text.
792 + try { ws.webrtc.rtcchannel.pipe(ws.httprequest.desktop.kvm, { dataTypeSkip: 1, end: false }); } catch (e) { sendConsoleText('EX2'); } // 0 = Binary, 1 = Text.
793 ws.resume(); // Resume the websocket to keep receiving control data
794 }
795 ws.write("{\"ctrlChannel\":\"102938\",\"type\":\"webrtc2\"}"); // Indicates we will no longer get any data on websocket, switching to WebRTC at this point.
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.GetNodeEventsWithLimit = function (nodeid, domain, limit, func) { if (obj.databaseType == 1) { obj.file.find({ type: 'event', domain: domain, nodeid: nodeid }, { 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.GetNodeEventsWithLimit = function (nodeid, domain, limit, func) { if (obj.databaseType == 1) { obj.file.find({ type: 'event', domain: domain, nodeid: nodeid }, { 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, nodeid: nodeid }, { type: 0, _id: 0, domain: 0, ids: 0, node: 0 }).sort({ time: -1 }).limit(limit, func); } }
103 obj.RemoveMesh = function (id) { obj.file.remove({ mesh: id }, { multi: true }); obj.file.remove({ _id: id }); obj.file.remove({ _id: 'nt' + id }); }
104 obj.RemoveAllEvents = function (domain) { obj.file.remove({ type: 'event', domain: domain }, { multi: true }); }
105 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]); } }); }
meshuser.js
+7 -1
@@ -366,7 +366,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain) {
366 delete userinfo.domain;
367 delete userinfo.subscriptions;
368 delete userinfo.passtype;
369 - obj.parent.parent.DispatchEvent(['*', 'server-users', user._id], obj, { etype: 'user', username: userinfo.name, account: userinfo, action: 'accountchange', msg: 'Changed email of user ' + userinfo.name + ' from ' + oldemail + ' to ' + user.email, domain: domain.id })
369 + var message = { etype: 'user', username: userinfo.name, account: userinfo, action: 'accountchange', domain: domain.id };
370 + if (oldemail != null) {
371 + message.msg = 'Changed email of user ' + userinfo.name + ' from ' + oldemail + ' to ' + user.email;
372 + } else {
373 + message.msg = 'Set email of user ' + userinfo.name + ' to ' + user.email;
374 + }
375 + obj.parent.parent.DispatchEvent(['*', 'server-users', user._id], obj, message);
376 }
377 });
378 }
package.json
+1 -1
@@ -1,6 +1,6 @@
1 {
2 "name": "meshcentral",
3 - "version": "0.1.6-m",
3 + "version": "0.1.6-q",
4 "keywords": [
5 "Remote Management",
6 "Intel AMT",
public/images/User-200.png
Binary files a/public/images/User-200.png and b/public/images/User-200.png differ
public/images/User.png
Binary files a/public/images/User.png and /dev/null differ
public/images/images16.png
Binary files a/public/images/images16.png and b/public/images/images16.png differ
public/scripts/agent-redir-ws-0.1.0.js
+7 -7
@@ -82,12 +82,7 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
82 }
83
84 // Close the WebRTC connection, should be called if a problem occurs during WebRTC setup.
85 - obj.xxCloseWebRTC = function () {
86 - sendCtrlMsg("{\"ctrlChannel\":\"102938\",\"type\":\"close\"}");
87 - if (obj.webchannel != null) { try { obj.webchannel.close(); } catch (e) { } obj.webchannel = null; }
88 - if (obj.webrtc != null) { try { obj.webrtc.close(); } catch (e) { } obj.webrtc = null; }
89 - obj.webRtcActive = false;
90 - }
85 + obj.xxCloseWebRTC = function () { obj.Stop(); }
86
87 obj.xxOnMessage = function (e) {
88 //if (obj.debugmode == 1) { console.log('Recv', e.data); }
@@ -213,9 +208,14 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) {
208
209 obj.Stop = function (x) {
210 if (obj.debugmode == 1) { console.log('stop', x); }
211 +
212 + // Close WebRTC
213 + if (obj.webchannel != null) { try { obj.webchannel.close(); } catch (e) { } obj.webchannel = null; }
214 + if (obj.webrtc != null) { try { obj.webrtc.close(); } catch (e) { } obj.webrtc = null; }
215 + obj.webRtcActive = false;
216 +
217 //obj.debug("Agent Redir Socket Stopped");
218 obj.connectstate = -1;
218 - obj.xxCloseWebRTC();
219 if (obj.socket != null) {
220 try { if (obj.socket.readyState == 1) { sendCtrlMsg("{\"ctrlChannel\":\"102938\",\"type\":\"close\"}"); obj.socket.close(); } } catch (e) { }
221 obj.socket = null;
views/default.handlebars
+61 -32
@@ -780,7 +780,7 @@
780 // Check if we are in debug mode
781 args = parseUriArgs();
782 debugmode = (args.debug == 1);
783 - if (args.webrtc) { attemptWebRTC = (args.webrtc == 1); }
783 + if (args.webrtc != null) { attemptWebRTC = (args.webrtc == 1); }
784 QV('p13AutoConnect', debugmode); // Files
785 QV('autoconnectbutton2', debugmode); // Terminal
786 QV('autoconnectbutton1', debugmode); // Desktop
@@ -2824,7 +2824,7 @@
2824 }
2825
2826 // Attribute: Mesh Agent Tag
2827 - if ((node.agent != null) && (node.agent.tag != null)) {
2827 + if ((node.agent != null) && (node.agent.tag != null) && (node.agent.tag != 'mailto:')) {
2828 var tag = EscapeHtml(node.agent.tag);
2829 if (tag.startsWith('mailto:')) { tag = '<a href="' + tag + '">' + tag.substring(7) + '</a>'; }
2830 x += addDeviceAttribute('Agent Tag', tag);
@@ -4991,36 +4991,25 @@
4991 sortedUserIds.sort();
4992
4993 // Display the users using the sorted list
4994 - var x = '<table style=width:100% cellpadding=0 cellspacing=0>';
4994 + var x = '<table style=width:100% cellpadding=0 cellspacing=0>', addHeader = true;
4995 + // Online users
4996 for (var i in sortedUserIds) {
4996 - var user = users[sortedUserIds[i]], icon = 'm2', msg = '', self = (user.name != userinfo.name);
4997 - if (wssessions != null && wssessions[user._id]) {
4998 - if (self) { msg += "<a onclick=showUserAlertDialog(event,\"" + encodeURIComponent(user._id) + "\")>"; }
4999 - var sessions = wssessions[user._id];
5000 - if (sessions == 1) { msg += '1 active session'; } else { msg += sessions + ' active sessions'; }
5001 - if (self) { msg += "</a>"; }
4997 + var user = users[sortedUserIds[i]], sessions = null;
4998 + if (wssessions != null) { sessions = wssessions[user._id]; }
4999 + if (sessions != null) {
5000 + if (addHeader) { x += '<tr><td style="border-bottom:1pt solid lightgray;padding-top:4px;padding-bottom:4px">Online Users</td></tr>'; addHeader = false; }
5001 + x += addUserHtml(user, sessions);
5002 }
5003 - if (msg != '') msg += ', ';
5004 - if (self) { msg += "<a onclick=showUserAdminDialog(event,\"" + encodeURIComponent(user._id) + "\")>"; }
5005 - if ((user.siteadmin != null) && ((user.siteadmin & 32) != 0) && (user.siteadmin != 0xFFFFFFFF)) { msg += "Locked, "; }
5006 - if ((user.siteadmin == null) || (user.siteadmin == 0) || (user.siteadmin == 32)) {
5007 - msg += "User";
5008 - } else if (user.siteadmin == 8) {
5009 - msg += "User with server files";
5010 - } else if (user.siteadmin == 0xFFFFFFFF) {
5011 - msg += "Full Admin";
5012 - } else {
5013 - msg += "Partial Admin";
5003 + }
5004 + addHeader = true;
5005 + // Offline users
5006 + for (var i in sortedUserIds) {
5007 + var user = users[sortedUserIds[i]], sessions = null;
5008 + if (wssessions != null) { sessions = wssessions[user._id]; }
5009 + if (sessions == null) {
5010 + if (addHeader) { x += '<tr><td style="border-bottom:1pt solid lightgray;padding-top:4px;padding-bottom:4px">Offline Users</td></tr>'; addHeader = false; }
5011 + x += addUserHtml(user, sessions);
5012 }
5015 - if ((user.quota != null) && ((user.siteadmin & 8) != 0)) { msg += ", " + (user.quota / 1024) + " k"; }
5016 - if (self) { msg += "</a>"; }
5017 - var username = EscapeHtml(user.name);
5018 - if (user.email != null) { username += ', <a onclick=doemail(event,\"' + user.email + '\")>' + user.email + '</a>' + (((serverinfo.emailcheck == true) && (user.emailVerified != true))?' (unverified)':''); }
5019 - x += '<tr><td style=cursor:pointer onclick=gotoUser(\"' + encodeURIComponent(user._id) + '\")>';
5020 - x += '<div class=bar style=height:24px;width:100%;font-size:medium>';
5021 - x += '<div style=float:left;height:24px;width:24px;background-color:white><div class=' + icon + ' style=width:16px;margin-top:4px;margin-left:2px;height:16px></div></div>';
5022 - x += '<div class=g1 style=height:24px;float:left></div><div class=g2 style=height:24px;float:right></div>';
5023 - x += '<div><span>' + username + '</span><span style=float:right>' + msg + '</span></div></div></td></tr>';
5013 }
5014 x += '</table>';
5015 QH('p3users', x);
@@ -5029,6 +5018,43 @@
5018 if ((currentUser != null) && (xxcurrentView == 30)) { gotoUser(encodeURIComponent(currentUser._id),true); }
5019 }
5020
5021 + function addUserHtml(user, sessions) {
5022 + var x = '', gray = ' gray', icon = 'm2', msg = '', self = (user.name != userinfo.name);
5023 + if (sessions != null) {
5024 + gray = '';
5025 + if (self) { msg += "<a onclick=showUserAlertDialog(event,\"" + encodeURIComponent(user._id) + "\")>"; }
5026 + if (sessions == 1) { msg += '1 active session'; } else { msg += sessions + ' active sessions'; }
5027 + if (self) { msg += "</a>"; }
5028 + } else {
5029 + if (user.login) { msg += '<span title="Last login: ' + new Date(user.login).toLocaleString() + '">' + new Date(user.login).toLocaleDateString() + '</span>'; }
5030 + }
5031 + if (msg != '') msg += ', ';
5032 + if (self) { msg += "<a onclick=showUserAdminDialog(event,\"" + encodeURIComponent(user._id) + "\")>"; }
5033 + if ((user.siteadmin != null) && ((user.siteadmin & 32) != 0) && (user.siteadmin != 0xFFFFFFFF)) { msg += "Locked, "; }
5034 + msg += "<span title='Server Permissions'>";
5035 + if ((user.siteadmin == null) || (user.siteadmin == 0) || (user.siteadmin == 32)) {
5036 + msg += "User";
5037 + } else if (user.siteadmin == 8) {
5038 + msg += "User with server files";
5039 + } else if (user.siteadmin == 0xFFFFFFFF) {
5040 + msg += "Administrator";
5041 + } else {
5042 + msg += "Partial";
5043 + }
5044 + msg += "</span>";
5045 + if ((user.quota != null) && ((user.siteadmin & 8) != 0)) { msg += ", " + (user.quota / 1024) + " k"; }
5046 + if (self) { msg += "</a>"; }
5047 + var username = EscapeHtml(user.name), emailVerified = '';
5048 + if (serverinfo.emailcheck == true) { emailVerified = ((user.emailVerified != true)?' <b style=color:red title="Email is not verified">&#x1F5F4</b>':' <b style=color:green title="Email is verified">&#x1F5F8</b>'); }
5049 + if (user.email != null) { username += ', <a onclick=doemail(event,\"' + user.email + '\")>' + user.email + '</a>' + emailVerified; }
5050 + x += '<tr><td style=cursor:pointer onclick=gotoUser(\"' + encodeURIComponent(user._id) + '\")>';
5051 + x += '<div class=bar style=height:24px;width:100%;font-size:medium>';
5052 + x += '<div style=float:left;height:24px;width:24px;background-color:white><div class="' + icon + gray + '" style=width:16px;margin-top:4px;margin-left:2px;height:16px></div></div>';
5053 + x += '<div class=g1 style=height:24px;float:left></div><div class=g2 style=height:24px;float:right></div>';
5054 + x += '<div><span>' + username + '</span><span style=float:right>' + msg + '</span></div></div></td></tr>';
5055 + return x;
5056 + }
5057 +
5058 function showUserAlertDialog(e, userid) {
5059 if (xxdialogMode) return;
5060 haltEvent(e);
@@ -5139,9 +5165,12 @@
5165 QH('p30userName', user.name);
5166 QH('p31userName', user.name);
5167 var self = (user.name == userinfo.name), activeSessions = 0;
5142 -
5168 if (wssessions != null && wssessions[user._id]) { activeSessions = wssessions[user._id]; }
5169
5170 + // Change user grayscale
5171 + Q('MainUserImage').classList.remove('gray');
5172 + if (activeSessions == 0) { Q('MainUserImage').classList.add('gray'); }
5173 +
5174 // Server permissions
5175 var msg = '';
5176 if ((user.siteadmin != null) && ((user.siteadmin & 32) != 0) && (user.siteadmin != 0xFFFFFFFF)) { msg += "Locked account, "; }
@@ -5150,8 +5179,8 @@
5179 // Show user attributes
5180 var x = '<div style=min-height:80px><table style=width:100%>';
5181 var email = user.email?EscapeHtml(user.email):'<i>Not set</i>', everify = '';
5153 - if (serverinfo.emailcheck) { everify = ((user.emailVerified == true)?'':', Unverified'); }
5154 - x += addDeviceAttribute('Email', "<a style=cursor:pointer onclick=p30showUserEmailChangeDialog(event,\"" + userid + "\")>" + email + everify + '</a> <a style=cursor:pointer onclick=doemail(event,\"' + user.email + '\")><img src="images/link1.png" /></a>');
5182 + if (serverinfo.emailcheck) { everify = ((user.emailVerified == true)?'<b style=color:green;cursor:pointer title="Email is verified">&#x1F5F8</b> ':'<b style=color:red;cursor:pointer title="Email not verified">&#x1F5F4</b> '); }
5183 + x += addDeviceAttribute('Email', everify + "<a style=cursor:pointer onclick=p30showUserEmailChangeDialog(event,\"" + userid + "\")>" + email + '</a> <a style=cursor:pointer onclick=doemail(event,\"' + user.email + '\")><img src="images/link1.png" /></a>');
5184 x += addDeviceAttribute('Server Rights', "<a style=cursor:pointer onclick=showUserAdminDialog(event,\"" + userid + "\")>" + msg + "</a>");
5185 if (user.quota) x += addDeviceAttribute('Server Quota', EscapeHtml(parseInt(user.quota) / 1024) + ' k');
5186 x += addDeviceAttribute('Creation', new Date(user.creation).toLocaleString());