add changes
This commit is contained in:
421
routes/admin.routes.js
Normal file
421
routes/admin.routes.js
Normal file
@@ -0,0 +1,421 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const questionController = require('../controllers/question.controller');
|
||||
const adminController = require('../controllers/admin.controller');
|
||||
const { verifyToken, isAdmin } = require('../middleware/auth.middleware');
|
||||
const { adminLimiter } = require('../middleware/rateLimiter');
|
||||
const { cacheStatistics, cacheGuestAnalytics, cacheGuestSettings, invalidateCacheMiddleware, invalidateCache } = require('../middleware/cache');
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /admin/statistics:
|
||||
* get:
|
||||
* summary: Get system-wide statistics for admin dashboard
|
||||
* tags: [Admin]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Statistics retrieved successfully
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* users:
|
||||
* type: object
|
||||
* properties:
|
||||
* total:
|
||||
* type: integer
|
||||
* active:
|
||||
* type: integer
|
||||
* inactiveLast7Days:
|
||||
* type: integer
|
||||
* quizzes:
|
||||
* type: object
|
||||
* properties:
|
||||
* totalSessions:
|
||||
* type: integer
|
||||
* averageScore:
|
||||
* type: number
|
||||
* passRate:
|
||||
* type: number
|
||||
* content:
|
||||
* type: object
|
||||
* properties:
|
||||
* totalCategories:
|
||||
* type: integer
|
||||
* totalQuestions:
|
||||
* type: integer
|
||||
* 401:
|
||||
* $ref: '#/components/responses/UnauthorizedError'
|
||||
* 403:
|
||||
* $ref: '#/components/responses/ForbiddenError'
|
||||
*
|
||||
* /admin/guest-settings:
|
||||
* get:
|
||||
* summary: Get guest user settings
|
||||
* tags: [Admin]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Guest settings retrieved successfully
|
||||
* 401:
|
||||
* $ref: '#/components/responses/UnauthorizedError'
|
||||
* 403:
|
||||
* $ref: '#/components/responses/ForbiddenError'
|
||||
* put:
|
||||
* summary: Update guest user settings
|
||||
* tags: [Admin]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* requestBody:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* maxQuizzes:
|
||||
* type: integer
|
||||
* minimum: 1
|
||||
* maximum: 100
|
||||
* expiryHours:
|
||||
* type: integer
|
||||
* minimum: 1
|
||||
* maximum: 168
|
||||
* publicCategories:
|
||||
* type: array
|
||||
* items:
|
||||
* type: integer
|
||||
* featureRestrictions:
|
||||
* type: object
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Settings updated successfully
|
||||
* 401:
|
||||
* $ref: '#/components/responses/UnauthorizedError'
|
||||
* 403:
|
||||
* $ref: '#/components/responses/ForbiddenError'
|
||||
*
|
||||
* /admin/guest-analytics:
|
||||
* get:
|
||||
* summary: Get guest user analytics
|
||||
* tags: [Admin]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Analytics retrieved successfully
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* overview:
|
||||
* type: object
|
||||
* properties:
|
||||
* totalGuestSessions:
|
||||
* type: integer
|
||||
* activeGuestSessions:
|
||||
* type: integer
|
||||
* convertedGuestSessions:
|
||||
* type: integer
|
||||
* conversionRate:
|
||||
* type: number
|
||||
* quizActivity:
|
||||
* type: object
|
||||
* behavior:
|
||||
* type: object
|
||||
* 401:
|
||||
* $ref: '#/components/responses/UnauthorizedError'
|
||||
* 403:
|
||||
* $ref: '#/components/responses/ForbiddenError'
|
||||
*
|
||||
* /admin/users:
|
||||
* get:
|
||||
* summary: Get all users with pagination and filtering
|
||||
* tags: [Admin]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: query
|
||||
* name: page
|
||||
* schema:
|
||||
* type: integer
|
||||
* default: 1
|
||||
* - in: query
|
||||
* name: limit
|
||||
* schema:
|
||||
* type: integer
|
||||
* default: 10
|
||||
* maximum: 100
|
||||
* - in: query
|
||||
* name: role
|
||||
* schema:
|
||||
* type: string
|
||||
* enum: [user, admin]
|
||||
* - in: query
|
||||
* name: isActive
|
||||
* schema:
|
||||
* type: boolean
|
||||
* - in: query
|
||||
* name: sortBy
|
||||
* schema:
|
||||
* type: string
|
||||
* enum: [createdAt, username, email]
|
||||
* - in: query
|
||||
* name: sortOrder
|
||||
* schema:
|
||||
* type: string
|
||||
* enum: [asc, desc]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Users retrieved successfully
|
||||
* 401:
|
||||
* $ref: '#/components/responses/UnauthorizedError'
|
||||
* 403:
|
||||
* $ref: '#/components/responses/ForbiddenError'
|
||||
*
|
||||
* /admin/users/{userId}:
|
||||
* get:
|
||||
* summary: Get user details by ID
|
||||
* tags: [Admin]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: userId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* responses:
|
||||
* 200:
|
||||
* description: User details retrieved successfully
|
||||
* 401:
|
||||
* $ref: '#/components/responses/UnauthorizedError'
|
||||
* 403:
|
||||
* $ref: '#/components/responses/ForbiddenError'
|
||||
* 404:
|
||||
* $ref: '#/components/responses/NotFoundError'
|
||||
*/
|
||||
|
||||
// Apply admin rate limiter to all routes
|
||||
router.use(adminLimiter);
|
||||
|
||||
router.get('/statistics', verifyToken, isAdmin, cacheStatistics, adminController.getSystemStatistics);
|
||||
router.get('/guest-settings', verifyToken, isAdmin, cacheGuestSettings, adminController.getGuestSettings);
|
||||
router.put('/guest-settings', verifyToken, isAdmin, invalidateCacheMiddleware(() => invalidateCache.guestSettings()), adminController.updateGuestSettings);
|
||||
router.get('/guest-analytics', verifyToken, isAdmin, cacheGuestAnalytics, adminController.getGuestAnalytics);
|
||||
router.get('/users', verifyToken, isAdmin, adminController.getAllUsers);
|
||||
router.get('/users/:userId', verifyToken, isAdmin, adminController.getUserById);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /admin/users/{userId}/role:
|
||||
* put:
|
||||
* summary: Update user role
|
||||
* tags: [Admin]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: userId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - role
|
||||
* properties:
|
||||
* role:
|
||||
* type: string
|
||||
* enum: [user, admin]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: User role updated successfully
|
||||
* 401:
|
||||
* $ref: '#/components/responses/UnauthorizedError'
|
||||
* 403:
|
||||
* $ref: '#/components/responses/ForbiddenError'
|
||||
* 404:
|
||||
* $ref: '#/components/responses/NotFoundError'
|
||||
*
|
||||
* /admin/users/{userId}/activate:
|
||||
* put:
|
||||
* summary: Reactivate deactivated user
|
||||
* tags: [Admin]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: userId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* responses:
|
||||
* 200:
|
||||
* description: User reactivated successfully
|
||||
* 401:
|
||||
* $ref: '#/components/responses/UnauthorizedError'
|
||||
* 403:
|
||||
* $ref: '#/components/responses/ForbiddenError'
|
||||
* 404:
|
||||
* $ref: '#/components/responses/NotFoundError'
|
||||
*
|
||||
* /admin/users/{userId}:
|
||||
* delete:
|
||||
* summary: Deactivate user (soft delete)
|
||||
* tags: [Admin]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: userId
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* responses:
|
||||
* 200:
|
||||
* description: User deactivated successfully
|
||||
* 401:
|
||||
* $ref: '#/components/responses/UnauthorizedError'
|
||||
* 403:
|
||||
* $ref: '#/components/responses/ForbiddenError'
|
||||
* 404:
|
||||
* $ref: '#/components/responses/NotFoundError'
|
||||
*
|
||||
* /admin/questions:
|
||||
* post:
|
||||
* summary: Create a new question
|
||||
* tags: [Questions]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - questionText
|
||||
* - questionType
|
||||
* - correctAnswer
|
||||
* - difficulty
|
||||
* - categoryId
|
||||
* properties:
|
||||
* questionText:
|
||||
* type: string
|
||||
* questionType:
|
||||
* type: string
|
||||
* enum: [multiple_choice, trueFalse, short_answer]
|
||||
* options:
|
||||
* type: array
|
||||
* items:
|
||||
* type: string
|
||||
* correctAnswer:
|
||||
* type: string
|
||||
* difficulty:
|
||||
* type: string
|
||||
* enum: [easy, medium, hard]
|
||||
* points:
|
||||
* type: integer
|
||||
* explanation:
|
||||
* type: string
|
||||
* categoryId:
|
||||
* type: integer
|
||||
* tags:
|
||||
* type: array
|
||||
* items:
|
||||
* type: string
|
||||
* keywords:
|
||||
* type: array
|
||||
* items:
|
||||
* type: string
|
||||
* responses:
|
||||
* 201:
|
||||
* description: Question created successfully
|
||||
* 401:
|
||||
* $ref: '#/components/responses/UnauthorizedError'
|
||||
* 403:
|
||||
* $ref: '#/components/responses/ForbiddenError'
|
||||
*
|
||||
* /admin/questions/{id}:
|
||||
* put:
|
||||
* summary: Update a question
|
||||
* tags: [Questions]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* requestBody:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* questionText:
|
||||
* type: string
|
||||
* options:
|
||||
* type: array
|
||||
* items:
|
||||
* type: string
|
||||
* correctAnswer:
|
||||
* type: string
|
||||
* difficulty:
|
||||
* type: string
|
||||
* enum: [easy, medium, hard]
|
||||
* isActive:
|
||||
* type: boolean
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Question updated successfully
|
||||
* 401:
|
||||
* $ref: '#/components/responses/UnauthorizedError'
|
||||
* 403:
|
||||
* $ref: '#/components/responses/ForbiddenError'
|
||||
* 404:
|
||||
* $ref: '#/components/responses/NotFoundError'
|
||||
* delete:
|
||||
* summary: Delete a question (soft delete)
|
||||
* tags: [Questions]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: id
|
||||
* required: true
|
||||
* schema:
|
||||
* type: integer
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Question deleted successfully
|
||||
* 401:
|
||||
* $ref: '#/components/responses/UnauthorizedError'
|
||||
* 403:
|
||||
* $ref: '#/components/responses/ForbiddenError'
|
||||
* 404:
|
||||
* $ref: '#/components/responses/NotFoundError'
|
||||
*/
|
||||
// Apply admin rate limiter to all routes
|
||||
router.use(adminLimiter);
|
||||
|
||||
router.put('/users/:userId/role', verifyToken, isAdmin, adminController.updateUserRole);
|
||||
router.put('/users/:userId/activate', verifyToken, isAdmin, adminController.reactivateUser);
|
||||
router.delete('/users/:userId', verifyToken, isAdmin, adminController.deactivateUser);
|
||||
router.get('/questions', verifyToken, isAdmin, questionController.getAllQuestions);
|
||||
router.get('/questions/:id', verifyToken, isAdmin, questionController.getQuestionByIdAdmin);
|
||||
router.post('/questions', verifyToken, isAdmin, questionController.createQuestion);
|
||||
router.put('/questions/:id', verifyToken, isAdmin, questionController.updateQuestion);
|
||||
router.delete('/questions/:id', verifyToken, isAdmin, questionController.deleteQuestion);
|
||||
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user