const jwt = require('jsonwebtoken'); const { logger } = require('./logger'); const UnitOfWork = require('../database/UnitOfWork'); const UserStatusRepository = require('../repositories/status/UserStatusRepository'); async function authMiddleware(req, res, next) { const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { logger.warn('authMiddleware:missingToken', { method: req.method, route: req.originalUrl }); return res.status(401).json({ success: false, message: 'No access token provided' }); } const token = authHeader.split(' ')[1]; try { const payload = jwt.verify(token, process.env.JWT_SECRET); // edit profile context awareness const isEditProfile = req.originalUrl?.includes('/profile/personal') || req.baseUrl?.includes('/profile/personal'); // derive and log user type data const derivedUserType = payload.userType ?? payload.user_type ?? payload.type; const authDebug = { context: isEditProfile ? 'edit-profile' : 'general', method: req.method, route: req.originalUrl, id: payload.id ?? payload.userId ?? payload.sub, email: payload.email, userType: payload.userType, user_type: payload.user_type, derivedUserType, payloadKeys: Object.keys(payload || {}) }; logger.info(`authMiddleware:verified context=${authDebug.context} userType=${authDebug.derivedUserType}`, authDebug); // console fallback for local dev console.log('[authMiddleware] verified', authDebug); // Normalize common user fields for downstream checks const normalizedUserId = payload.userId ?? payload.id ?? payload.sub; const normalizedRole = payload.role ?? payload.userRole ?? payload.user_role ?? payload.type; // Attach user info to request (with normalized userType for downstream checks) req.user = { ...payload, userId: normalizedUserId, role: normalizedRole ?? payload.role, userType: payload.userType ?? payload.user_type, user_type: payload.user_type ?? payload.userType }; // Block suspended users try { const unitOfWork = new UnitOfWork(); await unitOfWork.start(); unitOfWork.registerRepository('status', new UserStatusRepository(unitOfWork)); const statusRepo = unitOfWork.getRepository('status'); const userStatus = await statusRepo.getStatusByUserId(normalizedUserId); await unitOfWork.commit(); if (userStatus && userStatus.status === 'suspended') { logger.warn('authMiddleware:user_suspended', { userId: normalizedUserId, route: req.originalUrl }); return res.status(403).json({ success: false, message: 'Account suspended' }); } } catch (statusError) { logger.error('authMiddleware:statusCheckFailed', { userId: normalizedUserId, route: req.originalUrl, error: statusError?.message }); return res.status(500).json({ success: false, message: 'Internal server error' }); } next(); } catch (error) { logger.warn('authMiddleware:tokenInvalid', { method: req.method, route: req.originalUrl, reason: error?.message }); return res.status(401).json({ success: false, message: 'Invalid or expired access token' }); } } module.exports = authMiddleware;