Skip to content

Supabase Integration#5

Merged
orimcoding merged 11 commits intomainfrom
supabase-integration
Apr 20, 2026
Merged

Supabase Integration#5
orimcoding merged 11 commits intomainfrom
supabase-integration

Conversation

@orimcoding
Copy link
Copy Markdown
Owner

@orimcoding orimcoding commented Apr 20, 2026

Pull Request

Description

  • Created middleware to interact with Supabase responses.
  • Temporary client / server handling.
  • Developed mock login / signup API routes and useAuth.ts

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Performance improvement
  • Other (please describe):

Related Issues

Screenshots (If it is a front end feature screenshot is reccomended)

Additional Notes

Summary by CodeRabbit

  • New Features

    • Added user authentication endpoints for signup and login.
    • Added client-side auth hook to surface current session and loading state.
    • Added request middleware to evaluate session/auth state on incoming requests.
  • Chores

    • Integrated Supabase packages and browser/server clients; added local Supabase configuration and ignore rules.

@orimcoding orimcoding self-assigned this Apr 20, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
swale Ready Ready Preview, Comment Apr 20, 2026 5:42pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 20, 2026

Warning

Rate limit exceeded

@orimcoding has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 3 minutes and 0 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 3 minutes and 0 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b742b171-dc26-4fdd-a060-9a503bc745f5

📥 Commits

Reviewing files that changed from the base of the PR and between b93d06f and 85d38bf.

📒 Files selected for processing (3)
  • src/app/api/auth/login/route.ts
  • src/app/api/auth/signup/route.ts
  • src/middleware.ts

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key(s) in object: 'version'
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
📝 Walkthrough

Walkthrough

Adds Supabase-based authentication: new dependencies, server and browser Supabase clients, middleware to sync cookies and check sessions, API POST routes for signup/login, a client-side useAuth hook, and local Supabase config and .gitignore.

Changes

Cohort / File(s) Summary
Dependencies
package.json
Added @supabase/ssr (^0.10.2) and @supabase/supabase-js (^2.103.0); newline added at EOF.
Server Supabase & Middleware
src/lib/supabase/server.ts, src/middleware.ts
Added server-side SSR client factory using Next.js cookies() and middleware that initializes SSR client, synchronizes cookies to the response, and invokes supabase.auth.getUser().
Client Supabase
src/lib/supabase/client.ts, src/lib/hooks/useAuth.ts
Added createClient() creating a browser Supabase client from NEXT_PUBLIC env vars and a useAuth hook that fetches session, tracks loading, and subscribes to auth state changes.
Auth API Routes
src/app/api/auth/login/route.ts, src/app/api/auth/signup/route.ts
Added POST handlers parsing JSON, validating email/password, calling supabase.auth.signInWithPassword / signUp, and returning appropriate JSON error or success responses.
Supabase Local Config
supabase/config.toml, supabase/.gitignore
Added comprehensive local Supabase configuration and .gitignore entries for Supabase temp and env files.

Sequence Diagram

sequenceDiagram
    participant Browser as User Browser
    participant Client as Next.js Client
    participant Middleware as Next.js Middleware
    participant API as Next.js API Route
    participant Supabase as Supabase Server

    Browser->>Client: Submit credentials (signup/login)
    Client->>API: POST /api/auth/(signup|login) with JSON
    API->>Middleware: request passes through (middleware initializes SSR client)
    Middleware->>Supabase: createServerClient + sync cookies
    API->>Supabase: supabase.auth.signUp / signInWithPassword
    Supabase-->>API: { data } or { error }
    API-->>Browser: JSON response (success or error)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped through code with a tiny hop,

I stitched the cookies and polished the top.
Signup and login, a carrot in sight,
Sessions snug under moonlit byte.
— your jubilant rabbit

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Supabase Integration' accurately reflects the main change—adding Supabase authentication infrastructure—but is somewhat broad and generic, covering multiple components without highlighting the most specific aspect.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch supabase-integration

Comment @coderabbitai help to get the list of available commands and usage tips.

@supabase
Copy link
Copy Markdown

supabase Bot commented Apr 20, 2026

Updates to Preview Branch (supabase-integration) ↗︎

