Skip to content

Backend schema change - #121

Open
Priyamanjare54 wants to merge 4 commits into
tarinagarwal:mainfrom
Priyamanjare54:database-schema-change
Open

Backend schema change#121
Priyamanjare54 wants to merge 4 commits into
tarinagarwal:mainfrom
Priyamanjare54:database-schema-change

Conversation

@Priyamanjare54

@Priyamanjare54 Priyamanjare54 commented Jan 17, 2026

Copy link
Copy Markdown

📝 Description

Implemented full Labs CRUD functionality with authentication and authorization.Fixes #58

Key highlights:

  • Added Create, Read, Update, Delete APIs for Labs
  • Secured routes using JWT-based authentication
  • Ensured only the creator can update/delete their lab
  • Fixed MongoDB connection to support Prisma transactions using a replica set
  • Verified protected endpoints using Bearer token flow

This completes the Labs module backend functionality and prepares it for frontend integration.


🔗 Related Issue

Closes: N/A


🏷️ Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (fix or feature that would cause existing functionality to change)
  • 📝 Documentation update
  • 🎨 Style/UI update
  • ♻️ Code refactoring
  • ⚡ Performance improvement
  • 🧪 Test update

📸 Screenshots (if applicable)

N/A (Backend-only changes)


✅ Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have tested my changes locally
  • Any dependent changes have been merged and published

🧪 Testing

How I tested:

  • Generated JWT token via login

  • Tested protected endpoints using Authorization header

  • Verified ownership checks for update/delete

  • Confirmed Prisma works with MongoDB replica set

  • Tested API endpoints (Postman)

  • Tested on Chrome

  • Tested on Firefox

  • Tested on mobile


📋 Additional Notes

  • MongoDB replica set was configured locally to support Prisma transactions.
  • All endpoints return correct HTTP status codes (201, 403, 404, etc.).
  • Ready for frontend consumption.

SWOC 2026 Participant
Please add the swoc2026 label to this PR 🎉

@tarinagarwal tarinagarwal left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work on the Labs CRUD implementation! The core functionality is solid. A few improvements needed:

1. Use existing Prisma instance
Replace const prisma = new PrismaClient(); with import prisma from "../db.js"; to use the existing connection.

2. Add input validation

  • Validate required fields (title, language, difficulty, etc.)
  • Validate enum values for difficulty ("beginner", "intermediate", "advanced")
  • Validate visibility ("private", "public", "link")

3. Add filters to GET /api/labs
Add query parameter support for filtering by language, difficulty, creator, etc.

4. Minor fixes

  • Add newline at end of schema.prisma file
  • Add basic validation for empty/invalid ObjectIds

5. Error handling
Add validation for invalid ObjectId format in route parameters.

The MongoDB adaptations and ObjectId usage are perfect for this setup. Core CRUD logic and auth checks look excellent!

@Priyamanjare54

Copy link
Copy Markdown
Author

Hello, @tarinagarwal
I've completed the changes for Backend schema change #121
Please review when you have time. Happy to address any feedback!

@Priyamanjare54

Copy link
Copy Markdown
Author

Hello @tarinagarwal please review the changes

@tarinagarwal

Copy link
Copy Markdown
Owner

@Priyamanjare54 going thru it

@Priyamanjare54

Copy link
Copy Markdown
Author

Hello any changes required?

@tarin-lgtm tarin-lgtm Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes Requested 🐈

This PR implements full CRUD functionality for Labs with JWT authentication and authorization. Review found critical performance issue due to missing pagination on GET /api/labs, multiple high-severity documentation gaps, and security concerns on unauthenticated GET endpoints. Additional improvements in validation, error handling, and code structure are recommended.

There are a few things I'd like to see addressed before we merge this:

Before merging

  1. Add pagination and limit to GET /api/labs endpoint to prevent performance degradation.
  2. Provide comprehensive API documentation for all Labs routes including methods, parameters, responses, authentication, and error handling.
  3. Implement authentication and authorization checks on GET endpoints and sanitize user inputs to mitigate security risks.
Findings breakdown (33 total)

1 critical / 6 high / 8 medium / 11 low / 7 info

Confidence: 95%


🔗 View Full Review Report — detailed findings, severity breakdown, and agent analysis

Reviewed by Looks Good To Meow — AI-powered code review


💬 You can interact with me directly in this PR:

  • @tarin-lgtm fix [any constraints]
  • @tarin-lgtm explain [your question]
  • @tarin-lgtm improve [focus area]
  • @tarin-lgtm test [what to focus on]

Comment thread server/routes/labs.js
});

