Skip to content

SOme frontend and couple of sql queries in the backend - #52

Merged
reijjo merged 2 commits into
mainfrom
front
Apr 1, 2026
Merged

SOme frontend and couple of sql queries in the backend#52
reijjo merged 2 commits into
mainfrom
front

Conversation

@reijjo

@reijjo reijjo commented Apr 1, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Email verification page for users to confirm their address.
    • Server-side check to validate email/username availability.
    • Token-based account verification flow (verify via link).
  • Improvements

    • Better browser autofill behavior for registration fields (username, password, email).
    • Updated authentication screen styling (verification layout, centered card container).
  • Tests

    • Improved test reliability by running tests serially and coordinating test DB resets.

@coderabbitai

coderabbitai Bot commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

Adds an email verification flow: client verify page and styles, client autocomplete tweaks, backend token lookup and verify handlers/queries/types, auth route base path changed to /api/auth, and test infra updated for serial DB-safe test execution.

Changes

Cohort / File(s) Summary
Client Auth Styling
client/src/app/(auth)/layout.css
Expanded auth grid selector to include .auth-verify; added .auth-verify single-column centered layout with radial gradient and a new .container card class.
Client Form Autofill
client/src/app/(auth)/register/_components/RegisterCredentials.tsx, client/src/app/(auth)/register/_components/RegisterEmail.tsx
Replaced generic autoComplete="on" with semantic values ("username", "new-password", "email") on registration inputs.
Client Verify Page
client/src/app/(auth)/verify/page.tsx
Added client-side verify page that reads token from URL search params and renders verification instructions (server validation TODO).
Client Auth API Base
client/src/lib/api/auth.ts, client/src/lib/api/auth.spec.ts
Changed auth base URL from /auth to /api/auth; updated tests to expect new endpoints.
Rust DB Query Helpers
rust-server/src/db/queries.rs
Added find_user_by_id and find_token_by_value helpers and imported uuid::Uuid.
Rust Auth Handlers / Types / Queries / Routes
rust-server/src/features/auth/handlers.rs, rust-server/src/features/auth/queries.rs, rust-server/src/features/auth/types.rs, rust-server/src/features/auth/routes.rs
Added check_availability and verify_account handlers; added verify_user query; introduced AvailabilityQuery and VerifyQuery types; adjusted register_user control flow (hash password after duplicate checks); registered new GET routes under /register, /available, /verify.
Rust Routing Composition
rust-server/src/features/mod.rs
Moved auth nesting to /api/auth in router composition.
Rust Test Infrastructure
rust-server/tests/api/common.rs
Introduced TestServerHandle, process-wide statics for one-time DB reset, updated build_test_server* signatures, and Drop-based cleanup that truncates DB when last server is dropped.
Rust Test Runtime Config
rust-server/.cargo/config.toml
Added config forcing single-threaded test execution (RUST_TEST_THREADS = "1").

Sequence Diagram

sequenceDiagram
    participant User as User
    participant Client as Client App
    participant Server as Backend API
    participant DB as Database

    User->>Client: Submit registration
    Client->>Server: POST /api/auth/register
    Server->>DB: Insert user + create token
    DB-->>Server: Insert result
    Server-->>Client: Success (guidance to verify)

    User->>Client: Open /verify?token=xxx
    Client->>Client: read token from URL
    Client->>Server: GET /api/auth/verify?token=xxx
    Server->>DB: find_token_by_value(token)
    DB-->>Server: token row (user_id, expires_at)
    Server->>DB: verify_user(user_id) (UPDATE users set verified=true)
    DB-->>Server: Update result
    Server-->>Client: Verification success
    Client->>User: Show verified message
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.88% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is vague and uses non-descriptive phrasing ('SOme frontend', 'couple of sql queries') that obscures the actual scope and purpose of substantial changes across authentication flows. Revise to clearly describe the main changes, such as: 'Add email verification flow with account availability checks' or 'Implement email verification and check availability endpoints'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch front

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.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
rust-server/tests/api/common.rs (1)

