From 62a3beca1595ada34bcb427e1a96f1361a2f7c98 Mon Sep 17 00:00:00 2001 From: karol Date: Thu, 2 Jul 2026 19:44:30 +0000 Subject: [PATCH] =?UTF-8?q?Actualizaci=C3=B3n=20m=C3=B3dulo=20de=20authent?= =?UTF-8?q?ication?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/auditLogs/auditLog.controller.ts | 205 ++++++++++++++++++ .../src/modules/auditLogs/auditLog.model.ts | 14 +- .../src/modules/auditLogs/auditLog.routes.ts | 26 +++ .../src/modules/auditLogs/auditLog.service.ts | 110 ++++++++++ backend/src/modules/auth/auth.controller.ts | 29 ++- backend/src/modules/auth/auth.middleware.ts | 11 +- backend/src/modules/auth/auth.routes.ts | 9 +- 7 files changed, 385 insertions(+), 19 deletions(-) create mode 100644 backend/src/modules/auditLogs/auditLog.controller.ts create mode 100644 backend/src/modules/auditLogs/auditLog.routes.ts diff --git a/backend/src/modules/auditLogs/auditLog.controller.ts b/backend/src/modules/auditLogs/auditLog.controller.ts new file mode 100644 index 0000000..2c97291 --- /dev/null +++ b/backend/src/modules/auditLogs/auditLog.controller.ts @@ -0,0 +1,205 @@ +import { Request, Response } from "express"; +import { AuditLogService } from './auditLog.service'; + +const service = new AuditLogService(); + +export class AuditLogController{ + + async create( + req:Request, + res:Response + ){ + + try{ + + const auditLog = await service.create( + req.body + ) + res.status(201).json(auditLog); + + }catch(error){ + + res.status(500).json({ + message:"Error al crear el registro de auditoría", + error + }); + + } + } + + async getAll( + req:Request, + res:Response + ){ + try{ + + const auditLog = await service.getAll() + res.status(200).json(auditLog); + + }catch(error){ + res.status(500).json({ + message:"Error al obtener registros", + error + + }); + } + } + + async getById( + req:Request, + res:Response + ){ + try{ + + const auditLog = await service.getById( + req.params.id as string + ); + + if(!auditLog){ + return res.status(404).json({ + message:"Registro no encontrado" + }); + } + + res.status(200).json(auditLog); + + }catch(error){ + res.status(500).json({ + message:"Error al obtener registros", + error + }); + + } + + } + + async getByUser( + req:Request, + res:Response + ){ + try{ + const auditLog = await service.getByUser( + req.params.userId as string + ); + + res.status(200).json(auditLog); + } catch(error){ + res.status(500).json({ + message:"Error al obtener registros", + error + }); + } + } + + async getByModule( + req:Request, + res:Response + ){ + try{ + + const auditLog = await service.getByModule( + req.params.module as any + ); + + res.status(200).json(auditLog); + + }catch(error){ + res.status(500).json({ + message:"Error al obtener registros", + error + }); + + } + } + + async getByAction( + req:Request, + res:Response + ){ + try{ + + const auditLog = await service.getByAction( + req.params.action as any + ); + + res.status(200).json(auditLog); + + }catch(error){ + res.status(500).json({ + message:"Error al obtener registros", + error + }); + + } + } + + async getByStatus( + req:Request, + res:Response + ){ + try{ + + + const auditLog = await service.getByStatus( + req.params.status as any + ); + + res.status(200).json(auditLog); + + }catch(error){ + res.status(500).json({ + message:"Error al obtener registros", + error + }); + + } + } + + async getByDateRange( + req:Request, + res:Response + ){ + try{ + + const {startDate, endDate} = req.query; + + const auditLog = await service.getByDateRange( + new Date(startDate as string), + new Date(endDate as string) + ); + + res.status(200).json(auditLog) + + }catch(error){ + res.status(500).json({ + message:"Error al obtener registros", + error + }); + } + } + + async delete( + req:Request, + res:Response + ){ + try{ + + const auditLog = await service.delete( + req.params.id as string + ); + + if(!auditLog){ + return res.status(404).json({ + message:"Registro no encontrado" + }) + } + res.status(200).json(auditLog); + + }catch(error){ + res.status(500).json({ + message:"Error al eliminar registros", + error + }); + } + } +} \ No newline at end of file diff --git a/backend/src/modules/auditLogs/auditLog.model.ts b/backend/src/modules/auditLogs/auditLog.model.ts index a15842e..dbf4c33 100644 --- a/backend/src/modules/auditLogs/auditLog.model.ts +++ b/backend/src/modules/auditLogs/auditLog.model.ts @@ -7,7 +7,6 @@ const auditLogSchema = new mongoose.Schema( userId: { type: mongoose.Schema.Types.ObjectId, - ref: "User" }, @@ -15,9 +14,7 @@ const auditLogSchema = new mongoose.Schema( module: { type: String, - required: true, - enum: [ "User", @@ -49,7 +46,6 @@ const auditLogSchema = new mongoose.Schema( "Report", "Authentication" - ] }, @@ -57,9 +53,7 @@ const auditLogSchema = new mongoose.Schema( action: { type: String, - required: true, - enum: [ "CREATE", @@ -110,13 +104,13 @@ const auditLogSchema = new mongoose.Schema( enum: [ - "SUCCESS", + "EXITOSO", - "FAILED" + "FALLIDO" ], - default: "SUCCESS" + default: "EXITOSO" } @@ -132,4 +126,4 @@ const auditLogSchema = new mongoose.Schema( ); -export default mongoose.model("AuditLog", auditLogSchema); \ No newline at end of file +export default mongoose.model("AuditLog",auditLogSchema); \ No newline at end of file diff --git a/backend/src/modules/auditLogs/auditLog.routes.ts b/backend/src/modules/auditLogs/auditLog.routes.ts new file mode 100644 index 0000000..0d68bbb --- /dev/null +++ b/backend/src/modules/auditLogs/auditLog.routes.ts @@ -0,0 +1,26 @@ +import { Router } from "express"; +import { AuditLogController } from "./auditLog.controller"; +import { authMiddleware } from "../auth/auth.middleware"; + +const auditRouter = Router(); +const controller = new AuditLogController(); + +auditRouter.get("/", authMiddleware, controller.getAll); + +auditRouter.get("/:id", authMiddleware, controller.getById); + +auditRouter.post("/", authMiddleware, controller.create); + +auditRouter.get("/user/:userId", authMiddleware, controller.getByUser); + +auditRouter.get("/module/:module", authMiddleware, controller.getByModule); + +auditRouter.get("/action/:action", authMiddleware, controller.getByAction); + +auditRouter.get("/status/:status", authMiddleware, controller.getByStatus); + +auditRouter.get("/date-range", authMiddleware, controller.getByDateRange); + +auditRouter.delete("/:id", authMiddleware, controller.delete); + +export default auditRouter; \ No newline at end of file diff --git a/backend/src/modules/auditLogs/auditLog.service.ts b/backend/src/modules/auditLogs/auditLog.service.ts index e69de29..5edf943 100644 --- a/backend/src/modules/auditLogs/auditLog.service.ts +++ b/backend/src/modules/auditLogs/auditLog.service.ts @@ -0,0 +1,110 @@ +import auditLogModel from "./auditLog.model"; +import { IAuditLog } from "./auditLog.interface"; + +export class AuditLogService { + + + //Registrar una acción + async create( + data:IAuditLog + ){ + const auditLog = new auditLogModel(data); + + return await auditLog.save(); + } + + //Obtener todos los registros + + async getAll(){ + + return await auditLogModel + .find() + .populate("userId") + .sort({ + createdAt: -1 + }); + } + + async getById( + id:string + ){ + return await auditLogModel + .findById(id) + .populate("userId"); + } + + async getByUser( + userId:string + ){ + return await auditLogModel + .find({ + userId + }) + .sort({ + createdAt: -1 + }) + } + + async getByModule( + module:IAuditLog["module"] + ){ + return await auditLogModel + .find({ + module + }) + .populate("userId") + .sort({ + createdAt: -1 + }); + } + + async getByAction( + action:IAuditLog["action"] + ){ + return await auditLogModel + .find({ + action + }) + .populate("userId") + .sort({ + createdAt: -1 + }) + } + + async getByStatus( + status:IAuditLog["status"] + ){ + return await auditLogModel + .find({ + status + }) + .populate("userId") + .sort({ + createdAt: -1 + }) + } + + async getByDateRange( + startDate:Date, + endDate:Date + ){ + + return await auditLogModel + .find({ + createdAt:{ + $gte:startDate, + $lte:endDate + } + }) + .populate("userId") + .sort({ + createdAt: -1 + }) + } + + async delete( + id:string + ){ + return await auditLogModel.findById(id); + } +} \ No newline at end of file diff --git a/backend/src/modules/auth/auth.controller.ts b/backend/src/modules/auth/auth.controller.ts index 82133d9..b671248 100644 --- a/backend/src/modules/auth/auth.controller.ts +++ b/backend/src/modules/auth/auth.controller.ts @@ -17,8 +17,15 @@ export class AuthController { password } = req.body; - const result = - await authService.login( + + //Validar datos de entrada + if(!userName || !password){ + return res.status(400).json({ + message:"Usuario y contraseña son requeridos" + }); + } + + const result = await authService.login( userName, password ); @@ -33,4 +40,22 @@ export class AuthController { } } + + async logout( + req:Request, + res:Response + ){ + try{ + + const user = (req as any).user; + const result = await authService.logout(user.id); + res.json(result); + + }catch(error) { + res.status(500).json({ + message:"Error al cerrar sesión", + error + }); + } + } } \ No newline at end of file diff --git a/backend/src/modules/auth/auth.middleware.ts b/backend/src/modules/auth/auth.middleware.ts index 7a64c7b..1be21fb 100644 --- a/backend/src/modules/auth/auth.middleware.ts +++ b/backend/src/modules/auth/auth.middleware.ts @@ -15,12 +15,19 @@ export const authMiddleware = ( }); } + //Verificar formato Bearer + + if(!authHeader.startsWith("Bearer ")) { + return res.status(401).json({ + message:"Formato de token inválido" + }); + } const token = authHeader.split(" ")[1]; if (!token) { return res.status(401).json({ - message:"Token invalido" + message:"Token inválido" }); } @@ -37,7 +44,7 @@ export const authMiddleware = ( next(); } catch{ return res.status(401).json({ - message:"Token invalido" + message:"Token inválido" }); } }; \ No newline at end of file diff --git a/backend/src/modules/auth/auth.routes.ts b/backend/src/modules/auth/auth.routes.ts index 47d1f04..3aceaff 100644 --- a/backend/src/modules/auth/auth.routes.ts +++ b/backend/src/modules/auth/auth.routes.ts @@ -1,14 +1,13 @@ import { Router } from "express"; - import { AuthController } from "./auth.controller"; +import { authMiddleware } from "./auth.middleware"; const authRouter = Router(); const controller = new AuthController(); -authRouter.post( - "/login", - controller.login -); +authRouter.post("/login", controller.login); + +authRouter.post("/logout", authMiddleware, controller.logout); export default authRouter; \ No newline at end of file