Skip to content

Commit 2bfa627

Browse files
committed
add: swagger-ui api
1 parent c760880 commit 2bfa627

File tree

10 files changed

+1873
-21
lines changed

10 files changed

+1873
-21
lines changed

apps/backend/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727
"passport": "^0.7.0",
2828
"passport-jwt": "^4.0.1",
2929
"passport-local": "^1.0.0",
30-
"pg": "^8.16.0"
30+
"pg": "^8.16.0",
31+
"swagger-jsdoc": "^6.2.8",
32+
"swagger-ui-express": "^5.0.1"
3133
},
3234
"devDependencies": {
3335
"dotenv-cli": "^7.4.2",

apps/backend/src/index.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,29 @@ import express from "express";
22
import cors from "cors";
33
import path from "path";
44
import passport from "./middleware/passport.js";
5-
import { startTokenCleanupJob } from "./jobs/tokenCleanup.js";
65
import authRoutes from "./routes/auth.js";
76
import companyRoutes from "./routes/companies.js";
87
import dashboardRoutes from "./routes/dashboard.js";
98
import userRoutes from "./routes/users.js";
109
import historyRoutes from "./routes/history.js";
10+
// swagger imports
11+
import swaggerJSDoc from 'swagger-jsdoc';
12+
import swaggerUI from 'swagger-ui-express';
13+
import swaggerSpec from "./swaggerSpec.js";
1114

12-
// i use express for backend in this project
1315
const app = express();
1416

1517
const PORT = process.env.PORT || 3001;
1618

17-
// Middleware to enable CORS for all routes and parse JSON requests
19+
// middleware to enable CORS for all routes and parse JSON requests
1820
app.use(cors());
1921
app.use(express.json({ limit: '10mb' }));
2022
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
2123

22-
// Initialize Passport middleware
24+
// initialize Passport auth middleware
2325
app.use(passport.initialize());
2426

25-
// Serve static files from public directory
27+
// serve static files from public directory
2628
app.use("/public", express.static(path.join(process.cwd(), "public")));
2729

2830
// mount different api routes on specific paths
@@ -38,6 +40,8 @@ app.get("/api/health", (req, res) => {
3840
res.json({ status: "OK", timestamp: new Date().toISOString() });
3941
});
4042

43+
app.use("/api-docs", swaggerUI.serve, swaggerUI.setup(swaggerSpec));
44+
4145
app.listen(PORT, () => {
4246
console.log(`Server running on http://localhost:${PORT}`);
4347
});

apps/backend/src/routes/auth.js

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,49 @@ import {
1313

1414
const router = express.Router();
1515

16+
/**
17+
* @swagger
18+
* /auth/login:
19+
* post:
20+
* summary: User login
21+
* tags:
22+
* - Authentication
23+
* requestBody:
24+
* required: true
25+
* content:
26+
* application/json:
27+
* schema:
28+
* type: object
29+
* properties:
30+
* email:
31+
* type: string
32+
* format: email
33+
* password:
34+
* type: string
35+
* required:
36+
* - email
37+
* - password
38+
* responses:
39+
* 200:
40+
* description: Login successful
41+
* content:
42+
* application/json:
43+
* schema:
44+
* type: object
45+
* properties:
46+
* user:
47+
* type: object
48+
* accessToken:
49+
* type: string
50+
* refreshToken:
51+
* type: string
52+
* expiresIn:
53+
* type: string
54+
* 401:
55+
* description: Invalid credentials
56+
* 500:
57+
* description: Server error
58+
*/
1659
// Login через Passport Local Strategy
1760
router.post("/login", (req, res, next) => {
1861
authenticateLocal(req, res, async (err) => {
@@ -54,6 +97,55 @@ router.post("/login", (req, res, next) => {
5497
});
5598
});
5699

100+
/**
101+
* @swagger
102+
* /auth/register:
103+
* post:
104+
* summary: User registration
105+
* tags:
106+
* - Authentication
107+
* requestBody:
108+
* required: true
109+
* content:
110+
* application/json:
111+
* schema:
112+
* type: object
113+
* properties:
114+
* email:
115+
* type: string
116+
* format: email
117+
* password:
118+
* type: string
119+
* firstName:
120+
* type: string
121+
* lastName:
122+
* type: string
123+
* required:
124+
* - email
125+
* - password
126+
* - firstName
127+
* - lastName
128+
* responses:
129+
* 201:
130+
* description: Registration successful
131+
* content:
132+
* application/json:
133+
* schema:
134+
* type: object
135+
* properties:
136+
* user:
137+
* type: object
138+
* accessToken:
139+
* type: string
140+
* refreshToken:
141+
* type: string
142+
* expiresIn:
143+
* type: string
144+
* 400:
145+
* description: User already exists
146+
* 500:
147+
* description: Server error
148+
*/
57149
// Register with refresh token support
58150
router.post("/register", async (req, res) => {
59151
try {
@@ -107,6 +199,39 @@ router.post("/register", async (req, res) => {
107199
}
108200
});
109201

202+
/**
203+
* @swagger
204+
* /auth/refresh:
205+
* post:
206+
* summary: Refresh access token
207+
* tags:
208+
* - Authentication
209+
* requestBody:
210+
* required: true
211+
* content:
212+
* application/json:
213+
* schema:
214+
* type: object
215+
* properties:
216+
* refreshToken:
217+
* type: string
218+
* required:
219+
* - refreshToken
220+
* responses:
221+
* 200:
222+
* description: Token refreshed successfully
223+
* content:
224+
* application/json:
225+
* schema:
226+
* type: object
227+
* properties:
228+
* accessToken:
229+
* type: string
230+
* expiresIn:
231+
* type: string
232+
* 401:
233+
* description: Invalid refresh token
234+
*/
110235
// Refresh access token
111236
router.post("/refresh", async (req, res) => {
112237
try {
@@ -132,6 +257,38 @@ router.post("/refresh", async (req, res) => {
132257
}
133258
});
134259

260+
/**
261+
* @swagger
262+
* /auth/logout:
263+
* post:
264+
* summary: User logout
265+
* tags:
266+
* - Authentication
267+
* security:
268+
* - bearerAuth: []
269+
* requestBody:
270+
* content:
271+
* application/json:
272+
* schema:
273+
* type: object
274+
* properties:
275+
* refreshToken:
276+
* type: string
277+
* responses:
278+
* 200:
279+
* description: Logout successful
280+
* content:
281+
* application/json:
282+
* schema:
283+
* type: object
284+
* properties:
285+
* success:
286+
* type: boolean
287+
* message:
288+
* type: string
289+
* 500:
290+
* description: Server error
291+
*/
135292
// Logout через Passport JWT
136293
router.post('/logout', authenticateJWT, async (req, res) => {
137294
try {
@@ -171,6 +328,44 @@ router.post('/logout', authenticateJWT, async (req, res) => {
171328
}
172329
});
173330

331+
/**
332+
* @swagger
333+
* /auth/profile-passport:
334+
* get:
335+
* summary: Get user profile (Passport.js example)
336+
* description: Alternative endpoint to get user profile using Passport.js JWT authentication
337+
* tags:
338+
* - Authentication
339+
* security:
340+
* - bearerAuth: []
341+
* responses:
342+
* 200:
343+
* description: User profile retrieved successfully
344+
* content:
345+
* application/json:
346+
* schema:
347+
* type: object
348+
* properties:
349+
* user:
350+
* type: object
351+
* properties:
352+
* id:
353+
* type: integer
354+
* email:
355+
* type: string
356+
* firstName:
357+
* type: string
358+
* lastName:
359+
* type: string
360+
* role:
361+
* type: string
362+
* message:
363+
* type: string
364+
* 401:
365+
* description: Unauthorized
366+
* 500:
367+
* description: Server error
368+
*/
174369
// Alternative Passport.js protected route (example)
175370
router.get("/profile-passport", authenticateJWT, async (req, res) => {
176371
try {
@@ -184,6 +379,44 @@ router.get("/profile-passport", authenticateJWT, async (req, res) => {
184379
}
185380
});
186381

382+
/**
383+
* @swagger
384+
* /auth/verify:
385+
* get:
386+
* summary: Verify JWT token
387+
* description: Verify if the provided JWT token is valid and return user information
388+
* tags:
389+
* - Authentication
390+
* security:
391+
* - bearerAuth: []
392+
* responses:
393+
* 200:
394+
* description: Token is valid
395+
* content:
396+
* application/json:
397+
* schema:
398+
* type: object
399+
* properties:
400+
* user:
401+
* type: object
402+
* properties:
403+
* id:
404+
* type: integer
405+
* email:
406+
* type: string
407+
* firstName:
408+
* type: string
409+
* lastName:
410+
* type: string
411+
* role:
412+
* type: string
413+
* authenticated:
414+
* type: boolean
415+
* 401:
416+
* description: Unauthorized
417+
* 500:
418+
* description: Server error
419+
*/
187420
// Verify через Passport JWT
188421
router.get("/verify", authenticateJWT, async (req, res) => {
189422
try {
@@ -197,6 +430,45 @@ router.get("/verify", authenticateJWT, async (req, res) => {
197430
}
198431
});
199432

433+
/**
434+
* @swagger
435+
* /auth/profile:
436+
* get:
437+
* summary: Get user profile
438+
* description: Get current authenticated user's profile information
439+
* tags:
440+
* - Authentication
441+
* security:
442+
* - bearerAuth: []
443+
* responses:
444+
* 200:
445+
* description: User profile retrieved successfully
446+
* content:
447+
* application/json:
448+
* schema:
449+
* type: object
450+
* properties:
451+
* id:
452+
* type: integer
453+
* email:
454+
* type: string
455+
* firstName:
456+
* type: string
457+
* lastName:
458+
* type: string
459+
* role:
460+
* type: string
461+
* createdAt:
462+
* type: string
463+
* format: date-time
464+
* updatedAt:
465+
* type: string
466+
* format: date-time
467+
* 401:
468+
* description: Unauthorized
469+
* 500:
470+
* description: Server error
471+
*/
200472
// Profile через Passport JWT
201473
router.get("/profile", authenticateJWT, async (req, res) => {
202474
try {

0 commit comments

Comments
 (0)