diff --git a/meshsms.js b/meshsms.js index fecb209e..0b9a65cf 100644 --- a/meshsms.js +++ b/meshsms.js @@ -43,7 +43,6 @@ module.exports.CreateMeshSMS = function (parent) { // Send an SMS message obj.sendSMS = function (to, msg, func) { parent.debug('email', 'Sending SMS to: ' + to + ': ' + msg); - console.log({ from: parent.config.sms.from, to: to, body: msg }); if (parent.config.sms.provider == 'twilio') { obj.provider.messages.create({ from: parent.config.sms.from, @@ -78,7 +77,7 @@ module.exports.CreateMeshSMS = function (parent) { } // Get the english email - if ((htmlfile == null) || (txtfile == null)) { + if (txtfile == null) { var pathTxt = obj.parent.path.join(emailsPath, 'sms-messages.txt'); if (obj.parent.fs.existsSync(pathTxt)) { txtfile = obj.parent.fs.readFileSync(pathTxt).toString(); @@ -89,8 +88,8 @@ module.exports.CreateMeshSMS = function (parent) { if (txtfile == null) { return null; } // Decode the TXT file - lines = txtfile.split('\r\n').join('\n').split('\n') - if (lines.length >= templateNumber) return null; + var lines = txtfile.split('\r\n').join('\n').split('\n') + if (lines.length <= templateNumber) return null; return lines[templateNumber]; } @@ -99,22 +98,16 @@ module.exports.CreateMeshSMS = function (parent) { obj.sendPhoneCheck = function (domain, phoneNumber, verificationCode, language, func) { parent.debug('email', "Sending verification SMS to " + phoneNumber); - var template = getTemplate(0, domain, language); - if ((template == null) || (template.htmlSubject == null) || (template.txtSubject == null)) { - parent.debug('email', "Error: Failed to get SMS template"); // No SMS template found - return; - } + var sms = getTemplate(0, domain, language); + if (sms == null) { parent.debug('email', "Error: Failed to get SMS template"); return; } // No SMS template found // Setup the template - template.split("[[0]]").join(domain.title ? domain.title : 'MeshCentral'); - template.split("[[1]]").join(verificationCode); + sms = sms.split('[[0]]').join(domain.title ? domain.title : 'MeshCentral'); + sms = sms.split('[[1]]').join(verificationCode); // Send the SMS - obj.sendSMS(phoneNumber, template, func); + obj.sendSMS(phoneNumber, sms, func); }; return obj; }; - -// +18632703894 -// SMS 5032700426 "This is a test" diff --git a/meshuser.js b/meshuser.js index 0507a711..9ee3cc99 100644 --- a/meshuser.js +++ b/meshuser.js @@ -3713,24 +3713,20 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (parent.parent.smsserver == null) return; if (common.validateString(command.phone, 1, 18) == false) break; // Check phone length if (command.phone.match(/^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/) == false) break; // Check phone - var code = getRandomEightDigitInteger(); - //console.log(code); + const code = getRandomEightDigitInteger(); - // TODO: We need to tie this cookie to this session and limit how many times we can guess the code - const phoneCookie = parent.parent.encodeCookie({ a: 'verifyPhone', c: code, p: command.phone }); - - ws.send(JSON.stringify({ action: 'verifyPhone', cookie: phoneCookie, success: true })); // DEBUG - /* + // TODO: We need limit how many times we can guess the code + const phoneCookie = parent.parent.encodeCookie({ a: 'verifyPhone', c: code, p: command.phone, s: ws.sessionId }); parent.parent.smsserver.sendPhoneCheck(domain, command.phone, code, parent.getLanguageCodes(req), function (success) { ws.send(JSON.stringify({ action: 'verifyPhone', cookie: phoneCookie, success: success })); }); - */ break; } case 'confirmPhone': { if ((parent.parent.smsserver == null) || (typeof command.cookie != 'string') || (typeof command.code != 'number')) break; // Input checks var cookie = parent.parent.decodeCookie(command.cookie); if (cookie == null) break; // Invalid cookie + if (cookie.s != ws.sessionId) break; // Invalid session if (cookie.c != command.code) { ws.send(JSON.stringify({ action: 'verifyPhone', cookie: command.cookie, success: true })); break; } // Code does not match // Set the user's phone @@ -3758,6 +3754,18 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use break; } + case 'smsuser': { // Send a SMS message to a user + if (parent.parent.smsserver == null) break; + if ((user.siteadmin & 2) == 0) break; + if (common.validateString(command.userid, 1, 2048) == false) break; + if (common.validateString(command.msg, 1, 160) == false) break; + var smsuser = parent.users[command.userid]; + if ((smsuser == null) || (smsuser.phone == null)) break; + parent.parent.smsserver.sendSMS(smsuser.phone, command.msg, function (success) { + // TODO + }); + break; + } case 'getClip': { if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid diff --git a/public/images/phone12.png b/public/images/phone12.png new file mode 100644 index 00000000..cca43f65 Binary files /dev/null and b/public/images/phone12.png differ diff --git a/views/default.handlebars b/views/default.handlebars index bf3aecec..9489c9c0 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -9799,6 +9799,7 @@ } if ((user.otpsecret > 0) || (user.otphkeys > 0)) { username += ' '; } + if (user.phone != null) { username += ' '; } if ((user.siteadmin != null) && ((user.siteadmin & 32) != 0) && (user.siteadmin != 0xFFFFFFFF)) { username += ' '; } x += ''; @@ -9907,6 +9908,16 @@ return false; } + function showSendSMS(userid) { + if (xxdialogMode) return; + setDialogMode(2, "Send SMS", 3, showSendSMSEx, '', decodeURIComponent(userid)); + Q('d2smsText').focus(); + showSendSMSValidate(); + } + + function showSendSMSValidate() { QE('idx_dlgOkButton', Q('d2smsText').value.length > 0); } + function showSendSMSEx(b, tag) { if (Q('d2smsText').value.length > 0) { meshserver.send({ action: 'smsuser', userid: tag, msg: Q('d2smsText').value }); } } + function showUserAlertDialog(e, userid) { if (xxdialogMode) return; haltEvent(e); @@ -10657,6 +10668,7 @@ // Add action buttons x += ''; + if (user.phone && (features & 0x02000000)) { x += ''; } if (!self && (activeSessions > 0)) { x += ''; } // Setup the panel