Third round of Telegram support changes, can now edit messaging account (#4650)
Ylian Saint-Hilaire committed
Oct 22, 2022 at 10:42 UTC
c62bc9c962fd72edff34dac0b3e1730b619ec641
5 files changed
+52
-11
meshcentral-config-schema.json
+1
@@ -527,6 +527,7 @@
527
"sms2factor": { "type": "boolean", "default": true, "description": "Set to false to disable SMS 2FA." },
528
"push2factor": { "type": "boolean", "default": true, "description": "Set to false to disable push notification 2FA." },
529
"otp2factor": { "type": "boolean", "default": true, "description": "Set to false to disable one-time-password 2FA." },
530
+ "msg2factor": { "type": "boolean", "default": true, "description": "Set to false to disable user messaging 2FA." },
531
"backupcode2factor": { "type": "boolean", "default": true, "description": "Set to false to disable 2FA backup codes." },
532
"single2factorWarning": { "type": "boolean", "default": true, "description": "Set to false to disable single 2FA warning." },
533
"lock2factor": { "type": "boolean", "default": false, "description": "When set to true, prevents any changes to 2FA." },
meshuser.js
+21
-2
@@ -1387,6 +1387,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
1387
if (command.resetNextLogin === true) { chguser.passchange = -1; }
1388
if ((command.consent != null) && (typeof command.consent == 'number')) { if (command.consent == 0) { delete chguser.consent; } else { chguser.consent = command.consent; } change = 1; }
1389
if ((command.phone != null) && (typeof command.phone == 'string') && ((command.phone == '') || isPhoneNumber(command.phone))) { if (command.phone == '') { delete chguser.phone; } else { chguser.phone = command.phone; } change = 1; }
1390
+ if ((command.msghandle != null) && (typeof command.msghandle == 'string')) { if (command.msghandle == '') { delete chguser.msghandle; } else { chguser.msghandle = command.msghandle; } change = 1; }
1391
if ((command.flags != null) && (typeof command.flags == 'number')) {
1392
// Flags: 1 = Account Image, 2 = Session Recording
1393
if ((command.flags == 0) && (chguser.flags != null)) { delete chguser.flags; change = 1; } else { if (command.flags !== chguser.flags) { chguser.flags = command.flags; change = 1; } }
@@ -5250,7 +5251,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
5251
'pong': serverCommandPong,
5252
'powertimeline': serverCommandPowerTimeline,
5253
'print': serverCommandPrint,
5253
- 'removePhone': serverCommandremovePhone,
5254
+ 'removePhone': serverCommandRemovePhone,
5255
+ 'removeMessaging': serverCommandRemoveMessaging,
5256
'removeuserfromusergroup': serverCommandRemoveUserFromUserGroup,
5257
'report': serverCommandReport,
5258
'serverclearerrorlog': serverCommandServerClearErrorLog,
@@ -6304,7 +6306,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
6306
6307
function serverCommandPrint(command) { console.log(command.value); }
6308
6307
- function serverCommandremovePhone(command) {
6309
+ function serverCommandRemovePhone(command) {
6310
// Do not allow this command when logged in using a login token
6311
if (req.session.loginToken != null) return;
6312
@@ -6321,6 +6323,23 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
6323
parent.parent.DispatchEvent(['*', 'server-users', user._id], obj, event);
6324
}
6325
6326
+ function serverCommandRemoveMessaging(command) {
6327
+ // Do not allow this command when logged in using a login token
6328
+ if (req.session.loginToken != null) return;
6329
+
6330
+ if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return; // If this account is settings locked, return here.
6331
+ if (user.msghandle == null) return;
6332
+
6333
+ // Clear the user's phone
6334
+ delete user.msghandle;
6335
+ db.SetUser(user);
6336
+
6337
+ // Event the change
6338
+ var event = { etype: 'user', userid: user._id, username: user.name, account: parent.CloneSafeUser(user), action: 'accountchange', msgid: 157, msgArgs: [user.name], msg: 'Removed messaging account of user ' + EscapeHtml(user.name), domain: domain.id };
6339
+ if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the user. Another event will come.
6340
+ parent.parent.DispatchEvent(['*', 'server-users', user._id], obj, event);
6341
+ }
6342
+
6343
function serverCommandRemoveUserFromUserGroup(command) {
6344
var err = null;
6345
try {
public/images/messaging12.png
Binary files /dev/null and b/public/images/messaging12.png differ
public/images/messaging40.png
Binary files a/public/images/messaging40.png and b/public/images/messaging40.png differ
views/default.handlebars
+30
-9
@@ -11964,7 +11964,7 @@
11964
x = '<table style=width:100%><tr><td style=width:56px><img src="images/messaging40.png" style=padding:8px>';
11965
x += '<td style=text-align:center><div style=padding:6px>' + "Verified handle" + '</div><div style=font-size:20px>' + EscapeHtml(userinfo.msghandle) + '</div>';
11966
x += '<div style=margin:10px><label><input id=d2delPhone type=checkbox onclick=account_managePhoneRemoveValidate() />' + "Remove messaging" + '</label></div>';
11967
- setDialogMode(2, "Messaging Notifications", 3, account_managePhoneRemove, x);
11967
+ setDialogMode(2, "Messaging Notifications", 3, account_manageMessagingRemove, x);
11968
account_managePhoneRemoveValidate();
11969
} else {
11970
x = '<table style=width:100%><tr><td style=width:56px;vertical-align:top><img src="images/messaging40.png" style=padding:8px>';
@@ -11985,6 +11985,7 @@
11985
function account_manageMessagingValidate(x) { var ok = (Q('d2handleinput').value.length > 0); QE('idx_dlgOkButton', ok); if ((x == 1) && ok) { dialogclose(1); } }
11986
function account_manageMessagingAdd() { if (Q('d2handleinput').value.length == 0) return; QE('d2handleinput', false); meshserver.send({ action: 'verifyMessaging', service: Q('d2serviceselect').value, handle: Q('d2handleinput').value }); }
11987
function account_manageMessagingConfirm(b, tag) { meshserver.send({ action: 'confirmMessaging', code: Q('d2phoneCodeInput').value, cookie: tag }); }
11988
+ function account_manageMessagingRemove() { if (Q('d2delPhone').checked) { meshserver.send({ action: 'removeMessaging' }); } }
11989
11990
function account_manageAuthEmail() {
11991
if (xxdialogMode || ((features & 0x00800000) == 0)) return;
@@ -14616,6 +14617,7 @@
14617
if ((user.otpsecret > 0) || (user.otphkeys > 0) || ((user.otpekey == 1) && (features & 0x00800000)) || ((user.phone != null) && (features & 0x04000000))) { username += ' <img src="images/key12.png" height=12 width=11 title="' + "2nd factor authentication enabled" + '" style="margin-top:2px" />'; }
14618
if (user.phone != null) { username += ' <img src="images/phone12.png" height=12 width=7 title="' + "Verified phone number" + '" style="margin-top:2px" />'; }
14619
if ((user.siteadmin != null) && ((user.siteadmin & 32) != 0) && (user.siteadmin != 0xFFFFFFFF)) { username += ' <img src="images/padlock12.png" height=12 width=8 title="' + "Account is locked" + '" style="margin-top:2px" />'; }
14620
+ if ((user.msghandle != null) && (features2 & 0x02000000)) { username += ' <img src="images/messaging12.png" height=12 width=12 title="' + "Verified messaging account" + '" style="margin-top:2px" />'; }
14621
x += '<tr tabindex=0 onmouseover=userMouseHover(this,1) onmouseout=userMouseHover(this,0) onkeypress="if (event.key==\'Enter\') gotoUser(\'' + encodeURIComponentEx(user._id) + '\')"><td>';
14622
x += '<div class=bar>';
14623
x += '<div class=baricon><input class=UserCheckbox value=' + encodeURIComponentEx(user._id) + ' onclick=p3updateInfo() type=checkbox' + ((user._id == userinfo._id)?' disabled':'') + '></div><div style=cursor:pointer onclick=gotoUser("' + encodeURIComponentEx(user._id) + '",false,event)>';
@@ -15686,7 +15688,7 @@
15688
}
15689
15690
if ((features2 & 0x02000000) || (user.msghandle != null)) { // If user messaging is enabled on the server or user has a messaging handle
15689
- x += addDeviceAttribute("Messaging", (user.msghandle?user.msghandle:('<i>' + "None" + '</i>')) + ' <img class=hoverButton style=cursor:pointer src="images/link5.png" onclick=p30editMessaging() />');
15691
+ x += addDeviceAttribute("Messaging", '<img src="images/messaging12.png" height=12 width=12 title="' + "Messaging enabled" + '" style="margin-top:2px" /> ' + (user.msghandle?user.msghandle:('<i>' + "None" + '</i>')) + ' <img class=hoverButton style=cursor:pointer src="images/link5.png" onclick=p30editMessaging() />');
15692
}
15693
15694
// Display features
@@ -15757,6 +15759,7 @@
15759
if (user.otpkeys > 0) { factors.push("Backup Codes"); }
15760
if (user.otpdev > 0) { factors.push("Device Push"); }
15761
if ((user.phone != null) && (features & 0x04000000)) { factors.push("SMS"); }
15762
+ if ((user.msghandle != null) && (features2 & 0x04000000)) { factors.push("Messaging"); }
15763
x += addDeviceAttribute("Security", '<img src="images/key12.png" height=12 width=11 title="' + "2nd factor authentication enabled" + '" style="margin-top:2px" /> ' + factors.join(', '));
15764
}
15765
@@ -15831,14 +15834,32 @@
15834
p30editPhoneValidate();
15835
}
15836
15834
- function p30editMessaging() { // TODO
15837
+ function p30editMessaging() {
15838
if (xxdialogMode) return;
15836
- var x = '<table style=width:100%><tr><td style=width:56px><img src="images/phone80.png" style=padding:8px>';
15837
- x += '<td style=width:100%;text-align:center>' + "SMS capable phone number for this user." + '<br />' + "Leave blank for none.";
15838
- x += '<br /><br /><div style=width:100%;text-align:center>' + "Phone number:" + ' <input type=tel pattern="[0-9]" autocomplete="tel" value="' + (currentUser.phone?currentUser.phone:'') + '" inputmode="tel" maxlength=18 id=d2phoneinput onKeyUp=p30editPhoneValidate() onkeypress="if (event.key==\'Enter\') p30editPhoneValidate(1)"></div></table>';
15839
- setDialogMode(2, "Phone Notifications", 3, p30editPhoneEx, x, 'verifyPhone');
15840
- Q('d2phoneinput').focus();
15841
- p30editPhoneValidate();
15839
+ var x = '<table style=width:100%><tr><td style=width:56px;vertical-align:top><img src="images/messaging40.png" style=padding:8px>';
15840
+ x += '<td style=width:100%>' + "Messaging account for this user." + '<br />' + "Leave blank for none.";
15841
+
15842
+ var y = '<select id=d2serviceselect style=width:160px;margin-left:8px>';
15843
+ if ((serverinfo.userMsgProviders & 1) != 0) { y += '<option value=1>' + "Telegram" + '</option>'; }
15844
+ if ((serverinfo.userMsgProviders & 2) != 0) { y += '<option value=2>' + "Signal Messenger" + '</option>'; }
15845
+ y += '</select>';
15846
+ x += '<table style=margin-top:12px><tr><td>' + "Service" + '<td>' + y;
15847
+ x += '<tr><td>' + "Handle" + '<td><input maxlength=64 style=width:160px;margin-left:8px id=d2handleinput onKeyUp=p30editMessagingValidate() onkeypress="if (event.key==\'Enter\') p30editMessagingValidate(1)">';
15848
+ x += '</table>';
15849
+
15850
+ setDialogMode(2, "Messaging Notifications", 3, p30editMessagingEx, x, 'verifyMessaging');
15851
+ Q('d2handleinput').focus();
15852
+ p30editMessagingValidate();
15853
+ }
15854
+
15855
+ function p30editMessagingValidate(x) { if (x == 1) { dialogclose(1); } }
15856
+
15857
+ // Send to the server the user's messaging account
15858
+ function p30editMessagingEx() {
15859
+ var handle = null;
15860
+ if (Q('d2handleinput').value == '') { handle = ''; }
15861
+ else if (Q('d2serviceselect').value == 1) { handle = 'telegram:@' + Q('d2handleinput').value; }
15862
+ if (handle != null) { meshserver.send({ action: 'edituser', id: currentUser._id, msghandle: handle }); }
15863
}
15864
15865
function p20edituserfeatures() {