250 lines
7.2 KiB
JavaScript
250 lines
7.2 KiB
JavaScript
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'];
|
|
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;
|