128-158: 🧹 Nitpick | 🔵 Trivial

Good approach for testing DB failure scenarios.

Setting db: None lets you verify your app handles database outages gracefully — that's defensive programming at its finest.

One subtle observation for your learning: this function sets TEST_DB_URL and returns a TestServerHandle, meaning when dropped, it will attempt DB truncation even though this test never connected to the DB. That's harmless (the cleanup silently ignores failures), but slightly wasteful.

If you wanted to be meticulous, you could introduce a variant that skips DB cleanup entirely for "no-DB" test scenarios. But honestly, the current approach is pragmatic — one cleanup path is simpler to maintain than conditional paths. Sometimes "good enough" is the professional choice.

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

In `@rust-server/tests/api/common.rs` around lines 128 - 158, The test currently
calls TEST_DB_URL.set(...) and returns a TestServerHandle which triggers DB
cleanup on drop even though AppState.db is None; to avoid the unnecessary
truncation, either (A) stop setting TEST_DB_URL in build_test_server_without_db
(remove the TEST_DB_URL.set call and test_db_url local), or (B) add a new
handle/constructor (e.g., TestServerHandle::new_no_db or
TestServer::new_no_cleanup) that skips registering the DB truncation cleanup and
return that from build_test_server_without_db; locate symbols
build_test_server_without_db, TEST_DB_URL, AppState { db: None },
TestServerHandle::new/TestServer::new to implement the chosen change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@client/src/app/`(auth)/verify/page.tsx:
- Line 10: Remove the client-side logging of the verification token by deleting
the console.log("token:", token) statement in verify/page.tsx; ensure no other
calls log the token variable in that file (or any client code) so the sensitive
token is not output to the browser console.
- Around line 8-18: The page currently only logs the token and shows a static
success message; replace the TODO and the static UI in the verify page to
actually validate the token by calling your backend verification endpoint (use
the token variable), handle success and error responses, and render distinct UI
states (loading, verified success, invalid/expired error) accordingly; update
the component (the page default export / verify page code that uses token) to
POST/GET the token to the server, process the JSON response, and conditionally
render messages and any follow-up actions (redirect, signin link) based on the
server result.

In `@client/src/lib/api/auth.ts`:
- Around line 90-95: The verifyAccount helper is missing in
client/src/lib/api/auth.ts so the frontend verify page cannot complete
verification; implement an exported async function verifyAccount(token: string)
that calls the backend GET endpoint (e.g., "/auth/verify" or the project API
base + "/auth/verify") passing the token (query param or header to match
backend), checks response.ok, parses JSON or handles non-2xx by throwing an
Error with server message, and returns the parsed result or boolean success;
ensure signatures and exports match existing helpers in auth.ts (same error
handling and types) so client/src/app/(auth)/verify/page.tsx can import and
await verifyAccount(token).

In `@rust-server/.cargo/config.toml`:
- Around line 1-7: The [test] section and test-threads setting are ignored by
Cargo; remove the invalid [test] table and instead set RUST_TEST_THREADS = "1"
inside the existing [env] table so the Rust test harness runs single-threaded;
specifically, delete the [test] block (and test-threads) and add the environment
variable RUST_TEST_THREADS = "1" under the [env] section in this config.

In `@rust-server/src/db/queries.rs`:
- Around line 31-33: find_token_by_value currently selects user_id by token
only, allowing expired tokens to pass; update the SQL in find_token_by_value to
include an expiry check (e.g., "SELECT user_id FROM tokens WHERE token = $1 AND
expires_at > now()") and bind token as before (no extra params needed if using
now()), or if you prefer explicit time use chrono::Utc::now() and bind it as a
second parameter; ensure the function still returns Ok(None) when no row is
found (expired or missing) and that the query maps the returned user_id to Uuid
as before.

In `@rust-server/src/features/auth/handlers.rs`:
- Around line 126-130: The token lookup currently accepts any matching value;
change the find_token_by_value query to also require expires_at > now() (or
equivalent DB timestamp check) so expired tokens are rejected, and return None
if not found so the existing ok_or_else(AppError::not_found(...)) still works;
after calling verify_user(db, user_id) consume the token in the database (either
delete the row or set a used/consumed flag) to enforce one-time use—update the
post-verification logic in the handler to call the token-deletion/mark-used
function (or add that logic to the same transaction that verified the user) so
find_token_by_value, expires_at, and verify_user are referenced and the token
cannot be replayed.
- Around line 88-106: The availability check currently treats Some("") or
whitespace as valid — update the logic to trim and reject empty/whitespace-only
inputs before hitting the DB: after the initial match on
params.email/params.username, normalize &params.email and &params.username by
trimming and treat trimmed empty strings as None (or return
Err(AppError::bad_request("Invalid query"))), then only call
find_user_by_email(db, email) and find_user_by_username(db, username) when the
trimmed value is non-empty; reference params.email, params.username,
find_user_by_email, and find_user_by_username to locate where to add the
trim-and-empty check and return appropriate AppError::bad_request for blank
inputs.

In `@rust-server/src/features/auth/routes.rs`:
- Around line 13-15: Routes in auth module currently hardcode the "/auth"
prefix, causing tight coupling when mounted; change the route definitions in
auth::routes (the .route calls that reference register_user, check_availability,
verify_account) to use relative paths ("/register", "/available", "/verify") and
then mount the module with a namespace where it belongs (e.g. use auth_router()
from auth::routes and nest it at "/api/auth" in the features/module that
composes routers) so the auth_router remains reusable and free of its own
namespace.

In `@rust-server/src/features/auth/types.rs`:
- Around line 35-38: The public struct name AvailibilityQuery contains a
spelling typo; rename the type to AvailabilityQuery throughout the codebase (the
struct definition and all references/imports/usages) to avoid breaking changes
and maintain consistency: update the struct declaration for AvailibilityQuery,
any pattern matches, constructor calls, type annotations, function signatures,
and module exports that reference AvailibilityQuery to use AvailabilityQuery
instead.

---

Outside diff comments:
In `@rust-server/tests/api/common.rs`:
- Around line 128-158: The test currently calls TEST_DB_URL.set(...) and returns
a TestServerHandle which triggers DB cleanup on drop even though AppState.db is
None; to avoid the unnecessary truncation, either (A) stop setting TEST_DB_URL
in build_test_server_without_db (remove the TEST_DB_URL.set call and test_db_url
local), or (B) add a new handle/constructor (e.g., TestServerHandle::new_no_db
or TestServer::new_no_cleanup) that skips registering the DB truncation cleanup
and return that from build_test_server_without_db; locate symbols
build_test_server_without_db, TEST_DB_URL, AppState { db: None },
TestServerHandle::new/TestServer::new to implement the chosen change.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 01f0607b-3c9d-452b-bd4f-58f8b7051721

📥 Commits

Reviewing files that changed from the base of the PR and between 0899f3a and 1d75383.

📒 Files selected for processing (12)
  • client/src/app/(auth)/layout.css
  • client/src/app/(auth)/register/_components/RegisterCredentials.tsx
  • client/src/app/(auth)/register/_components/RegisterEmail.tsx
  • client/src/app/(auth)/verify/page.tsx
  • client/src/lib/api/auth.ts
  • rust-server/.cargo/config.toml
  • rust-server/src/db/queries.rs
  • rust-server/src/features/auth/handlers.rs
  • rust-server/src/features/auth/queries.rs
  • rust-server/src/features/auth/routes.rs
  • rust-server/src/features/auth/types.rs
  • rust-server/tests/api/common.rs

Comment thread client/src/app/(auth)/verify/page.tsx
Comment thread client/src/app/(auth)/verify/page.tsx Outdated
Comment thread client/src/lib/api/auth.ts
Comment thread rust-server/.cargo/config.toml Outdated
Comment thread rust-server/src/db/queries.rs Outdated
Comment thread rust-server/src/features/auth/handlers.rs
Comment thread rust-server/src/features/auth/handlers.rs Outdated
Comment thread rust-server/src/features/auth/routes.rs Outdated
Comment thread rust-server/src/features/auth/types.rs Outdated

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 3

♻️ Duplicate comments (3)
rust-server/.cargo/config.toml (1)

1-3: ⚠️ Potential issue | 🟠 Major

Move RUST_TEST_THREADS under [env]; current placement may be ignored.

RUST_TEST_THREADS should be nested in an [env] table in Cargo config. As written on Line 3 at top-level, Cargo may not apply it, so tests can still execute in parallel.

🔧 Proposed fix
+[env]
 # Force single-threaded test execution to avoid database race conditions.
 # Each test truncates the database, so concurrent execution causes conflicts.
 RUST_TEST_THREADS = "1"
In Cargo `.cargo/config.toml`, are environment variables like `RUST_TEST_THREADS` only valid under the `[env]` table, and is a top-level `RUST_TEST_THREADS = "1"` ignored?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rust-server/.cargo/config.toml` around lines 1 - 3, The RUST_TEST_THREADS
setting is currently at top-level and may be ignored; move the RUST_TEST_THREADS
= "1" entry into an [env] table so Cargo picks it up (i.e., add an [env] section
and place RUST_TEST_THREADS = "1" under it), ensuring the environment variable
is applied for test runs; verify the change by running cargo test to confirm
single-threaded execution.
client/src/app/(auth)/verify/page.tsx (1)

