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>
This commit is contained in:
MegaProxy 2025-08-02 02:13:05 +00:00
commit 1a60cf55a3
69 changed files with 24471 additions and 0 deletions

344
src/routes/api.js Normal file
View file

@ -0,0 +1,344 @@
/**
* Player API Routes
* Defines all player-facing API endpoints with proper middleware and validation
*/
const express = require('express');
const router = express.Router();
// Import middleware
const { authenticatePlayer, optionalPlayerAuth, requireOwnership, injectPlayerId } = require('../middleware/auth.middleware');
const { rateLimiters } = require('../middleware/rateLimit.middleware');
const { validators, validateRequest } = require('../middleware/validation.middleware');
const corsMiddleware = require('../middleware/cors.middleware');
// Import controllers
const authController = require('../controllers/api/auth.controller');
const playerController = require('../controllers/api/player.controller');
// Apply CORS to all API routes
router.use(corsMiddleware);
// Apply general API rate limiting
router.use(rateLimiters.player);
/**
* API Status and Information
*/
router.get('/', (req, res) => {
res.json({
name: 'Shattered Void - Player API',
version: process.env.npm_package_version || '0.1.0',
status: 'operational',
timestamp: new Date().toISOString(),
correlationId: req.correlationId,
endpoints: {
authentication: '/api/auth',
player: '/api/player',
game: {
colonies: '/api/colonies',
fleets: '/api/fleets',
research: '/api/research',
galaxy: '/api/galaxy'
}
}
});
});
/**
* Authentication Routes
* /api/auth/*
*/
const authRoutes = express.Router();
// Public authentication endpoints (with stricter rate limiting)
authRoutes.post('/register',
rateLimiters.auth,
validators.validatePlayerRegistration,
authController.register
);
authRoutes.post('/login',
rateLimiters.auth,
validators.validatePlayerLogin,
authController.login
);
// Protected authentication endpoints
authRoutes.post('/logout',
authenticatePlayer,
authController.logout
);
authRoutes.post('/refresh',
rateLimiters.auth,
authController.refresh
);
authRoutes.get('/me',
authenticatePlayer,
authController.getProfile
);
authRoutes.put('/me',
authenticatePlayer,
validateRequest(require('joi').object({
username: require('joi').string().alphanum().min(3).max(20).optional()
}), 'body'),
authController.updateProfile
);
authRoutes.get('/verify',
authenticatePlayer,
authController.verifyToken
);
authRoutes.post('/change-password',
authenticatePlayer,
rateLimiters.auth,
validateRequest(require('joi').object({
currentPassword: require('joi').string().required(),
newPassword: require('joi').string().min(8).max(128).required()
}), 'body'),
authController.changePassword
);
// Mount authentication routes
router.use('/auth', authRoutes);
/**
* Player Management Routes
* /api/player/*
*/
const playerRoutes = express.Router();
// All player routes require authentication
playerRoutes.use(authenticatePlayer);
playerRoutes.get('/dashboard', playerController.getDashboard);
playerRoutes.get('/resources', playerController.getResources);
playerRoutes.get('/stats', playerController.getStats);
playerRoutes.put('/settings',
validateRequest(require('joi').object({
// TODO: Define settings schema
notifications: require('joi').object({
email: require('joi').boolean().optional(),
push: require('joi').boolean().optional(),
battles: require('joi').boolean().optional(),
colonies: require('joi').boolean().optional()
}).optional(),
ui: require('joi').object({
theme: require('joi').string().valid('light', 'dark').optional(),
language: require('joi').string().valid('en', 'es', 'fr', 'de').optional()
}).optional()
}), 'body'),
playerController.updateSettings
);
playerRoutes.get('/activity',
validators.validatePagination,
playerController.getActivity
);
playerRoutes.get('/notifications',
validateRequest(require('joi').object({
unreadOnly: require('joi').boolean().default(false)
}), 'query'),
playerController.getNotifications
);
playerRoutes.put('/notifications/read',
validateRequest(require('joi').object({
notificationIds: require('joi').array().items(
require('joi').number().integer().positive()
).min(1).required()
}), 'body'),
playerController.markNotificationsRead
);
// Mount player routes
router.use('/player', playerRoutes);
/**
* Game Feature Routes
* These will be expanded with actual game functionality
*/
// Colonies Routes (placeholder)
router.get('/colonies',
authenticatePlayer,
validators.validatePagination,
(req, res) => {
res.json({
success: true,
message: 'Colonies endpoint - feature not yet implemented',
data: {
colonies: [],
pagination: {
page: 1,
limit: 20,
total: 0,
totalPages: 0
}
},
correlationId: req.correlationId
});
}
);
router.post('/colonies',
authenticatePlayer,
rateLimiters.gameAction,
validators.validateColonyCreation,
(req, res) => {
res.status(501).json({
success: false,
message: 'Colony creation feature not yet implemented',
correlationId: req.correlationId
});
}
);
// Fleets Routes (placeholder)
router.get('/fleets',
authenticatePlayer,
validators.validatePagination,
(req, res) => {
res.json({
success: true,
message: 'Fleets endpoint - feature not yet implemented',
data: {
fleets: [],
pagination: {
page: 1,
limit: 20,
total: 0,
totalPages: 0
}
},
correlationId: req.correlationId
});
}
);
router.post('/fleets',
authenticatePlayer,
rateLimiters.gameAction,
validators.validateFleetCreation,
(req, res) => {
res.status(501).json({
success: false,
message: 'Fleet creation feature not yet implemented',
correlationId: req.correlationId
});
}
);
// Research Routes (placeholder)
router.get('/research',
authenticatePlayer,
(req, res) => {
res.json({
success: true,
message: 'Research endpoint - feature not yet implemented',
data: {
currentResearch: null,
availableResearch: [],
completedResearch: []
},
correlationId: req.correlationId
});
}
);
router.post('/research',
authenticatePlayer,
rateLimiters.gameAction,
validators.validateResearchInitiation,
(req, res) => {
res.status(501).json({
success: false,
message: 'Research initiation feature not yet implemented',
correlationId: req.correlationId
});
}
);
// Galaxy Routes (placeholder)
router.get('/galaxy',
authenticatePlayer,
validateRequest(require('joi').object({
sector: require('joi').string().pattern(/^[A-Z]\d+$/).optional(),
coordinates: require('joi').string().pattern(/^[A-Z]\d+-\d+-[A-Z]$/).optional()
}), 'query'),
(req, res) => {
const { sector, coordinates } = req.query;
res.json({
success: true,
message: 'Galaxy endpoint - feature not yet implemented',
data: {
sector: sector || null,
coordinates: coordinates || null,
systems: [],
playerColonies: [],
playerFleets: []
},
correlationId: req.correlationId
});
}
);
// Messages Routes (placeholder)
router.get('/messages',
authenticatePlayer,
validators.validatePagination,
(req, res) => {
res.json({
success: true,
message: 'Messages endpoint - feature not yet implemented',
data: {
messages: [],
unreadCount: 0,
pagination: {
page: 1,
limit: 20,
total: 0,
totalPages: 0
}
},
correlationId: req.correlationId
});
}
);
router.post('/messages',
authenticatePlayer,
rateLimiters.messaging,
validators.validateMessageSend,
(req, res) => {
res.status(501).json({
success: false,
message: 'Message sending feature not yet implemented',
correlationId: req.correlationId
});
}
);
/**
* Error handling for API routes
*/
router.use('*', (req, res) => {
res.status(404).json({
success: false,
error: 'API endpoint not found',
message: `The endpoint ${req.method} ${req.originalUrl} does not exist`,
correlationId: req.correlationId,
timestamp: new Date().toISOString()
});
});
module.exports = router;