From 34a99ee92e918d8efec3a610d2e8142d1f427888 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 7 Feb 2026 07:18:19 +0000 Subject: [PATCH 1/2] Update authorize flow for logged-in users Co-authored-by: Kent C. Dodds --- client/client-routes.tsx | 191 ++++++++++++++++++++++++---------- worker/oauth-handlers.test.ts | 48 ++++++++- worker/oauth-handlers.ts | 72 +++++++++---- 3 files changed, 230 insertions(+), 81 deletions(-) diff --git a/client/client-routes.tsx b/client/client-routes.tsx index a8bf8c6..98e85e0 100644 --- a/client/client-routes.tsx +++ b/client/client-routes.tsx @@ -347,6 +347,8 @@ type OAuthAuthorizeInfo = { type OAuthAuthorizeStatus = 'idle' | 'loading' | 'ready' | 'error' type OAuthAuthorizeMessage = { type: 'error' | 'info'; text: string } +type OAuthSession = { email: string } +type OAuthSessionStatus = 'idle' | 'loading' | 'ready' function OAuthAuthorizeForm(handle: Handle) { let info: OAuthAuthorizeInfo | null = null @@ -354,6 +356,8 @@ function OAuthAuthorizeForm(handle: Handle) { let message: OAuthAuthorizeMessage | null = null let submitting = false let lastSearch = '' + let session: OAuthSession | null = null + let sessionStatus: OAuthSessionStatus = 'idle' function setMessage(next: OAuthAuthorizeMessage | null) { message = next @@ -420,6 +424,31 @@ function OAuthAuthorizeForm(handle: Handle) { } } + async function loadSession() { + if (sessionStatus !== 'idle') return + sessionStatus = 'loading' + + try { + const response = await fetch('/session', { + headers: { Accept: 'application/json' }, + credentials: 'include', + }) + const payload = await response.json().catch(() => null) + const email = + response.ok && + payload?.ok && + typeof payload?.session?.email === 'string' + ? payload.session.email.trim() + : '' + session = email ? { email } : null + } catch { + session = null + } + + sessionStatus = 'ready' + handle.update() + } + async function submitDecision( decision: 'approve' | 'deny', form?: HTMLFormElement, @@ -486,7 +515,11 @@ function OAuthAuthorizeForm(handle: Handle) { async function handleSubmit(event: SubmitEvent) { event.preventDefault() if (!(event.currentTarget instanceof HTMLFormElement)) return - await submitDecision('approve', event.currentTarget) + const hasSession = Boolean(session?.email) + await submitDecision( + 'approve', + hasSession ? undefined : event.currentTarget, + ) } return () => { @@ -496,12 +529,26 @@ function OAuthAuthorizeForm(handle: Handle) { lastSearch = currentSearch void loadInfo() } + if (sessionStatus === 'idle') { + void loadSession() + } const clientLabel = info?.client?.name ?? 'Unknown client' const scopes = info?.scopes ?? [] const scopeLabel = scopes.length > 0 ? scopes.join(', ') : 'No scopes requested.' - const actionsDisabled = status !== 'ready' || submitting + const sessionEmail = session?.email ?? '' + const isSessionReady = sessionStatus === 'ready' + const isSessionLoading = + sessionStatus === 'loading' || sessionStatus === 'idle' + const isLoggedIn = isSessionReady && Boolean(sessionEmail) + const actionsDisabled = status !== 'ready' || submitting || isSessionLoading + const formReady = status === 'ready' && !isSessionLoading + const authorizeLabel = submitting + ? 'Submitting...' + : isLoggedIn + ? 'Approve connection' + : 'Authorize' return (

{scopeLabel}

+ {isSessionLoading ? ( +

Checking your session…

+ ) : null} + {isLoggedIn ? ( +
+

+ Signed in as {sessionEmail} +

+

+ Approve to continue with this account. +

+
+ ) : null} {status === 'loading' ? (

Loading authorization details… @@ -573,62 +648,66 @@ function OAuthAuthorizeForm(handle: Handle) { border: `1px solid ${colors.border}`, backgroundColor: colors.surface, boxShadow: shadows.sm, - opacity: status === 'ready' ? 1 : 0.7, + opacity: formReady ? 1 : 0.7, }} on={{ submit: handleSubmit }} > - - + {!isLoggedIn && isSessionReady ? ( + <> + + + + ) : null}