4-21: ⚠️ Potential issue | 🟠 Major

Hey, padawan! This verification page needs to actually... verify something.

Right now, you're reading the token but not doing anything with it. The backend endpoint at GET /api/auth/verify?token=... is ready and waiting! Here's the professional approach:

  1. Call your backend when the page loads (via useEffect)
  2. Handle all three states: loading, success, and error
  3. Fix the messaging — this page is where users land after clicking the email link, so "check your inbox" doesn't make sense here

This is a core UX principle: never show success until you've confirmed it. Users clicking an expired or invalid link will see "success" messaging, which erodes trust.

🛠️ Here's the pattern you want to learn
 "use client";
+import { useEffect, useState } from "react";
 import { useSearchParams } from "next/navigation";

 export default function VerifyPage() {
   const searchParams = useSearchParams();
   const token = searchParams.get("token");
+  const [status, setStatus] = useState<"loading" | "success" | "error">("loading");
+  const [message, setMessage] = useState("Verifying your account...");

-  // TODO: Implement actual verification logic by sending the token to the server for validation
+  useEffect(() => {
+    if (!token) {
+      setStatus("error");
+      setMessage("Missing verification token.");
+      return;
+    }
+
+    fetch(`${process.env.NEXT_PUBLIC_BACKEND_URL}/api/auth/verify?token=${encodeURIComponent(token)}`)
+      .then((res) => res.json())
+      .then((data) => {
+        if (data.success) {
+          setStatus("success");
+          setMessage(data.message ?? "Your account is now verified!");
+        } else {
+          setStatus("error");
+          setMessage(data.error ?? "Verification failed.");
+        }
+      })
+      .catch(() => {
+        setStatus("error");
+        setMessage("Network error. Please try again.");
+      });
+  }, [token]);

   return (
     <div className="auth-verify">
       <div className="container">
         <h1>Verify your email</h1>
-        <p>
-          A verification link has been sent to your email. Please check your
-          inbox and click the link to verify your account.
-        </p>
+        <p>{message}</p>
+        {status === "success" && <a href="/login">Sign in</a>}
       </div>
     </div>
   );
 }

