Shatteredvoid/src/controllers/api/auth.controller.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

298 lines
No EOL
7.1 KiB
JavaScript

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