Fix OAuth token import and table filters

This commit is contained in:
fawney19
2026-05-01 02:14:49 +08:00
parent 9570e5c2c1
commit 4fc7cecf30
54 changed files with 3160 additions and 727 deletions

View File

@@ -2,7 +2,9 @@ import { describe, expect, it } from 'vitest'
import {
getAccountStatusDisplay,
getOAuthRefreshButtonTitle,
getOAuthStatusDisplay,
getOAuthStatusDisplayWithFallback,
getOAuthStatusTitle,
} from '@/utils/providerKeyStatus'
@@ -155,4 +157,50 @@ describe('providerKeyStatus', () => {
oauth_expires_at: future,
}, 0)).toContain('Token 剩余有效期:')
})
it('shows missing refresh token state for access-token-only oauth credentials', () => {
const input = {
auth_type: 'oauth',
oauth_managed: true,
oauth_temporary: true,
}
expect(getOAuthStatusDisplay(input, 0)).toBeNull()
expect(getOAuthStatusDisplayWithFallback(input, 0)).toEqual({
text: '未添加',
isExpired: false,
isExpiringSoon: false,
isInvalid: false,
})
expect(getOAuthStatusTitle(input, 0)).toBe('Refresh Token 未添加,无法自动刷新')
expect(getOAuthRefreshButtonTitle(input, 0)).toBe('仅 Access Token 导入,无法自动刷新,到期后需要重新导入')
})
it('does not show invalid oauth state when refresh token is missing', () => {
const input = {
auth_type: 'oauth',
oauth_managed: true,
oauth_temporary: true,
status_snapshot: {
oauth: {
code: 'invalid',
reason: 'missing_refresh_token',
requires_reauth: true,
},
account: {
code: 'ok',
blocked: false,
},
quota: { code: 'ok', exhausted: false },
},
}
expect(getOAuthStatusDisplayWithFallback(input, 0)).toEqual({
text: '未添加',
isExpired: false,
isExpiringSoon: false,
isInvalid: false,
})
expect(getOAuthStatusTitle(input, 0)).toBe('Refresh Token 未添加,无法自动刷新')
})
})

View File

@@ -3,6 +3,7 @@ export interface ProviderKeyAuthCarrier {
credential_kind?: string | null
runtime_auth_kind?: string | null
oauth_managed?: boolean | null
oauth_temporary?: boolean | null
can_refresh_oauth?: boolean | null
can_export_oauth?: boolean | null
can_edit_oauth?: boolean | null
@@ -68,12 +69,19 @@ export function isServiceAccountCredential(input: ProviderKeyAuthCarrier): boole
}
export function canRefreshOAuthCredential(input: ProviderKeyAuthCarrier): boolean {
if (input.oauth_temporary === true) {
return false
}
if (typeof input.can_refresh_oauth === 'boolean') {
return input.can_refresh_oauth
}
return isOAuthManagedCredential(input)
}
export function shouldShowOAuthRefreshControl(input: ProviderKeyAuthCarrier): boolean {
return isOAuthManagedCredential(input)
}
export function canExportOAuthCredential(input: ProviderKeyAuthCarrier): boolean {
if (typeof input.can_export_oauth === 'boolean') {
return input.can_export_oauth

View File

@@ -7,6 +7,7 @@ import {
isRefreshFailedReason,
} from './accountBlock'
import {
canRefreshOAuthCredential,
isOAuthManagedCredential,
type ProviderKeyAuthCarrier,
} from './providerKeyAuth'
@@ -157,6 +158,19 @@ function mergeOAuthStatusDisplay(
return snapshotStatus ?? legacyStatus
}
function isOAuthCredentialWithoutRefreshToken(input: ProviderKeyStatusCarrier): boolean {
return isOAuthManagedCredential(input) && !canRefreshOAuthCredential(input)
}
function getMissingRefreshTokenStatus(): OAuthStatusInfo {
return {
text: '未添加',
isExpired: false,
isExpiringSoon: false,
isInvalid: false,
}
}
export function getOAuthStatusDisplay(
input: ProviderKeyStatusCarrier,
tick: number,
@@ -167,12 +181,38 @@ export function getOAuthStatusDisplay(
)
}
export function getOAuthStatusDisplayWithFallback(
input: ProviderKeyStatusCarrier,
tick: number,
): OAuthStatusInfo | null {
if (isOAuthCredentialWithoutRefreshToken(input)) {
return getMissingRefreshTokenStatus()
}
const status = getOAuthStatusDisplay(input, tick)
if (status) return status
if (!isOAuthManagedCredential(input)) return null
return {
text: '有效期未知',
isExpired: false,
isExpiringSoon: false,
isInvalid: false,
}
}
export function getOAuthStatusTitle(
input: ProviderKeyStatusCarrier,
tick: number,
): string {
if (isOAuthCredentialWithoutRefreshToken(input)) {
return 'Refresh Token 未添加,无法自动刷新'
}
const status = getOAuthStatusDisplay(input, tick)
if (!status) return ''
if (!status) {
return isOAuthManagedCredential(input) ? 'Token 有效期未知' : ''
}
if (status.isInvalid) {
const reason = normalizeText(status.invalidReason)
return reason ? `Token 已失效: ${reason}` : 'Token 已失效'
@@ -187,6 +227,13 @@ export function getOAuthRefreshButtonTitle(
input: ProviderKeyStatusCarrier,
tick: number,
): string {
if (isOAuthManagedCredential(input) && !canRefreshOAuthCredential(input)) {
if (input.oauth_temporary === true) {
return '仅 Access Token 导入,无法自动刷新,到期后需要重新导入'
}
return '当前 OAuth 凭据无法自动刷新,到期后需要重新导入'
}
const status = getOAuthStatusDisplay(input, tick)
if (status?.isInvalid || status?.isExpired) {
return '重新授权'