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">🗴</b>':' <b style=color:green title="Email is verified">🗸</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">🗸</b> ':'<b style=color:red;cursor:pointer title="Email not verified">🗴</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());