Se reacomoda un poco el servicio auth.service.js haciendo una separación de responsabilidades, se crea el método sendRecovery el cual contiene la lógica para generar un link para recuperar la contraseña y el método sendMail contiene la configuración para poder enviar un email (transporter).
Lo que hace es:
-
Validar si el email se encuentra en la base de datos, si todo bien, se obtiene el
user. -
Se genera un
payloadcon eluser.id. -
Se genera un
tokenque expira en 15 minutos, incluye elpayloadcon el id del usuario que solicita recuperar su contraseña. Por seguridad, el token debe guardarse en la BD y comprobarlo para evitar que envíen un token indeseado. -
Se genera un link que incluye el token necesario para recuperar la contraseña. Desde el frontend debe haber una vista para ello.
-
Se llama el método
updatedeUserServicepara actualizar los datos del usuario asignandole el token generado. -
Se establece el cuerpo del
email. -
Se ejecuta el método
sendMailque recibe el cuerpo delemail.
const boom = require('@hapi/boom');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const nodemailer = require('nodemailer');
const { config } = require('../config/config');
const UserService = require('./user.service');
const service = new UserService();
class AuthService {
async getUser(email, password) {
const user = await service.findByEmail(email);
if (!user) {
throw boom.unauthorized();
}
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
throw boom.unauthorized();
}
delete user.dataValues.password;
return user;
}
signToken(user) {
const payload = {
sub: user.id,
role: user.role,
};
const token = jwt.sign(payload, config.jwtSecret);
return {
user,
token,
};
}
async sendRecovery(email) {
const user = await service.findByEmail(email);
if (!user) {
throw boom.unauthorized();
}
const payload = { sub: user.id };
const token = jwt.sign(payload, config.jwtRecoverySecret, {
expiresIn: '15min',
});
const link = `https://myfrontend.com/recovery?token=${token}`;
await service.update(user.id, { recoveryToken: token });
const mail = {
from: `"Foo Boo 👻" <${config.mailerEmail}>`,
to: `${user.email}`,
subject: 'Email para recuperar contraseña',
html: `<b>Ingresa a este link para recuperar tu contraseña: ${link}</b>`,
};
const rta = await this.sendMail(mail);
return rta;
}
async sendMail(infoMail) {
const transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
secure: true, // true for 465, false for other ports
port: 465,
auth: {
user: config.mailerEmail,
pass: config.mailerPassword,
},
});
await transporter.sendMail(infoMail);
return { message: 'Mail sent' };
}
}
module.exports = AuthService;