// --- GET ALL Labs ---
router.get("/", async (req, res) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 Critical — The GET /api/labs endpoint fetches all labs without any pagination or limit, potentially returning a very large dataset which can degrade performance and increase memory usage.

Implement pagination by accepting page and limit query parameters and use Prisma's skip and take options to limit the number of labs returned per request.

performance

Comment thread server/routes/labs.js
@@ -0,0 +1,199 @@
import express from "express";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ High — The Express router defines multiple API endpoints for labs but lacks any documentation describing the HTTP methods, paths, request body schemas, response schemas, authentication requirements, or error responses.

Add comprehensive JSDoc or API documentation comments above each route handler describing the endpoint's purpose, HTTP method, URL path, expected request parameters and body schema, response format, authentication requirements, and possible error responses.

documentation

Comment thread server/routes/labs.js
const ALLOWED_VISIBILITY = ["private", "public", "link"];

// --- CREATE Lab ---
router.post("/", authenticateToken, async (req, res) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ High — The POST /api/labs endpoint for creating a lab is missing documentation including description, request body schema, response schema, authentication, and error responses.

Add JSDoc or API documentation for this endpoint specifying it is a POST request to create a lab, detailing required and optional fields in the request body, authentication via JWT, the structure of the success response, and possible error responses with status codes.

documentation

Comment thread server/routes/labs.js
});

// --- GET ALL Labs ---
router.get("/", async (req, res) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ High — The GET /api/labs endpoint for fetching all labs is undocumented. It lacks details on query parameters, response schema, and error handling.

Add documentation describing this GET endpoint, including optional query parameters (language, difficulty, creator), the structure of the returned labs array, and error responses.

documentation

Comment thread server/routes/labs.js
});

// --- GET SINGLE Lab ---
router.get("/:id", async (req, res) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ High — The GET /api/labs/:id endpoint for fetching a single lab by ID is undocumented. Missing details on path parameter, response schema, and error cases.

Add documentation specifying this GET endpoint accepts a lab ID as a path parameter, returns the lab object with related data, and possible error responses for invalid ID or not found.

documentation

Comment thread server/routes/labs.js
return res.status(400).json({ error: "Invalid visibility value" });
}

const lab = await prisma.lab.update({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Suggestion — The PUT /:id route does not handle the case where no fields are provided for update, which may cause Prisma to update with undefined values.

Filter out undefined fields from the update data before passing to Prisma to avoid overwriting fields with undefined.

best-practices

Comment thread server/routes/labs.js

if (existing.creatorId !== req.user.id) return res.status(403).json({ error: "Forbidden" });

await prisma.lab.delete({ where: { id } });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Suggestion — The DELETE /:id route returns a JSON message on success but does not set an explicit HTTP status code. The default 200 is acceptable but 204 No Content is more conventional for successful deletes.

Consider returning status 204 No Content with no body for successful DELETE requests to align with REST conventions.

best-practices

Comment thread server/routes/labs.js
});

// --- UPDATE Lab ---
router.put("/:id", authenticateToken, async (req, res) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Suggestion — The PUT /api/labs/:id endpoint updates lab fields without sanitizing or validating string inputs such as title, description, content, tasks, testCases, and solution. This could lead to stored XSS if these fields are rendered in a client without proper escaping.

Implement input sanitization or escaping for user-supplied string fields before storing them in the database. Additionally, consider validating the structure and content of complex fields like tasks and testCases.

security

Comment thread server/routes/labs.js
visibility,
} = req.body;

if (difficulty && !ALLOWED_DIFFICULTIES.includes(difficulty)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Suggestion — In the UPDATE Lab route, the difficulty validation returns a generic error without listing allowed values, unlike the CREATE Lab route which provides allowed values for better client feedback.

Include the allowedValues array in the error response for consistency and better client-side validation feedback.

bugs

Comment thread server/routes/labs.js
return res.status(400).json({ error: "Invalid difficulty value" });
}

