Repository navigation
fix(auth): translate event onboarding and retry failed invite lookups - #389
Conversation
…e lookups Event join was overwritten back to English-only copy with an endless spinner on lookup failure. Wire the existing auth.onboard keys, community wording, typed redeem reasons, and a Retry state so attendees can finish joining. Co-authored-by: Cursor <cursoragent@cursor.com>
A lapsed session now says to sign in with a different account, closed invites say to contact the community, and the step bar no longer depends on login i18n being in scope. Co-authored-by: Cursor <cursoragent@cursor.com>
…le copy Revoked and used-up invites no longer fail the browser suite on old "revoked"/"reached its limit" wording, and a completed join still shows the success panel if the QR expires before the attendee reloads. Co-authored-by: Cursor <cursoragent@cursor.com>
The regression job died because it asked for the pnpm store path before pnpm existed, so the cache path was empty. Also keep the plugin test loop from failing on folders with no package.json.
Regression HTML loads were treating valid session cookies as signed-out because Playwright stored them as localhost domain cookies and a cached null session skipped the real getSession read.
|
@private-review full |
|
|
||
| const [accountCreated, setAccountCreated] = useState(false); | ||
| const [redeemed, setRedeemed] = useState<Redeemed | null>(null); | ||
| const [redeemed, setRedeemed] = useState<Redeemed | null>(() => readStoredRedeemed(code)); |
There was a problem hiding this comment.
🟠 Medium · correctness: Cached join is keyed only by invite code, so another user or a signed-out visitor sees “You're in” without joining
readStoredRedeemed(code) sets redeemed from sessionStorage using only citynode.onboard.redeemed:<code>. It does not check who is signed in. Once redeemed is truthy, two things follow: the join effect returns early, so redeemOnboardingCode never runs, and the joined panel renders.
Concrete scenario: user A joins via /onboard?code=X. A signs out in the same tab, which happens on a shared phone or a borrowed device at an event. User B then signs in and opens the same link. B is shown “You've joined Chicago Builders…” but is never added to the organization or team.
The same applies to a signed-out visitor whose session has lapsed. They get the joined panel, and because session?.user.name is undefined they also get the DisplayNameStep, whose updateUser call then fails.
The cache is also unnecessary for the case it was added for. The server already treats a repeat redeem as idempotent: a prior redeemer who is still a member gets the joined result even after the code expires (services/onboarding.ts lines 395–413). Stale entries (for example after the member was removed) also keep showing the joined state for the rest of the tab session.
Suggested fix: Store the user id with the cached result and only restore it when session.user.id matches, ignoring it while the session is pending or null. Alternatively, drop the sessionStorage cache and rely on the server's idempotent redeem, which already handles reloads after the code expires.
Multi Review ·
|
… cache Return the resolved session from the auth plugin's getContext() so the host's SSR auth sees signed-in users again, and revert the requireSession workaround in ui/src/app.ts. Drop the sessionStorage join cache on /onboard. It was keyed only by the invite code, so a later visitor in the same tab (another user or a signed-out one) saw the joined state without redeeming. The server already treats a repeat redeem by an existing member as idempotent, including after the code expires, so a reload re-redeems and still lands on the joined panel.
|
@multi-review |
|
@MisbahAnsar resolve merge conflicts. |
…lookup-errors # Conflicts: # plugins/auth-ui/vitest.config.ts
adenarc
left a comment
There was a problem hiding this comment.
Went through this twice. The i18n coverage looks complete (every key used exists in all 4 locales) and the wording is all "community" now. A few things inline, mostly around error states.
…ying refused joins Only show the invitation load error when there is no invitation to show, and drop the Retry spinner that could not render. An unrecognised FORBIDDEN or BAD_REQUEST from redeem now shows a contact-the-community state instead of Retry. An expired session now asks the member to sign in again rather than use a different account. Status panels put their test id on the panel root.
|
Hold off on this one @MisbahAnsar, I can take it from here |
…ss unit-test CI job Salvage of #386-onboard-i18n-lookup-errors after local auth-ui moved to the upstream published auth plugin (#425): - Extract cookie mapping/encoding into tests/regression/lib/playwright-cookies.mjs with unit tests (Cookie values and Secure flag now follow the stack origin, so Chromium sends minted session cookies back to the app) - auth-test-instance: pin baseURL + cookie options to the stack origin - ci-child: gate a regression-unit job (test:regression:unit) The onboard i18n/retry half of the original PR now belongs upstream in everything-dev plugins/auth/ui/ (see citynode#386).
|
Resolved the conflicts by rebranching onto current Kept (this PR, salvaged from the original):
Dropped (superseded / dead here):
Moved upstream: the actual #386 fix (i18n + "community" wording + retry on failed invite lookup) now belongs in Also picked up a tiny formatting fix in |
…om/NEARBuilders/citynode.app into fix/386-onboard-i18n-lookup-errors
Closes #386
Summary
Event
/onboard?code=was overwritten back to English-only copy with an endless spinner when invite lookup failed.