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:
commit
1a60cf55a3
69 changed files with 24471 additions and 0 deletions
344
src/routes/api.js
Normal file
344
src/routes/api.js
Normal 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;
|
||||
Loading…
Add table
Add a link
Reference in a new issue