From 29cfcc4d39eed85d630a725680e2418502c0f204 Mon Sep 17 00:00:00 2001 From: GideonBature Date: Tue, 29 Jul 2025 03:50:11 +0100 Subject: [PATCH] Implement api swagger documentation with OpenAPI/SwaggerUI --- src/model/user.model.ts | 40 +++++++ src/router/auth.router.ts | 243 ++++++++++++++++++++++++++++++++++++-- src/swagger.ts | 43 ++++++- 3 files changed, 309 insertions(+), 17 deletions(-) diff --git a/src/model/user.model.ts b/src/model/user.model.ts index 8ef2966..13e6e93 100644 --- a/src/model/user.model.ts +++ b/src/model/user.model.ts @@ -1,3 +1,43 @@ +/** + * @openapi + * components: + * schemas: + * User: + * type: object + * required: + * - email + * - password + * properties: + * id: + * type: string + * description: The auto-generated id of the user + * email: + * type: string + * description: The email of the user + * password: + * type: string + * description: The password of the user + * isEmailVerified: + * type: boolean + * description: Whether the user's email is verified + * socialId: + * type: string + * description: The social id of the user + * socialProvider: + * type: string + * description: The social provider of the user + * walletAddress: + * type: string + * description: The wallet address of the user + * createdAt: + * type: string + * format: date-time + * description: The date the user was created + * updatedAt: + * type: string + * format: date-time + * description: The date the user was last updated + */ import { User } from '../types/user.types'; import crypto from 'crypto'; diff --git a/src/router/auth.router.ts b/src/router/auth.router.ts index 124bdf9..67b1f2f 100644 --- a/src/router/auth.router.ts +++ b/src/router/auth.router.ts @@ -16,33 +16,252 @@ import { authRateLimiter, passwordResetRateLimiter } from '../middleware/ratelim const router = Router(); -// Register user +/** + * @openapi + * tags: + * name: Authentication + * description: User authentication and authorization + */ + +/** + * @openapi + * /auth/register: + * post: + * summary: Register a new user + * tags: [Authentication] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - email + * - password + * - confirmPassword + * properties: + * email: + * type: string + * example: test@email.com + * password: + * type: string + * example: Test@123 + * confirmPassword: + * type: string + * example: Test@123 + * responses: + * 201: + * description: User created successfully + * 400: + * description: Bad request + */ router.post('/register', authRateLimiter, register); -// Login user +/** + * @openapi + * /auth/login: + * post: + * summary: Login a user + * tags: [Authentication] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - email + * - password + * properties: + * email: + * type: string + * example: test@email.com + * password: + * type: string + * example: Test@123 + * responses: + * 200: + * description: User logged in successfully + * 401: + * description: Unauthorized + */ router.post('/login', authRateLimiter, login); -// Logout user +/** + * @openapi + * /auth/logout: + * post: + * summary: Logout a user + * tags: [Authentication] + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: User logged out successfully + * 401: + * description: Unauthorized + */ router.post('/logout', protect, logout); -// Resend verification OTP - -// Verify OTP +/** + * @openapi + * /auth/verify/otp: + * post: + * summary: Verify OTP + * tags: [Authentication] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - email + * - otp + * properties: + * email: + * type: string + * example: test@email.com + * otp: + * type: string + * example: 123456 + * responses: + * 200: + * description: OTP verified successfully + * 400: + * description: Bad request + */ router.post('/verify/otp', verifyOTP); + +/** + * @openapi + * /auth/resend-otp: + * post: + * summary: Resend OTP + * tags: [Authentication] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - email + * properties: + * email: + * type: string + * example: test@email.com + * responses: + * 200: + * description: OTP resent successfully + * 400: + * description: Bad request + */ router.post('/resend-otp', authRateLimiter, resendOTP); -// Request password reset +/** + * @openapi + * /auth/forgot-password: + * post: + * summary: Request password reset + * tags: [Authentication] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - email + * properties: + * email: + * type: string + * example: test@email.com + * responses: + * 200: + * description: Password reset email sent + * 400: + * description: Bad request + */ router.post('/forgot-password', passwordResetRateLimiter, forgotPassword); -// Verify password reset OTP - -// Reset password +/** + * @openapi + * /auth/reset-password: + * post: + * summary: Reset password + * tags: [Authentication] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - token + * - password + * properties: + * token: + * type: string + * password: + * type: string + * example: Reset@123 + * responses: + * 200: + * description: Password reset successfully + * 400: + * description: Bad request + */ router.post('/reset-password', resetPassword); -// Verify email +/** + * @openapi + * /auth/verify-email: + * post: + * summary: Verify email + * tags: [Authentication] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - token + * properties: + * token: + * type: string + * responses: + * 200: + * description: Email verified successfully + * 400: + * description: Bad request + */ router.post('/verify-email', verifyEmail); -// Google login +/** + * @openapi + * /auth/google-login: + * post: + * summary: Google login + * tags: [Authentication] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - token + * properties: + * token: + * type: string + * responses: + * 200: + * description: User logged in successfully + * 401: + * description: Unauthorized + */ router.post('/google-login', authRateLimiter, googleLogin); export default router; diff --git a/src/swagger.ts b/src/swagger.ts index d911cc7..475dccf 100644 --- a/src/swagger.ts +++ b/src/swagger.ts @@ -1,29 +1,62 @@ import swaggerJSDoc from 'swagger-jsdoc'; import swaggerUi from 'swagger-ui-express'; import { Express } from 'express'; +import { version } from '../package.json'; const swaggerDefinition = { openapi: '3.0.0', info: { - title: 'ChainRemit API', - version: '1.0.0', - description: 'API documentation for ChainRemit backend', + title: 'ChainRemit Backend API', + version, + description: + 'Comprehensive API documentation for the ChainRemit backend, a decentralized microfinance and remittance platform built on StarkNet.', + contact: { + name: 'Support', + url: 'https://github.com/MetroLogic/chainremit_backend/issues', + email: 'support@chainremit.com', + }, + license: { + name: 'MIT', + url: 'https://github.com/MetroLogic/chainremit_backend/blob/main/LICENSE', + }, }, servers: [ { - url: 'http://localhost:3000', + url: `http://localhost:${process.env.PORT || 3000}`, description: 'Development server', }, + { + url: 'https://api.chainremit.com', + description: 'Production server', + }, + ], + components: { + securitySchemes: { + bearerAuth: { + type: 'http', + scheme: 'bearer', + bearerFormat: 'JWT', + }, + }, + }, + security: [ + { + bearerAuth: [], + }, ], }; const options = { swaggerDefinition, - apis: ['./src/app.ts'], // Add more files as needed + apis: ['./src/router/*.ts', './src/model/*.ts'], }; const swaggerSpec = swaggerJSDoc(options); export function setupSwagger(app: Express) { app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec)); + app.get('/api-docs.json', (req, res) => { + res.setHeader('Content-Type', 'application/json'); + res.send(swaggerSpec); + }); }