Shatteredvoid/src/routes/admin.js
MegaProxy 1a60cf55a3 Initial commit: Shattered Void MMO foundation
- Complete PostgreSQL database schema with 21+ tables
- Express.js server with dual authentication (player/admin)
- WebSocket support for real-time features
- Comprehensive middleware (auth, validation, logging, security)
- Game systems: colonies, resources, fleets, research, factions
- Plugin-based combat architecture
- Admin panel foundation
- Production-ready logging and error handling
- Docker support and CI/CD ready
- Complete project structure following CLAUDE.md patterns

🤖 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-02 02:13:05 +00:00

401 lines
No EOL
12 KiB
JavaScript

/**
* 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;