Deployments Status Updated
Database Mon, 20 Apr 2026 17:42:34 UTC
Services Mon, 20 Apr 2026 17:42:34 UTC
APIs Mon, 20 Apr 2026 17:42:34 UTC

Tasks are run on every commit but only new migration files are pushed.
Close and reopen this PR if you want to apply changes from existing seed or migration files.

Tasks Status Updated
Configurations Mon, 20 Apr 2026 17:42:34 UTC
Migrations Mon, 20 Apr 2026 17:42:34 UTC
Seeding Mon, 20 Apr 2026 17:42:34 UTC
Edge Functions Mon, 20 Apr 2026 17:42:34 UTC

View logs for this Workflow Run ↗︎.
Learn more about Supabase for Git ↗︎.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (1)
supabase/config.toml (1)

216-220: Add guardrails for non-local environments on relaxed email auth settings.

At Line 216, Line 218, and Line 220, email confirmation is off, secure password change is off, and resend interval is 1s. If this config leaks into shared envs, auth posture is weak. Recommend documenting this as strictly local/testing or parameterizing these values via env-specific config.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@supabase/config.toml` around lines 216 - 220, The config currently disables
email confirmations (enable_confirmations), disables secure password change
(secure_password_change), and sets a 1s resend interval (max_frequency) which
are safe only for local/testing; update these settings so they are either
documented as strictly local/testing and moved into a local-only config, or
parameterized behind environment-specific controls (e.g., require an explicit
DEV_ONLY env flag before allowing enable_confirmations=false,
secure_password_change=false, max_frequency="1s"); change defaults to secure
values for shared/staging/prod (enable_confirmations=true,
secure_password_change=true, reasonable max_frequency like "1m" or configurable)
and add a short comment near enable_confirmations / secure_password_change /
max_frequency warning that the relaxed values must not be used outside local dev
without explicit opt-in via an env variable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/api/auth/login/route.ts`:
- Around line 6-23: The route handler currently calls request.json() and
proceeds to auth without validating the payload; update the handler around the
request.json() call in the route (the code that extracts { email, password }) to
explicitly validate the parsed body: wrap request.json() in its own try/catch to
catch malformed JSON and return NextResponse.json({ error: "Invalid JSON" }, {
status: 400 }); then validate that email and password exist and are strings
(e.g., if (!email || typeof email !== "string" || !password || typeof password
!== "string") return NextResponse.json({ error: "Missing or invalid credentials"
}, { status: 400 });) before calling supabase.auth.signInWithPassword so
credential errors remain 400 and unexpected exceptions still fall through to the
existing 500 catch.

In `@src/app/api/auth/signup/route.ts`:
- Around line 6-23: The signup handler currently trusts await request.json() and
the destructured { email, password } which can throw or yield invalid payloads
and push malformed requests into the 500 catch; update the logic around
request.json(), validate the parsed body before calling supabase.auth.signUp
(ensure email and password exist, are strings, and optionally validate email
format and password length/constraints), return NextResponse.json({ error:
"Invalid request" }, { status: 400 }) for malformed JSON or invalid credentials,
and only let unexpected exceptions fall through to the existing 500 catch;
locate and modify the code around request.json(), the destructuring of { email,
password }, the call to supabase.auth.signUp, and the NextResponse error returns
to implement these checks.

In `@src/lib/hooks/useAuth.ts`:
- Around line 10-27: The supabase client is being recreated each render causing
the useEffect (which depends on supabase.auth) to re-run and repeatedly
subscribe; wrap createClient() in useMemo (e.g. const supabase = useMemo(() =>
createClient(), [])) to stabilize the instance, change the effect dependency to
[supabase], replace the getSession().then(...) call with
getSession().then(...).finally(() => setLoading(false)) to guarantee loading is
cleared, and keep the auth change listener via
supabase.auth.onAuthStateChange(...) with the same cleanup return () =>
subscription?.unsubscribe().

