From 7a6986faaed01a214790764e776d64880e3042d1 Mon Sep 17 00:00:00 2001 From: IO420 <320154041@pcpuma.acatlan.unam.mx> Date: Thu, 22 May 2025 18:33:00 -0400 Subject: [PATCH] add validation and add pool --- db.js | 28 ++++--- envConfigurations/EnvConfigurations.js | 3 +- index.js | 6 ++ middleware/handleValidation.js | 1 + middleware/verifyToken.js | 1 + routes/impressions.js | 110 ++++++++++++------------- routes/login.js | 51 ++++++------ routes/receipt.js | 69 +++++++--------- routes/student.js | 32 +++---- routes/token.js | 1 + validators/impressionValidator.js | 1 + validators/loginValidator.js | 1 + validators/receiptValidator.js | 1 + validators/studentValidator.js | 1 + 14 files changed, 161 insertions(+), 145 deletions(-) diff --git a/db.js b/db.js index c85c8f5..4d8b71a 100644 --- a/db.js +++ b/db.js @@ -1,20 +1,28 @@ -const mysql = require('mysql2'); +const mysql = require('mysql2/promise'); const envConfig = require('./envConfigurations/EnvConfigurations'); -const connection = mysql.createConnection({ +const pool = mysql.createPool({ host: envConfig.db.host, port: envConfig.db.port, user: envConfig.db.user, password: envConfig.db.password, - database: envConfig.db.name + database: envConfig.db.name, + waitForConnections: true, + connectionLimit: 10, + queueLimit: 40, + connectTimeout: 5000 }); -connection.connect(err => { - if (err) { - console.error('Error al conectarse con la base de datos:', err); - return; +(async () => { + try { + const connection = await pool.getConnection(); + console.log('Conectado con la base de datos'); + connection.release(); + } catch (err) { + console.error('Error al conectarse con la base de datos:', err.message); + process.exit(1); } - console.log('Conectado con la base de datos'); -}); +})(); -module.exports = connection; +module.exports = pool; +//IO \ No newline at end of file diff --git a/envConfigurations/EnvConfigurations.js b/envConfigurations/EnvConfigurations.js index 103c473..40f5da7 100644 --- a/envConfigurations/EnvConfigurations.js +++ b/envConfigurations/EnvConfigurations.js @@ -22,4 +22,5 @@ const envConfig = { } }; -module.exports = envConfig; \ No newline at end of file +module.exports = envConfig; +//IO \ No newline at end of file diff --git a/index.js b/index.js index 9a36a04..af6e4e1 100644 --- a/index.js +++ b/index.js @@ -37,6 +37,12 @@ app.get('/', (req, res) => { res.send(textoLegal); }); +app.use((err, req, res, next) => { + console.error('Error general:', err.message); + console.error(err.stack); + res.status(500).json({ error: 'Error interno del servidor' }); +}); + app.listen(PORT, () => { console.log(`Servidor al escucha en el puerto ${PORT}`); }); diff --git a/middleware/handleValidation.js b/middleware/handleValidation.js index 7f5d3ca..32f48a9 100644 --- a/middleware/handleValidation.js +++ b/middleware/handleValidation.js @@ -7,3 +7,4 @@ module.exports = (req, res, next) => { } next(); } +//IO \ No newline at end of file diff --git a/middleware/verifyToken.js b/middleware/verifyToken.js index 3777b91..b9313cb 100644 --- a/middleware/verifyToken.js +++ b/middleware/verifyToken.js @@ -16,3 +16,4 @@ function verifyToken(req, res, next) { } module.exports = verifyToken; +//IO \ No newline at end of file diff --git a/routes/impressions.js b/routes/impressions.js index 53e3534..73292a7 100644 --- a/routes/impressions.js +++ b/routes/impressions.js @@ -1,82 +1,76 @@ const express = require('express'); const router = express.Router(); -const connection = require('../db'); +const pool = require('../db'); const impressionValidator = require('../validators/impressionValidator'); const handleValidation = require('../middleware/handleValidation'); const verifyToken = require('../middleware/verifyToken'); router.post('/', verifyToken, - impressionValidator, handleValidation, - (req, res) => { + impressionValidator, + async (req, res) => { const { cost, numAccount, pages } = req.body; const idUser = req.user.id_usuario; - connection.query( - 'SELECT credito FROM alumno WHERE id_cuenta = ?', - [numAccount], - (err, results) => { - if (err) { - return res.status(500).json({ error: 'Error al consultar crédito del alumno'+ err }); - } + let connection; + try { + // Obtener conexión del pool + connection = await pool.getConnection(); - if (results.length === 0) { - return res.status(404).json({ error: 'Alumno no encontrado' }); - } + // Consultar crédito actual + const [rows] = await connection.execute( + 'SELECT credito FROM alumno WHERE id_cuenta = ?', + [numAccount] + ); - const currentCredit = parseFloat(results[0].credito); - const requestedCost = parseFloat(cost); + if (rows.length === 0) { + return res.status(404).json({ error: 'Alumno no encontrado' }); + } - if (isNaN(currentCredit) || isNaN(requestedCost)) { - return res.status(400).json({ error: 'Valores numéricos inválidos' }); - } + const currentCredit = parseFloat(rows[0].credito); + const requestedCost = parseFloat(cost); - if (currentCredit < requestedCost) { - return res.status(400).json({ error: 'Crédito insuficiente' }); - } + if (isNaN(currentCredit) || isNaN(requestedCost)) { + return res.status(400).json({ error: 'Valores numéricos inválidos' }); + } - // Paso 3: Iniciar transacción - connection.beginTransaction((err) => { - if (err) { - return res.status(500).json({ error: 'Error al iniciar la transacción' }); - } + if (currentCredit < requestedCost) { + return res.status(400).json({ error: 'Crédito insuficiente' }); + } - const insertQuery = ` - INSERT INTO detalle_servicio (monto, fecha_operacion, id_cuenta, id_servicio, id_usuario, numero_hojas) - VALUES (?, NOW(), ?, 1, ?, ?) - `; - connection.query(insertQuery, [requestedCost, numAccount, idUser, pages], (err, results) => { - if (err) { - return connection.rollback(() => { - res.status(500).json({ error: 'Error al insertar detalle_servicio' }); - }); - } + // Iniciar transacción + await connection.beginTransaction(); - const updateQuery = ` - UPDATE alumno SET credito = credito - ? WHERE id_cuenta = ? - `; - connection.query(updateQuery, [requestedCost, numAccount], (err, results) => { - if (err) { - return connection.rollback(() => { - res.status(500).json({ error: 'Error al actualizar crédito' }); - }); - } + // Insertar detalle de impresión + await connection.execute( + `INSERT INTO detalle_servicio + (monto, fecha_operacion, id_cuenta, id_servicio, id_usuario, numero_hojas) + VALUES (?, NOW(), ?, 1, ?, ?)`, + [requestedCost, numAccount, idUser, pages] + ); - connection.commit((err) => { - if (err) { - return connection.rollback(() => { - res.status(500).json({ error: 'Error al confirmar transacción' }); - }); - } + // Actualizar crédito + await connection.execute( + 'UPDATE alumno SET credito = credito - ? WHERE id_cuenta = ?', + [requestedCost, numAccount] + ); + + // Confirmar transacción + await connection.commit(); + + res.json({ message: 'Impresión registrada y crédito actualizado correctamente' }); + + } catch (err) { + if (connection) await connection.rollback(); + console.error(err); + res.status(500).json({ error: 'Error en el servidor durante la impresión' }); + + } finally { + if (connection) connection.release(); + } - res.json({ message: 'Impresión registrada y crédito actualizado correctamente' }); - }); - }); - }); - }); - } - ); }); module.exports = router; +//IO \ No newline at end of file diff --git a/routes/login.js b/routes/login.js index 09ea72a..dd9a0a1 100644 --- a/routes/login.js +++ b/routes/login.js @@ -1,42 +1,45 @@ const express = require('express'); const router = express.Router(); -const connection = require('../db'); +const pool = require('../db'); const loginValidator = require('../validators/loginValidator'); const handleValidation = require('../middleware/handleValidation'); const envConfig = require('../envConfigurations/EnvConfigurations'); const jwt = require('jsonwebtoken'); router.post('/', - loginValidator, handleValidation, - (req, res) => { + loginValidator, + async (req, res) => { const { user, password } = req.body; - connection.query( - 'SELECT a.id_usuario , a.usuario , a.password , b.id_perfil , perfil FROM usuario a JOIN perfil b ON (a.id_perfil = b.id_perfil) WHERE a.usuario = ? AND a.password = ? AND a.activo = 1;', - [user, password], - (err, results) => { - if (err) { - return res.status(500).json({ error: 'Error al consultar ' + err }); - } - if (results.length === 0) { - return res.status(404).json({ error: 'User o password incorrecta' }); - } - const userData = results[0]; + try { + const [results] = await pool.query( + 'SELECT a.id_usuario , a.usuario , a.password , b.id_perfil , perfil FROM usuario a JOIN perfil b ON (a.id_perfil = b.id_perfil) WHERE a.usuario = ? AND a.password = ? AND a.activo = 1;', + [user, password] + ) - const payload = { - id_usuario: userData.id_usuario, - usuario: userData.usuario, - perfil: userData.perfil, - id_perfil: userData.id_perfil, - }; + if (results.length === 0) { + return res.status(404).json({ error: 'Usuario o contraseña incorrectos' }); + } - const token = jwt.sign(payload, envConfig.jwtSecret, { - expiresIn: '8h', - }); + const userData = results[0]; - res.json({ token: token }); + const payload = { + id_usuario: userData.id_usuario, + usuario: userData.usuario, + perfil: userData.perfil, + id_perfil: userData.id_perfil, + }; + + const token = jwt.sign(payload, envConfig.jwtSecret, { + expiresIn: '14h', }); + + res.json({ token: token }); + } catch (err) { + res.status(500).json({ error: 'Error al consultar: ' + err.message }); + } }); module.exports = router; +//IO \ No newline at end of file diff --git a/routes/receipt.js b/routes/receipt.js index dbc5a3b..f369c1e 100644 --- a/routes/receipt.js +++ b/routes/receipt.js @@ -1,54 +1,49 @@ const express = require('express'); const router = express.Router(); -const connection = require('../db'); +const pool = require('../db'); const receiptValidator = require('../validators/receiptValidator'); const handleValidation = require('../middleware/handleValidation'); const verifyToken = require('../middleware/verifyToken'); router.post('/', verifyToken, + handleValidation, receiptValidator, - handleValidation, - (req, res) => { + async (req, res) => { const { fol, amount, date, numAccount } = req.body; const idUser = req.user.id_usuario; - connection.query( - 'SELECT * FROM recibo WHERE folio_recibo = ?;', - [fol], - (err, results) => { - if (err) { - return res.status(500).json({ error: 'Error al verificar recibo' + err }); - } + if(amount > 1000){ + return res.status(409).json({ error: 'El monto no puede superar $1000.00' }); + } - if (results.length > 0) { - return res.status(409).json({ error: 'El recibo ya existe' }); - } - - connection.query( - 'INSERT INTO recibo (folio_recibo, monto, fecha_recibo, id_cuenta, id_usuario) VALUES (?, ?, ?, ?, ?);', - [fol, amount, date, numAccount, idUser], - (err) => { - if (err) { - return res.status(500).json({ error: 'Error al guardar recibo' }); - } - - // Luego actualizamos el crédito - connection.query( - 'UPDATE alumno SET credito = credito + ? WHERE id_cuenta = ?;', - [amount, numAccount], - (err) => { - if (err) { - return res.status(500).json({ error: 'Recibo guardado pero falló la actualización del crédito' }); - } - - res.json({ message: 'Recibo guardado correctamente y crédito actualizado' }); - } - ); - } - ); + try { + const [existing] = await pool.execute( + 'SELECT * FROM recibo WHERE folio_recibo = ?;', + [fol] + ); + + if (existing.length > 0) { + return res.status(409).json({ error: 'El recibo ya existe' }); } - ); + + await pool.execute( + 'INSERT INTO recibo (folio_recibo, monto, fecha_recibo, id_cuenta, id_usuario) VALUES (?, ?, ?, ?, ?);', + [fol, amount, date, numAccount, idUser] + ); + + await pool.execute( + 'UPDATE alumno SET credito = credito + ? WHERE id_cuenta = ?;', + [amount, numAccount] + ); + + res.json({ message: 'Recibo guardado correctamente y crédito actualizado' }); + + } catch (err) { + res.status(500).json({ error: 'Error en el servidor: '+ err }); + } + }); module.exports = router; +//IO \ No newline at end of file diff --git a/routes/student.js b/routes/student.js index f1406d3..d00df60 100644 --- a/routes/student.js +++ b/routes/student.js @@ -1,29 +1,31 @@ const express = require('express'); const router = express.Router(); -const connection = require('../db'); +const pool = require('../db'); const studentValidator = require('../validators/studentValidator'); const handleValidation = require('../middleware/handleValidation'); const verifyToken = require('../middleware/verifyToken'); router.post('/', verifyToken, - studentValidator, handleValidation, - (req, res) => { + studentValidator, + async (req, res) => { const { numAccount } = req.body; - connection.query( - 'SELECT a.id_cuenta, a.nombre , a.correo , a.credito, b.carrera FROM alumno a JOIN carrera b ON (a.id_carrera = b.id_carrera) WHERE a.id_cuenta = ?;', - [numAccount], - (err, results) => { - if (err) { - return res.status(500).json({ error: 'Error al consultar' + err }); - } - if (results.length === 0) { - return res.status(404).json({ error: 'Alumno no encontrado' }); - } - res.json(results); + + try { + const [results] = await pool.query( + 'SELECT a.id_cuenta, a.nombre , a.correo , a.credito, b.carrera FROM alumno a JOIN carrera b ON (a.id_carrera = b.id_carrera) WHERE a.id_cuenta = ?;', + [numAccount] + ) + if (results.length === 0) { + return res.status(404).json({ error: 'Alumno no encontrado' }); } - ); + + res.json(results); + } catch (err) { + res.status(500).json({ error: 'Error al consultar: ' + err.message }) + } }); module.exports = router; +//IO \ No newline at end of file diff --git a/routes/token.js b/routes/token.js index 62316da..73109b1 100644 --- a/routes/token.js +++ b/routes/token.js @@ -21,3 +21,4 @@ router.get('/', (req, res) => { }); module.exports = router; +//IO \ No newline at end of file diff --git a/validators/impressionValidator.js b/validators/impressionValidator.js index d51a1d5..46cdcf8 100644 --- a/validators/impressionValidator.js +++ b/validators/impressionValidator.js @@ -14,3 +14,4 @@ module.exports = [ .isInt().withMessage('Número de cuenta debe ser un número entero'), ]; +//IO \ No newline at end of file diff --git a/validators/loginValidator.js b/validators/loginValidator.js index 2c8da25..0acd582 100644 --- a/validators/loginValidator.js +++ b/validators/loginValidator.js @@ -9,3 +9,4 @@ module.exports = [ .notEmpty().withMessage('La contraseña es obligatoria') .isString().withMessage('La contraseña debe ser una cadena') ]; +//IO \ No newline at end of file diff --git a/validators/receiptValidator.js b/validators/receiptValidator.js index 065582d..a1f53ed 100644 --- a/validators/receiptValidator.js +++ b/validators/receiptValidator.js @@ -17,3 +17,4 @@ module.exports = [ .notEmpty().withMessage('Número de cuenta obligatorio') .isInt().withMessage('Número de cuenta debe ser un número entero'), ]; +//IO \ No newline at end of file diff --git a/validators/studentValidator.js b/validators/studentValidator.js index 83a8d09..c21eff8 100644 --- a/validators/studentValidator.js +++ b/validators/studentValidator.js @@ -5,3 +5,4 @@ module.exports = [ .notEmpty().withMessage('El numero de cuenta es obligatorio') .isInt().withMessage('Número de cuenta debe ser un número entero'), ]; +//IO \ No newline at end of file