Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 102 additions & 1 deletion controllers/usuario.controller.js
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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: `<div style="font-family: Arial, sans-serif; text-align: center;">
<img src="cid:logo" alt="Logo de ZuustentoTracker" style="width: 150px; margin-bottom: 20px;" />
<h2>¿Olvidaste tu contraseña?</h2>
<p>Este correo es automatizado, se solicitó el cambio de contraseña para:</p>
<p style="font-weight: bold">${usuario}</p>
<p>Nueva Contraseña:</p>
<p style="font-weight: bold">${nuevaContrasena}</p>
<p style="margin-top: 20px;">Si no solicitaste este cambio, puedes ignorar este correo.</p>
</div>`,
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();
Expand All @@ -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);
Expand All @@ -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));
Expand All @@ -44,4 +145,4 @@ exports.eliminarUsuario = async (req, res) => {
} catch (error){
return res.status(500).json({ code: 500 });
}
}
}
50 changes: 49 additions & 1 deletion models/usuario.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand All @@ -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);

Expand All @@ -121,11 +130,50 @@ 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: {
usuarioId: usuarioId
}
})
}

/**
* @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
}
});
}
};
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
Binary file added public/ZuustentoTracker_AppIcon.PNG
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions routes/usuario.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down