/** * Admin API Routes * Defines all administrative API endpoints with proper authentication and permissions */ const express = require('express'); const router = express.Router(); // Import middleware const { authenticateAdmin, requirePermissions, requirePlayerAccess, auditAdminAction, ADMIN_PERMISSIONS } = require('../middleware/admin.middleware'); const { rateLimiters } = require('../middleware/rateLimit.middleware'); const { validators, validateRequest } = require('../middleware/validation.middleware'); const corsMiddleware = require('../middleware/cors.middleware'); // Import controllers const adminAuthController = require('../controllers/admin/auth.controller'); // Import services for direct admin operations const AdminService = require('../services/user/AdminService'); const adminService = new AdminService(); // Apply CORS to all admin routes router.use(corsMiddleware); // Apply admin-specific rate limiting router.use(rateLimiters.admin); /** * Admin API Status and Information */ router.get('/', (req, res) => { res.json({ name: 'Shattered Void - Admin API', version: process.env.npm_package_version || '0.1.0', status: 'operational', timestamp: new Date().toISOString(), correlationId: req.correlationId, endpoints: { authentication: '/api/admin/auth', players: '/api/admin/players', system: '/api/admin/system', events: '/api/admin/events', analytics: '/api/admin/analytics' }, note: 'Administrative access required for all endpoints' }); }); /** * Admin Authentication Routes * /api/admin/auth/* */ const authRoutes = express.Router(); // Public admin authentication endpoints authRoutes.post('/login', rateLimiters.auth, validators.validateAdminLogin, auditAdminAction('admin_login'), adminAuthController.login ); // Protected admin authentication endpoints authRoutes.post('/logout', authenticateAdmin, auditAdminAction('admin_logout'), adminAuthController.logout ); authRoutes.get('/me', authenticateAdmin, adminAuthController.getProfile ); authRoutes.get('/verify', authenticateAdmin, adminAuthController.verifyToken ); authRoutes.post('/refresh', rateLimiters.auth, adminAuthController.refresh ); authRoutes.get('/stats', authenticateAdmin, requirePermissions([ADMIN_PERMISSIONS.ANALYTICS_READ]), auditAdminAction('view_system_stats'), adminAuthController.getSystemStats ); authRoutes.post('/change-password', authenticateAdmin, rateLimiters.auth, validateRequest(require('joi').object({ currentPassword: require('joi').string().required(), newPassword: require('joi').string().min(8).max(128).required() }), 'body'), auditAdminAction('admin_password_change'), adminAuthController.changePassword ); // Mount admin authentication routes router.use('/auth', authRoutes); /** * Player Management Routes * /api/admin/players/* */ const playerRoutes = express.Router(); // All player management routes require authentication playerRoutes.use(authenticateAdmin); // Get players list playerRoutes.get('/', requirePermissions([ADMIN_PERMISSIONS.PLAYER_DATA_READ]), validators.validatePagination, validateRequest(require('joi').object({ search: require('joi').string().max(50).optional(), activeOnly: require('joi').boolean().optional(), sortBy: require('joi').string().valid('created_at', 'updated_at', 'username', 'email', 'last_login_at').default('created_at'), sortOrder: require('joi').string().valid('asc', 'desc').default('desc') }), 'query'), auditAdminAction('list_players'), async (req, res) => { try { const { page = 1, limit = 20, search = '', activeOnly = null, sortBy = 'created_at', sortOrder = 'desc' } = req.query; const result = await adminService.getPlayersList({ page: parseInt(page), limit: parseInt(limit), search, activeOnly, sortBy, sortOrder }, req.correlationId); res.json({ success: true, message: 'Players list retrieved successfully', data: result, correlationId: req.correlationId }); } catch (error) { res.status(500).json({ success: false, error: 'Failed to retrieve players list', message: error.message, correlationId: req.correlationId }); } } ); // Get specific player details playerRoutes.get('/:playerId', requirePlayerAccess('playerId'), validators.validatePlayerId, auditAdminAction('view_player_details'), async (req, res) => { try { const playerId = parseInt(req.params.playerId); const playerDetails = await adminService.getPlayerDetails(playerId, req.correlationId); res.json({ success: true, message: 'Player details retrieved successfully', data: { player: playerDetails }, correlationId: req.correlationId }); } catch (error) { const statusCode = error.name === 'NotFoundError' ? 404 : 500; res.status(statusCode).json({ success: false, error: error.name === 'NotFoundError' ? 'Player not found' : 'Failed to retrieve player details', message: error.message, correlationId: req.correlationId }); } } ); // Update player status (activate/deactivate) playerRoutes.put('/:playerId/status', requirePermissions([ADMIN_PERMISSIONS.PLAYER_MANAGEMENT]), validators.validatePlayerId, validateRequest(require('joi').object({ isActive: require('joi').boolean().required(), reason: require('joi').string().max(200).optional() }), 'body'), auditAdminAction('update_player_status'), async (req, res) => { try { const playerId = parseInt(req.params.playerId); const { isActive, reason } = req.body; const updatedPlayer = await adminService.updatePlayerStatus( playerId, isActive, req.correlationId ); res.json({ success: true, message: `Player ${isActive ? 'activated' : 'deactivated'} successfully`, data: { player: updatedPlayer, action: isActive ? 'activated' : 'deactivated', reason: reason || null }, correlationId: req.correlationId }); } catch (error) { const statusCode = error.name === 'NotFoundError' ? 404 : 500; res.status(statusCode).json({ success: false, error: error.name === 'NotFoundError' ? 'Player not found' : 'Failed to update player status', message: error.message, correlationId: req.correlationId }); } } ); // Mount player management routes router.use('/players', playerRoutes); /** * System Management Routes * /api/admin/system/* */ const systemRoutes = express.Router(); // All system routes require authentication systemRoutes.use(authenticateAdmin); // Get detailed system statistics systemRoutes.get('/stats', requirePermissions([ADMIN_PERMISSIONS.SYSTEM_MANAGEMENT]), auditAdminAction('view_detailed_system_stats'), async (req, res) => { try { const stats = await adminService.getSystemStats(req.correlationId); // Add additional system information const systemInfo = { ...stats, server: { version: process.env.npm_package_version || '0.1.0', environment: process.env.NODE_ENV || 'development', uptime: process.uptime(), nodeVersion: process.version, memory: { used: Math.round(process.memoryUsage().heapUsed / 1024 / 1024), total: Math.round(process.memoryUsage().heapTotal / 1024 / 1024), rss: Math.round(process.memoryUsage().rss / 1024 / 1024) } } }; res.json({ success: true, message: 'System statistics retrieved successfully', data: systemInfo, correlationId: req.correlationId }); } catch (error) { res.status(500).json({ success: false, error: 'Failed to retrieve system statistics', message: error.message, correlationId: req.correlationId }); } } ); // System health check systemRoutes.get('/health', requirePermissions([ADMIN_PERMISSIONS.SYSTEM_MANAGEMENT]), async (req, res) => { try { // TODO: Implement comprehensive health checks // - Database connectivity // - Redis connectivity // - WebSocket server status // - External service connectivity const healthStatus = { status: 'healthy', timestamp: new Date().toISOString(), services: { database: 'healthy', redis: 'healthy', websocket: 'healthy' }, performance: { uptime: process.uptime(), memory: process.memoryUsage(), cpu: process.cpuUsage() } }; res.json({ success: true, message: 'System health check completed', data: healthStatus, correlationId: req.correlationId }); } catch (error) { res.status(500).json({ success: false, error: 'Health check failed', message: error.message, correlationId: req.correlationId }); } } ); // Mount system routes router.use('/system', systemRoutes); /** * Events Management Routes (placeholder) * /api/admin/events/* */ router.get('/events', authenticateAdmin, requirePermissions([ADMIN_PERMISSIONS.EVENT_MANAGEMENT]), validators.validatePagination, auditAdminAction('view_events'), (req, res) => { res.json({ success: true, message: 'Events endpoint - feature not yet implemented', data: { events: [], pagination: { page: 1, limit: 20, total: 0, totalPages: 0 } }, correlationId: req.correlationId }); } ); /** * Analytics Routes (placeholder) * /api/admin/analytics/* */ router.get('/analytics', authenticateAdmin, requirePermissions([ADMIN_PERMISSIONS.ANALYTICS_READ]), auditAdminAction('view_analytics'), (req, res) => { res.json({ success: true, message: 'Analytics endpoint - feature not yet implemented', data: { analytics: {}, timeRange: 'daily', metrics: [] }, correlationId: req.correlationId }); } ); /** * Error handling for admin routes */ router.use('*', (req, res) => { res.status(404).json({ success: false, error: 'Admin API endpoint not found', message: `The endpoint ${req.method} ${req.originalUrl} does not exist`, correlationId: req.correlationId, timestamp: new Date().toISOString() }); }); module.exports = router;