mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-24 22:58:08 +00:00
fix: surface OAuth resume errors on social-login path + i18n + test cleanup
CodeRabbit follow-ups: - Surface OAuth resume failures via a toast in CloudLoginView and CloudSignupView. authError only renders in email-form mode, so a Google/GitHub user who hits a session-cookie failure would see nothing. - Move the session-error fallback string to i18n (oauth.consent.sessionError) instead of hardcoding it in the composable. - Wrap the location override in submitOAuthConsentDecision's test in try/finally so the Proxy'd globalThis.location can't leak into later tests on assertion failure.
This commit is contained in:
@@ -2149,7 +2149,9 @@
|
||||
"appTypeWeb": "Web app",
|
||||
"errorExpired": "This consent request has expired or has already been used. Please restart from the client app.",
|
||||
"errorScopeBroadening": "The previously approved permissions don't cover this request. You'll need to re-authorize with the new permissions.",
|
||||
"errorUnavailable": "This feature isn't available right now. Please contact support if the problem persists."
|
||||
"errorUnavailable": "This feature isn't available right now. Please contact support if the problem persists.",
|
||||
"sessionError": "Failed to establish session. Please try again.",
|
||||
"sessionErrorToastSummary": "Couldn't continue OAuth sign-in"
|
||||
},
|
||||
"scopes": {
|
||||
"mcp:tools:read": {
|
||||
|
||||
@@ -171,21 +171,25 @@ describe('submitOAuthConsentDecision', () => {
|
||||
})
|
||||
})
|
||||
|
||||
await submitOAuthConsentDecision({
|
||||
oauthRequestId: validChallenge.oauth_request_id,
|
||||
csrfToken: validChallenge.csrf_token,
|
||||
decision: 'allow',
|
||||
workspaceId: 'personal-workspace'
|
||||
})
|
||||
try {
|
||||
await submitOAuthConsentDecision({
|
||||
oauthRequestId: validChallenge.oauth_request_id,
|
||||
csrfToken: validChallenge.csrf_token,
|
||||
decision: 'allow',
|
||||
workspaceId: 'personal-workspace'
|
||||
})
|
||||
|
||||
expect(hrefSetter).toHaveBeenCalledWith(
|
||||
'http://127.0.0.1:50632/cb?code=xyz'
|
||||
)
|
||||
|
||||
Object.defineProperty(globalThis, 'location', {
|
||||
configurable: true,
|
||||
value: originalLocation
|
||||
})
|
||||
expect(hrefSetter).toHaveBeenCalledWith(
|
||||
'http://127.0.0.1:50632/cb?code=xyz'
|
||||
)
|
||||
} finally {
|
||||
// Restore unconditionally so an assertion failure doesn't leak the
|
||||
// Proxy'd location into later tests.
|
||||
Object.defineProperty(globalThis, 'location', {
|
||||
configurable: true,
|
||||
value: originalLocation
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
it('throws OAuthApiError on non-2xx', async () => {
|
||||
|
||||
@@ -15,6 +15,15 @@ vi.mock('@/platform/auth/session/useSessionCookie', () => ({
|
||||
useSessionCookie: () => ({ createSessionOrThrow })
|
||||
}))
|
||||
|
||||
vi.mock('vue-i18n', () => ({
|
||||
useI18n: () => ({
|
||||
t: (key: string) =>
|
||||
key === 'oauth.consent.sessionError'
|
||||
? 'Failed to establish session. Please try again.'
|
||||
: key
|
||||
})
|
||||
}))
|
||||
|
||||
describe('useOAuthPostLoginRedirect', () => {
|
||||
beforeEach(() => {
|
||||
sessionStorage.clear()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import type { LocationQuery } from 'vue-router'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
@@ -12,8 +13,6 @@ type OAuthResumeResult =
|
||||
| { kind: 'resumed' }
|
||||
| { kind: 'error'; message: string }
|
||||
|
||||
const FALLBACK_ERROR_MESSAGE = 'Failed to establish session. Please try again.'
|
||||
|
||||
/**
|
||||
* Post-login OAuth resume. If the current login flow originated from an OAuth
|
||||
* authorize request, establishes the Cloud session cookie and navigates to the
|
||||
@@ -22,6 +21,7 @@ const FALLBACK_ERROR_MESSAGE = 'Failed to establish session. Please try again.'
|
||||
export function useOAuthPostLoginRedirect() {
|
||||
const router = useRouter()
|
||||
const sessionCookie = useSessionCookie()
|
||||
const { t } = useI18n()
|
||||
|
||||
async function resumeOAuthIfNeeded(
|
||||
query: LocationQuery
|
||||
@@ -35,7 +35,10 @@ export function useOAuthPostLoginRedirect() {
|
||||
} catch (error) {
|
||||
return {
|
||||
kind: 'error',
|
||||
message: error instanceof Error ? error.message : FALLBACK_ERROR_MESSAGE
|
||||
message:
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: t('oauth.consent.sessionError')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,15 @@ const onSuccess = async () => {
|
||||
|
||||
const oauthResume = await resumeOAuthIfNeeded(route.query)
|
||||
if (oauthResume.kind === 'error') {
|
||||
// authError renders only in email-form mode; surface the failure via
|
||||
// a toast so social-login users (Google / GitHub) can see it too.
|
||||
authError.value = oauthResume.message
|
||||
toastStore.add({
|
||||
severity: 'error',
|
||||
summary: t('oauth.consent.sessionErrorToastSummary'),
|
||||
detail: oauthResume.message,
|
||||
life: 4000
|
||||
})
|
||||
return
|
||||
}
|
||||
if (oauthResume.kind === 'resumed') return
|
||||
|
||||
@@ -183,7 +183,15 @@ const onSuccess = async () => {
|
||||
|
||||
const oauthResume = await resumeOAuthIfNeeded(route.query)
|
||||
if (oauthResume.kind === 'error') {
|
||||
// authError renders only in email-form mode; surface the failure via
|
||||
// a toast so social-login users (Google / GitHub) can see it too.
|
||||
authError.value = oauthResume.message
|
||||
toastStore.add({
|
||||
severity: 'error',
|
||||
summary: t('oauth.consent.sessionErrorToastSummary'),
|
||||
detail: oauthResume.message,
|
||||
life: 4000
|
||||
})
|
||||
return
|
||||
}
|
||||
if (oauthResume.kind === 'resumed') return
|
||||
|
||||
Reference in New Issue
Block a user