mirror of
https://github.com/fawney19/Aether.git
synced 2026-10-09 02:47:45 +08:00
fix: restore security hardening compatibility and validation
Restore authorized rule reveal, explicit full HTTP capture and retention, video task business fields, and valid payment URLs. Add opt-in credential preservation for trusted recovery, fix frontend type contracts and async races, and eliminate PostgreSQL test fixture resource leaks. Document audit coverage and successful fmt and CI-scoped Clippy checks.
This commit is contained in:
+86
-16
@@ -1,4 +1,5 @@
|
||||
import apiClient from './client'
|
||||
import type { ImageProgress } from './requestTrace'
|
||||
import type { ActivityHeatmap } from '@/types/activity'
|
||||
import type { TieredPricingConfig } from './endpoints/types'
|
||||
import { cachedRequest, buildCacheKey } from '@/utils/cache'
|
||||
@@ -238,13 +239,13 @@ export const meApi = {
|
||||
username?: string
|
||||
feature_settings?: FeatureSettingsMap | null
|
||||
}): Promise<{ message: string }> {
|
||||
const response = await apiClient.put('/api/users/me', data)
|
||||
const response = await apiClient.put<{ message: string }>('/api/users/me', data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 修改密码
|
||||
async changePassword(data: ChangePasswordRequest): Promise<{ message: string }> {
|
||||
const response = await apiClient.patch('/api/users/me/password', data)
|
||||
const response = await apiClient.patch<{ message: string }>('/api/users/me/password', data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
@@ -261,12 +262,12 @@ export const meApi = {
|
||||
},
|
||||
|
||||
async revokeSession(sessionId: string): Promise<{ message: string }> {
|
||||
const response = await apiClient.delete(`/api/users/me/sessions/${sessionId}`)
|
||||
const response = await apiClient.delete<{ message: string }>(`/api/users/me/sessions/${sessionId}`)
|
||||
return response.data
|
||||
},
|
||||
|
||||
async revokeOtherSessions(): Promise<{ message: string; revoked_count: number }> {
|
||||
const response = await apiClient.delete('/api/users/me/sessions/others')
|
||||
const response = await apiClient.delete<{ message: string; revoked_count: number }>('/api/users/me/sessions/others')
|
||||
return response.data
|
||||
},
|
||||
|
||||
@@ -303,7 +304,7 @@ export const meApi = {
|
||||
},
|
||||
|
||||
async deleteApiKey(keyId: string): Promise<{ message: string }> {
|
||||
const response = await apiClient.delete(`/api/users/me/api-keys/${keyId}`)
|
||||
const response = await apiClient.delete<{ message: string }>(`/api/users/me/api-keys/${keyId}`)
|
||||
return response.data
|
||||
},
|
||||
|
||||
@@ -396,16 +397,61 @@ export const meApi = {
|
||||
reasoning_effort?: string | null
|
||||
service_tier?: string | null
|
||||
actual_service_tier?: string | null
|
||||
image_progress?: ImageProgress | null
|
||||
}>
|
||||
}> {
|
||||
const params = ids ? { ids } : {}
|
||||
const response = await apiClient.get('/api/users/me/usage/active', { params })
|
||||
const response = await apiClient.get<{
|
||||
requests: Array<{
|
||||
id: string
|
||||
status: 'pending' | 'streaming' | 'completed' | 'failed' | 'cancelled'
|
||||
input_tokens: number
|
||||
effective_input_tokens?: number | null
|
||||
output_tokens: number
|
||||
cache_creation_input_tokens?: number | null
|
||||
cache_creation_ephemeral_5m_input_tokens?: number | null
|
||||
cache_creation_ephemeral_1h_input_tokens?: number | null
|
||||
cache_read_input_tokens?: number | null
|
||||
cost: number
|
||||
actual_cost?: number | null
|
||||
rate_multiplier?: number | null
|
||||
response_time_ms: number | null
|
||||
first_byte_time_ms: number | null
|
||||
end_to_end_time_ms?: number | null
|
||||
end_to_end_first_byte_time_ms?: number | null
|
||||
updated_at?: string | null
|
||||
response_time_updated_at?: string | null
|
||||
status_code?: number | null
|
||||
error_message?: string | null
|
||||
api_format?: string | null
|
||||
endpoint_api_format?: string | null
|
||||
is_stream?: boolean | null
|
||||
is_websocket?: boolean | null
|
||||
websocket_transport?: string | null
|
||||
usage_available?: boolean | null
|
||||
usage_pricing_available?: boolean | null
|
||||
input_audio_tokens?: number | null
|
||||
output_audio_tokens?: number | null
|
||||
upstream_is_stream?: boolean | null
|
||||
client_requested_stream?: boolean | null
|
||||
client_is_stream?: boolean | null
|
||||
has_format_conversion?: boolean | null
|
||||
has_fallback?: boolean | null
|
||||
target_model?: string | null
|
||||
request_type?: string | null
|
||||
requested_reasoning_effort?: string | null
|
||||
reasoning_effort?: string | null
|
||||
service_tier?: string | null
|
||||
actual_service_tier?: string | null
|
||||
image_progress?: ImageProgress | null
|
||||
}>
|
||||
}>('/api/users/me/usage/active', { params })
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 获取可用的提供商
|
||||
async getAvailableProviders(): Promise<Array<Record<string, unknown>>> {
|
||||
const response = await apiClient.get('/api/users/me/providers')
|
||||
const response = await apiClient.get<Array<Record<string, unknown>>>('/api/users/me/providers')
|
||||
return response.data
|
||||
},
|
||||
|
||||
@@ -429,24 +475,38 @@ export const meApi = {
|
||||
}>
|
||||
total: number
|
||||
}> {
|
||||
const response = await apiClient.get('/api/users/me/available-models', { params })
|
||||
const response = await apiClient.get<{
|
||||
models: Array<{
|
||||
id: string
|
||||
name: string
|
||||
display_name: string | null
|
||||
is_active: boolean
|
||||
default_price_per_request: number | null
|
||||
default_tiered_pricing: TieredPricingConfig | null
|
||||
supported_capabilities: string[] | null
|
||||
supports_embedding?: boolean | null
|
||||
config: Record<string, unknown> | null
|
||||
usage_count: number
|
||||
}>
|
||||
total: number
|
||||
}>('/api/users/me/available-models', { params })
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 获取端点状态(不包含敏感信息)
|
||||
async getEndpointStatus(): Promise<Array<Record<string, unknown>>> {
|
||||
const response = await apiClient.get('/api/users/me/endpoint-status')
|
||||
const response = await apiClient.get<Array<Record<string, unknown>>>('/api/users/me/endpoint-status')
|
||||
return response.data
|
||||
},
|
||||
|
||||
// 偏好设置
|
||||
async getPreferences(): Promise<UserPreferences> {
|
||||
const response = await apiClient.get('/api/users/me/preferences')
|
||||
const response = await apiClient.get<UserPreferences>('/api/users/me/preferences')
|
||||
return response.data
|
||||
},
|
||||
|
||||
async updatePreferences(data: Partial<UserPreferences>): Promise<{ message: string }> {
|
||||
const response = await apiClient.put('/api/users/me/preferences', data)
|
||||
const response = await apiClient.put<{ message: string }>('/api/users/me/preferences', data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
@@ -456,7 +516,7 @@ export const meApi = {
|
||||
async updateApiKeyProviders(keyId: string, data: {
|
||||
allowed_providers?: ProviderConfig[]
|
||||
}): Promise<{ message: string }> {
|
||||
const response = await apiClient.put(`/api/users/me/api-keys/${keyId}/providers`, data)
|
||||
const response = await apiClient.put<{ message: string }>(`/api/users/me/api-keys/${keyId}/providers`, data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
@@ -464,7 +524,7 @@ export const meApi = {
|
||||
async updateApiKeyCapabilities(keyId: string, data: {
|
||||
force_capabilities?: Record<string, boolean> | null
|
||||
}): Promise<{ message: string; force_capabilities?: Record<string, boolean> | null }> {
|
||||
const response = await apiClient.put(`/api/users/me/api-keys/${keyId}/capabilities`, data)
|
||||
const response = await apiClient.put<{ message: string; force_capabilities?: Record<string, boolean> | null }>(`/api/users/me/api-keys/${keyId}/capabilities`, data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
@@ -472,7 +532,9 @@ export const meApi = {
|
||||
async getModelCapabilitySettings(): Promise<{
|
||||
model_capability_settings: Record<string, Record<string, boolean>>
|
||||
}> {
|
||||
const response = await apiClient.get('/api/users/me/model-capabilities')
|
||||
const response = await apiClient.get<{
|
||||
model_capability_settings: Record<string, Record<string, boolean>>
|
||||
}>('/api/users/me/model-capabilities')
|
||||
return response.data
|
||||
},
|
||||
|
||||
@@ -482,7 +544,10 @@ export const meApi = {
|
||||
message: string
|
||||
model_capability_settings: Record<string, Record<string, boolean>> | null
|
||||
}> {
|
||||
const response = await apiClient.put('/api/users/me/model-capabilities', data)
|
||||
const response = await apiClient.put<{
|
||||
message: string
|
||||
model_capability_settings: Record<string, Record<string, boolean>> | null
|
||||
}>('/api/users/me/model-capabilities', data)
|
||||
return response.data
|
||||
},
|
||||
|
||||
@@ -500,7 +565,12 @@ export const meApi = {
|
||||
return cachedRequest(
|
||||
cacheKey,
|
||||
async () => {
|
||||
const response = await apiClient.get('/api/users/me/usage/interval-timeline', { params })
|
||||
const response = await apiClient.get<{
|
||||
analysis_period_hours: number
|
||||
total_points: number
|
||||
points: Array<{ x: string; y: number; model?: string }>
|
||||
models?: string[]
|
||||
}>('/api/users/me/usage/interval-timeline', { params })
|
||||
return response.data
|
||||
},
|
||||
30000
|
||||
|
||||
Reference in New Issue
Block a user