diff --git a/controllers/usuario.controller.js b/controllers/usuario.controller.js
index a923013..f02a977 100644
--- a/controllers/usuario.controller.js
+++ b/controllers/usuario.controller.js
@@ -1,4 +1,8 @@
const Usuario = require('../models/usuario.model.js');
+const nodemailer = require('nodemailer');
+const path = require('path');
+const dotenv = require('dotenv');
+dotenv.config();
/**
* @description Registra un nuevo usuario en la base de datos.
@@ -16,6 +20,91 @@ exports.registrarUsuario = async (req, res) => {
}
}
+/**
+ * @description Genera una contraseña aleatoria.
+ * @param {int} longitud - Longitud de la contraseña.
+ * @returns {String} Contraseña nueva.
+ */
+function generarContrasena(longitud = 6) {
+ const caracteres = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+ let contrasena = '';
+ for (let it = 0; it < longitud; it++) {
+ const indice = Math.floor(Math.random() * caracteres.length);
+ contrasena += caracteres[indice];
+ }
+ return contrasena;
+}
+
+/**
+ * @description Manda un correo de recuperación para recuperar la contraseña
+ * @param {*} req - Solicitud HTTP que contiene información del usuario.
+ * @param {*} res - Respuesta HTTP que se usa para enviar el resultado.
+ * @returns {JSON} Código de respuesta
+ */
+exports.mandarCorreo = async (req, res) => {
+ try{
+ const usuario = req.query.usuario;
+ const usuarioId = await Usuario.obtenerId(usuario);
+ if (usuarioId == null){
+ res.status(201).json({code: 201});
+ return;
+ }
+
+ const nuevaContrasena = generarContrasena();
+
+ const transporter = nodemailer.createTransport({
+ service: 'gmail',
+ auth: {
+ user: process.env.MAIL_USER,
+ pass: process.env.MAIL_PASSWORD,
+ },
+ });
+
+ const mailOptions = {
+ from: process.env.MAIL_USER,
+ to: process.env.MAIL_RECEIVER,
+ subject: 'Recuperar contraseña ZuustentoTracker',
+ html: `
+

+
¿Olvidaste tu contraseña?
+
Este correo es automatizado, se solicitó el cambio de contraseña para:
+
${usuario}
+
Nueva Contraseña:
+
${nuevaContrasena}
+
Si no solicitaste este cambio, puedes ignorar este correo.
+
`,
+ attachments: [
+ {
+ filename: 'logo.png',
+ path: path.join(__dirname, '..', 'public', 'ZuustentoTracker_AppIcon.png'),
+ cid: 'logo'
+ }
+ ]
+ };
+
+ transporter.sendMail(mailOptions, (error, info) => {
+ if (error) {
+ console.log(error)
+ res.status(500).json({code: 500});
+ return;
+ }
+ });
+
+ await Usuario.cambiarContrasena(usuarioId.usuarioId, nuevaContrasena);
+
+ res.status(200).json({code: 200});
+ } catch (error){
+ console.log(error)
+ res.status(500).json({code: 500})
+ }
+};
+
+/**
+ * @description Obtiene todos los usuarios de la base de datos
+ * @param {*} req - Solicitud HTTP que contiene información del usuario.
+ * @param {*} res - Respuesta HTTP que se usa para enviar el resultado.
+ * @returns {JSON} Código de respuesta
+ */
exports.obtenerUsuarios = async (req, res) => {
try{
const resultado = await Usuario.obtenerUsuarios();
@@ -25,6 +114,12 @@ exports.obtenerUsuarios = async (req, res) => {
}
}
+/**
+ * @description Edita la informacion de un usuario
+ * @param {*} req - Solicitud HTTP que contiene información del usuario.
+ * @param {*} res - Respuesta HTTP que se usa para enviar el resultado.
+ * @returns {JSON} Código de respuesta
+ */
exports.editarUsuario = async (req, res) => {
try{
const resultado = await Usuario.editarUsuario(parseInt(req.query.usuarioId), req.body);
@@ -36,6 +131,12 @@ exports.editarUsuario = async (req, res) => {
}
}
+/**
+ * @description Elimina un usuario de la plataforma
+ * @param {*} req - Solicitud HTTP que contiene información del usuario.
+ * @param {*} res - Respuesta HTTP que se usa para enviar el resultado.
+ * @returns {JSON} Código de respuesta
+ */
exports.eliminarUsuario = async (req, res) => {
try{
const resultado = await Usuario.eliminarUsuario(parseInt(req.query.usuarioId));
@@ -44,4 +145,4 @@ exports.eliminarUsuario = async (req, res) => {
} catch (error){
return res.status(500).json({ code: 500 });
}
-}
\ No newline at end of file
+}
diff --git a/models/usuario.model.js b/models/usuario.model.js
index f9cc149..9226e45 100644
--- a/models/usuario.model.js
+++ b/models/usuario.model.js
@@ -84,7 +84,10 @@ module.exports = class Usuario {
return nuevo;
}
-
+ /**
+ * @description Extrae todos los usuarios de la base de datos y especifica sus roles
+ * @returns {Array} Resultado de la consulta.
+ */
static async obtenerUsuarios(){
const usuarios = await prisma.USUARIO.findMany({
include: {
@@ -104,6 +107,12 @@ module.exports = class Usuario {
return resultado;
}
+ /**
+ * @description Edita la informacion de un usuario
+ * @param {Object} infoUsuario - Objeto con información del usuario.
+ * @param {int} usuarioId - Id del usuario a editar.
+ * @returns {Array} Resultado de la consulta
+ */
static async editarUsuario(usuarioId, infoUsuario){
const contrasenaHash = await bcrypt.hash(infoUsuario.contrasena, 12);
@@ -121,6 +130,10 @@ module.exports = class Usuario {
})
}
+ /**
+ * @description Elimina la informacion de un usuario
+ * @param {int} usuarioId - Id del usuario a editar.
+ */
static async eliminarUsuario(usuarioId){
await prisma.USUARIO.delete({
where: {
@@ -128,4 +141,39 @@ module.exports = class Usuario {
}
})
}
+
+ /**
+ * @description Obtiene el id de un usuario apartir de su nombre
+ * @param {String} nombreUsuario Nombre del usuario
+ * @returns {int} Resultado de la consulta
+ */
+ static async obtenerId(nombreUsuario) {
+ return await prisma.USUARIO.findFirst({
+ where: {
+ user: nombreUsuario
+ },
+ select: {
+ usuarioId: true
+ }
+ })
+ }
+
+ /**
+ * @description Cambia la contraseña de un usuario
+ * @param {int} usuarioId Id del usuario
+ * @param {String} contrasena Contraseña nueva
+ * @returns {int} Resultado de la consulta
+ */
+ static async cambiarContrasena(usuarioId, contrasena) {
+ const contrasenaHash = await bcrypt.hash(contrasena, 12);
+
+ await prisma.USUARIO.update({
+ where: {
+ usuarioId: usuarioId
+ },
+ data: {
+ contrasena: contrasenaHash
+ }
+ });
+ }
};
diff --git a/package-lock.json b/package-lock.json
index d6d9ddd..f522b32 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -26,6 +26,7 @@
"mariadb": "^3.4.0",
"mysql2": "^3.14.0",
"nodejs": "^0.0.0",
+ "nodemailer": "^7.0.3",
"winston": "^3.17.0"
},
"devDependencies": {
@@ -6379,6 +6380,14 @@
"integrity": "sha512-1V+0HwaB/dhxzidEFc4uJ3k52gLI4B6YBZgJIofjwYCSAkD6CI0me6TDBT2QM2nbGWNxCHcq9/wVynzQYZOhUg==",
"license": "ISC"
},
+ "node_modules/nodemailer": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.3.tgz",
+ "integrity": "sha512-Ajq6Sz1x7cIK3pN6KesGTah+1gnwMnx5gKl3piQlQQE/PwyJ4Mbc8is2psWYxK3RJTVeqsDaCv8ZzXLCDHMTZw==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
diff --git a/package.json b/package.json
index b30f619..fa3794b 100644
--- a/package.json
+++ b/package.json
@@ -39,6 +39,7 @@
"mariadb": "^3.4.0",
"mysql2": "^3.14.0",
"nodejs": "^0.0.0",
+ "nodemailer": "^7.0.3",
"winston": "^3.17.0"
},
"devDependencies": {
diff --git a/public/ZuustentoTracker_AppIcon.PNG b/public/ZuustentoTracker_AppIcon.PNG
new file mode 100644
index 0000000..1495dc2
Binary files /dev/null and b/public/ZuustentoTracker_AppIcon.PNG differ
diff --git a/routes/usuario.routes.js b/routes/usuario.routes.js
index 2e332cf..0bfeaee 100644
--- a/routes/usuario.routes.js
+++ b/routes/usuario.routes.js
@@ -18,6 +18,7 @@ router.get("/obtenerUsuarios", usuarioController.obtenerUsuarios);
/* POST METHODS */
router.post("/iniciarSesion", autenticacionController.iniciarSesion);
router.post("/registrarUsuario", usuarioController.registrarUsuario);
+router.post("/recuperarContrasena", usuarioController.mandarCorreo);
/* ----------- */
/* PUT METHODS */