In `@src/middleware.ts`:
- Around line 26-29: The middleware currently awaits supabase.auth.getUser()
with no error handling which can throw and block requests; wrap the await
supabase.auth.getUser() call in a try/catch inside the middleware, ignore the
call's result (since it isn't used), and on error log the exception (e.g.,
console.error or your process logger) and proceed to return supabaseResponse so
transient auth failures don't break matched requests.
- Around line 33-42: Update the middleware matcher pattern in src/middleware.ts
(the "matcher" array entry) to exclude auth routes and additional static asset
extensions so supabase.auth.getUser() does not run for them; specifically adjust
the existing regex "/((?!_next/static|_next/image|favicon.ico|.*\\.svg).*)" to
also negative-match "/api/auth/login" and "/api/auth/signup" and file extensions
like .png, .jpg, .jpeg, .gif, .webp, .txt, .xml (and .svg if not already
covered), ensuring the middleware only runs for intended dynamic routes.

In `@supabase/config.toml`:
- Around line 154-157: site_url and additional_redirect_urls have mismatched
schemes which will break Supabase auth exact-match checks; update the entries so
their schemes match exactly (either change additional_redirect_urls to
"http://127.0.0.1:3000" to match site_url, or change site_url to
"https://127.0.0.1:3000" if you intend HTTPS), and ensure the host and port
remain identical for the values referenced by site_url and
additional_redirect_urls.

---

Nitpick comments:
In `@supabase/config.toml`:
- Around line 216-220: The config currently disables email confirmations
(enable_confirmations), disables secure password change
(secure_password_change), and sets a 1s resend interval (max_frequency) which
are safe only for local/testing; update these settings so they are either
documented as strictly local/testing and moved into a local-only config, or
parameterized behind environment-specific controls (e.g., require an explicit
DEV_ONLY env flag before allowing enable_confirmations=false,
secure_password_change=false, max_frequency="1s"); change defaults to secure
values for shared/staging/prod (enable_confirmations=true,
secure_password_change=true, reasonable max_frequency like "1m" or configurable)
and add a short comment near enable_confirmations / secure_password_change /
max_frequency warning that the relaxed values must not be used outside local dev
without explicit opt-in via an env variable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2bc287e0-a8da-4bb7-9625-24996b738f05

📥 Commits

Reviewing files that changed from the base of the PR and between 3656e4a and ed4107a.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • package.json
  • src/app/api/auth/login/route.ts
  • src/app/api/auth/signup/route.ts
  • src/lib/hooks/useAuth.ts
  • src/lib/supabase/client.ts
  • src/lib/supabase/server.ts
  • src/middleware.ts
  • supabase/.gitignore
  • supabase/config.toml

Comment thread src/app/api/auth/login/route.ts Outdated
Comment thread src/app/api/auth/signup/route.ts Outdated
Comment thread src/lib/hooks/useAuth.ts Outdated
Comment thread src/middleware.ts
Comment thread src/middleware.ts
Comment on lines +33 to +42
matcher: [
/*
* Match all request paths except for the ones starting with:
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
* - public folder
*/
"/((?!_next/static|_next/image|favicon.ico|.*\\.svg).*)",
],
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -name "middleware.ts" -type f | head -20

Repository: orimcoding/swale

Length of output: 79


🏁 Script executed:

cat -n ./src/middleware.ts

Repository: orimcoding/swale

Length of output: 1444


🏁 Script executed:

find ./public -type f | head -20

Repository: orimcoding/swale

Length of output: 154


🏁 Script executed:

# Check for other static file types that might be served
find ./public -type f -exec file {} \; | cut -d: -f2 | sort | uniq -c

Repository: orimcoding/swale

Length of output: 259


🏁 Script executed:

# Check file extensions in public directory
find ./public -type f | sed 's/.*\.//' | sort | uniq -c

Repository: orimcoding/swale

Length of output: 71


🏁 Script executed:

# Check if there's a public folder mentioned in config or package.json
cat -n ./package.json | head -50

Repository: orimcoding/swale

Length of output: 1116


🏁 Script executed:

# Check for API routes and other routes
find ./src -type f -name "*.ts" -o -name "*.tsx" | head -20

Repository: orimcoding/swale

Length of output: 273


🏁 Script executed:

# Check what routes exist in the app
find ./src/app -type f -name "route.ts" -o -name "route.tsx" | xargs -I {} bash -c 'echo "=== {} ===" && head -10 {}'

Repository: orimcoding/swale

Length of output: 890


🏁 Script executed:

# Let me verify the regex pattern syntax
# First, let's understand the current matcher pattern better
python3 << 'EOF'
import re

