Skip to content

fix: change-password in-form validation, reauth warning, global sign-out (#1945)#1969

Open
larryro wants to merge 1 commit into
mainfrom
tale/xs725mv32qt5x0z63wesg1aaah897fjk
Open

fix: change-password in-form validation, reauth warning, global sign-out (#1945)#1969
larryro wants to merge 1 commit into
mainfrom
tale/xs725mv32qt5x0z63wesg1aaah897fjk

Conversation

@larryro

@larryro larryro commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Resolves #1945.

What changed

1. In-form validation of the current password

A wrong current password is now surfaced as an inline field error on the current-password input (matching the 2FA / add-member flows) instead of a generic destructive toast.

  • Backend (convex/users/update_user_password.ts): the changePassword call is wrapped so a Better Auth INVALID_PASSWORD APIError is re-raised as a structured ConvexError({ code: 'INVALID_CURRENT_PASSWORD' }).
  • Frontend (account-form.tsx): onSubmit inspects the error with convexErrorCode() and calls setError('currentPassword', …) for that code; only unexpected failures fall through to the toast.

2. Reauth / global sign-out warning

The Change-password dialog now shows a warning Alert before submit: changing the password signs you out of all devices and requires signing in again.

3. Global sign-out (verified + test-backed)

The voluntary credential flow already passes revokeOtherSessions: true to Better Auth (revokes every other session); the client then signs the current session out, so the net effect is a global sign-out. Added/strengthened backend tests asserting:

  • changePassword is called with revokeOtherSessions: true,
  • the forced-rotation path calls revokeOtherSessions,
  • a wrong current password raises INVALID_CURRENT_PASSWORD.

Ripple

  • Locale strings added to en/de/fr (+de-CH override): auth.changePassword.validation.currentIncorrect and auth.changePassword.warning.{title,description}.
  • Docs updated in docs/{en,de,fr}/platform/member/preferences.md.

Verification

  • bunx vitest run convex/users/update_user_password.test.ts → 6 passed
  • lib/i18n/messages.test.ts (locale parity) → 23 passed
  • bun run --filter @tale/platform typecheck → exit 0
  • bunx oxlint → 0 errors (type-aware tsgolint phase OOMs in the sandbox; runs in CI)

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@larryro, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 44 minutes and 2 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses rolling per-developer review limits. Reviews become available again as older review attempts age out of the rolling limit window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c954b730-482f-4ac0-b35b-8fb0a33ee8e2

📥 Commits

Reviewing files that changed from the base of the PR and between b418075 and 1bee2c0.

📒 Files selected for processing (10)
  • docs/de/platform/member/preferences.md
  • docs/en/platform/member/preferences.md
  • docs/fr/platform/member/preferences.md
  • services/platform/app/features/settings/account/components/account-form.tsx
  • services/platform/convex/users/update_user_password.test.ts
  • services/platform/convex/users/update_user_password.ts
  • services/platform/messages/de-CH.json
  • services/platform/messages/de.json
  • services/platform/messages/en.json
  • services/platform/messages/fr.json
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch tale/xs725mv32qt5x0z63wesg1aaah897fjk

Warning

Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption.


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.

@larryro

larryro commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator Author

Desk Review — #1945 change-password flow (in-form validation, reauth warning, global sign-out)

Verdict: READY TO MERGE. All three acceptance criteria are met, the change is minimal and follows repo conventions, the new behavior is test-backed, the full server suite passes locally, and CI is green.

CI

47 checks pass, 4 skipping (fork-PR duplicate jobs — Smoke test (fork PR), Validate images (fork PR), Web container test, Trivy — each superseded by its passing non-fork equivalent). 0 failing, 0 pending.

Tests run locally (this branch)

  • bunx vitest --run --project server convex/users/update_user_password.test.ts6 passed
  • bunx vitest --run --project server (full backend suite) → 516 files, 6247 tests passed, no regressions.

Acceptance criteria

  • AC1 — wrong current password shows an inline field error, no generic toast. ✅ Backend (convex/users/update_user_password.ts:95-108) catches Better Auth's APIError and re-raises ConvexError({code:'INVALID_CURRENT_PASSWORD'}); the dialog (account-form.tsx:328-334) maps that code to setError('currentPassword', …) and only falls back to a toast for other errors. Verified against the installed Better Auth: the wrong-password path throws APIError with body.code === 'INVALID_PASSWORD' / message "Invalid password" (node_modules/better-auth/dist/api/routes/update-user.mjs:167), so isInvalidPasswordError matches it and does not false-match the distinct PASSWORD_TOO_SHORT/TOO_LONG/CREDENTIAL_ACCOUNT_NOT_FOUND codes. convexErrorCode is the established repo convention (also used by the automation create/rename dialogs and WebDAV handlers) and is unit-tested.
  • AC2 — dialog warns about global sign-out / reauth before submit.<Alert variant="warning" icon={AlertTriangle} …/> renders unconditionally at the top of the dialog (account-form.tsx:376-381), before the inputs. Strings added to en/de/fr (and de-CH overlays the one ß→ss string); de-CH correctly falls back through de → en for the rest.
  • AC3 — other sessions invalidated after change, test-backed. ✅ Voluntary path passes revokeOtherSessions: true to changePassword (update_user_password.ts:87-94), asserted by the test at update_user_password.test.ts:173-192; the forced path calls auth.api.revokeOtherSessions and is asserted at :215-235. The client additionally signs out and hard-navigates after success.

Non-blocking observations (optional follow-ups, not required for merge)

  1. Test coverage of defensive branches. Three branches of the new error handling are not directly exercised: the message-regex fallback in isInvalidPasswordError (when body.code is absent), the re-throw of a non-INVALID_PASSWORD APIError, and a setPassword failure. The primary new behavior is tested; these are secondary paths.
  2. setPassword (OAuth-only, first-time password) does not revoke sessions. This is pre-existing, untouched by this PR, and out of scope for Improvement: Change-password flow — in-form validation, reauth warning, and global sign-out #1945 (which is about changing an existing password) — noting only for completeness.

Nice work — the fix mirrors the structured-error pattern the issue asked for and the global sign-out is genuinely enforced server-side.

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.

Improvement: Change-password flow — in-form validation, reauth warning, and global sign-out

1 participant