Pro tip: Extract this into a custom hook or API helper (like verifyAccount(token)) to keep your component clean and testable. You've already got that pattern going in client/src/lib/api/auth.ts!

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

In `@client/src/app/`(auth)/verify/page.tsx around lines 4 - 21, The VerifyPage
currently reads token via useSearchParams but never calls the backend; update
VerifyPage to call the verification endpoint (or existing verifyAccount(token)
helper from client/src/lib/api/auth.ts) inside a useEffect when a token is
present, manage loading/success/error states (e.g., local state variables like
isLoading, isSuccess, error), and render appropriate messages for each state
(loading indicator, success confirmation when API returns success, and a clear
error message with possible actions on failure); ensure the GET
/api/auth/verify?token=... request is awaited and errors are caught and stored
in error state.
rust-server/src/features/auth/handlers.rs (1)

127-151: ⚠️ Potential issue | 🔴 Critical

Security gap: Token replay attack — tokens must be single-use.

You're checking expiry (great!), but after verify_user succeeds, the token remains valid in the database. This means:

  1. Replay attacks: Anyone who intercepts the verification link can use it repeatedly
  2. Audit trail confusion: You can't tell when verification actually happened
  3. Resource exhaustion: Attackers could hammer verify with valid tokens

The fix: Delete or mark the token as consumed after successful verification. This is a fundamental principle — verification tokens are bearer credentials and must be one-time use.

