const express = require('express'); const router = express.Router(); const quizController = require('../controllers/quiz.controller'); const { verifyToken } = require('../middleware/auth.middleware'); const { verifyGuestToken } = require('../middleware/guest.middleware'); const { quizLimiter } = require('../middleware/rateLimiter'); /** * Middleware to handle both authenticated users and guests * Tries user auth first, then guest auth */ const authenticateUserOrGuest = async (req, res, next) => { // Try to verify user token first const authHeader = req.headers['authorization']; if (authHeader && authHeader.startsWith('Bearer ')) { try { await new Promise((resolve, reject) => { verifyToken(req, res, (err) => { if (err) reject(err); else resolve(); }); }); if (req.user) { return next(); } } catch (error) { // User auth failed, continue to guest auth } } // Try to verify guest token const guestToken = req.headers['x-guest-token']; console.log(guestToken); if (guestToken) { try { await new Promise((resolve, reject) => { verifyGuestToken(req, res, (err) => { if (err) reject(err); else resolve(); }); }); if (req.guestId) { return next(); } } catch (error) { // Guest auth also failed } } // Neither authentication method worked return res.status(401).json({ success: false, message: 'Authentication required. Please login or start a guest session.' }); }; /** * @swagger * /quiz/start: * post: * summary: Start a new quiz session * description: Can be used by authenticated users or guest users * tags: [Quiz] * security: * - bearerAuth: [] * parameters: * - in: header * name: x-guest-token * schema: * type: string * format: uuid * description: Guest session token (for guest users) * requestBody: * required: true * content: * application/json: * schema: * type: object * required: * - categoryId * properties: * categoryId: * type: integer * description: Category ID for the quiz * example: 1 * questionCount: * type: integer * minimum: 1 * maximum: 50 * default: 10 * description: Number of questions in quiz * difficulty: * type: string * enum: [easy, medium, hard, mixed] * default: mixed * quizType: * type: string * enum: [practice, timed, exam] * default: practice * responses: * 201: * description: Quiz session started successfully * content: * application/json: * schema: * type: object * properties: * message: * type: string * session: * $ref: '#/components/schemas/QuizSession' * currentQuestion: * $ref: '#/components/schemas/Question' * 401: * $ref: '#/components/responses/UnauthorizedError' * 404: * description: Category not found * * /quiz/submit: * post: * summary: Submit an answer for a quiz question * tags: [Quiz] * security: * - bearerAuth: [] * parameters: * - in: header * name: x-guest-token * schema: * type: string * format: uuid * requestBody: * required: true * content: * application/json: * schema: * type: object * required: * - quizSessionId * - questionId * - userAnswer * properties: * quizSessionId: * type: integer * questionId: * type: integer * userAnswer: * type: string * timeSpent: * type: integer * description: Time spent on question in seconds * responses: * 200: * description: Answer submitted successfully * 401: * $ref: '#/components/responses/UnauthorizedError' * 404: * description: Session or question not found * * /quiz/complete: * post: * summary: Complete a quiz session and get final results * tags: [Quiz] * security: * - bearerAuth: [] * parameters: * - in: header * name: x-guest-token * schema: * type: string * format: uuid * requestBody: * required: true * content: * application/json: * schema: * type: object * required: * - sessionId * properties: * sessionId: * type: integer * responses: * 200: * description: Quiz completed successfully * 401: * $ref: '#/components/responses/UnauthorizedError' * 404: * description: Session not found * * /quiz/session/{sessionId}: * get: * summary: Get quiz session details with questions and answers * tags: [Quiz] * security: * - bearerAuth: [] * parameters: * - in: path * name: sessionId * required: true * schema: * type: integer * - in: header * name: x-guest-token * schema: * type: string * format: uuid * responses: * 200: * description: Session details retrieved successfully * content: * application/json: * schema: * $ref: '#/components/schemas/QuizSession' * 401: * $ref: '#/components/responses/UnauthorizedError' * 404: * $ref: '#/components/responses/NotFoundError' * * /quiz/review/{sessionId}: * get: * summary: Review completed quiz with all answers and explanations * tags: [Quiz] * security: * - bearerAuth: [] * parameters: * - in: path * name: sessionId * required: true * schema: * type: integer * - in: header * name: x-guest-token * schema: * type: string * format: uuid * responses: * 200: * description: Quiz review retrieved successfully * 401: * $ref: '#/components/responses/UnauthorizedError' * 404: * $ref: '#/components/responses/NotFoundError' */ router.post('/start', quizLimiter, authenticateUserOrGuest, quizController.startQuizSession); router.post('/submit', authenticateUserOrGuest, quizController.submitAnswer); router.post('/complete', authenticateUserOrGuest, quizController.completeQuizSession); router.get('/session/:sessionId', authenticateUserOrGuest, quizController.getSessionDetails); router.get('/review/:sessionId', authenticateUserOrGuest, quizController.reviewQuizSession); module.exports = router;