import { Request, Response, NextFunction } from 'express' import jwt from 'jsonwebtoken' import { prisma } from '../config/database' export interface AuthRequest extends Request { // Use a loose type here to avoid dependency on generated Prisma types user?: any } export const authMiddleware = async ( req: AuthRequest, res: Response, next: NextFunction ) => { try { const authHeader = req.headers.authorization if (!authHeader || !authHeader.startsWith('Bearer ')) { return res.status(401).json({ success: false, error: 'Access token required' }) } const token = authHeader.substring(7) // Remove 'Bearer ' prefix if (!token) { return res.status(401).json({ success: false, error: 'Access token required' }) } // Verify JWT token const decoded = jwt.verify(token, process.env.JWT_SECRET!) as { userId: string } // Get user from database const user = await prisma.user.findUnique({ where: { id: decoded.userId }, select: { id: true, email: true, username: true, displayName: true, avatar: true, bio: true, isOnline: true, lastSeen: true, isAdmin: true, isVerified: true, createdAt: true, updatedAt: true, } }) if (!user) { return res.status(401).json({ success: false, error: 'Invalid token - user not found' }) } // Attach user to request req.user = user next() } catch (error) { if (error instanceof jwt.JsonWebTokenError) { return res.status(401).json({ success: false, error: 'Invalid token' }) } if (error instanceof jwt.TokenExpiredError) { return res.status(401).json({ success: false, error: 'Token expired' }) } console.error('Auth middleware error:', error) return res.status(500).json({ success: false, error: 'Authentication failed' }) } } export const adminMiddleware = ( req: AuthRequest, res: Response, next: NextFunction ) => { if (!req.user) { return res.status(401).json({ success: false, error: 'Authentication required' }) } if (!req.user.isAdmin) { return res.status(403).json({ success: false, error: 'Admin access required' }) } next() } export const optionalAuthMiddleware = async ( req: AuthRequest, res: Response, next: NextFunction ) => { try { const authHeader = req.headers.authorization if (!authHeader || !authHeader.startsWith('Bearer ')) { return next() } const token = authHeader.substring(7) if (!token) { return next() } const decoded = jwt.verify(token, process.env.JWT_SECRET!) as { userId: string } const user = await prisma.user.findUnique({ where: { id: decoded.userId }, select: { id: true, email: true, username: true, displayName: true, avatar: true, bio: true, isOnline: true, lastSeen: true, isAdmin: true, isVerified: true, createdAt: true, updatedAt: true, } }) if (user) { req.user = user } next() } catch (error) { // Ignore auth errors for optional auth next() } }