🔐 Here's how to fix it

First, add a delete function in your queries:

// In rust-server/src/db/queries.rs or auth/queries.rs
pub async fn delete_token(db: &PgPool, token: &str) -> Result<(), AppError> {
    sqlx::query("DELETE FROM tokens WHERE token = $1")
        .bind(token)
        .execute(db)
        .await
        .map_err(AppError::Sql)?;
    Ok(())
}

Then use it in your handler:

     verify_user(db, user_id).await?;
+    delete_token(db, &token).await?;

     Ok(ApiResponse::ok("Email verified successfully", None))
 }

Alternatively, use a transaction to make verify_user + delete_token atomic — that's the production-grade approach.

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

In `@rust-server/src/features/auth/handlers.rs` around lines 127 - 151,
verify_account currently leaves the verification token valid after calling
verify_user, enabling token replay; fix by removing or marking the token
consumed after successful verification (e.g., call a new delete_token(db,
&token) or mark_token_consumed(db, &token) once verify_user(db, user_id) returns
Ok) and handle/delete errors appropriately; for correctness and safety make the
verify_user + delete_token operation atomic by running them inside a database
transaction (use your DB transaction API), and ensure you reference
find_token_by_value, verify_user, and the new delete_token/mark_token_consumed
functions when implementing the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@rust-server/src/db/queries.rs`:
- Around line 22-29: The #[allow(dead_code)] attribute on the find_user_by_id
function masks unused code rot; remove the attribute and either keep the
function in active use or delete it and rely on Git to restore it later—locate
the pub async fn find_user_by_id(...) definition and delete the
#[allow(dead_code)] line (or remove the whole function if it's not needed yet)
so unused scaffolding doesn't linger in production code.
- Around line 31-39: In find_token_by_value, avoid "SELECT *" — change the SQL
to explicitly list the token table columns you need (e.g., id, token, user_id,
expires_at, created_at) in the sqlx::query string and keep using
.bind(token).fetch_optional(db).await; also update any downstream reads that
access columns from the returned PgRow to reference those explicit column names
(or better: map the row into a typed struct) so schema changes won’t break
parsing and you only fetch required fields.

In `@rust-server/src/features/auth/handlers.rs`:
- Line 148: verify_user currently executes an UPDATE but ignores the execution
result so a non-existent user (rows_affected == 0) will appear as a successful
verification; change verify_user in auth/queries.rs to capture the
sqlx::query(...).execute(db).await result, check result.rows_affected(), and
return an AppError::not_found (or appropriate error) when rows_affected() == 0,
ensuring the existing caller in handlers.rs (which calls verify_user(db,
user_id).await?) will propagate the error instead of reporting "Email verified
successfully".

---

Duplicate comments:
In `@client/src/app/`(auth)/verify/page.tsx:
- Around line 4-21: The VerifyPage currently reads token via useSearchParams but
never calls the backend; update VerifyPage to call the verification endpoint (or
existing verifyAccount(token) helper from client/src/lib/api/auth.ts) inside a
useEffect when a token is present, manage loading/success/error states (e.g.,
local state variables like isLoading, isSuccess, error), and render appropriate
messages for each state (loading indicator, success confirmation when API
returns success, and a clear error message with possible actions on failure);
ensure the GET /api/auth/verify?token=... request is awaited and errors are
caught and stored in error state.

In `@rust-server/.cargo/config.toml`:
- Around line 1-3: The RUST_TEST_THREADS setting is currently at top-level and
may be ignored; move the RUST_TEST_THREADS = "1" entry into an [env] table so
Cargo picks it up (i.e., add an [env] section and place RUST_TEST_THREADS = "1"
under it), ensuring the environment variable is applied for test runs; verify
the change by running cargo test to confirm single-threaded execution.

In `@rust-server/src/features/auth/handlers.rs`:
- Around line 127-151: verify_account currently leaves the verification token
valid after calling verify_user, enabling token replay; fix by removing or
marking the token consumed after successful verification (e.g., call a new
delete_token(db, &token) or mark_token_consumed(db, &token) once verify_user(db,
user_id) returns Ok) and handle/delete errors appropriately; for correctness and
safety make the verify_user + delete_token operation atomic by running them
inside a database transaction (use your DB transaction API), and ensure you
reference find_token_by_value, verify_user, and the new
delete_token/mark_token_consumed functions when implementing the change.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c9451327-f7f3-466f-903f-536f470625b6

📥 Commits

Reviewing files that changed from the base of the PR and between 1d75383 and 50bb520.

📒 Files selected for processing (8)
  • client/src/app/(auth)/verify/page.tsx
  • client/src/lib/api/auth.spec.ts
  • rust-server/.cargo/config.toml
  • rust-server/src/db/queries.rs
  • rust-server/src/features/auth/handlers.rs
  • rust-server/src/features/auth/routes.rs
  • rust-server/src/features/auth/types.rs
  • rust-server/src/features/mod.rs

Comment thread rust-server/src/db/queries.rs
Comment thread rust-server/src/db/queries.rs
return Err(AppError::bad_request("Token has expired"));
}

verify_user(db, user_id).await?;

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 | 🟡 Minor

Silent success on non-existent users.

Looking at verify_user in auth/queries.rs, it runs an UPDATE without checking rows_affected. If user_id doesn't exist (e.g., user deleted between token creation and verification), the query silently succeeds and you return "Email verified successfully" for a ghost user.

Consider checking the result:

pub async fn verify_user<'e, E>(db: E, user_id: Uuid) -> Result<(), AppError>
where
    E: Executor<'e, Database = Postgres>,
{
    let result = sqlx::query("UPDATE users SET verified = true WHERE id = $1")
        .bind(user_id)
        .execute(db)
        .await
        .map_err(AppError::Sql)?;

    if result.rows_affected() == 0 {
        return Err(AppError::not_found("User not found"));
    }
    Ok(())
}

This is edge-case defensive coding, but it prevents confusing scenarios in production.

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

In `@rust-server/src/features/auth/handlers.rs` at line 148, verify_user currently
executes an UPDATE but ignores the execution result so a non-existent user
(rows_affected == 0) will appear as a successful verification; change
verify_user in auth/queries.rs to capture the sqlx::query(...).execute(db).await
result, check result.rows_affected(), and return an AppError::not_found (or
appropriate error) when rows_affected() == 0, ensuring the existing caller in
handlers.rs (which calls verify_user(db, user_id).await?) will propagate the
error instead of reporting "Email verified successfully".

@reijjo
reijjo merged commit 607cbcd into main Apr 1, 2026
4 checks passed
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.

1 participant