ENG-1909 Add no-op Next.js content upsert endpoint#1220
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
4cd8e3f to
7fc6f80
Compare
7fc6f80 to
d43d61e
Compare
1127f9a to
284254a
Compare
615145c to
9445331
Compare
9445331 to
856b6fc
Compare
| const userId = await getAccountId(supabase); | ||
| if (userId === undefined) | ||
| return createApiResponse( | ||
| request, | ||
| asPostgrestFailure("Please login", "invalid", 401), | ||
| ); |
There was a problem hiding this comment.
🔴 Database errors during user account lookup crash the request instead of returning a formatted error
The user account lookup is performed outside the error-handling block (getAccountId(supabase) at apps/website/app/api/internal/space/[id]/content/route.ts:32) before the try-catch that starts at line 38, so a database failure during that lookup produces an unformatted 500 crash instead of a structured API error response.
Impact: Clients receive a raw server error instead of a JSON error message when the account database query fails.
Mechanism: getAccountId throws outside the try-catch scope
The getAccountId function at apps/website/app/utils/supabase/account.ts:20 explicitly throws when the database query errors:
if (accountReq.error) throw accountReq.error;
In the route handler, this call sits at line 32, while the try block that wraps the rest of the logic and calls handleRouteError only begins at line 38. Any PostgrestError thrown by the account lookup propagates as an unhandled exception.
The existing content route at apps/website/app/api/supabase/content/route.ts:43 wraps all logic inside its try-catch, making this new route inconsistent with the established pattern.
Prompt for agents
The getAccountId call at line 32 and its undefined-check at lines 33-37 are outside the try-catch block that starts at line 38. Since getAccountId can throw a PostgrestError (see account.ts:20), this call should be moved inside the try block so that handleRouteError can catch and format the error. Move the try statement (line 38) to before the getAccountId call (before line 32), so that lines 32-37 are inside the try-catch. This matches the pattern used in other API routes like apps/website/app/api/supabase/content/route.ts where all logic is inside the try-catch.
Was this helpful? React with 👍 or 👎 to provide feedback.
| const body = (await request.json()) as StandaloneCrossAppContent[]; | ||
| // TODO: Zed validator | ||
| const content = body | ||
| .map((c) => | ||
| crossAppStandaloneContentToDbContent( | ||
| { | ||
| ...c, | ||
| createdAt: new Date(c.createdAt), | ||
| modifiedAt: new Date(c.modifiedAt || c.createdAt), | ||
| }, | ||
| spaceId, | ||
| ), | ||
| ) | ||
| .filter((c) => c !== undefined); |
There was a problem hiding this comment.
🟨 No input validation on untrusted request body before database processing
The POST handler at apps/website/app/api/internal/space/[id]/content/route.ts:39 casts the raw JSON body with as StandaloneCrossAppContent[] without any runtime validation. Arbitrary JSON payloads are spread into objects and passed to the database RPC. While the database may reject some malformed data, missing fields or unexpected types could cause unexpected behavior or partial writes. The code itself acknowledges this gap with a // TODO: Zed validator comment.
Was this helpful? React with 👍 or 👎 to provide feedback.
https://linear.app/discourse-graphs/issue/ENG-1909/add-no-op-nextjs-content-upsert-endpoint
Content upsert, based on cross-app types.
This introduces a StandaloneContent type for upserting contents outside of concepts, following existing sync functions.
https://www.loom.com/share/202c49deb3014d2e8f60632f38ff71b4