if (visibility && !ALLOWED_VISIBILITY.includes(visibility)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Suggestion — In the UPDATE Lab route, the visibility validation returns a generic error without listing allowed values, unlike the CREATE Lab route which provides allowed values for better client feedback.

Include the allowedValues array in the error response for consistency and better client-side validation feedback.

bugs

@tarin-lgtm tarin-lgtm Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes Requested 🐈

PR #121 adds Labs CRUD APIs with JWT auth and creator-only update/delete, plus a Prisma/Mongo replica set connection fix. Review flags several high-severity problems in server/routes/labs.js including a malformed/misaligned Prisma include block (potential runtime failure) and missing rate limiting, pagination, and endpoint documentation for state-changing and listing endpoints.

There are a few things I'd like to see addressed before we merge this:

Before merging

  1. Fix the malformed Prisma include block / any likely syntax or brace/indentation issues in server/routes/labs.js (validate route loads and queries are correct).
  2. Add rate limiting (and ideally abuse controls) to authenticated state-changing endpoints: POST /labs, PUT /labs/:id, DELETE /labs/:id.
  3. Add pagination/limits for GET /api/labs and reduce eager relational includes; also fill in missing validation and endpoint documentation (request/response, auth rules, error cases).

Findings

🎯 6 actionable · 💡 4 suggestions

Severity breakdown (23 total)

6 high / 13 medium / 4 low

Confidence: 93%


🔗 View Full Review Report — detailed findings, severity breakdown, and agent analysis

Reviewed by Looks Good To Meow — AI-powered code review

Comment thread server/routes/labs.js
if (difficulty) where.difficulty = difficulty;
if (creator) where.creatorId = creator;

const labs = await prisma.lab.findMany({

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Actionable — High — The include block is malformed: progress: true is indented inconsistently and there’s a missing closing brace/parenthesis alignment, which can cause a runtime syntax error or incorrect query structure.

Fix the indentation/bracing so the include object is correctly closed before ending the findMany call.

Flagged by: best-practices, bugs, performance, readability

Comment thread server/routes/labs.js

if (existing.creatorId !== req.user.id) return res.status(403).json({ error: "Forbidden" });

const {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Actionable — High — The update handler has inconsistent indentation around destructuring and const lab = await prisma.lab.update...; while not strictly semantic, this commonly indicates a missing brace/semicolon or mis-scoped block that can prevent the server from loading the route.

Reformat and verify all braces are balanced in the PUT /:id handler, ensuring the destructuring and update call are inside the try block.

Flagged by: best-practices, bugs, readability

Comment thread server/routes/labs.js
const ALLOWED_VISIBILITY = ["private", "public", "link"];

// --- CREATE Lab ---
router.post("/", authenticateToken, async (req, res) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Actionable — High — The new lab creation endpoint accepts authenticated requests but has no rate limiting. An attacker with a valid token (or via token theft) could repeatedly create labs and cause storage/compute exhaustion in the database.

Flagged by: documentation, security

Comment thread server/routes/labs.js
});

// --- DELETE Lab ---
router.delete("/:id", authenticateToken, async (req, res) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Actionable — High — The new DELETE lab endpoint is authenticated but has no rate limiting. With a valid token, an attacker could rapidly delete resources causing denial of service and integrity damage.

Flagged by: documentation, security

Comment thread server/routes/labs.js
});

// --- UPDATE Lab ---
router.put("/:id", authenticateToken, async (req, res) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Actionable — High — The new lab update endpoint is authenticated but has no rate limiting. With a valid token, an attacker could repeatedly update labs to degrade service availability and increase database write load.

Flagged by: documentation, security

Comment thread server/routes/labs.js
});

// --- GET ALL Labs ---
router.get("/", async (req, res) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Actionable — High — GET /api/labs returns an unbounded list of labs with no limit/offset (or cursor) controls. Under real usage, this can cause large payloads and slow database response times as the dataset grows.

Add pagination parameters (e.g., limit/offset or cursor) and apply them to prisma.lab.findMany; also consider selecting only needed fields and/or adding default sorting.

Flagged by: best-practices, documentation, performance

Comment thread server/routes/labs.js
return res.status(400).json({
error: "Invalid visibility value",
allowedValues: ALLOWED_VISIBILITY,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Suggestion — Mediumvisibility is validated only if truthy; this means an empty string bypasses validation but is still stored (or overwritten) with '', which may not match the intended enum values.

Validate visibility whenever the field is present in the request body (e.g., check visibility !== undefined), and reject empty strings.

Flagged by: bugs

Comment thread server/routes/labs.js
visibility,
} = req.body;

if (difficulty && !ALLOWED_DIFFICULTIES.includes(difficulty)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Suggestion — Medium — In the update route, the enum validation also only runs when visibility/difficulty are truthy, so difficulty: '' or visibility: '' will bypass validation and be written to the database.

Change the conditionals to validate when the key is provided (e.g., difficulty !== undefined) rather than when it’s truthy.

Flagged by: bugs, readability

Comment thread server/routes/labs.js
const router = express.Router();


const ALLOWED_DIFFICULTIES = ["beginner", "intermediate", "advanced"];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Suggestion — Medium — The route imports/exports are fine, but there are multiple indentation/formatting inconsistencies (e.g., uneven alignment around required fields and include blocks) that make reviews harder and increase the chance of introducing subtle syntax errors later.

Flagged by: best-practices

Comment thread server/routes/labs.js
});

// --- GET SINGLE Lab ---
router.get("/:id", async (req, res) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Suggestion — Medium — GET /api/labs/:id returns a lab with creator/shares/progress included, but there is no documentation for access control/visibility rules (especially for private/link labs) or response schema. This is non-obvious given the include fields and the presence of a custom ObjectId validator.

Document GET /api/labs/:id access rules (auth/visibility), required/optional response fields (including nested relations: creator, shares, progress), and explicit error responses (400 invalid ID, 404 not found, 500).

Flagged by: documentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AI Labs (1/6): Database Schema & Basic API

2 participants