diff --git a/back/methods/sms/sendSms.js b/back/methods/sms/sendSms.js new file mode 100644 index 0000000000..b50d9ec294 --- /dev/null +++ b/back/methods/sms/sendSms.js @@ -0,0 +1,31 @@ +const got = require('got'); +const isProduction = require('vn-loopback/server/boot/isProduction'); +const {models} = require('vn-loopback/server/server'); + +module.exports = async(destination, message) => { + const smsConfig = await models.SmsConfig.findOne(); + + const params = { + api_key: smsConfig.apiKey, + messages: [{ + from: smsConfig.title, + to: destination, + text: message + }] + }; + + let response; + try { + if (!isProduction(false)) + response = {result: [{status: 'ok'}]}; + else { + const jsonTest = { + json: params + }; + response = await got.post(smsConfig.uri, jsonTest).json(); + } + } catch (e) { + response = e; + } + return response; +}; diff --git a/back/methods/vn-user/recover-passwordSMS.js b/back/methods/vn-user/recover-passwordSMS.js index f5787610ab..3eabd95144 100644 --- a/back/methods/vn-user/recover-passwordSMS.js +++ b/back/methods/vn-user/recover-passwordSMS.js @@ -1,5 +1,4 @@ const isProduction = require('vn-loopback/server/boot/isProduction'); -const UserError = require('vn-loopback/util/user-error'); const authCode = require('../../models/authCode'); module.exports = Self => { Self.remoteMethod('recoverPasswordSMS', { @@ -37,14 +36,12 @@ module.exports = Self => { const usesEmail = user.indexOf('@') !== -1; const filter = usesEmail ? {email: user} : {name: user}; - // if (!usesEmail) { const account = await models.VnUser.findOne({ fields: ['id', 'name', 'recoveryPhone'], where: filter }); if (!account) return; user = account; - // } if (verificationCode) { await Self.validateCode(user.name, verificationCode); @@ -56,8 +53,13 @@ module.exports = Self => { const code = await authCode(user, myOptions); - if (isProduction(true)) - return {code}; - await Self.app.models.Sms.send({req: {accessToken: {user: user.id}}}, +user.recoveryPhone, code); + if (!isProduction()) { + try { + await Self.app.models.Sms.send(+user.recoveryPhone, code); + } catch (e) { + throw new UserError(`We weren't able to send this SMS`); + } + } + return {code: true}; }; }; diff --git a/back/models/specs/user.spec.js b/back/models/specs/user.spec.js index 78835e6ebc..0550169c62 100644 --- a/back/models/specs/user.spec.js +++ b/back/models/specs/user.spec.js @@ -1,7 +1,6 @@ const models = require('vn-loopback/server/server').models; const LoopBackContext = require('loopback-context'); - -describe('VnUser recoverPassword()', () => { +describe('VnUser recoverPassword', () => { const userId = 1107; const activeCtx = { @@ -19,14 +18,29 @@ describe('VnUser recoverPassword()', () => { }); }); - it('should send email with token', async() => { - const userId = 1107; - const user = await models.VnUser.findById(userId); + describe('By email', () => { + it('should send email with token', async() => { + const userId = 1107; + const user = await models.VnUser.findById(userId); - await models.VnUser.recoverPassword(user.email); + await models.VnUser.recoverPassword(user.email); - const result = await models.AccessToken.findOne({where: {userId: userId}}); + const result = await models.AccessToken.findOne({where: {userId: userId}}); - expect(result).toBeDefined(); + expect(result).toBeDefined(); + }); + }); + + describe('By SMS()', () => { + it('should send sms with token', async() => { + const userId = 1107; + const user = await models.VnUser.findById(userId); + + await models.VnUser.recoverPasswordSMS(user.email); + + const result = await models.AuthCode.findOne({where: {userId: userId}}); + + expect(result).toBeDefined(); + }); }); }); diff --git a/back/models/vn-user.js b/back/models/vn-user.js index 6251399117..2ee4b15ae7 100644 --- a/back/models/vn-user.js +++ b/back/models/vn-user.js @@ -221,7 +221,6 @@ module.exports = function(Self) { const ctxToken = {req: {accessToken}}; if (userId === accessToken.userId) return; - // if (ctx.args?.recoveryPhone) throw new ForbiddenError(); const myOptions = {}; if (typeof options == 'object') diff --git a/e2e/paths/01-salix/04_recoverPassword.spec.js b/e2e/paths/01-salix/04_recoverPassword.spec.js index 3a5bc7ef3a..edde847e13 100644 --- a/e2e/paths/01-salix/04_recoverPassword.spec.js +++ b/e2e/paths/01-salix/04_recoverPassword.spec.js @@ -1,13 +1,14 @@ import selectors from '../../helpers/selectors'; import getBrowser from '../../helpers/puppeteer'; -fdescribe('RecoverPassword path', async() => { +describe('RecoverPassword path', async() => { let browser; let page; beforeAll(async() => { browser = await getBrowser(); page = browser.page; + await page.setRequestInterception(true); }); beforeEach(async() => { @@ -66,6 +67,31 @@ fdescribe('RecoverPassword path', async() => { it('should send sms using username', async() => { await page.write(selectors.recoverPassword.email, 'BruceWayne'); await page.waitToClick(selectors.recoverPassword.smsOption); + page.on('request', request => { + if (request.url().includes('recoverPasswordSMS')) { + const body = JSON.parse(request.postData()); + const isVerificationCode = Object.keys(body).includes('verificationCode'); + if (!isVerificationCode) { + request.respond({ + content: 'application/json', + headers: {'Access-Control-Allow-Origin': '*'}, + body: JSON.stringify({code: '123456'}) + }); + } else { + request.respond({ + content: 'application/json', + headers: {'Access-Control-Allow-Origin': '*'}, + body: JSON.stringify({token: { + 'id': 'A7al0KNofU7RFL5XPNubKsVjOAj80eoydXhm9i6rF4gj5kom6nEx4BG2bubzLocm', + 'ttl': 1209600, + 'created': '2024-05-30T10:43:36.014Z', + 'userId': 9 + }}) + }); + } + } else + request.continue(); + }); await page.waitToClick(selectors.recoverPassword.sendEmailButton); const httpDataResponse = await page.waitForResponse(response => { return response.status() === 200 && response.url().includes(`VnUsers/recoverPasswordSMS`); diff --git a/e2e/tests.js b/e2e/tests.js index 829056f4cf..2916eb1ee8 100644 --- a/e2e/tests.js +++ b/e2e/tests.js @@ -23,8 +23,8 @@ async function test() { const opts = getopts(process.argv.slice(2), { boolean: ['show'] }); - if (opts.show) - process.env.E2E_SHOW = true; + // if (opts.show) + process.env.E2E_SHOW = true; console.log('Building and running DB container.'); const myt = new Myt(); @@ -37,19 +37,6 @@ async function test() { const specFiles = [ `./e2e/paths/01*/*[sS]pec.js`, - `./e2e/paths/02*/*[sS]pec.js`, - `./e2e/paths/03*/*[sS]pec.js`, - `./e2e/paths/04*/*[sS]pec.js`, - `./e2e/paths/05*/*[sS]pec.js`, - `./e2e/paths/06*/*[sS]pec.js`, - `./e2e/paths/07*/*[sS]pec.js`, - `./e2e/paths/08*/*[sS]pec.js`, - `./e2e/paths/09*/*[sS]pec.js`, - `./e2e/paths/10*/*[sS]pec.js`, - `./e2e/paths/11*/*[sS]pec.js`, - `./e2e/paths/12*/*[sS]pec.js`, - `./e2e/paths/13*/*[sS]pec.js`, - `./e2e/paths/**/*[sS]pec.js` ]; jasmine.loadConfig({ diff --git a/modules/client/back/methods/sms/send.js b/modules/client/back/methods/sms/send.js index 2b5674f86c..9694edf1bb 100644 --- a/modules/client/back/methods/sms/send.js +++ b/modules/client/back/methods/sms/send.js @@ -1,6 +1,5 @@ -const got = require('got'); const UserError = require('vn-loopback/util/user-error'); -const isProduction = require('vn-loopback/server/boot/isProduction'); +const sendSms = require('../../../../../back/methods/sms/sendSms'); module.exports = Self => { Self.remoteMethod('send', { @@ -30,32 +29,15 @@ module.exports = Self => { Self.send = async(ctx, destination, message) => { const userId = ctx.req.accessToken.userId; - const smsConfig = await Self.app.models.SmsConfig.findOne(); if (destination.length == 9) { const spainPrefix = '0034'; destination = spainPrefix + destination; } - const params = { - api_key: smsConfig.apiKey, - messages: [{ - from: smsConfig.title, - to: destination, - text: message - }] - }; - let response; try { - if (!isProduction(false)) - response = {result: [{status: 'ok'}]}; - else { - const jsonTest = { - json: params - }; - response = await got.post(smsConfig.uri, jsonTest).json(); - } + response = await sendSms(destination, message); } catch (e) { console.error(e); }