More SMS work.

Ylian Saint-Hilaire committed Apr 22, 2020 at 02:23 UTC 2b6925205ff36d4966a08dd14ea4af570468b4b4
4 files changed +36 -23
meshsms.js
+8 -15
@@ -43,7 +43,6 @@ module.exports.CreateMeshSMS = function (parent) {
43 // Send an SMS message
44 obj.sendSMS = function (to, msg, func) {
45 parent.debug('email', 'Sending SMS to: ' + to + ': ' + msg);
46 - console.log({ from: parent.config.sms.from, to: to, body: msg });
46 if (parent.config.sms.provider == 'twilio') {
47 obj.provider.messages.create({
48 from: parent.config.sms.from,
@@ -78,7 +77,7 @@ module.exports.CreateMeshSMS = function (parent) {
77 }
78
79 // Get the english email
81 - if ((htmlfile == null) || (txtfile == null)) {
80 + if (txtfile == null) {
81 var pathTxt = obj.parent.path.join(emailsPath, 'sms-messages.txt');
82 if (obj.parent.fs.existsSync(pathTxt)) {
83 txtfile = obj.parent.fs.readFileSync(pathTxt).toString();
@@ -89,8 +88,8 @@ module.exports.CreateMeshSMS = function (parent) {
88 if (txtfile == null) { return null; }
89
90 // Decode the TXT file
92 - lines = txtfile.split('\r\n').join('\n').split('\n')
93 - if (lines.length >= templateNumber) return null;
91 + var lines = txtfile.split('\r\n').join('\n').split('\n')
92 + if (lines.length <= templateNumber) return null;
93
94 return lines[templateNumber];
95 }
@@ -99,22 +98,16 @@ module.exports.CreateMeshSMS = function (parent) {
98 obj.sendPhoneCheck = function (domain, phoneNumber, verificationCode, language, func) {
99 parent.debug('email', "Sending verification SMS to " + phoneNumber);
100
102 - var template = getTemplate(0, domain, language);
103 - if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null)) {
104 - parent.debug('email', "Error: Failed to get SMS template"); // No SMS template found
105 - return;
106 - }
101 + var sms = getTemplate(0, domain, language);
102 + if (sms == null) { parent.debug('email', "Error: Failed to get SMS template"); return; } // No SMS template found
103
104 // Setup the template
109 - template.split("[[0]]").join(domain.title ? domain.title : 'MeshCentral');
110 - template.split("[[1]]").join(verificationCode);
105 + sms = sms.split('[[0]]').join(domain.title ? domain.title : 'MeshCentral');
106 + sms = sms.split('[[1]]').join(verificationCode);
107
108 // Send the SMS
113 - obj.sendSMS(phoneNumber, template, func);
109 + obj.sendSMS(phoneNumber, sms, func);
110 };
111
112 return obj;
113 };
118 -
119 -// +18632703894
120 -// SMS 5032700426 "This is a test"
meshuser.js
+16 -8
@@ -3713,24 +3713,20 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
3713 if (parent.parent.smsserver == null) return;
3714 if (common.validateString(command.phone, 1, 18) == false) break; // Check phone length
3715 if (command.phone.match(/^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/) == false) break; // Check phone
3716 - var code = getRandomEightDigitInteger();
3717 - //console.log(code);
3716 + const code = getRandomEightDigitInteger();
3717
3719 - // TODO: We need to tie this cookie to this session and limit how many times we can guess the code
3720 - const phoneCookie = parent.parent.encodeCookie({ a: 'verifyPhone', c: code, p: command.phone });
3721 -
3722 - ws.send(JSON.stringify({ action: 'verifyPhone', cookie: phoneCookie, success: true })); // DEBUG
3723 - /*
3718 + // TODO: We need limit how many times we can guess the code
3719 + const phoneCookie = parent.parent.encodeCookie({ a: 'verifyPhone', c: code, p: command.phone, s: ws.sessionId });
3720 parent.parent.smsserver.sendPhoneCheck(domain, command.phone, code, parent.getLanguageCodes(req), function (success) {
3721 ws.send(JSON.stringify({ action: 'verifyPhone', cookie: phoneCookie, success: success }));
3722 });
3727 - */
3723 break;
3724 }
3725 case 'confirmPhone': {
3726 if ((parent.parent.smsserver == null) || (typeof command.cookie != 'string') || (typeof command.code != 'number')) break; // Input checks
3727 var cookie = parent.parent.decodeCookie(command.cookie);
3728 if (cookie == null) break; // Invalid cookie
3729 + if (cookie.s != ws.sessionId) break; // Invalid session
3730 if (cookie.c != command.code) { ws.send(JSON.stringify({ action: 'verifyPhone', cookie: command.cookie, success: true })); break; } // Code does not match
3731
3732 // Set the user's phone
@@ -3758,6 +3754,18 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
3754
3755 break;
3756 }
3757 + case 'smsuser': { // Send a SMS message to a user
3758 + if (parent.parent.smsserver == null) break;
3759 + if ((user.siteadmin & 2) == 0) break;
3760 + if (common.validateString(command.userid, 1, 2048) == false) break;
3761 + if (common.validateString(command.msg, 1, 160) == false) break;
3762 + var smsuser = parent.users[command.userid];
3763 + if ((smsuser == null) || (smsuser.phone == null)) break;
3764 + parent.parent.smsserver.sendSMS(smsuser.phone, command.msg, function (success) {
3765 + // TODO
3766 + });
3767 + break;
3768 + }
3769 case 'getClip': {
3770 if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
3771
public/images/phone12.png
Binary files /dev/null and b/public/images/phone12.png differ
views/default.handlebars
+12
@@ -9799,6 +9799,7 @@
9799 }
9800
9801 if ((user.otpsecret > 0) || (user.otphkeys > 0)) { username += ' <img src="images/key12.png" height=12 width=11 title="' + "2nd factor authentication enabled" + '" style="margin-top:2px" />'; }
9802 + if (user.phone != null) { username += ' <img src="images/phone12.png" height=12 width=7 title="' + "Verified phone number" + '" style="margin-top:2px" />'; }
9803 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" />'; }
9804
9805 x += '<tr tabindex=0 onmouseover=userMouseHover(this,1) onmouseout=userMouseHover(this,0) onkeypress="if (event.key==\'Enter\') gotoUser(\'' + encodeURIComponent(user._id) + '\')"><td>';
@@ -9907,6 +9908,16 @@
9908 return false;
9909 }
9910
9911 + function showSendSMS(userid) {
9912 + if (xxdialogMode) return;
9913 + setDialogMode(2, "Send SMS", 3, showSendSMSEx, '<textarea id=d2smsText maxlength=160 style=background-color:#fcf3cf;width:100%;height:100px;resize:none onKeyUp=showSendSMSValidate()></textarea><span style=font-size:10px><span>', decodeURIComponent(userid));
9914 + Q('d2smsText').focus();
9915 + showSendSMSValidate();
9916 + }
9917 +
9918 + function showSendSMSValidate() { QE('idx_dlgOkButton', Q('d2smsText').value.length > 0); }
9919 + function showSendSMSEx(b, tag) { if (Q('d2smsText').value.length > 0) { meshserver.send({ action: 'smsuser', userid: tag, msg: Q('d2smsText').value }); } }
9920 +
9921 function showUserAlertDialog(e, userid) {
9922 if (xxdialogMode) return;
9923 haltEvent(e);
@@ -10657,6 +10668,7 @@
10668
10669 // Add action buttons
10670 x += '<input type=button value=\"' + "Notes" + '\" title=\"' + "View notes about this user" + '\" onclick=showNotes(false,"' + userid + '") />';
10671 + if (user.phone && (features & 0x02000000)) { x += '<input type=button value=\"' + "SMS" + '\" title=\"' + "Send a SMS message to this user" + '\" onclick=showSendSMS("' + encodeURIComponent(userid) + '") />'; }
10672 if (!self && (activeSessions > 0)) { x += '<input type=button value=\"' + "Notify" + '\" title=\"' + "Send user notification" + '\" onclick=showUserAlertDialog(event,"' + userid + '") />'; }
10673
10674 // Setup the panel