Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/No-Country-simulation/S02-26-Equipo-33-Web-App/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Horse Trust backend uses several middleware functions for authentication, authorization, and request validation.

Authentication Middleware

authenticate

Verifies JWT tokens in the Authorization header.
import { Response, NextFunction } from "express";
import jwt from "jsonwebtoken";
import { AuthRequest, JwtPayload } from "../types/index";

export const authenticate = (req: AuthRequest, res: Response, next: NextFunction): void => {
  const authHeader = req.headers.authorization;

  if (!authHeader || !authHeader.startsWith("Bearer ")) {
    res.status(401).json({ success: false, message: "No token provided" });
    return;
  }

  const token = authHeader.split(" ")[1];

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET as string) as JwtPayload;
    req.user = decoded;
    next();
  } catch (err) {
    res.status(401).json({ success: false, message: "Invalid or expired token" });
  }
};
Reference: middleware/auth.ts:6-23 Usage:
import { authenticate } from "./middleware/auth";

router.get("/profile", authenticate, profileController);
Expected Header Format:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Response on Failure:
{
  "success": false,
  "message": "No token provided"
}
or
{
  "success": false,
  "message": "Invalid or expired token"
}

Authorization Middleware

requireAdmin

Ensures the authenticated user has admin role.
export const requireAdmin = (req: AuthRequest, res: Response, next: NextFunction): void => {
  if (req.user?.role !== "admin") {
    res.status(403).json({ success: false, message: "Admin access required" });
    return;
  }
  next();
};
Reference: middleware/auth.ts:26-32 Usage:
router.delete("/users/:id", authenticate, requireAdmin, deleteUserController);
Response on Failure:
{
  "success": false,
  "message": "Admin access required"
}

requireSeller

Allows access to users with seller or admin role.
export const requireSeller = (req: AuthRequest, res: Response, next: NextFunction): void => {
  if (!req.user || !["seller", "admin"].includes(req.user.role)) {
    res.status(403).json({ success: false, message: "Seller access required" });
    return;
  }
  next();
};
Reference: middleware/auth.ts:35-41 Usage:
router.post("/horses", authenticate, requireSeller, createHorseController);
Response on Failure:
{
  "success": false,
  "message": "Seller access required"
}

optionalAuth

Attempts to authenticate but allows the request to proceed even if no token is provided. Useful for public routes that can benefit from user context.
export const optionalAuth = (req: AuthRequest, _res: Response, next: NextFunction): void => {
  const authHeader = req.headers.authorization;
  if (authHeader?.startsWith("Bearer ")) {
    const token = authHeader.split(" ")[1];
    try {
      req.user = jwt.verify(token, process.env.JWT_SECRET as string) as JwtPayload;
    } catch {
      // Token invalid but route is public — ignore silently
    }
  }
  next();
};
Reference: middleware/auth.ts:44-55 Usage:
// Public route that can track views per user if authenticated
router.get("/horses/:id", optionalAuth, getHorseController);

Middleware Chain Examples

Admin-Only Route

router.post(
  "/admin/verify-seller",
  authenticate,      // Verify token exists and is valid
  requireAdmin,      // Verify user is admin
  verifySeller
);

Seller Route (Seller or Admin)

router.post(
  "/horses",
  authenticate,      // Verify token exists and is valid
  requireSeller,     // Verify user is seller or admin
  createHorse
);

Public Route with Optional Auth

router.get(
  "/horses",
  optionalAuth,      // Add user context if token provided
  listHorses
);

Auth-Protected Route

router.get(
  "/me",
  authenticate,      // Only verify token
  getCurrentUser
);

AuthRequest Type

The middleware extends Express’s Request type with user information:
interface JwtPayload {
  userId: string;
  role: "admin" | "seller";
  email: string;
  iat: number;
  exp: number;
}

interface AuthRequest extends Request {
  user?: JwtPayload;
}

Rate Limiting Middleware

Defined in app.ts, two rate limiters are configured:

Global Rate Limiter

Applies to all routes:
const limiter = rateLimit({
  windowMs: Number(process.env.RATE_LIMIT_WINDOW_MS) || 15 * 60 * 1000,  // 15 min
  max: Number(process.env.RATE_LIMIT_MAX) || 100,
  standardHeaders: true,
  legacyHeaders: false,
  message: { success: false, message: "Too many requests, please try again later" },
});
app.use(limiter);
Reference: app.ts:37-44

Auth Rate Limiter

Stricter limits for authentication endpoints:
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 10,
  message: { success: false, message: "Too many auth attempts. Try again in 15 minutes." },
});

app.use("/api/auth", authLimiter, authRoutes);
Reference: app.ts:47-51

Validation Middleware

Validation errors are caught globally:
import { validationResult } from "express-validator";

app.use((req: Request, res: Response, next: NextFunction): void => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    res.status(422).json({ success: false, errors: errors.array() });
    return;
  }
  next();
});
Reference: app.ts:55-62 Example Error Response:
{
  "success": false,
  "errors": [
    {
      "msg": "Email is required",
      "param": "email",
      "location": "body"
    },
    {
      "msg": "Password must be at least 8 characters",
      "param": "password",
      "location": "body"
    }
  ]
}

Build docs developers (and LLMs) love