import { Request, Response, NextFunction } from "express"; import jwt from "jsonwebtoken"; const JWT_SECRET = process.env.ADMIN_JWT_SECRET || "changeme"; const COOKIE_NAME = "pw_customer"; export interface CustomerPayload { customerId: number; email: string; } declare global { namespace Express { interface Request { customer?: CustomerPayload; } } } /** Middleware: attach customer from cookie JWT. Never blocks — sets req.customer if valid. */ export function optionalCustomerAuth(req: Request, _res: Response, next: NextFunction) { const token = req.cookies?.[COOKIE_NAME]; if (!token) return next(); try { req.customer = jwt.verify(token, JWT_SECRET) as CustomerPayload; } catch { // expired or invalid — ignore, let route decide } next(); } /** Middleware: require valid customer session. Returns 401 if not logged in. */ export function requireCustomerAuth(req: Request, res: Response, next: NextFunction) { optionalCustomerAuth(req, res, () => { if (!req.customer) { return res.status(401).json({ error: "Login required", code: "UNAUTHENTICATED" }); } next(); }); } /** Issue a customer session JWT cookie (7-day). */ export function issueCustomerCookie(res: Response, payload: CustomerPayload) { const token = jwt.sign(payload, JWT_SECRET, { expiresIn: "7d" }); res.cookie(COOKIE_NAME, token, { httpOnly: true, secure: process.env.NODE_ENV === "production", sameSite: "lax", maxAge: 7 * 24 * 60 * 60 * 1000, path: "/", }); } /** Clear the customer session cookie. */ export function clearCustomerCookie(res: Response) { res.clearCookie(COOKIE_NAME, { path: "/" }); }