-
Notifications
You must be signed in to change notification settings - Fork 44
feat: implement comment API routes #132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
feat: implement comment API routes #132
Conversation
WalkthroughAdds four Comment API routes: POST /api/comment/create, GET /api/comment/find-by-payout/[payout_id], PATCH /api/comment/update/[id], and DELETE /api/comment/delete/[id]. Each route validates input, checks existence/ownership (User, Payout), performs DB operations, returns structured JSON, and centralizes database error mapping. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Client
participant API
participant DB
rect rgba(200,230,255,0.25)
note over Client,API: Create Comment (POST /api/comment/create)
Client->>API: POST { message, user_id, payout_id }
API->>DB: SELECT user WHERE id=user_id
DB-->>API: user | 404 if missing
API->>DB: SELECT payout WHERE id=payout_id
DB-->>API: payout | 404 if missing
API->>DB: INSERT comment (link user+payout)
DB-->>API: comment (with user fields)
API-->>Client: 201 { success, comment }
end
rect rgba(220,255,220,0.18)
note over Client,API: Get by Payout (GET /comment/find-by-payout/:payout_id)
Client->>API: GET payout_id
API->>DB: SELECT payout WHERE id=payout_id
DB-->>API: payout | 404 if missing
API->>DB: SELECT comments WHERE payout_id ORDER BY created_at ASC INCLUDE user
DB-->>API: comments[]
API-->>Client: 200 { success, comments, count }
end
rect rgba(255,245,200,0.18)
note over Client,API: Update Comment (PATCH /comment/update/:id)
Client->>API: PATCH { id, user_id, message }
API->>DB: SELECT comment WHERE id
DB-->>API: comment | 404 if missing
API->>DB: Verify owner (comment.user_id == user_id) -> 403 if not
API->>DB: UPDATE comment.message
DB-->>API: updated comment (with user fields)
API-->>Client: 200 { success, comment }
end
rect rgba(255,225,225,0.18)
note over Client,API: Delete Comment (DELETE /comment/delete/:id)
Client->>API: DELETE { id, user_id }
API->>DB: SELECT comment WHERE id
DB-->>API: comment | 404 if missing
API->>DB: Verify owner -> 403 if not
API->>DB: DELETE comment
DB-->>API: OK
API-->>Client: 200 { success, message }
end
alt DB error or invalid input
API-->>Client: 400/4xx/5xx with mapped error via handleDatabaseError
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Nitpick comments (12)
src/app/api/(comment)/comment/find-by-payout/[payout_id]/route.ts (3)
17-22: Tighten param validation; drop string-literal checks.
"undefined"/"null"string checks aren’t useful for route params. Validate presence and shape (uuid/cuid) and return 400 on failure.Example:
- if (!payout_id || payout_id === "undefined" || payout_id === "null") { + if (!payout_id?.trim()) { return NextResponse.json( { error: "Invalid payout_id parameter" }, { status: 400 } ); }Optionally add Zod validation (uuid/cuid) for
payout_id.
8-10: Make response freshness explicit (avoid unintended caching).If comments must always be fresh, mark this route dynamic (or set
Cache-Control: no-store). Next.js 15 changed GET Route Handler caching defaults; be explicit.import { handleDatabaseError, prisma } from "@/lib/prisma"; import { NextResponse } from "next/server"; +export const dynamic = "force-dynamic";Based on learnings.
37-51: DB indexes for query path (payout_id, created_at).This query filters by
payout_idand orders bycreated_at. Ensure a composite index(payout_id, created_at)exists to avoid scans on large tables.src/app/api/(comment)/comment/update/[id]/route.ts (3)
19-21: Return 400 on invalid JSON; don’t map it as a DB error.If
request.json()fails, it hits the catch and becomes a 500 “Database error”. Handle parse errors explicitly.- const body = await request.json(); + let body: unknown; + try { + body = await request.json(); + } catch { + return NextResponse.json({ error: "Invalid JSON body" }, { status: 400 }); + }
13-19: Validate route param shape (uuid/cuid) before querying.Add a quick Zod check for
idto fail fast with 400 instead of a DB round trip.
31-39: Minor: prefer const + destructuring.
s/user_idisn’t reassigned; useconst { user_id } = body as { user_id?: string };.src/app/api/(comment)/comment/delete/[id]/route.ts (3)
18-19: Return 400 on invalid JSON; don’t treat as DB error.Guard
request.json()with a try/catch and return 400 on parse failure.- const body = await request.json(); + let body: unknown; + try { + body = await request.json(); + } catch { + return NextResponse.json({ error: "Invalid JSON body" }, { status: 400 }); + }
20-25: Simplify/strengthen ID validation.Drop
"undefined"/"null"string checks; validate presence and format (uuid/cuid) and return 400 if invalid.
12-15: Note: DELETE bodies can be brittle across clients.Some clients/proxies strip DELETE bodies. If feasible, derive user from auth and avoid needing a request body here.
src/app/api/(comment)/comment/create/route.ts (3)
13-21: Return 400 on invalid JSON; don’t let parse errors become 500.- const body = await request.json(); - const parsed = commentCreateSchema.safeParse(body); + let body: unknown; + try { + body = await request.json(); + } catch { + return NextResponse.json({ error: "Invalid JSON body" }, { status: 400 }); + } + const parsed = commentCreateSchema.safeParse(body);
46-53: Minor: avoid selecting unused fields.
statusandcreated_byaren’t used. Drop them to reduce payload/compute.- select: { - payout_id: true, - status: true, - created_by: true - } + select: { payout_id: true }
63-79: Operational: add/confirm indexes.Comment creation and listing will benefit from indexes on
(payout_id, created_at)and(user_id, created_at). Add a migration if not present.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/app/api/(comment)/comment/create/route.ts(1 hunks)src/app/api/(comment)/comment/delete/[id]/route.ts(1 hunks)src/app/api/(comment)/comment/find-by-payout/[payout_id]/route.ts(1 hunks)src/app/api/(comment)/comment/update/[id]/route.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/frontend-rule.mdc)
**/*.{js,jsx,ts,tsx}: Use early returns whenever possible to make the code more readable.
Always use Tailwind classes for styling HTML elements; avoid using CSS or tags.
Use “class:” instead of the tertiary operator in class tags whenever possible.
Use descriptive variable and function/const names. Also, event functions should be named with a “handle” prefix, like “handleClick” for onClick and “handleKeyDown” for onKeyDown.
Implement accessibility features on elements. For example, a tag should have a tabindex=“0”, aria-label, on:click, and on:keydown, and similar attributes.
Everything must be 100% responsive (using all the sizes of tailwind) and compatible with dark/light shadcn's mode.
Use consts instead of functions, for example, “const toggle = () =>”. Also, define a type if possible.
Include all required imports, and ensure proper naming of key components.
**/*.{js,jsx,ts,tsx}: enum/const object members should be written UPPERCASE_WITH_UNDERSCORE.
Gate flag-dependent code on a check that verifies the flag's values are valid and expected.
If a custom property for a person or event is at any point referenced in two or more files or two or more callsites in the same file, use an enum or const object, as above in feature flags.
Files:
src/app/api/(comment)/comment/find-by-payout/[payout_id]/route.tssrc/app/api/(comment)/comment/create/route.tssrc/app/api/(comment)/comment/delete/[id]/route.tssrc/app/api/(comment)/comment/update/[id]/route.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/frontend-rule.mdc)
You can never use anys.
If using TypeScript, use an enum to store flag names.
Files:
src/app/api/(comment)/comment/find-by-payout/[payout_id]/route.tssrc/app/api/(comment)/comment/create/route.tssrc/app/api/(comment)/comment/delete/[id]/route.tssrc/app/api/(comment)/comment/update/[id]/route.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/posthog-integration.mdc)
Never hallucinate an API key. Instead, always use the API key populated in the .env file.
Files:
src/app/api/(comment)/comment/find-by-payout/[payout_id]/route.tssrc/app/api/(comment)/comment/create/route.tssrc/app/api/(comment)/comment/delete/[id]/route.tssrc/app/api/(comment)/comment/update/[id]/route.ts
🧬 Code graph analysis (4)
src/app/api/(comment)/comment/find-by-payout/[payout_id]/route.ts (2)
src/lib/prisma.ts (2)
prisma(7-19)handleDatabaseError(24-60)src/app/api/(payout)/payout/find-one/[id]/route.ts (1)
GET(4-29)
src/app/api/(comment)/comment/create/route.ts (2)
src/components/modules/comment/schema/comment.schema.ts (1)
commentCreateSchema(3-14)src/lib/prisma.ts (2)
prisma(7-19)handleDatabaseError(24-60)
src/app/api/(comment)/comment/delete/[id]/route.ts (1)
src/lib/prisma.ts (2)
prisma(7-19)handleDatabaseError(24-60)
src/app/api/(comment)/comment/update/[id]/route.ts (2)
src/components/modules/comment/schema/comment.schema.ts (1)
commentUpdateSchema(16-21)src/lib/prisma.ts (2)
prisma(7-19)handleDatabaseError(24-60)
src/app/api/(comment)/comment/find-by-payout/[payout_id]/route.ts
Outdated
Show resolved
Hide resolved
|
Let me know if you consider the changes suggested by coderabbit are needed! |
|
Fixed 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/app/api/(comment)/comment/update/[id]/route.ts (1)
33-41: Past critical issue resolved: now uses server-side session authentication.This implementation correctly addresses the IDOR vulnerability flagged in the previous review. The code now derives the authenticated user from the server-side Supabase session instead of trusting
body.user_id, eliminating the spoofing risk.
Note: Consider migrating from deprecated auth package.
The learnings indicate
@supabase/auth-helpers-nextjsis deprecated in favor of@supabase/ssr. While the current implementation follows established project patterns correctly, consider planning a codebase-wide migration to the recommended package.Based on learnings
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (4)
src/app/api/(comment)/comment/create/route.ts(1 hunks)src/app/api/(comment)/comment/delete/[id]/route.ts(1 hunks)src/app/api/(comment)/comment/find-by-payout/[payout_id]/route.ts(1 hunks)src/app/api/(comment)/comment/update/[id]/route.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- src/app/api/(comment)/comment/find-by-payout/[payout_id]/route.ts
- src/app/api/(comment)/comment/delete/[id]/route.ts
- src/app/api/(comment)/comment/create/route.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/frontend-rule.mdc)
**/*.{js,jsx,ts,tsx}: Use early returns whenever possible to make the code more readable.
Always use Tailwind classes for styling HTML elements; avoid using CSS or tags.
Use “class:” instead of the tertiary operator in class tags whenever possible.
Use descriptive variable and function/const names. Also, event functions should be named with a “handle” prefix, like “handleClick” for onClick and “handleKeyDown” for onKeyDown.
Implement accessibility features on elements. For example, a tag should have a tabindex=“0”, aria-label, on:click, and on:keydown, and similar attributes.
Everything must be 100% responsive (using all the sizes of tailwind) and compatible with dark/light shadcn's mode.
Use consts instead of functions, for example, “const toggle = () =>”. Also, define a type if possible.
Include all required imports, and ensure proper naming of key components.
**/*.{js,jsx,ts,tsx}: enum/const object members should be written UPPERCASE_WITH_UNDERSCORE.
Gate flag-dependent code on a check that verifies the flag's values are valid and expected.
If a custom property for a person or event is at any point referenced in two or more files or two or more callsites in the same file, use an enum or const object, as above in feature flags.
Files:
src/app/api/(comment)/comment/update/[id]/route.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/frontend-rule.mdc)
You can never use anys.
If using TypeScript, use an enum to store flag names.
Files:
src/app/api/(comment)/comment/update/[id]/route.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/posthog-integration.mdc)
Never hallucinate an API key. Instead, always use the API key populated in the .env file.
Files:
src/app/api/(comment)/comment/update/[id]/route.ts
🧬 Code graph analysis (1)
src/app/api/(comment)/comment/update/[id]/route.ts (2)
src/components/modules/comment/schema/comment.schema.ts (1)
commentUpdateSchema(16-21)src/lib/prisma.ts (2)
prisma(7-19)handleDatabaseError(24-60)
🔇 Additional comments (5)
src/app/api/(comment)/comment/update/[id]/route.ts (5)
19-31: LGTM!Request parsing and validation logic is correct. Using
safeParsewith detailed error responses provides good developer experience.
43-55: LGTM!Comment existence check is properly implemented with efficient field selection and appropriate 404 response.
57-60: LGTM!Authorization check correctly compares the authenticated user's ID from the session against the comment owner's ID, completing the fix for the IDOR vulnerability. The 403 status is appropriate for authorization failures.
62-76: LGTM!Update operation correctly modifies only the message field and includes the user relation with appropriate field selection for API response consistency.
78-86: LGTM!Response structure and error handling follow established patterns. Proper delegation to
handleDatabaseErrorensures consistent error responses across the API.
| /** | ||
| * PATCH /api/comment/update/[id] | ||
| * Update an existing comment (only author can edit) | ||
| * | ||
| * Params: { id: string } | ||
| * Body: { message: string, user_id: string } | ||
| * Returns: { success: boolean, comment: Comment, message: string } | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update JSDoc to reflect actual request body.
The JSDoc states Body: { message: string, user_id: string } but user_id is no longer accepted in the request body—it's now derived from the authenticated session. This outdated documentation could mislead API consumers.
Apply this diff to correct the documentation:
/**
* PATCH /api/comment/update/[id]
* Update an existing comment (only author can edit)
*
* Params: { id: string }
- * Body: { message: string, user_id: string }
+ * Body: { message: string }
* Returns: { success: boolean, comment: Comment, message: string }
*/📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /** | |
| * PATCH /api/comment/update/[id] | |
| * Update an existing comment (only author can edit) | |
| * | |
| * Params: { id: string } | |
| * Body: { message: string, user_id: string } | |
| * Returns: { success: boolean, comment: Comment, message: string } | |
| */ | |
| /** | |
| * PATCH /api/comment/update/[id] | |
| * Update an existing comment (only author can edit) | |
| * | |
| * Params: { id: string } | |
| * Body: { message: string } | |
| * Returns: { success: boolean, comment: Comment, message: string } | |
| */ |
🤖 Prompt for AI Agents
In src/app/api/(comment)/comment/update/[id]/route.ts around lines 1 to 8, the
JSDoc incorrectly lists the request body as { message: string, user_id: string }
even though user_id is now derived from the authenticated session; update the
comment to remove user_id from the Body section (e.g., Body: { message: string
}) and add a short note that the user is taken from the authenticated session so
consumers know not to send user_id.
|
hey @coxmars, could you review this? |
Pull Request | GrantChain
1. Issue Link
2. Brief Description of the Issue
Implemented the API routes for comments: added create (POST), find by payout (GET), update (PATCH) and delete (DELETE).
These work in a way so that the comments can only be edited or deleted by their creator. Also, comments have a user_id and payout_id.
3. Type of Change
Mark with an
xall the checkboxes that apply (like[x]).4. Changes Made
Implemented comment API Routes: CRUD functionality.
Added proper error handling.
When doing find-by-payout, comments are ordered chronologically.
5. Evidence Before Solution
No UI Change.
6. Evidence After Solution
No UI Change.
7. Important Notes
Any feedback/suggestion is greatly appreciated! Thanks for reviewing this PR.
If you don't use this template, you'd be ignored
Summary by CodeRabbit