fix: improve Grok OAuth, image, and usage flows

This commit is contained in:
Heatherm Huang
2026-07-09 17:54:08 +08:00
parent 668c79ea86
commit b480545c19
10 changed files with 254 additions and 6 deletions
@@ -0,0 +1,55 @@
import { describe, expect, it, vi } from 'vitest'
vi.mock('@/stores/app', () => ({
useAppStore: () => ({
showError: vi.fn()
})
}))
vi.mock('vue-i18n', () => ({
useI18n: () => ({
t: (key: string) => {
const messages: Record<string, string> = {
'admin.accounts.oauth.grok.failedToExchangeCode': 'Grok 授权码兑换失败',
'admin.accounts.oauth.grok.errors.GROK_OAUTH_INVALID_STATE':
'Grok OAuth state 与当前会话不匹配。请粘贴同一次生成的授权链接返回的回调 URL。'
}
return messages[key] ?? key
}
})
}))
vi.mock('@/api/admin', () => ({
adminAPI: {
grok: {
generateAuthUrl: vi.fn(),
exchangeCode: vi.fn(),
refreshGrokToken: vi.fn()
}
}
}))
import { useGrokOAuth } from '@/composables/useGrokOAuth'
import { adminAPI } from '@/api/admin'
describe('useGrokOAuth.exchangeAuthCode', () => {
it('shows a state mismatch recovery hint from structured backend errors', async () => {
vi.mocked(adminAPI.grok.exchangeCode).mockRejectedValueOnce({
status: 400,
reason: 'GROK_OAUTH_INVALID_STATE',
message: 'invalid oauth state'
})
const oauth = useGrokOAuth()
const tokenInfo = await oauth.exchangeAuthCode({
code: 'code',
sessionId: 'session-id',
state: 'wrong-state'
})
expect(tokenInfo).toBeNull()
expect(oauth.error.value).toBe(
'Grok OAuth state 与当前会话不匹配。请粘贴同一次生成的授权链接返回的回调 URL。'
)
})
})
+14 -3
View File
@@ -3,6 +3,7 @@ import { useI18n } from 'vue-i18n'
import { useAppStore } from '@/stores/app'
import { adminAPI } from '@/api/admin'
import type { GrokTokenInfo } from '@/api/admin/grok'
import { extractApiErrorMessage, extractI18nErrorMessage } from '@/utils/apiError'
export function useGrokOAuth() {
const appStore = useAppStore()
@@ -39,7 +40,7 @@ export function useGrokOAuth() {
state.value = response.state
return true
} catch (err: any) {
error.value = err.response?.data?.detail || t('admin.accounts.oauth.grok.failedToGenerateUrl')
error.value = extractApiErrorMessage(err, t('admin.accounts.oauth.grok.failedToGenerateUrl'))
appStore.showError(error.value)
return false
} finally {
@@ -72,7 +73,12 @@ export function useGrokOAuth() {
return await adminAPI.grok.exchangeCode(payload as any)
} catch (err: any) {
error.value = err.response?.data?.detail || t('admin.accounts.oauth.grok.failedToExchangeCode')
error.value = extractI18nErrorMessage(
err,
t,
'admin.accounts.oauth.grok.errors',
t('admin.accounts.oauth.grok.failedToExchangeCode')
)
appStore.showError(error.value)
return null
} finally {
@@ -95,7 +101,12 @@ export function useGrokOAuth() {
try {
return await adminAPI.grok.refreshGrokToken(refreshToken.trim(), proxyId)
} catch (err: any) {
error.value = err.response?.data?.detail || t('admin.accounts.oauth.grok.failedToValidateRT')
error.value = extractI18nErrorMessage(
err,
t,
'admin.accounts.oauth.grok.errors',
t('admin.accounts.oauth.grok.failedToValidateRT')
)
return null
} finally {
loading.value = false