Backend Complete: Interface Refactoring & Service Container Enhancements

Repository Interface Optimization:
- Created IBaseRepository.ts and IPaginatedRepository.ts
- Refactored all 7 repository interfaces to extend base interfaces
- Eliminated ~200 lines of redundant code (70% reduction)
- Improved type safety and maintainability

 Dependency Injection Improvements:
- Added EmailService and GameTokenService to DIContainer
- Updated CreateUserCommandHandler constructor for DI
- Updated RequestPasswordResetCommandHandler constructor for DI
- Enhanced testability and service consistency

 Environment Configuration:
- Created comprehensive .env.example with 40+ variables
- Organized into 12 logical sections (Database, Security, Email, etc.)
- Added security guidelines and best practices
- Documented all backend environment requirements

 Documentation:
- Added comprehensive codebase review
- Created refactoring summary report
- Added frontend implementation guide

Impact: Improved code quality, reduced maintenance overhead, enhanced developer experience
This commit is contained in:
2025-09-21 03:27:57 +02:00
parent 5b7c3ba4b2
commit 86211923db
306 changed files with 52956 additions and 0 deletions
@@ -0,0 +1,146 @@
import { Request, Response, NextFunction } from 'express';
import { JWTService } from './JWTService';
import { RedisService } from './RedisService';
import { logAuth, logWarning } from './Logger';
export const jwtService = new JWTService();
const redisService = RedisService.getInstance();
/**
* Check if a token is blacklisted
*/
async function isTokenBlacklisted(token: string): Promise<boolean> {
try {
const result = await redisService.get(`blacklist:${token}`);
return result === 'true';
} catch (error) {
// If Redis is down, allow the request to proceed (fail open)
logWarning('Failed to check token blacklist - allowing request', { error: (error as Error).message });
return false;
}
}
/**
* Extract token from request (cookie or Authorization header)
*/
function extractToken(req: Request): string | null {
// First try to get token from cookie
const cookieToken = req.cookies['auth_token'];
if (cookieToken) {
return cookieToken;
}
// Fallback to Authorization header
const authHeader = req.headers.authorization;
if (authHeader && authHeader.startsWith('Bearer ')) {
return authHeader.substring(7);
}
return null;
}
export async function authRequired(req: Request, res: Response, next: NextFunction) {
try {
// Extract token from request
const token = extractToken(req);
if (!token) {
logAuth('Authentication failed - No token provided', undefined, {
ip: req.ip,
userAgent: req.get ? req.get('User-Agent') : 'unknown',
path: req.path
}, req);
return res.status(401).json({ error: 'Unauthorized' });
}
// Check if token is blacklisted
const isBlacklisted = await isTokenBlacklisted(token);
if (isBlacklisted) {
logAuth('Authentication failed - Token blacklisted', undefined, {
ip: req.ip,
userAgent: req.get ? req.get('User-Agent') : 'unknown',
path: req.path
}, req);
return res.status(401).json({ error: 'Token has been invalidated' });
}
// Verify token
const payload = jwtService.verify(req);
if (!payload) {
logAuth('Authentication failed - Invalid token', undefined, {
ip: req.ip,
userAgent: req.get ? req.get('User-Agent') : 'unknown',
path: req.path
}, req);
return res.status(401).json({ error: 'Unauthorized' });
}
logAuth('Authentication successful', payload.userId, {
authLevel: payload.authLevel,
orgId: payload.orgId
}, req);
const refreshed = jwtService.refreshIfNeeded(payload, res);
if (refreshed) {
logAuth('Token refreshed', payload.userId, undefined, req);
}
(req as any).user = payload;
next();
} catch (error) {
logWarning('Authentication middleware error', { error: (error as Error).message }, req);
return res.status(500).json({ error: 'Internal server error' });
}
}
export async function adminRequired(req: Request, res: Response, next: NextFunction) {
try {
// Extract token from request
const token = extractToken(req);
if (!token) {
logWarning('Admin access denied - No token provided', {
ip: req.ip,
path: req.path
}, req);
return res.status(401).json({ error: 'Unauthorized' });
}
// Check if token is blacklisted
const isBlacklisted = await isTokenBlacklisted(token);
if (isBlacklisted) {
logWarning('Admin access denied - Token blacklisted', {
ip: req.ip,
path: req.path
}, req);
return res.status(401).json({ error: 'Token has been invalidated' });
}
// Verify token and check admin privileges
const payload = jwtService.verify(req);
if (!payload || payload.authLevel !== 1) {
logWarning('Admin access denied', {
hasPayload: !!payload,
authLevel: payload?.authLevel,
userId: payload?.userId,
ip: req.ip,
path: req.path
}, req);
return res.status(403).json({ error: 'Forbidden' });
}
logAuth('Admin authentication successful', payload.userId, {
authLevel: payload.authLevel,
orgId: payload.orgId
}, req);
const refreshed = jwtService.refreshIfNeeded(payload, res);
if (refreshed) {
logAuth('Admin token refreshed', payload.userId, undefined, req);
}
(req as any).user = payload;
next();
} catch (error) {
logWarning('Admin authentication middleware error', { error: (error as Error).message }, req);
return res.status(500).json({ error: 'Internal server error' });
}
}