Skip to content

Latest commit

 

History

History
262 lines (236 loc) · 9.2 KB

File metadata and controls

262 lines (236 loc) · 9.2 KB

📚 API Documentation – Placement Test Platform Backend

Welcome to the backend API documentation for the AI-Powered Placement Test Platform. This backend is built using Node.js, Express.js, and Mongoose (MongoDB). It communicates with OpenAI to dynamically generate questions and auto-grade responses, secured with Clerk Authentication.


🔒 Authentication & Role-Based Access Control (RBAC)

Authentication is handled securely via Clerk. Every protected route expects a Clerk Session JWT passed in the HTTP headers:

Authorization: Bearer <clerk_session_jwt>

Roles:

  • Student: Default authenticated user role. Allowed to sync their profile, generate tests, and submit answers.
  • Admin: Users with "role": "admin" in their Clerk publicMetadata. Allowed to access global test results and student performance dashboards.

📈 Base URL

  • Local Development: http://localhost:5000
  • Prefix: /api (all routes below are appended to this prefix, e.g., http://localhost:5000/api/auth/me)

🛠️ API Endpoint Reference

1. Authentication & Sync (/api/auth)

GET /api/auth/me

  • Description: Fetches session information for the currently authenticated user. When hit, it fetches user profile details from Clerk (first name, last name, email) and automatically creates or updates the user profile in MongoDB.
  • Authentication: Required (Student or Admin).
  • Request Headers:
    • Authorization: Bearer <clerk_session_jwt>
  • Response (200 OK):
    {
      "userId": "user_2tW6DaPXhQ6X8F3o...",
      "email": "student@example.com",
      "name": "Jane Doe",
      "hasTakenTest": false,
      "score": 0,
      "testDate": null,
      "publicMetadata": {
        "role": "student"
      },
      "isAdmin": false
    }
  • Error Responses:
    • 401 Unauthorized: Missing or malformed Authorization header, or invalid JWT.

2. Test Generation & Submission (/api/test)

GET /api/test/generate

  • Description: Generates exactly 10 interview questions (5 JavaScript, 5 Node.js) across different question types (MCQ, Output, UseCase, Theory, Code).
  • Idempotency: If the authenticated user has an active, unfinished test record in the database, this endpoint returns that existing record instead of generating a new one.
  • Rate Limiting: Restricted to a maximum of 2 generation requests per 24 hours per user (based on Clerk userId / IP).
  • Authentication: Required (Student or Admin).
  • Request Headers:
    • Authorization: Bearer <clerk_session_jwt>
  • Response (200 OK):
    {
      "testRecordId": "664fa7d39ef38b47cf29f55e",
      "questions": [
        {
          "qid": "q_1",
          "type": "MCQ",
          "questionText": "What is the output of console.log(typeof null) in JavaScript?",
          "options": ["string", "object", "null", "undefined"],
          "correctAnswer": "object"
        },
        {
          "qid": "q_2",
          "type": "Output",
          "questionText": "What does this code output?\n```js\nconst a = {};\nconst b = { key: 'b' };\nconst c = { key: 'c' };\na[b] = 123;\na[c] = 456;\nconsole.log(a[b]);\n```",
          "options": [],
          "correctAnswer": "456"
        }
        // ... 8 more questions
      ]
    }
  • Error Responses:
    • 429 Too Many Requests: Exceeded 2 test generations per 24-hour window.
    • 502 Bad Gateway: AI failed to generate exactly 10 questions or returned malformed JSON.

POST /api/test/submit

  • Description: Submits the user's answers to the active test record. The answers are sent to the OpenAI grading system which scores them (0-10) and provides detailed explanation/feedback for each question. The scores, answers, and feedbacks are persisted to the database and the User document is updated to mark hasTakenTest: true and record their score.
  • Authentication: Required (Student or Admin).
  • Request Headers:
    • Authorization: Bearer <clerk_session_jwt>
    • Content-Type: application/json
  • Request Body:
    {
      "testRecordId": "664fa7d39ef38b47cf29f55e",
      "answers": [
        {
          "questionId": "q_1",
          "answerText": "object"
        },
        {
          "questionId": "q_2",
          "answerText": "456"
        }
        // ... answers for remaining questions
      ]
    }
  • Response (200 OK):
    {
      "score": 9,
      "feedback": [
        {
          "questionId": "q_1",
          "isCorrect": true,
          "pointsAwarded": 1,
          "feedback": "Correct. 'typeof null' evaluates to 'object' due to a historical implementation bug in JavaScript."
        },
        {
          "questionId": "q_2",
          "isCorrect": true,
          "pointsAwarded": 1,
          "feedback": "Correct. Since objects are converted to strings when used as keys, both 'b' and 'c' serialize to '[object Object]', overwriting the value."
        }
        // ... feedback for remaining answers
      ]
    }
  • Error Responses:
    • 400 Bad Request: Missing testRecordId or answers array in the request body.
    • 404 Not Found: Test record not found or does not belong to the authenticated user.
    • 502 Bad Gateway: AI grading failed or returned a malformed response.

GET /api/test/history

  • Description: Fetches all completed test records (tasks, answers, and marks/score) for the currently authenticated user.
  • Authentication: Required (Student or Admin).
  • Request Headers:
    • Authorization: Bearer <clerk_session_jwt>
  • Response (200 OK):
    {
      "success": true,
      "data": [
        {
          "_id": "6a1379fef908f3e610b80972",
          "user": "user_3EBlpw7mMcIMmoaP6vLxnqWYMke",
          "questions": [
            {
              "qid": "q_1",
              "type": "MCQ",
              "questionText": "...",
              "options": ["...", "..."],
              "correctAnswer": "..."
            }
          ],
          "answers": [
            {
              "questionId": "q_1",
              "answerText": "...",
              "feedback": "...",
              "isCorrect": true,
              "pointsAwarded": 1
            }
          ],
          "finalScore": 2
        }
      ]
    }
  • Error Responses:
    • 401 Unauthorized: Missing or invalid session token.

3. Admin & Performance Management (/api/admin)

GET /api/admin/results

  • Description: Retrieves a list of all registered users in MongoDB, and aggregates all of their test records (completed and in-progress). This is designed to populate admin dashboard tables.
  • Authentication: Required. User must have Admin role (role === 'admin' in Clerk public metadata).
  • Request Headers:
    • Authorization: Bearer <clerk_session_jwt>
  • Response (200 OK):
    {
      "success": true,
      "data": [
        {
          "_id": "user_2tW6DaPXhQ6X8F3o...",
          "name": "Jane Doe",
          "email": "student@example.com",
          "hasTakenTest": true,
          "score": 9,
          "testDate": "2026-05-24T18:25:34.123Z",
          "testRecords": [
            {
              "_id": "664fa7d39ef38b47cf29f55e",
              "user": "user_2tW6DaPXhQ6X8F3o...",
              "questions": [ ... ],
              "answers": [
                {
                  "questionId": "q_1",
                  "answerText": "object",
                  "feedback": "Correct. ...",
                  "isCorrect": true,
                  "pointsAwarded": 1,
                  "_id": "664fa82c9ef38b47cf29f560"
                }
                // ... answers
              ],
              "finalScore": 9,
              "createdAt": "2026-05-24T18:20:01.000Z",
              "updatedAt": "2026-05-24T18:25:34.123Z"
            }
          ]
        }
      ]
    }
  • Error Responses:
    • 401 Unauthorized: Missing or invalid session token.
    • 403 Forbidden: Authenticated user is not an Admin.

🗂️ Database Schemas (MongoDB / Mongoose)

User Schema (models/User.js)

Stores the synced Clerk profile and placement test metadata.

  • _id (String): Clerk User ID (e.g. user_...).
  • name (String, Required): User's display name.
  • email (String, Required, Unique): User's primary email.
  • hasTakenTest (Boolean, Default: false): Tracks if the user has submitted at least one test.
  • score (Number, Default: 0): The score of the most recently submitted test.
  • testDate (Date): Timestamp of the last test submission.

TestRecord Schema (models/TestRecord.js)

Stores individual test attempts, including generated questions, user answers, and AI feedback.

  • user (String, Ref: 'User', Required): Reference to the User ID.
  • questions (Array of questionSchema):
    • qid (String): Short identifier (e.g., q_1, q_2).
    • type (String): Question type (MCQ, Output, UseCase, Theory, Code).
    • questionText (String): Prompt displayed to the user.
    • options (Array of String): Available choices (only for MCQ).
    • correctAnswer (String): Ideal answer used for grading.
  • answers (Array of answerSchema):
    • questionId (String): Reference to the generated question's qid.
    • answerText (String): User's response.
    • feedback (String): Detailed explanation generated by OpenAI.
    • isCorrect (Boolean): Correctness flag.
    • pointsAwarded (Number): 0 or 1.
  • finalScore (Number, Default: 0): Total points awarded (out of 10).