# Current pattern
current = r"/((?!_next/static|_next/image|favicon.ico|.*\.svg).*)"

# Proposed pattern from fix
proposed = r"/((?!_next/static|_next/image|favicon.ico|api/auth|.*\.(?:svg|png|jpg|jpeg|gif|webp|ico|txt|xml)$).*)"

# Test various paths
test_paths = [
    "/",
    "/dashboard",
    "/api/auth/login",
    "/api/auth/signup",
    "/image.svg",
    "/image.png",
    "/style.css",
    "/robots.txt",
    "/sitemap.xml",
    "/favicon.ico",
    "/_next/static/something",
    "/_next/image/something",
    "/public/file.svg"
]

print("CURRENT PATTERN MATCHES:")
for path in test_paths:
    match = re.match(current, path)
    print(f"  {path}: {bool(match)}")

print("\nPROPOSED PATTERN MATCHES:")
for path in test_paths:
    match = re.match(proposed, path)
    print(f"  {path}: {bool(match)}")
EOF

Repository: orimcoding/swale

Length of output: 696


🏁 Script executed:

# Check if there are other static file extensions commonly served
find ./src -name "*.css" -o -name "*.js" | head -10

Repository: orimcoding/swale

Length of output: 81


🏁 Script executed:

# Check for other file types that might be served from public
find . -type f \( -name "*.css" -o -name "*.js" -o -name "*.json" -o -name "*.webp" -o -name "*.woff" \) 2>/dev/null | grep -v node_modules | head -20

Repository: orimcoding/swale

Length of output: 145


Matcher scope is too broad for static/public assets and auth endpoints.
The current pattern unnecessarily runs the supabase.auth.getUser() async operation on requests to /api/auth/login, /api/auth/signup, and static assets like .png, .jpg, .gif, .webp, .txt, and .xml files. This adds unnecessary latency to these requests.

Proposed fix
-    "/((?!_next/static|_next/image|favicon.ico|.*\\.svg).*)",
+    "/((?!_next/static|_next/image|favicon.ico|api/auth|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|txt|xml)$).*)",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/middleware.ts` around lines 33 - 42, Update the middleware matcher
pattern in src/middleware.ts (the "matcher" array entry) to exclude auth routes
and additional static asset extensions so supabase.auth.getUser() does not run
for them; specifically adjust the existing regex
"/((?!_next/static|_next/image|favicon.ico|.*\\.svg).*)" to also negative-match
"/api/auth/login" and "/api/auth/signup" and file extensions like .png, .jpg,
.jpeg, .gif, .webp, .txt, .xml (and .svg if not already covered), ensuring the
middleware only runs for intended dynamic routes.

Comment thread supabase/config.toml
Comment on lines +154 to +157
site_url = "http://127.0.0.1:3000"
# A list of *exact* URLs that auth providers are permitted to redirect to post authentication.
additional_redirect_urls = ["https://127.0.0.1:3000"]
# How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 (1 week).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify scheme/host consistency between auth.site_url and auth.additional_redirect_urls
rg -n '^\s*site_url\s*=|^\s*additional_redirect_urls\s*=' supabase/config.toml -C1

Repository: orimcoding/swale

Length of output: 374


🌐 Web query:

Supabase auth redirect URL exact matching scheme validation

💡 Result:

Supabase Auth performs exact matching, including the scheme (http/https/custom), for redirect URL validation against the configured allow list (Site URL and Additional Redirect URLs). The provided redirectTo URL must match one of the allowed patterns precisely, including protocol/scheme, host, and path (with wildcard support for paths/domains but scheme is part of the pattern). Mismatches in scheme, such as http vs https, will fail validation, causing fallback to the Site URL. Examples from docs: http://localhost:3000/* matches only http scheme, not https. Normalization handles trailing slashes, but scheme remains exact. This is a security feature to prevent open redirects.

Citations:


🏁 Script executed:

# Check if there are other config references or documentation about this setup
rg -i 'redirect|site_url' supabase/ --type toml -n

Repository: orimcoding/swale

Length of output: 552


🏁 Script executed:

# Check if there are any comments or context about http vs https in the codebase
git log --oneline -n 20 -- supabase/config.toml 2>/dev/null || echo "Git history not available"

Repository: orimcoding/swale

Length of output: 104


🏁 Script executed:

# Check for any auth or environment configuration files that might clarify intent
fd -e env -e example -e sample | grep -i -E '(auth|supabase)' | head -20

Repository: orimcoding/swale

Length of output: 42


Fix redirect URL scheme mismatch to prevent auth callback rejection.

site_url at Line 154 is http://127.0.0.1:3000, but additional_redirect_urls at Line 156 is https://127.0.0.1:3000. Supabase auth performs exact URL matching including the scheme (http/https), so this mismatch will cause auth callback validation to fail and redirect to the fallback Site URL instead.

Suggested fix
-site_url = "http://127.0.0.1:3000"
-additional_redirect_urls = ["https://127.0.0.1:3000"]
+site_url = "http://127.0.0.1:3000"
+additional_redirect_urls = ["http://127.0.0.1:3000"]
📝 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.

Suggested change
site_url = "http://127.0.0.1:3000"
# A list of *exact* URLs that auth providers are permitted to redirect to post authentication.
additional_redirect_urls = ["https://127.0.0.1:3000"]
# How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 (1 week).
site_url = "http://127.0.0.1:3000"
# A list of *exact* URLs that auth providers are permitted to redirect to post authentication.
additional_redirect_urls = ["http://127.0.0.1:3000"]
# How long tokens are valid for, in seconds. Defaults to 3600 (1 hour), maximum 604,800 (1 week).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@supabase/config.toml` around lines 154 - 157, site_url and
additional_redirect_urls have mismatched schemes which will break Supabase auth
exact-match checks; update the entries so their schemes match exactly (either
change additional_redirect_urls to "http://127.0.0.1:3000" to match site_url, or
change site_url to "https://127.0.0.1:3000" if you intend HTTPS), and ensure the
host and port remain identical for the values referenced by site_url and
additional_redirect_urls.

