From bfb17bb2c1d5e0908c6833f9be916e01e347751d Mon Sep 17 00:00:00 2001 From: Joaco Date: Thu, 4 Sep 2025 06:11:18 -0600 Subject: [PATCH] feat/middlewares-unified --- src/middleware/authMiddleware.ts | 100 -------------------------- src/middleware/rateLimitMiddleware.ts | 78 -------------------- 2 files changed, 178 deletions(-) delete mode 100644 src/middleware/authMiddleware.ts delete mode 100644 src/middleware/rateLimitMiddleware.ts diff --git a/src/middleware/authMiddleware.ts b/src/middleware/authMiddleware.ts deleted file mode 100644 index 5a0384a..0000000 --- a/src/middleware/authMiddleware.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { Request, Response, NextFunction } from "express"; -import jwt from "jsonwebtoken"; -import { PrismaUserRepository } from "../modules/user/repositories/PrismaUserRepository"; -import { - AuthenticatedRequest, - DecodedUser, - toAuthenticatedUser, -} from "../types/auth.types"; - -const SECRET_KEY = process.env.JWT_SECRET || "defaultSecret"; -const userRepository = new PrismaUserRepository(); - -export const authMiddleware = async ( - req: Request, - res: Response, - next: NextFunction -): Promise => { - const token = req.headers.authorization?.split(" ")[1]; - - if (!token) { - res.status(401).json({ message: "No token provided" }); - return; - } - - try { - const decoded = jwt.verify(token, SECRET_KEY) as { - id: string; - role: string; - }; - const user = await userRepository.findById(`${decoded.id}`); - - if (!user) { - res.status(401).json({ message: "User not found" }); - return; - } - - if (!user.isVerified) { - res.status(403).json({ - message: "Email not verified. Please verify your email to proceed.", - }); - return; - } - - (req as AuthenticatedRequest).user = { - id: user.id, - email: user.email, - role: decoded.role, - isVerified: user.isVerified, - }; - - next(); - } catch (error) { - console.error("Error during authentication:", error); - res.status(401).json({ message: "Invalid token" }); - } -}; - -export const requireVerifiedEmail = async ( - req: Request, - res: Response, - next: NextFunction -): Promise => { - try { - const authenticatedReq = req as AuthenticatedRequest; - - if (!authenticatedReq.user) { - res - .status(401) - .json({ message: "Unauthorized - Authentication required" }); - return; - } - - const isVerified = await userRepository.isUserVerified( - authenticatedReq.user.id.toString() - ); - - if (!isVerified) { - res.status(403).json({ - message: "Forbidden - Email verification required", - verificationNeeded: true, - }); - return; - } - - authenticatedReq.user.isVerified = true; - next(); - } catch (error) { - // Use basic console.error here to avoid circular dependencies - console.error("Error checking email verification status:", error); - res.status(500).json({ - message: "Internal server error", - ...(req.traceId && { traceId: req.traceId }), - }); - } -}; - -export default { - requireVerifiedEmail, - authMiddleware, -}; diff --git a/src/middleware/rateLimitMiddleware.ts b/src/middleware/rateLimitMiddleware.ts deleted file mode 100644 index a598425..0000000 --- a/src/middleware/rateLimitMiddleware.ts +++ /dev/null @@ -1,78 +0,0 @@ -import express, { Request, Response, NextFunction, Router } from "express"; -import { RateLimitUseCase } from "./../modules/shared/middleware/rate-limit/use-cases/rate-limit-use-case"; -import { Logger } from "../utils/logger"; - -export class RateLimitMiddleware { - private rateLimitUseCase: RateLimitUseCase; - private logger: Logger; - - constructor(rateLimitUseCase?: RateLimitUseCase) { - this.rateLimitUseCase = rateLimitUseCase || new RateLimitUseCase(); - this.logger = new Logger("RATE_LIMIT_MIDDLEWARE"); - } - - // Returning a middleware function - rateLimiter = (req: Request, res: Response, next: NextFunction) => { - const checkRateLimit = async () => { - try { - const { allowed, remaining, retryAfter } = - await this.rateLimitUseCase.checkRateLimit(req); - console.log(allowed, remaining); - - // Add rate limit headers - res.setHeader("X-RateLimit-Remaining", remaining.toString()); - - if (!allowed) { - this.logger.warn( - `Rate limit exceeded for ${req.ip} on ${req.path}`, - { - remaining, - retryAfter, - ip: req.ip, - path: req.path, - traceId: req.traceId, - } - ); - return res.status(429).json({ - error: "Too Many Requests", - message: - "You have exceeded the rate limit. Please try again later.", - retryAfter: retryAfter * 60 + " seconds", // Default retry after 1 minute - ...(req.traceId && { traceId: req.traceId }), - }); - } - - next(); - } catch (error) { - this.logger.error("Rate limit check failed", { - error: error instanceof Error ? error.message : error, - stack: error instanceof Error ? error.stack : undefined, - path: req.path, - method: req.method, - ip: req.ip, - traceId: req.traceId, - }); - next(error); - } - }; - - checkRateLimit(); - }; - - //Method to apply middleware to specific routes - applyToRoutes(router: Router, routes: string[]) { - routes.forEach((route) => { - router.use(route, this.rateLimiter); - }); - return router; - } -} - -export function setupRateLimiting(app: express.Application) { - const rateLimitMiddleware = new RateLimitMiddleware(); - - // Explicit typing and direct method application - app.use("/auth", rateLimitMiddleware.rateLimiter); - app.use("/wallet", rateLimitMiddleware.rateLimiter); - app.use("/email", rateLimitMiddleware.rateLimiter); -}