salix/back/methods/vn-user/recover-passwordSMS.js

116 lines
3.2 KiB
JavaScript

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;
}
};
};