CodeRabbit suggestion

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/api/auth/login/route.ts`:
- Around line 47-48: There is an unmatched closing brace in the login route file
— remove the extra `}` that appears just before the final closing brace so the
function/block in src/app/api/auth/login/route.ts (the login route handler) has
balanced braces; keep the final `}` that ends the function/exports and delete
the stray closing brace immediately preceding it.
- Around line 13-27: The destructuring of body in the login route can throw when
body is null; before unpacking email and password (the const { email, password }
= body in route.ts inside the login handler), first check that body is a
non-null object (e.g. typeof body === "object" && body !== null) and return
NextResponse.json({ error: "Email and password are required" }, { status: 400 })
if it fails; only then destructure and run the existing string/emptiness checks
for email/password to ensure null JSON bodies yield a 400 rather than a 500.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 44015831-8474-4f98-854a-6003d3bbd715

📥 Commits

Reviewing files that changed from the base of the PR and between ed4107a and 51fd0e1.

📒 Files selected for processing (1)
  • src/app/api/auth/login/route.ts

Comment on lines +13 to +27
const { email, password } = body as {
email?: unknown;
password?: unknown;
};
if (
typeof email !== "string" ||
typeof password !== "string" ||
!email ||
!password
) {
return NextResponse.json(
{ error: "Email and password are required" },
{ status: 400 }
);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify there is currently no non-null object guard before destructuring.
nl -ba src/app/api/auth/login/route.ts | sed -n '1,40p'
rg -n 'const \{ email, password \} = body as' src/app/api/auth/login/route.ts
rg -n 'typeof body === "object"|body !== null' src/app/api/auth/login/route.ts

Repository: orimcoding/swale

Length of output: 162


🏁 Script executed:

cat -n src/app/api/auth/login/route.ts | head -50

Repository: orimcoding/swale

Length of output: 1519


Guard body shape before destructuring to avoid 500 on null.

At Line 13, destructuring body occurs before confirming it is a non-null object. When a request body is JSON null, it passes the JSON parsing check (Line 8) but causes a destructuring error on Line 13, which bubbles up to the outer catch block (Line 41) and returns 500 instead of 400.

Add a guard to validate body is a non-null object before destructuring:

Proposed fix
     let body: unknown;
     try {
       body = await request.json();
     } catch {
       return NextResponse.json({ error: "Invalid JSON body" }, { status: 400 });
     }

+    if (typeof body !== "object" || body === null) {
+      return NextResponse.json({ error: "Invalid request body" }, { status: 400 });
+    }
+
     const { email, password } = body as {
       email?: unknown;
       password?: unknown;
     };
📝 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.

Suggested change
const { email, password } = body as {
email?: unknown;
password?: unknown;
};
if (
typeof email !== "string" ||
typeof password !== "string" ||
!email ||
!password
) {
return NextResponse.json(
{ error: "Email and password are required" },
{ status: 400 }
);
}
let body: unknown;
try {
body = await request.json();
} catch {
return NextResponse.json({ error: "Invalid JSON body" }, { status: 400 });
}
if (typeof body !== "object" || body === null) {
return NextResponse.json({ error: "Invalid request body" }, { status: 400 });
}
const { email, password } = body as {
email?: unknown;
password?: unknown;
};
if (
typeof email !== "string" ||
typeof password !== "string" ||
!email ||
!password
) {
return NextResponse.json(
{ error: "Email and password are required" },
{ status: 400 }
);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/api/auth/login/route.ts` around lines 13 - 27, The destructuring of
body in the login route can throw when body is null; before unpacking email and
password (the const { email, password } = body in route.ts inside the login
handler), first check that body is a non-null object (e.g. typeof body ===
"object" && body !== null) and return NextResponse.json({ error: "Email and
password are required" }, { status: 400 }) if it fails; only then destructure
and run the existing string/emptiness checks for email/password to ensure null
JSON bodies yield a 400 rather than a 500.

Comment thread src/app/api/auth/login/route.ts Outdated
Comment thread src/app/api/auth/signup/route.ts Fixed
middleware error handling

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a 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

♻️ Duplicate comments (1)
src/app/api/auth/signup/route.ts (1)

71-71: ⚠️ Potential issue | 🟡 Minor

Remove the unused catch binding.

At Line 71, error is never used and triggers @typescript-eslint/no-unused-vars.

Proposed fix
-  } catch (error) {
+  } catch {
     return NextResponse.json(
       { error: "Internal server error" },
       { status: 500 }
     );
   }
#!/bin/bash
set -euo pipefail
# Verify there are no unused catch bindings in this route.
rg -n -C2 'catch\\s*\\(\\s*error\\s*\\)' src/app/api/auth/signup/route.ts || true

Expected result: no match after fix.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/api/auth/signup/route.ts` at line 71, The catch clause in the signup
route's POST handler currently declares an unused binding as "catch (error)"
which triggers the linter; remove the unused binding by changing the clause to
"catch {", i.e. update the try/catch in the POST handler (look for the "catch
(error)" occurrence) so the catch block has no parameter; no other logic changes
are required.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/app/api/auth/signup/route.ts`:
- Around line 43-44: The current emailRegex and its use (emailRegex.test(email))
in the signup route are vulnerable to catastrophic backtracking; replace this
with a deterministic, linear-time validation: ensure exactly one '@' using
indexOf/lastIndexOf, verify non-empty local and domain parts, ensure domain
contains at least one '.' not at start/end, and reject any whitespace
characters; alternatively use a vetted library (e.g., validator.isEmail) and
call it from the same signup handler where emailRegex is referenced.

---

Duplicate comments:
In `@src/app/api/auth/signup/route.ts`:
- Line 71: The catch clause in the signup route's POST handler currently
declares an unused binding as "catch (error)" which triggers the linter; remove
the unused binding by changing the clause to "catch {", i.e. update the
try/catch in the POST handler (look for the "catch (error)" occurrence) so the
catch block has no parameter; no other logic changes are required.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d1f7046c-445a-4dba-9790-e31558a18a93

📥 Commits

Reviewing files that changed from the base of the PR and between 51fd0e1 and b93d06f.

📒 Files selected for processing (2)
  • src/app/api/auth/signup/route.ts
  • src/lib/hooks/useAuth.ts

Comment thread src/app/api/auth/signup/route.ts Outdated
@orimcoding orimcoding merged commit 2c53fa6 into main Apr 20, 2026
9 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Apr 22, 2026
7 tasks
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.

2 participants