Files
codex-proxy-rs/frontend/src/api/modules/keys.ts
T
ZyyandCodex 7616fdf4ab feat(auth): add seamless admin session renewal
Renew active administrator sessions with atomic Redis expiry updates,
synchronized cookies, and idle and absolute lifetime limits. Preserve
revocation after logout and password changes.

Coordinate session recovery, bounded retries, error handling, and raw
responses through request plugins. Gate initial navigation in the router
and organize frontend API modules by their views.

Co-authored-by: Codex <noreply@openai.com>
2026-10-06 12:49:50 +08:00

159 lines
3.7 KiB
TypeScript

import type { RequestOptions } from '../request'
import type { AccountGroupRef } from './groups'
import type { ClientProfileSelection, ProviderRequestProfile, ProviderRequestProfiles, XaiClientProfileSelection } from './settings/profiles'
import request from '../request'
export type ApiKeyRoutingScope = 'all' | 'groups'
export type ApiKeyBudgetPeriod = 'daily' | 'weekly' | 'all'
export interface ApiKey {
providerRequestProfileOverrides: ProviderRequestProfiles
openaiClientProfileOverride: ClientProfileSelection | null
xaiClientProfileOverride: XaiClientProfileSelection | null
id: string
name: string
label: string | null
prefix: string
enabled: boolean
maxConcurrency: number
requestsPerMinute: number
dailyLimitUsd: string
weeklyLimitUsd: string
dailyUsedUsd: string
weeklyUsedUsd: string
dailyResetsAt: string | null
dailyResetsAtDisplay: string | null
weeklyResetsAt: string | null
weeklyResetsAtDisplay: string | null
createdAt: string
createdAtDisplay: string
updatedAt: string
updatedAtDisplay: string
lastUsedAt: string | null
lastUsedAtDisplay: string
lastUsedAtFullDisplay: string | null
routingScope: ApiKeyRoutingScope
groups: AccountGroupRef[]
providerKinds: string[]
}
export interface ApiKeyListResponse {
items: ApiKey[]
nextCursor: string | null
total: number
}
export interface ApiKeyCreateResponse {
id: string
prefix: string
plaintextKey: string
}
export interface ApiKeyRevealResponse {
id: string
plaintextKey: string
}
export interface ApiKeyMutationResponse {
id: string
}
// 请求参数类型:仅定义 API 边界的形状,调用方不依赖显式声明。
interface ApiKeyListParams {
cursor?: string
limit: number
search?: string
sortBy?: string
sortDirection?: string
}
export interface ApiKeyWriteParam {
name: string
label: string | null
groupIds: string[]
maxConcurrency: number
requestsPerMinute: number
dailyLimitUsd: string
weeklyLimitUsd: string
}
interface ApiKeyUpdateParam extends ApiKeyWriteParam {
id: string
providerRequestProfileOverrides: Record<string, ProviderRequestProfile | null>
}
interface ApiKeyCreateParam extends ApiKeyWriteParam {
providerRequestProfileOverrides: ProviderRequestProfiles
customKey?: string
}
interface ApiKeyIdParam {
id: string
}
export function getApiKeys(data: ApiKeyListParams, options: RequestOptions = {}) {
return request<ApiKeyListResponse>({
url: '/api/admin/client-keys',
method: 'GET',
params: data,
...options,
})
}
export function createApiKey(data: ApiKeyCreateParam) {
return request<ApiKeyCreateResponse>({
url: '/api/admin/client-keys/create',
method: 'POST',
data,
})
}
export function updateApiKey(data: ApiKeyUpdateParam) {
return request<ApiKeyMutationResponse>({
url: '/api/admin/client-keys/update',
method: 'POST',
data,
})
}
export function revealApiKey(data: ApiKeyIdParam) {
return request<ApiKeyRevealResponse>({
url: '/api/admin/client-keys/reveal',
method: 'GET',
params: data,
})
}
export function deleteApiKey(data: ApiKeyIdParam) {
return request<ApiKeyMutationResponse>({
url: '/api/admin/client-keys/delete',
method: 'POST',
data,
})
}
export function resetApiKeyBudget(data: ApiKeyIdParam & { period: ApiKeyBudgetPeriod }) {
return request<ApiKeyMutationResponse>({
url: '/api/admin/client-keys/reset-budget',
method: 'POST',
data,
})
}
export function disableApiKey(data: ApiKeyIdParam) {
return request<ApiKeyMutationResponse>({
url: '/api/admin/client-keys/disable',
method: 'POST',
data,
})
}
export function enableApiKey(data: ApiKeyIdParam) {
return request<ApiKeyMutationResponse>({
url: '/api/admin/client-keys/enable',
method: 'POST',
data,
})
}