const UserError = require('vn-loopback/util/user-error'); const authCode = require('../../models/authCode'); const OTP_CHAR = ':'; function original({id, phone}) { const total = parseInt(phone) + parseInt(id); const value = total.toString().slice(-6); return parseInt(value); // Devolvemos un nĂºmero entero, no una cadena } function reverse(params) { const _original = original(params); return parseInt(_original.toString().split('').reverse().join('')); } function selectOTPMethod() { const otpIndex = Math.floor(Math.random() * Object.keys(OTP_TYPES).length); return Object.keys(OTP_TYPES)[otpIndex]; } function generateOTP(params, _otpType, format = true) { const otpType = _otpType ?? selectOTPMethod(); const otp = OTP_TYPES[otpType](params); if (format) return formatOTP({otpType, otp}); return {otpType, otp}; } function formatOTP({otpType, otp}) { return `${otpType}${OTP_CHAR}${otp}`; } function checkOTP(params, otp) { const [otpType, value] = otp.split(OTP_CHAR); return generateOTP(params, otpType) === formatOTP(otpType, value); } const OTP_TYPES = { // 'A': original, 'B': reverse, }; module.exports = Self => { Self.remoteMethod('recoverPasswordSMS', { description: 'Send SMS to the user', accepts: [ { arg: 'ctx', type: 'Object', http: {source: 'context'} }, { arg: 'id', type: 'string', description: 'The user id', required: true }, { arg: 'phone', type: 'string', description: 'The user name or email', required: true }, { arg: 'otp', type: 'string', description: 'The directory for mail' } ], returns: { type: 'Object', root: true }, http: { path: `/recoverPasswordSMS`, verb: 'POST' } }); Self.recoverPasswordSMS = async function(ctx, id, phone, _otp, options) { const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); const usesPhone = new RegExp(/([+]\d{2})?\d{9}/, 'g').test(+phone); if (!usesPhone) throw new UserError('Phone not valid'); let query = { fields: ['id', 'phone', 'email', 'name'], where: {id, phone} }; const user = await Self.findOne(query); if (!user) throw new UserError('Credentials not valid'); try { if (_otp) { await Self.validateCode(user.name, _otp); return { token: await user.accessTokens.create({}) }; } const code = await authCode(user, myOptions); if (process.env.NODE_ENV != 'production') await Self.app.models.Sms.send({req: {accessToken: {userId: id}}}, +phone, code); return {otp: true}; } catch (err) { if (err.code === 'EMAIL_NOT_FOUND') return; else throw err; } }; };