Merge remote-tracking branch 'origin/main' into backend_complete
This commit is contained in:
@@ -10,7 +10,10 @@ import chatRouter from './routers/chatRouter';
|
||||
import contactRouter from './routers/contactRouter';
|
||||
import adminRouter from './routers/adminRouter';
|
||||
import deckImportExportRouter from './routers/deckImportExportRouter';
|
||||
<<<<<<< HEAD
|
||||
import gameRouter from './routers/gameRouter';
|
||||
=======
|
||||
>>>>>>> origin/main
|
||||
import { LoggingService, logStartup, logConnection, logError, logRequest } from '../Application/Services/Logger';
|
||||
import { WebSocketService } from '../Application/Services/WebSocketService';
|
||||
import { setupSwagger } from './swagger/swaggerUiSetup';
|
||||
@@ -132,7 +135,10 @@ app.use('/api/chats', chatRouter);
|
||||
app.use('/api/contacts', contactRouter);
|
||||
app.use('/api/admin', adminRouter);
|
||||
app.use('/api/deck-import-export', deckImportExportRouter);
|
||||
<<<<<<< HEAD
|
||||
app.use('/api/games', gameRouter);
|
||||
=======
|
||||
>>>>>>> origin/main
|
||||
|
||||
// Global error handler (must be after routes)
|
||||
app.use(loggingService.errorLoggingMiddleware());
|
||||
|
||||
@@ -107,6 +107,41 @@ router.get('/users/page/:from/:to', adminRequired, async (req: Request, res: Res
|
||||
}
|
||||
});
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
// Get users by page (admin only) - RECOMMENDED
|
||||
router.get('/users/page/:from/:to', adminRequired, async (req: Request, res: Response) => {
|
||||
try {
|
||||
const from = parseInt(req.params.from);
|
||||
const to = parseInt(req.params.to);
|
||||
const includeDeleted = req.query.includeDeleted === 'true';
|
||||
|
||||
if (isNaN(from) || isNaN(to) || from < 0 || to < from) {
|
||||
return res.status(400).json({ error: 'Invalid page parameters. "from" and "to" must be valid numbers with to >= from >= 0' });
|
||||
}
|
||||
|
||||
logRequest('Admin get users by page endpoint accessed', req, res, { from, to, includeDeleted });
|
||||
|
||||
const result = includeDeleted
|
||||
? await container.userRepository.findByPageIncludingDeleted(from, to)
|
||||
: await container.userRepository.findByPage(from, to);
|
||||
|
||||
logRequest('Admin users page retrieved successfully', req, res, {
|
||||
from,
|
||||
to,
|
||||
count: result.users.length,
|
||||
total: result.totalCount,
|
||||
includeDeleted
|
||||
});
|
||||
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
logError('Admin get users by page endpoint error', error as Error, req, res);
|
||||
res.status(500).json({ error: 'Internal server error' });
|
||||
}
|
||||
});
|
||||
|
||||
>>>>>>> origin/main
|
||||
// Get user by ID including soft-deleted ones
|
||||
router.get('/users/:userId',
|
||||
adminRequired,
|
||||
@@ -141,6 +176,7 @@ router.get('/users/:userId',
|
||||
});
|
||||
|
||||
// Search users including soft-deleted ones
|
||||
<<<<<<< HEAD
|
||||
// router.get('/users/search/:searchTerm',
|
||||
// adminRequired,
|
||||
// ValidationMiddleware.validateStringLength({ searchTerm: { min: 2, max: 100 } }),
|
||||
@@ -167,6 +203,34 @@ router.get('/users/:userId',
|
||||
// res.status(500).json({ error: 'Internal server error' });
|
||||
// }
|
||||
// });
|
||||
=======
|
||||
router.get('/users/search/:searchTerm',
|
||||
adminRequired,
|
||||
ValidationMiddleware.validateStringLength({ searchTerm: { min: 2, max: 100 } }),
|
||||
async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { searchTerm } = req.params;
|
||||
const includeDeleted = req.query.includeDeleted === 'true';
|
||||
|
||||
logRequest('Admin search users endpoint accessed', req, res, { searchTerm, includeDeleted });
|
||||
|
||||
const users = includeDeleted
|
||||
? await container.userRepository.searchIncludingDeleted(searchTerm)
|
||||
: await container.userRepository.search(searchTerm);
|
||||
|
||||
logRequest('Admin user search completed', req, res, {
|
||||
searchTerm,
|
||||
resultCount: Array.isArray(users) ? users.length : (users.totalCount || 0),
|
||||
includeDeleted
|
||||
});
|
||||
|
||||
res.json(users);
|
||||
} catch (error) {
|
||||
logError('Admin search users endpoint error', error as Error, req, res);
|
||||
res.status(500).json({ error: 'Internal server error' });
|
||||
}
|
||||
});
|
||||
>>>>>>> origin/main
|
||||
|
||||
// Update any user (admin only)
|
||||
router.patch('/users/:userId',
|
||||
@@ -358,6 +422,7 @@ router.get('/decks/search/:searchTerm', adminRequired, async (req: Request, res:
|
||||
}
|
||||
});
|
||||
|
||||
<<<<<<< HEAD
|
||||
//modify deck (admin only)
|
||||
router.patch('/decks/:id', adminRequired, async (req: Request, res: Response) => {
|
||||
try {
|
||||
@@ -382,6 +447,8 @@ router.patch('/decks/:id', adminRequired, async (req: Request, res: Response) =>
|
||||
}
|
||||
});
|
||||
|
||||
=======
|
||||
>>>>>>> origin/main
|
||||
// Hard delete deck (admin only)
|
||||
router.delete('/decks/:id/hard', adminRequired, async (req: Request, res: Response) => {
|
||||
try {
|
||||
|
||||
@@ -60,7 +60,11 @@ deckRouter.post('/', authRequired, async (req, res) => {
|
||||
try {
|
||||
const userId = (req as any).user.userId;
|
||||
logRequest('Create deck endpoint accessed', req, res, { name: req.body.name, userId });
|
||||
<<<<<<< HEAD
|
||||
req.body.userid = userId; // Set userId in request body
|
||||
=======
|
||||
|
||||
>>>>>>> origin/main
|
||||
const result = await container.createDeckCommandHandler.execute(req.body);
|
||||
|
||||
logRequest('Deck created successfully', req, res, { deckId: result.id, name: req.body.name, userId });
|
||||
@@ -140,7 +144,11 @@ deckRouter.get('/:id', authRequired, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
<<<<<<< HEAD
|
||||
deckRouter.patch('/:id', authRequired, async (req, res) => {
|
||||
=======
|
||||
deckRouter.put('/:id', authRequired, async (req, res) => {
|
||||
>>>>>>> origin/main
|
||||
try {
|
||||
const deckId = req.params.id;
|
||||
const userId = (req as any).user.userId;
|
||||
@@ -164,10 +172,13 @@ deckRouter.patch('/:id', authRequired, async (req, res) => {
|
||||
if (error instanceof Error && error.message.includes('validation')) {
|
||||
return res.status(400).json({ error: 'Invalid input data', details: error.message });
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
|
||||
if (error instanceof Error && error.message.includes('admin')) {
|
||||
return res.status(403).json({ error: 'Forbidden: ' + error.message });
|
||||
}
|
||||
=======
|
||||
>>>>>>> origin/main
|
||||
|
||||
res.status(500).json({ error: 'Internal server error' });
|
||||
}
|
||||
|
||||
@@ -32,7 +32,11 @@ userRouter.post('/login',
|
||||
logAuth('User login successful', result.user.id, { username: result.user.username }, req, res);
|
||||
res.json(result);
|
||||
} else {
|
||||
<<<<<<< HEAD
|
||||
throw new Error(`Login failed: ${result}`);
|
||||
=======
|
||||
return ErrorResponseService.sendUnauthorized(res, 'Invalid username or password');
|
||||
>>>>>>> origin/main
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
@@ -48,9 +52,12 @@ userRouter.post('/login',
|
||||
if (error.message.includes('not verified')) {
|
||||
return ErrorResponseService.sendUnauthorized(res, 'Please verify your email address');
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
if (error.message.includes('restriction')) {
|
||||
return ErrorResponseService.sendUnauthorized(res, 'Please verify your email address');
|
||||
}
|
||||
=======
|
||||
>>>>>>> origin/main
|
||||
if (error.message.includes('deactivated')) {
|
||||
return ErrorResponseService.sendUnauthorized(res, 'Account has been deactivated');
|
||||
}
|
||||
@@ -87,8 +94,12 @@ userRouter.post('/create',
|
||||
res.status(201).json(result);
|
||||
|
||||
} catch (error) {
|
||||
<<<<<<< HEAD
|
||||
// Don't log here since CreateUserCommandHandler already logs system errors
|
||||
// Only log validation/user input errors at router level
|
||||
=======
|
||||
logError('Create user endpoint error', error as Error, req, res);
|
||||
>>>>>>> origin/main
|
||||
|
||||
if (error instanceof Error) {
|
||||
if (error.message.includes('already exists')) {
|
||||
@@ -97,10 +108,13 @@ userRouter.post('/create',
|
||||
if (error.message.includes('validation')) {
|
||||
return ErrorResponseService.sendBadRequest(res, error.message);
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
// Log unexpected errors that weren't handled by the command handler
|
||||
if (!error.message.includes('Failed to create user')) {
|
||||
logError('Unexpected create user endpoint error', error as Error, req, res);
|
||||
}
|
||||
=======
|
||||
>>>>>>> origin/main
|
||||
}
|
||||
|
||||
return ErrorResponseService.sendInternalServerError(res);
|
||||
@@ -173,6 +187,7 @@ userRouter.patch('/profile', authRequired, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
<<<<<<< HEAD
|
||||
//Soft delete user (current user)
|
||||
userRouter.delete('/profile', authRequired, async (req, res) => {
|
||||
try {
|
||||
@@ -310,4 +325,6 @@ userRouter.post('/reset-password',
|
||||
}
|
||||
});
|
||||
|
||||
=======
|
||||
>>>>>>> origin/main
|
||||
export default userRouter;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import swaggerJSDoc from 'swagger-jsdoc';
|
||||
<<<<<<< HEAD
|
||||
import path from 'path';
|
||||
=======
|
||||
>>>>>>> origin/main
|
||||
|
||||
export const swaggerOptions = {
|
||||
definition: {
|
||||
@@ -19,12 +22,17 @@ export const swaggerOptions = {
|
||||
},
|
||||
servers: [
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
url: 'http://localhost:3001',
|
||||
description: 'Local development server'
|
||||
},
|
||||
{
|
||||
url: 'http://localhost:3000',
|
||||
description: 'Local development server (alt)'
|
||||
=======
|
||||
url: 'http://localhost:3000',
|
||||
description: 'Local development server'
|
||||
>>>>>>> origin/main
|
||||
},
|
||||
{
|
||||
url: 'https://api.serpentrace.com',
|
||||
@@ -66,6 +74,7 @@ export const swaggerOptions = {
|
||||
{
|
||||
name: 'Deck Import/Export',
|
||||
description: 'Import and export deck functionality'
|
||||
<<<<<<< HEAD
|
||||
},
|
||||
{
|
||||
name: 'Games',
|
||||
@@ -90,11 +99,17 @@ export const swaggerOptions = {
|
||||
{
|
||||
name: 'Admin - Contacts',
|
||||
description: 'Admin contact management operations'
|
||||
=======
|
||||
>>>>>>> origin/main
|
||||
}
|
||||
]
|
||||
},
|
||||
apis: [
|
||||
<<<<<<< HEAD
|
||||
'./src/Api/swagger/swaggerDefinitionsFixed.ts'
|
||||
=======
|
||||
'./src/Api/swagger/swaggerDefinitions.ts'
|
||||
>>>>>>> origin/main
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
/**
|
||||
* @swagger
|
||||
* components:
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
* securitySchemes:
|
||||
* bearerAuth:
|
||||
* type: http
|
||||
* scheme: bearer
|
||||
* bearerFormat: JWT
|
||||
>>>>>>> origin/main
|
||||
* schemas:
|
||||
* User:
|
||||
* type: object
|
||||
@@ -100,6 +108,7 @@
|
||||
* type: string
|
||||
* format: email
|
||||
*
|
||||
<<<<<<< HEAD
|
||||
* ForgotPasswordRequest:
|
||||
* type: object
|
||||
* required:
|
||||
@@ -131,6 +140,8 @@
|
||||
* message:
|
||||
* type: string
|
||||
*
|
||||
=======
|
||||
>>>>>>> origin/main
|
||||
* Organization:
|
||||
* type: object
|
||||
* properties:
|
||||
@@ -325,6 +336,7 @@
|
||||
* chatId:
|
||||
* type: string
|
||||
*
|
||||
<<<<<<< HEAD
|
||||
* Game:
|
||||
* type: object
|
||||
* properties:
|
||||
@@ -353,6 +365,8 @@
|
||||
* type: string
|
||||
* format: date-time
|
||||
*
|
||||
=======
|
||||
>>>>>>> origin/main
|
||||
* Error:
|
||||
* type: object
|
||||
* properties:
|
||||
@@ -363,6 +377,7 @@
|
||||
* format: date-time
|
||||
* details:
|
||||
* type: string
|
||||
<<<<<<< HEAD
|
||||
*/
|
||||
/**
|
||||
* @swagger
|
||||
@@ -392,6 +407,34 @@
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/Error'
|
||||
*
|
||||
=======
|
||||
*
|
||||
* paths:
|
||||
* /api/users/login:
|
||||
* post:
|
||||
* tags: [Users]
|
||||
* summary: User login
|
||||
* description: Authenticate user and return JWT token
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/LoginRequest'
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Login successful
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/LoginResponse'
|
||||
* 401:
|
||||
* description: Invalid credentials
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/Error'
|
||||
>>>>>>> origin/main
|
||||
*
|
||||
* /api/users/create:
|
||||
* post:
|
||||
@@ -1454,6 +1497,7 @@
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/Contact'
|
||||
<<<<<<< HEAD
|
||||
*
|
||||
* /api/games/start:
|
||||
* post:
|
||||
@@ -1611,6 +1655,8 @@
|
||||
* description: Game already started or not ready to start
|
||||
* 500:
|
||||
* description: Internal server error
|
||||
=======
|
||||
>>>>>>> origin/main
|
||||
*/
|
||||
|
||||
export {};
|
||||
|
||||
Reference in New Issue
Block a user