/** * Player Authentication Controller * Handles player registration, login, and authentication-related endpoints */ const PlayerService = require('../../services/user/PlayerService'); const { asyncHandler } = require('../../middleware/error.middleware'); const logger = require('../../utils/logger'); const playerService = new PlayerService(); /** * Register a new player * POST /api/auth/register */ const register = asyncHandler(async (req, res) => { const correlationId = req.correlationId; const { email, username, password } = req.body; logger.info('Player registration request received', { correlationId, email, username }); const player = await playerService.registerPlayer({ email, username, password }, correlationId); logger.info('Player registration successful', { correlationId, playerId: player.id, email: player.email, username: player.username }); res.status(201).json({ success: true, message: 'Player registered successfully', data: { player }, correlationId }); }); /** * Player login * POST /api/auth/login */ const login = asyncHandler(async (req, res) => { const correlationId = req.correlationId; const { email, password } = req.body; logger.info('Player login request received', { correlationId, email }); const authResult = await playerService.authenticatePlayer({ email, password }, correlationId); logger.info('Player login successful', { correlationId, playerId: authResult.player.id, email: authResult.player.email, username: authResult.player.username }); // Set refresh token as httpOnly cookie res.cookie('refreshToken', authResult.tokens.refreshToken, { httpOnly: true, secure: process.env.NODE_ENV === 'production', sameSite: 'strict', maxAge: 7 * 24 * 60 * 60 * 1000 // 7 days }); res.status(200).json({ success: true, message: 'Login successful', data: { player: authResult.player, accessToken: authResult.tokens.accessToken }, correlationId }); }); /** * Player logout * POST /api/auth/logout */ const logout = asyncHandler(async (req, res) => { const correlationId = req.correlationId; const playerId = req.user?.playerId; logger.info('Player logout request received', { correlationId, playerId }); // Clear refresh token cookie res.clearCookie('refreshToken'); // TODO: Add token to blacklist if implementing token blacklisting logger.info('Player logout successful', { correlationId, playerId }); res.status(200).json({ success: true, message: 'Logout successful', correlationId }); }); /** * Refresh access token * POST /api/auth/refresh */ const refresh = asyncHandler(async (req, res) => { const correlationId = req.correlationId; const refreshToken = req.cookies.refreshToken; if (!refreshToken) { logger.warn('Token refresh request without refresh token', { correlationId }); return res.status(401).json({ success: false, message: 'Refresh token not provided', correlationId }); } // TODO: Implement refresh token validation and new token generation // For now, return error indicating feature not implemented logger.warn('Token refresh requested but not implemented', { correlationId }); res.status(501).json({ success: false, message: 'Token refresh feature not yet implemented', correlationId }); }); /** * Get current player profile * GET /api/auth/me */ const getProfile = asyncHandler(async (req, res) => { const correlationId = req.correlationId; const playerId = req.user.playerId; logger.info('Player profile request received', { correlationId, playerId }); const profile = await playerService.getPlayerProfile(playerId, correlationId); logger.info('Player profile retrieved', { correlationId, playerId, username: profile.username }); res.status(200).json({ success: true, message: 'Profile retrieved successfully', data: { player: profile }, correlationId }); }); /** * Update current player profile * PUT /api/auth/me */ const updateProfile = asyncHandler(async (req, res) => { const correlationId = req.correlationId; const playerId = req.user.playerId; const updateData = req.body; logger.info('Player profile update request received', { correlationId, playerId, updateFields: Object.keys(updateData) }); const updatedProfile = await playerService.updatePlayerProfile( playerId, updateData, correlationId ); logger.info('Player profile updated successfully', { correlationId, playerId, username: updatedProfile.username }); res.status(200).json({ success: true, message: 'Profile updated successfully', data: { player: updatedProfile }, correlationId }); }); /** * Verify player token (for testing/debugging) * GET /api/auth/verify */ const verifyToken = asyncHandler(async (req, res) => { const correlationId = req.correlationId; const user = req.user; logger.info('Token verification request received', { correlationId, playerId: user.playerId, username: user.username }); res.status(200).json({ success: true, message: 'Token is valid', data: { user: { playerId: user.playerId, email: user.email, username: user.username, type: user.type, tokenIssuedAt: new Date(user.iat * 1000), tokenExpiresAt: new Date(user.exp * 1000) } }, correlationId }); }); /** * Change player password * POST /api/auth/change-password */ const changePassword = asyncHandler(async (req, res) => { const correlationId = req.correlationId; const playerId = req.user.playerId; const { currentPassword, newPassword } = req.body; logger.info('Password change request received', { correlationId, playerId }); // TODO: Implement password change functionality // This would involve: // 1. Verify current password // 2. Validate new password strength // 3. Hash new password // 4. Update in database // 5. Optionally invalidate existing tokens logger.warn('Password change requested but not implemented', { correlationId, playerId }); res.status(501).json({ success: false, message: 'Password change feature not yet implemented', correlationId }); }); module.exports = { register, login, logout, refresh, getProfile, updateProfile, verifyToken, changePassword };