Added user account real name support.
Ylian Saint-Hilaire committed
Jul 10, 2020 at 10:33 UTC
4b10e225dd2236688048b9f8704b5cc09702aad8
7 files changed
+62
-23
agents/meshcore.js
+15
-14
@@ -712,6 +712,7 @@ function createMeshCore(agent) {
712
tunnel.consent = data.consent;
713
tunnel.privacybartext = data.privacybartext ? data.privacybartext : "Sharing desktop with: {0}";
714
tunnel.username = data.username;
715
+ tunnel.realname = data.realname ? data.realname : data.username;
716
tunnel.userid = data.userid;
717
tunnel.remoteaddr = data.remoteaddr;
718
tunnel.state = 0;
@@ -1624,10 +1625,10 @@ function createMeshCore(agent) {
1625
};
1626
if (this.httprequest.desktop.kvm.hasOwnProperty('connectionCount')) {
1627
this.httprequest.desktop.kvm.connectionCount++;
1627
- this.httprequest.desktop.kvm.users.push(this.httprequest.username);
1628
+ this.httprequest.desktop.kvm.users.push(this.httprequest.realname);
1629
} else {
1630
this.httprequest.desktop.kvm.connectionCount = 1;
1630
- this.httprequest.desktop.kvm.users = [this.httprequest.username];
1631
+ this.httprequest.desktop.kvm.users = [this.httprequest.realname];
1632
}
1633
1634
if ((this.httprequest.rights == 0xFFFFFFFF) || (((this.httprequest.rights & MESHRIGHT_REMOTECONTROL) != 0) && ((this.httprequest.rights & MESHRIGHT_REMOTEVIEW) == 0))) {
@@ -1645,10 +1646,10 @@ function createMeshCore(agent) {
1646
// User Consent Prompt is required
1647
// Send a console message back using the console channel, "\n" is supported.
1648
this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 }));
1648
- var consentMessage = this.httprequest.username + " requesting remote desktop access. Grant access?", consentTitle = 'MeshCentral';
1649
+ var consentMessage = this.httprequest.realname + " requesting remote desktop access. Grant access?", consentTitle = 'MeshCentral';
1650
if (this.httprequest.soptions != null) {
1651
if (this.httprequest.soptions.consentTitle != null) { consentTitle = this.httprequest.soptions.consentTitle; }
1651
- if (this.httprequest.soptions.consentMsgDesktop != null) { consentMessage = this.httprequest.soptions.consentMsgDesktop.replace('{0}', this.httprequest.username); }
1652
+ if (this.httprequest.soptions.consentMsgDesktop != null) { consentMessage = this.httprequest.soptions.consentMsgDesktop.replace('{0}', this.httprequest.realname); }
1653
}
1654
var pr = require('message-box').create(consentTitle, consentMessage, 30, null, tsid);
1655
pr.ws = this;
@@ -1664,10 +1665,10 @@ function createMeshCore(agent) {
1665
this.ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: null, msgid: 0 }));
1666
if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 1)) {
1667
// User Notifications is required
1667
- var notifyMessage = this.ws.httprequest.username + " started a remote desktop session.", notifyTitle = "MeshCentral";
1668
+ var notifyMessage = this.ws.httprequest.realname + " started a remote desktop session.", notifyTitle = "MeshCentral";
1669
if (this.ws.httprequest.soptions != null) {
1670
if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; }
1670
- if (this.ws.httprequest.soptions.notifyMsgDesktop != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgDesktop.replace('{0}', this.ws.httprequest.username); }
1671
+ if (this.ws.httprequest.soptions.notifyMsgDesktop != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgDesktop.replace('{0}', this.ws.httprequest.realname); }
1672
}
1673
try { require('toaster').Toast(notifyTitle, notifyMessage, tsid); } catch (ex) { }
1674
}
@@ -1713,10 +1714,10 @@ function createMeshCore(agent) {
1714
if (this.httprequest.consent && (this.httprequest.consent & 1)) {
1715
// User Notifications is required
1716
MeshServerLog("Started remote desktop with toast notification (" + this.httprequest.remoteaddr + ")", this.httprequest);
1716
- var notifyMessage = this.httprequest.username + " started a remote desktop session.", notifyTitle = "MeshCentral";
1717
+ var notifyMessage = this.httprequest.realname + " started a remote desktop session.", notifyTitle = "MeshCentral";
1718
if (this.httprequest.soptions != null) {
1719
if (this.httprequest.soptions.notifyTitle != null) { notifyTitle = this.httprequest.soptions.notifyTitle; }
1719
- if (this.httprequest.soptions.notifyMsgDesktop != null) { notifyMessage = this.httprequest.soptions.notifyMsgDesktop.replace('{0}', this.httprequest.username); }
1720
+ if (this.httprequest.soptions.notifyMsgDesktop != null) { notifyMessage = this.httprequest.soptions.notifyMsgDesktop.replace('{0}', this.httprequest.realname); }
1721
}
1722
try { require('toaster').Toast(notifyTitle, notifyMessage, tsid); } catch (ex) { }
1723
} else {
@@ -1789,10 +1790,10 @@ function createMeshCore(agent) {
1790
// User Consent Prompt is required
1791
// Send a console message back using the console channel, "\n" is supported.
1792
this.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 }));
1792
- var consentMessage = this.httprequest.username + " requesting remote file Access. Grant access?", consentTitle = 'MeshCentral';
1793
+ var consentMessage = this.httprequest.realname + " requesting remote file Access. Grant access?", consentTitle = 'MeshCentral';
1794
if (this.httprequest.soptions != null) {
1795
if (this.httprequest.soptions.consentTitle != null) { consentTitle = this.httprequest.soptions.consentTitle; }
1795
- if (this.httprequest.soptions.consentMsgFiles != null) { consentMessage = this.httprequest.soptions.consentMsgFiles.replace('{0}', this.httprequest.username); }
1796
+ if (this.httprequest.soptions.consentMsgFiles != null) { consentMessage = this.httprequest.soptions.consentMsgFiles.replace('{0}', this.httprequest.realname); }
1797
}
1798
var pr = require('message-box').create(consentTitle, consentMessage, 30);
1799
pr.ws = this;
@@ -1808,10 +1809,10 @@ function createMeshCore(agent) {
1809
this.ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: null }));
1810
if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 4)) {
1811
// User Notifications is required
1811
- var notifyMessage = this.ws.httprequest.username + " started a remote file session.", notifyTitle = "MeshCentral";
1812
+ var notifyMessage = this.ws.httprequest.realname + " started a remote file session.", notifyTitle = "MeshCentral";
1813
if (this.ws.httprequest.soptions != null) {
1814
if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; }
1814
- if (this.ws.httprequest.soptions.notifyMsgFiles != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgFiles.replace('{0}', this.ws.httprequest.username); }
1815
+ if (this.ws.httprequest.soptions.notifyMsgFiles != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgFiles.replace('{0}', this.ws.httprequest.realname); }
1816
}
1817
try { require('toaster').Toast(notifyTitle, notifyMessage); } catch (ex) { }
1818
}
@@ -1829,10 +1830,10 @@ function createMeshCore(agent) {
1830
if (this.httprequest.consent && (this.httprequest.consent & 4)) {
1831
// User Notifications is required
1832
MeshServerLog("Started remote files with toast notification (" + this.httprequest.remoteaddr + ")", this.httprequest);
1832
- var notifyMessage = this.httprequest.username + " started a remote file session.", notifyTitle = "MeshCentral";
1833
+ var notifyMessage = this.httprequest.realname + " started a remote file session.", notifyTitle = "MeshCentral";
1834
if (this.httprequest.soptions != null) {
1835
if (this.httprequest.soptions.notifyTitle != null) { notifyTitle = this.httprequest.soptions.notifyTitle; }
1835
- if (this.httprequest.soptions.notifyMsgFiles != null) { notifyMessage = this.httprequest.soptions.notifyMsgFiles.replace('{0}', this.httprequest.username); }
1836
+ if (this.httprequest.soptions.notifyMsgFiles != null) { notifyMessage = this.httprequest.soptions.notifyMsgFiles.replace('{0}', this.httprequest.realname); }
1837
}
1838
try { require('toaster').Toast(notifyTitle, notifyMessage); } catch (ex) { }
1839
} else {
meshcentral-config-schema.json
+8
-5
@@ -159,14 +159,16 @@
159
"skip2factor": { "type": "string" }
160
}
161
},
162
- "agentInviteCodes": { "type": "boolean", "default": false },
163
- "agentNoProxy": { "type": "boolean", "default": false },
164
- "geoLocation": { "type": "boolean", "default": false },
165
- "novnc": { "type": "boolean", "default": true },
166
- "mstsc": { "type": "boolean", "default": false },
162
+ "agentInviteCodes": { "type": "boolean", "default": false, "description": "Enabled a feature where you can set one or more invitation codes in a device group. You can then give a invitation link to users who can use it to download the agent." },
163
+ "agentNoProxy": { "type": "boolean", "default": false, "description": "When enabled, all newly installed MeshAgents will be instructed to no use a HTTP/HTTPS proxy even if one is configured on the remote system" },
164
+ "geoLocation": { "type": "boolean", "default": false, "description": "Enables the geo-location feature and device location map in the user interface, this feature is not being worked on." },
165
+ "novnc": { "type": "boolean", "default": true, "description": "When enabled, activates the built-in web-based noVNC client." },
166
+ "mstsc": { "type": "boolean", "default": false, "description": "When enabled, activates the built-in web-based RDP client." },
167
+ "webEmailsPath": { "type": "string", "description": "Path where to find custom email templates for this domain." },
168
"customUI": { "type": "object" },
169
"consentMessages": {
170
"type": "object",
171
+ "description": "This section is user to customize user consent prompts, these show up when asking if a remote session is allowed or not.",
172
"additionalProperties": false,
173
"properties": {
174
"Title": { "type": "string" },
@@ -178,6 +180,7 @@
180
"notificationMessages": {
181
"type": "object",
182
"additionalProperties": false,
183
+ "description": "This section is user to customize user notifications when a remote desktop, terminal or file session is connected to a remote system.",
184
"properties": {
185
"Title": { "type": "string" },
186
"Desktop": { "type": "string" },
meshdesktopmultiplex.js
+2
@@ -888,6 +888,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
888
command.consent = mesh.consent; // Add user consent
889
if (typeof domain.userconsentflags == 'number') { command.consent |= domain.userconsentflags; } // Add server required consent flags
890
command.username = user.name; // Add user name
891
+ command.realname = user.realname; // Add real name
892
if (typeof domain.desktopprivacybartext == 'string') { command.privacybartext = domain.desktopprivacybartext; } // Privacy bar text
893
delete command.nodeid; // Remove the nodeid since it's implyed.
894
agent.send(JSON.stringify(command));
@@ -906,6 +907,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
907
command.consent = mesh.consent; // Add user consent
908
if (typeof domain.userconsentflags == 'number') { command.consent |= domain.userconsentflags; } // Add server required consent flags
909
command.username = user.name; // Add user name
910
+ command.realname = user.realname; // Add real name
911
if (typeof domain.desktopprivacybartext == 'string') { command.privacybartext = domain.desktopprivacybartext; } // Privacy bar text
912
parent.parent.multiServer.DispatchMessageSingleServer(command, routing.serverid);
913
return true;
meshrelay.js
+2
@@ -95,6 +95,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
95
command.consent = mesh.consent; // Add user consent
96
if (typeof domain.userconsentflags == 'number') { command.consent |= domain.userconsentflags; } // Add server required consent flags
97
command.username = user.name; // Add user name
98
+ command.realname = user.realname; // Add real name
99
if (typeof domain.desktopprivacybartext == 'string') { command.privacybartext = domain.desktopprivacybartext; } // Privacy bar text
100
delete command.nodeid; // Remove the nodeid since it's implyed.
101
agent.send(JSON.stringify(command));
@@ -113,6 +114,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
114
command.consent = mesh.consent; // Add user consent
115
if (typeof domain.userconsentflags == 'number') { command.consent |= domain.userconsentflags; } // Add server required consent flags
116
command.username = user.name; // Add user name
117
+ command.realname = user.realname; // Add real name
118
if (typeof domain.desktopprivacybartext == 'string') { command.privacybartext = domain.desktopprivacybartext; } // Privacy bar text
119
parent.parent.multiServer.DispatchMessageSingleServer(command, routing.serverid);
120
return true;
meshuser.js
+14
-3
@@ -195,8 +195,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
195
if (typeof node.consent == 'number') { command.consent |= node.consent; } // Add node user consent
196
if (typeof user.consent == 'number') { command.consent |= user.consent; } // Add user consent
197
command.username = user.name; // Add user name
198
+ command.realname = user.realname; // Add real name
199
command.userid = user._id; // Add user id
199
- command.remoteaddr = req.clientIp; // User's IP address
200
+ command.remoteaddr = req.clientIp; // User's IP address
201
if (typeof domain.desktopprivacybartext == 'string') { command.privacybartext = domain.desktopprivacybartext; } // Privacy bar text
202
delete command.nodeid; // Remove the nodeid since it's implied
203
try { agent.send(JSON.stringify(command)); } catch (ex) { }
@@ -218,8 +219,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
219
if (typeof node.consent == 'number') { command.consent |= node.consent; } // Add node user consent
220
if (typeof user.consent == 'number') { command.consent |= user.consent; } // Add user consent
221
command.username = user.name; // Add user name
222
+ command.realname = user.realname; // Add real name
223
command.userid = user._id; // Add user id
222
- command.remoteaddr = req.clientIp; // User's IP address
224
+ command.remoteaddr = req.clientIp; // User's IP address
225
if (typeof domain.desktopprivacybartext == 'string') { command.privacybartext = domain.desktopprivacybartext; } // Privacy bar text
226
parent.parent.multiServer.DispatchMessageSingleServer(command, routing.serverid);
227
}
@@ -1835,7 +1837,16 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1837
1838
// Validate and change email
1839
if (edituserdomain.usernameisemail !== true) {
1838
- if (common.validateString(command.email, 1, 1024) && (chguser.email != command.email)) { chguser.email = command.email.toLowerCase(); change = 1; }
1840
+ if (common.validateString(command.email, 1, 1024) && (chguser.email != command.email)) {
1841
+ if (command.email == '') { delete chguser.email; } else { chguser.email = command.email.toLowerCase(); }
1842
+ change = 1;
1843
+ }
1844
+ }
1845
+
1846
+ // Validate and change realm name
1847
+ if (common.validateString(command.realname, 1, 256) && (chguser.realname != command.realname)) {
1848
+ if (command.realname == '') { delete chguser.realname; } else { chguser.realname = command.realname; }
1849
+ change = 1;
1850
}
1851
1852
// Make changes
sample-config-advanced.json
+1
@@ -140,6 +140,7 @@
140
"_geoLocation": true,
141
"_novnc": false,
142
"_mstsc": true,
143
+ "_WebEmailsPath": "/myserver/email-templates",
144
"_consentMessages": {
145
"title": "MeshCentral",
146
"desktop": "{0} requesting remote desktop access. Grant access?",
views/default.handlebars
+20
-1
@@ -11349,6 +11349,7 @@
11349
var x = '<div style=min-height:80px><table style=width:100%>';
11350
if ((args.hide & 8) != 0) { x += '<br />' + addDeviceAttribute("Name", user.name); } // If title bar is hidden, display the user name here
11351
var email = user.email?EscapeHtml(user.email):'<i>' + "Not set" + '</i>', everify = '';
11352
+ var realname = user.realname?EscapeHtml(user.realname):'<i>' + "Not set" + '</i>';
11353
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> '); }
11354
11355
if ((serverinfo.crossDomain) || (debugmode != 0)) {
@@ -11359,10 +11360,12 @@
11360
if (user.name.toLowerCase() != user._id.split('/')[2]) { x += addDeviceAttribute("User Identifier", EscapeHtml(user._id.split('/')[2])); }
11361
}
11362
11362
- if (((user.siteadmin != 0xFFFFFFFF) || (userinfo.siteadmin == 0xFFFFFFFF))) { // If we are not site admin, we can't change a admin email.
11363
+ if (((user.siteadmin != 0xFFFFFFFF) || (userinfo.siteadmin == 0xFFFFFFFF))) { // If we are not site admin, we can't change a admin email or real name
11364
x += addDeviceAttribute("Email", everify + email + ' <a href="mailto:' + EscapeHtml(user.email) + '" \'><img class=hoverButton src="images/link1.png" /></a>' + ' <img class=hoverButton style=cursor:pointer src="images/link5.png" onclick=p30showUserEmailChangeDialog(event,"' + userid + '") />');
11365
+ x += addDeviceAttribute("Real Name", realname + ' <img class=hoverButton style=cursor:pointer src="images/link5.png" onclick=p30showUserRealNameChangeDialog(event,"' + userid + '") />');
11366
} else {
11367
x += addDeviceAttribute("Email", everify + email + ' <a href="mailto:' + EscapeHtml(user.email) + '" \'><img class=hoverButton src="images/link1.png" /></a>');
11368
+ x += addDeviceAttribute("Real Name", realname);
11369
}
11370
11371
if ((features & 0x02000000) || (user.phone != null)) { // If SMS is enabled on the server or user has a phone number
@@ -11483,6 +11486,22 @@
11486
// Send to the server the user's new phone number
11487
function p30editPhoneEx() { meshserver.send({ action: 'edituser', id: currentUser._id, phone: Q('d2phoneinput').value }); }
11488
11489
+ // Display the user's real name change dialog box
11490
+ function p30showUserRealNameChangeDialog(event) {
11491
+ if (xxdialogMode) return false;
11492
+ var x = '';
11493
+ x += addHtmlValue("Real Name", '<input id=dp30realname style=width:230px maxlength=256 />');
11494
+ setDialogMode(2, format("Change Real Name for {0}", EscapeHtml(currentUser.name)), 3, p30showUserRealNameChangeDialogEx, x);
11495
+ Q('dp30realname').focus();
11496
+ Q('dp30realname').value = (currentUser.realname?currentUser.realname:'');
11497
+ return false;
11498
+ }
11499
+
11500
+ // Send to the server the new user's real name
11501
+ function p30showUserRealNameChangeDialogEx() {
11502
+ meshserver.send({ action: 'edituser', id: currentUser._id, realname: Q('dp30realname').value });
11503
+ }
11504
+
11505
// Display the user's email change dialog box
11506
function p30showUserEmailChangeDialog(event) {
11507
if (xxdialogMode) return false;