diff --git a/middleware/authMiddleware.js b/middleware/authMiddleware.js index 9af2b9e..7f4ed0b 100644 --- a/middleware/authMiddleware.js +++ b/middleware/authMiddleware.js @@ -1,7 +1,9 @@ const jwt = require('jsonwebtoken'); const { logger } = require('./logger'); +const UnitOfWork = require('../database/UnitOfWork'); +const UserStatusRepository = require('../repositories/status/UserStatusRepository'); -function authMiddleware(req, res, next) { +async function authMiddleware(req, res, next) { const authHeader = req.headers.authorization; if (!authHeader || !authHeader.startsWith('Bearer ')) { logger.warn('authMiddleware:missingToken', { @@ -50,6 +52,31 @@ function authMiddleware(req, res, next) { 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', { diff --git a/services/login/LoginService.js b/services/login/LoginService.js index 89f86dd..e37c5dd 100644 --- a/services/login/LoginService.js +++ b/services/login/LoginService.js @@ -1,5 +1,6 @@ const UserRepository = require('../../repositories/user/UserRepository'); const LoginRepository = require('../../repositories/login/LoginRepository'); +const UserStatusRepository = require('../../repositories/status/UserStatusRepository'); const UnitOfWork = require('../../database/UnitOfWork'); const jwt = require('jsonwebtoken'); const crypto = require('crypto'); @@ -12,6 +13,7 @@ class LoginService { await unitOfWork.start(); unitOfWork.registerRepository('user', new UserRepository(unitOfWork)); unitOfWork.registerRepository('login', new LoginRepository(unitOfWork)); + unitOfWork.registerRepository('status', new UserStatusRepository(unitOfWork)); try { // Find user by email @@ -36,6 +38,17 @@ class LoginService { throw error; } + // Check user status (block suspended) + const statusRepo = unitOfWork.getRepository('status'); + const userStatus = await statusRepo.getStatusByUserId(user.id); + if (userStatus && userStatus.status === 'suspended') { + logger.warn('LoginService.login:user_suspended', { userId: user.id, email: user.email }); + await unitOfWork.rollback(); + const error = new Error('Account suspended'); + error.status = 403; + throw error; + } + // Generate access token (JWT) const accessToken = jwt.sign( { userId: user.id, email: user.email, userType: user.userType, role: user.role }, @@ -95,6 +108,7 @@ class LoginService { await unitOfWork.start(); unitOfWork.registerRepository('login', new LoginRepository(unitOfWork)); unitOfWork.registerRepository('user', new UserRepository(unitOfWork)); + unitOfWork.registerRepository('status', new UserStatusRepository(unitOfWork)); try { const loginRepo = unitOfWork.getRepository('login'); // Find refresh token in DB via LoginRepository @@ -135,6 +149,17 @@ class LoginService { const userRepo = unitOfWork.getRepository('user'); const user = await userRepo.findUserByEmailOrId(user_id); + // Check user status (block suspended) + const statusRepo = unitOfWork.getRepository('status'); + const userStatus = await statusRepo.getStatusByUserId(user.id); + if (userStatus && userStatus.status === 'suspended') { + logger.warn('LoginService.refresh:user_suspended', { userId: user.id, email: user.email }); + await unitOfWork.rollback(); + const error = new Error('Account suspended'); + error.status = 403; + throw error; + } + // Fetch user role directly from DB via LoginRepository const role = await loginRepo.getUserRole(user.id);