feat: improve OAuth provider configuration

This commit is contained in:
fawney19
2026-05-04 00:18:05 +08:00
parent cb5b8ee1ee
commit fb642f7d62
9 changed files with 934 additions and 122 deletions

View File

@@ -0,0 +1,53 @@
import { describe, expect, it } from 'vitest'
import { summarizeOAuthConfigTest } from '../oauthConfigTest'
describe('summarizeOAuthConfigTest', () => {
it('marks unreachable endpoints and unsupported secret as failed', () => {
const summary = summarizeOAuthConfigTest({
authorization_url_reachable: false,
token_url_reachable: false,
secret_status: 'unsupported',
details: 'OAuth 配置测试仅支持 Rust execution runtime',
})
expect(summary.severity).toBe('error')
expect(summary.failures).toEqual([
'Authorization URL 不可达',
'Token URL 不可达',
'Secret 不受支持',
])
expect(summary.message).toBe('测试失败Authorization URL 不可达Token URL 不可达Secret 不受支持')
})
it('uses warning when only secret validation is inconclusive', () => {
const summary = summarizeOAuthConfigTest({
authorization_url_reachable: true,
token_url_reachable: true,
secret_status: 'unknown',
})
expect(summary.severity).toBe('warning')
expect(summary.warnings).toEqual(['Secret 未验证'])
})
it('marks fully reachable config with a likely valid secret as successful', () => {
const summary = summarizeOAuthConfigTest({
authorization_url_reachable: true,
token_url_reachable: true,
secret_status: 'likely_valid',
})
expect(summary.severity).toBe('success')
expect(summary.message).toBe('测试通过')
})
it('accepts a configured secret because OAuth secrets are verified during code exchange', () => {
const summary = summarizeOAuthConfigTest({
authorization_url_reachable: true,
token_url_reachable: true,
secret_status: 'configured',
})
expect(summary.severity).toBe('success')
})
})

View File

@@ -0,0 +1,65 @@
import type { OAuthProviderTestResponse } from '@/api/oauth'
export type OAuthConfigTestSeverity = 'success' | 'warning' | 'error'
export interface OAuthConfigTestSummary {
severity: OAuthConfigTestSeverity
message: string
failures: string[]
warnings: string[]
}
function describeSecretStatus(status: string | undefined): string | null {
const normalized = (status || '').trim().toLowerCase()
if (!normalized || normalized === 'likely_valid' || normalized === 'configured') return null
if (normalized === 'invalid') return 'Secret 无效'
if (normalized === 'unsupported') return 'Secret 不受支持'
if (normalized === 'not_provided') return 'Secret 未提供'
if (normalized === 'unknown') return 'Secret 未验证'
return `Secret: ${status}`
}
export function summarizeOAuthConfigTest(result: OAuthProviderTestResponse): OAuthConfigTestSummary {
const failures: string[] = []
const warnings: string[] = []
if (!result.authorization_url_reachable) {
failures.push('Authorization URL 不可达')
}
if (!result.token_url_reachable) {
failures.push('Token URL 不可达')
}
const secretStatus = (result.secret_status || '').trim().toLowerCase()
const secretMessage = describeSecretStatus(result.secret_status)
if (secretMessage && (secretStatus === 'invalid' || secretStatus === 'unsupported')) {
failures.push(secretMessage)
} else if (secretMessage) {
warnings.push(secretMessage)
}
if (failures.length > 0) {
return {
severity: 'error',
message: `测试失败:${failures.join('')}`,
failures,
warnings,
}
}
if (warnings.length > 0) {
return {
severity: 'warning',
message: `测试完成,但有未确认项:${warnings.join('')}`,
failures,
warnings,
}
}
return {
severity: 'success',
message: '测试通过',
failures,
warnings,
}
}