Conversation
|
Warning Rate limit exceeded
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 14 minutes and 58 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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 configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
WalkthroughThis PR adds a resend verification email feature to the application. New ResendButton component is introduced client-side with styling, the verification page is refactored to use a component directory structure, and corresponding server actions and API helpers are added. The token database query is enhanced to fetch user verification status, and the verification handler gains stronger error handling and an additional check for already-verified accounts. Changes
Sequence DiagramsequenceDiagram
actor User
participant ResendButton as ResendButton Component
participant Action as resendVerificationEmailAction
participant API as resendVerificationEmailRequest
participant AuthServer as Auth Server
User->>ResendButton: Submit resend form with token
ResendButton->>Action: Dispatch server action via useActionState
Action->>API: Call API helper with extracted token
API->>AuthServer: POST /verify with {token}
AuthServer-->>API: Return success or error response
API-->>Action: Return ApiResponse object
Action-->>ResendButton: Update formState and isPending flag
ResendButton->>ResendButton: Render FormSuccessMessage or FormErrorMessage
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
A Word from Your MentorYou've just built something important here: a complete request–response cycle for a security-sensitive feature. Let me highlight a few professional touches I'm seeing: The Good:
A teaching moment: One thing to watch: You're building thoughtfully. Keep it up! 🚀 🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
rust-server/src/features/auth/handlers.rs (1)
170-201: 🧹 Nitpick | 🔵 TrivialResend token handler looks solid.
Good implementation of the resend flow. A few observations for your learning:
The
Json(body)destructuring directly (line 172) works because you're not usingResult<Json<_>, JsonRejection>here like you do inregister_user. This means malformed JSON will return Axum's default rejection error. Consider whether you want consistency:// Option: Match the register_user pattern for consistent error messages pub async fn resend_token( State(state): State<AppState>, payload: Result<Json<ResendTokenData>, JsonRejection>, ) -> Result<ApiResponse<()>, AppError> { let Json(body) = match payload { Ok(json) => json, Err(rejection) => return Err(AppError::Json(rejection)), }; // ... }However, for a simple single-field payload, the current approach is arguably fine since the error scenario is less likely.
The shortened success message "Check your inbox." (line 200) is cleaner than verbose alternatives. Concise is good!
🤖 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 170 - 201, Change the handler to mirror the register_user pattern so malformed JSON yields your AppError: update resend_token to accept payload: Result<Json<ResendTokenData>, JsonRejection> (instead of Json(body)), destructure with let Json(body) = match payload { Ok(j) => j, Err(rej) => return Err(AppError::Json(rej)) }, and keep the rest of the logic (use ResendTokenData, State(AppState), update_verification_token, and state.email.send_verification_email as before) so errors from invalid JSON are converted to your AppError::Json rather than Axum’s default rejection.
🤖 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)/layout.css:
- Line 37: The .container spacing change from 2rem to 1rem is global; revert
.container back to its original 2rem and instead create a modifier class (e.g.,
.container--compact) with gap: 1rem to target only the verification page; update
the verification page component (where ResendButton is rendered) to use both
classes (container container--compact) so other auth pages keep the original
spacing while the verify page gets the tighter layout.
In `@client/src/app/`(auth)/verify/_components/ResendButton.css:
- Around line 9-18: The CSS has a redundant broad rule "& div" that overlaps
with the direct-child rule "& > *" and can unintentionally style deeply nested
markup; either remove the "& div" rule if the target divs are direct children of
the ResendButton container, or replace it with a more specific selector (e.g.,
"& > .form-messages" or a class tied to FormErrorMessage/FormSuccessMessage) and
add that class to the appropriate components so only the intended nested
container(s) receive width: 100%.
In `@client/src/app/`(auth)/verify/_components/ResendButton.tsx:
- Around line 22-34: The conditional for the error message uses a truthy check
(formState.error && ...) which makes the ?? fallback unreachable; change the
error rendering to explicitly check for undefined (e.g., formState.error !==
undefined) and keep message={formState.error ?? "Failed to resend verification
email. Please try again."} so an empty string or nullish value still falls back;
keep the success branch as-is (formState.success with FormSuccessMessage) and
update references to formState, FormErrorMessage, and FormSuccessMessage
accordingly.
In `@client/src/app/`(auth)/verify/page.tsx:
- Around line 12-13: The code incorrectly constructs new URLSearchParams(params)
where params is the already-parsed searchParams; instead, read the token
directly from the parsed object (use params.token or the searchParams variable)
and call .trim() on that value (e.g., token = params.token?.trim()) to avoid
serializing the object; update the usage in page.tsx replacing the
URLSearchParams construction with direct property access of params/token.
In `@client/src/lib/actions/auth.ts`:
- Around line 176-196: The resendVerificationEmailAction function lacks a
try/catch and does unsafe casting of data.get("token"); update
resendVerificationEmailAction to validate the token (check that
data.get("token") is not null and is a string) and return a standardized error
object if missing, then wrap the call to resendVerificationEmailRequest(token)
in a try/catch that returns a consistent { success: false, error: ... } on
exceptions and preserves the existing success response shape on success.
---
Outside diff comments:
In `@rust-server/src/features/auth/handlers.rs`:
- Around line 170-201: Change the handler to mirror the register_user pattern so
malformed JSON yields your AppError: update resend_token to accept payload:
Result<Json<ResendTokenData>, JsonRejection> (instead of Json(body)),
destructure with let Json(body) = match payload { Ok(j) => j, Err(rej) => return
Err(AppError::Json(rej)) }, and keep the rest of the logic (use ResendTokenData,
State(AppState), update_verification_token, and
state.email.send_verification_email as before) so errors from invalid JSON are
converted to your AppError::Json rather than Axum’s default rejection.
🪄 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: fcec0159-1948-4305-8dd3-604e8c17ac2b
📒 Files selected for processing (9)
client/src/app/(auth)/layout.cssclient/src/app/(auth)/verify/_components/ResendButton.cssclient/src/app/(auth)/verify/_components/ResendButton.tsxclient/src/app/(auth)/verify/_components/VerifyContent.tsxclient/src/app/(auth)/verify/page.tsxclient/src/lib/actions/auth.tsclient/src/lib/api/auth.tsrust-server/src/db/queries.rsrust-server/src/features/auth/handlers.rs
Summary by CodeRabbit
New Features
Bug Fixes