diff --git a/.gitignore b/.gitignore index 4781473..e0a8937 100644 --- a/.gitignore +++ b/.gitignore @@ -129,4 +129,5 @@ dist .yarn/install-state.gz .pnp.* .clinic/ -features.md \ No newline at end of file +features.md +.qodo diff --git a/config/swagger.js b/config/swagger.js index 3cd6b0b..1c066f6 100644 --- a/config/swagger.js +++ b/config/swagger.js @@ -2,33 +2,50 @@ const swaggerJSDoc = require('swagger-jsdoc'); const swaggerUi = require('swagger-ui-express'); const swaggerOptions = { - definition: { - openapi: '3.0.0', - info: { - title: 'User API', - version: '1.0.0', - description: 'This API allows you to manage users, including authentication and CRUD operations.', + definition: { + openapi: '3.0.0', + info: { + title: 'User API', + version: '1.0.0', + description: 'User management API with authentication', + }, + servers: [ + { + url: 'http://localhost:3000', + description: 'Development server', }, - host: 'localhost:3000', - basePath: '/', - securityDefinitions: { + ], + components: { + securitySchemes: { bearerAuth: { - type: 'apiKey', - name: 'x-auth-token', + type: 'http', scheme: 'bearer', - in: 'header', - }, + bearerFormat: 'JWT', + description: 'Enter your JWT token' + } }, - security: [ - { - bearerAuth: [], // Apply bearer auth globally to all routes - }, - ], }, - apis: ['./routes/userRoutes.js', './controllers/userController.js'], - }; - + security: [ + { + bearerAuth: [] + } + ], + }, + apis: ['./routes/*.js'], +}; + // Initialize Swagger JSDoc const swaggerSpec = swaggerJSDoc(swaggerOptions); -module.exports = { swaggerUi, swaggerSpec }; +const swaggerUiOptions = { + explorer: true, + swaggerOptions: { + persistAuthorization: true, + }, +}; + +module.exports = { + swaggerUi, + swaggerSpec, + swaggerUiOptions +}; diff --git a/routes/loginRoutes.js b/routes/loginRoutes.js index a00774b..625636e 100644 --- a/routes/loginRoutes.js +++ b/routes/loginRoutes.js @@ -8,6 +8,7 @@ const authController = require('../controllers/authController'); * post: * summary: Login an existing user * description: Authenticates the user and returns a JWT token + * security: [] * requestBody: * required: true * content: @@ -17,16 +18,11 @@ const authController = require('../controllers/authController'); * properties: * email: * type: string - * description: The user's email * password: * type: string - * description: The user's password - * required: - * - email - * - password * responses: * 200: - * description: JWT token returned after successful login + * description: Login successful * content: * application/json: * schema: @@ -34,13 +30,9 @@ const authController = require('../controllers/authController'); * properties: * token: * type: string - * description: The JWT token for authentication - * 400: - * description: Bad request (invalid input) + * description: JWT token to be used for authentication * 401: - * description: Unauthorized (incorrect credentials) - * 500: - * description: Server error + * description: Invalid credentials */ router.post('/login', authController.login); diff --git a/routes/userRoutes.js b/routes/userRoutes.js index b14d431..7da54f2 100644 --- a/routes/userRoutes.js +++ b/routes/userRoutes.js @@ -1,91 +1,56 @@ const express = require('express'); const userController = require('../controllers/userController'); -const authenticateToken = require('../middleware/auth'); -const authorize = require('../middleware/authorize'); +const auth = require('../middleware/auth'); const multer = require('multer'); const upload = multer({ dest: 'uploads/' }); const router = express.Router(); /** - * @swagger + * @openapi + * components: + * securitySchemes: + * bearerAuth: + * type: http + * scheme: bearer + * bearerFormat: JWT + * schemas: + * User: + * type: object + * properties: + * name: + * type: string + * email: + * type: string + * password: + * type: string + * profile_picture: + * type: string + * format: binary + * * /users: * get: - * summary: Retrieve all users - * description: Returns a list of all users + * tags: + * - Users + * summary: Get all users * security: * - bearerAuth: [] * responses: * 200: - * description: A list of users - * content: - * application/json: - * schema: - * type: array - * items: - * type: object - * properties: - * id: - * type: integer - * name: - * type: string - * email: - * type: string + * description: List of users retrieved successfully * 401: - * description: Unauthorized access - * 500: - * description: Server error - */ -router.get('/', authenticateToken, userController.getUsers); - -/** - * @swagger - * /users/{id}: - * get: - * summary: Retrieve a user by ID - * description: Returns a single user identified by their ID - * parameters: - * - name: id - * in: path - * required: true - * description: The ID of the user to retrieve - * schema: - * type: integer - * security: - * - bearerAuth: [] - * responses: - * 200: - * description: User details - * content: - * application/json: - * schema: - * type: object - * properties: - * id: - * type: integer - * name: - * type: string - * email: - * type: string - * 401: - * description: Unauthorized access - * 404: - * description: User not found - * 500: - * description: Server error - */ -router.get('/:id', authenticateToken, userController.getUserById); - -/** - * @swagger - * /users: + * description: Unauthorized - invalid token + * * post: + * tags: + * - Users * summary: Create a new user - * description: Creates a new user in the system + * security: + * - bearerAuth: [] * requestBody: * required: true * content: - * application/json: + * multipart/form-data: * schema: * type: object * properties: @@ -95,44 +60,46 @@ router.get('/:id', authenticateToken, userController.getUserById); * type: string * password: * type: string - * required: - * - name - * - email - * - password - * security: - * - bearerAuth: [] + * picture: + * type: string + * format: binary * responses: * 201: * description: User created successfully - * content: - * application/json: - * schema: - * type: object - * properties: - * message: - * type: string - * userId: - * type: integer - * 400: - * description: Validation error * 401: - * description: Unauthorized access - * 500: - * description: Server error - */ -router.post('/', authenticateToken, upload.single('picture'), userController.createUser); - -/** - * @swagger + * description: Unauthorized - invalid token + * * /users/{id}: + * get: + * tags: + * - Users + * summary: Get user by ID + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: id + * required: true + * schema: + * type: integer + * responses: + * 200: + * description: User found successfully + * 401: + * description: Unauthorized - invalid token + * 404: + * description: User not found + * * put: - * summary: Update an existing user - * description: Updates the details of an existing user by ID + * tags: + * - Users + * summary: Update user + * security: + * - bearerAuth: [] * parameters: - * - name: id - * in: path + * - in: path + * name: id * required: true - * description: The ID of the user to update * schema: * type: integer * requestBody: @@ -146,52 +113,41 @@ router.post('/', authenticateToken, upload.single('picture'), userController.cre * type: string * email: * type: string - * required: - * - name - * - email - * security: - * - bearerAuth: [] + * password: + * type: string * responses: * 200: * description: User updated successfully - * 400: - * description: Bad request, validation error * 401: - * description: Unauthorized access + * description: Unauthorized - invalid token * 404: * description: User not found - * 500: - * description: Server error - */ -router.put('/:id', authenticateToken, userController.updateUser); - -/** - * @swagger - * /users/{id}: + * * delete: - * summary: Delete a user by ID - * description: Deletes a user from the system by their ID + * tags: + * - Users + * summary: Delete user + * security: + * - bearerAuth: [] * parameters: - * - name: id - * in: path + * - in: path + * name: id * required: true - * description: The ID of the user to delete * schema: * type: integer - * security: - * - bearerAuth: [] * responses: * 200: * description: User deleted successfully * 401: - * description: Unauthorized access - * 403: - * description: Forbidden, insufficient privileges + * description: Unauthorized - invalid token * 404: * description: User not found - * 500: - * description: Server error */ -router.delete('/:id', authenticateToken, authorize('admin'), userController.deleteUser); + +router.get('/', auth, userController.getUsers); +router.post('/', auth, upload.single('picture'), userController.createUser); +router.get('/:id', auth, userController.getUserById); +router.put('/:id', auth, userController.updateUser); +router.delete('/:id', auth, userController.deleteUser); module.exports = router; diff --git a/uploads/873409ad6aa037c801ba38a04be33200 b/uploads/873409ad6aa037c801ba38a04be33200 new file mode 100644 index 0000000..8c4a377 Binary files /dev/null and b/uploads/873409ad6aa037c801ba38a04be33200 differ