| |
| |
| |
| |
|
|
| import { apiClient } from '../client' |
| import type { AdminUser, UpdateUserRequest, PaginatedResponse, ApiKey } from '@/types' |
|
|
| export interface AdminBindAuthIdentityChannelRequest { |
| channel: string |
| channel_app_id: string |
| channel_subject: string |
| metadata?: Record<string, unknown> | null |
| } |
|
|
| export interface AdminBindAuthIdentityRequest { |
| provider_type: string |
| provider_key: string |
| provider_subject: string |
| issuer?: string | null |
| metadata?: Record<string, unknown> | null |
| channel?: AdminBindAuthIdentityChannelRequest |
| } |
|
|
| export interface AdminBoundAuthIdentityChannel { |
| channel: string |
| channel_app_id: string |
| channel_subject: string |
| metadata: Record<string, unknown> | null |
| created_at: string |
| updated_at: string |
| } |
|
|
| export interface AdminBoundAuthIdentity { |
| user_id: number |
| provider_type: string |
| provider_key: string |
| provider_subject: string |
| verified_at?: string | null |
| issuer?: string | null |
| metadata: Record<string, unknown> | null |
| created_at: string |
| updated_at: string |
| channel?: AdminBoundAuthIdentityChannel | null |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| export async function list( |
| page: number = 1, |
| pageSize: number = 20, |
| filters?: { |
| status?: 'active' | 'disabled' |
| role?: 'admin' | 'user' |
| search?: string |
| group_name?: string // fuzzy filter by allowed group name |
| attributes?: Record<number, string> // attributeId -> value |
| include_subscriptions?: boolean |
| sort_by?: string |
| sort_order?: 'asc' | 'desc' |
| }, |
| options?: { |
| signal?: AbortSignal |
| } |
| ): Promise<PaginatedResponse<AdminUser>> { |
| |
| const params: Record<string, any> = { |
| page, |
| page_size: pageSize, |
| status: filters?.status, |
| role: filters?.role, |
| search: filters?.search, |
| group_name: filters?.group_name, |
| include_subscriptions: filters?.include_subscriptions, |
| sort_by: filters?.sort_by, |
| sort_order: filters?.sort_order |
| } |
|
|
| |
| if (filters?.attributes) { |
| for (const [attrId, value] of Object.entries(filters.attributes)) { |
| if (value) { |
| params[`attr[${attrId}]`] = value |
| } |
| } |
| } |
| const { data } = await apiClient.get<PaginatedResponse<AdminUser>>('/admin/users', { |
| params, |
| signal: options?.signal |
| }) |
| return data |
| } |
|
|
| |
| |
| |
| |
| |
| export async function getById(id: number): Promise<AdminUser> { |
| const { data } = await apiClient.get<AdminUser>(`/admin/users/${id}`) |
| return data |
| } |
|
|
| |
| |
| |
| |
| |
| export async function create(userData: { |
| email: string |
| password: string |
| balance?: number |
| concurrency?: number |
| allowed_groups?: number[] | null |
| }): Promise<AdminUser> { |
| const { data } = await apiClient.post<AdminUser>('/admin/users', userData) |
| return data |
| } |
|
|
| |
| |
| |
| |
| |
| |
| export async function update(id: number, updates: UpdateUserRequest): Promise<AdminUser> { |
| const { data } = await apiClient.put<AdminUser>(`/admin/users/${id}`, updates) |
| return data |
| } |
|
|
| |
| |
| |
| |
| |
| export async function deleteUser(id: number): Promise<{ message: string }> { |
| const { data } = await apiClient.delete<{ message: string }>(`/admin/users/${id}`) |
| return data |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| export async function updateBalance( |
| id: number, |
| balance: number, |
| operation: 'set' | 'add' | 'subtract' = 'set', |
| notes?: string |
| ): Promise<AdminUser> { |
| const { data } = await apiClient.post<AdminUser>(`/admin/users/${id}/balance`, { |
| balance, |
| operation, |
| notes: notes || '' |
| }) |
| return data |
| } |
|
|
| |
| |
| |
| |
| |
| |
| export async function updateConcurrency(id: number, concurrency: number): Promise<AdminUser> { |
| return update(id, { concurrency }) |
| } |
|
|
| |
| |
| |
| |
| |
| |
| export async function toggleStatus(id: number, status: 'active' | 'disabled'): Promise<AdminUser> { |
| return update(id, { status }) |
| } |
|
|
| |
| |
| |
| |
| |
| export async function getUserApiKeys(id: number): Promise<PaginatedResponse<ApiKey>> { |
| const { data } = await apiClient.get<PaginatedResponse<ApiKey>>(`/admin/users/${id}/api-keys`) |
| return data |
| } |
|
|
| |
| |
| |
| |
| |
| |
| export async function getUserUsageStats( |
| id: number, |
| period: string = 'month' |
| ): Promise<{ |
| total_requests: number |
| total_cost: number |
| total_tokens: number |
| }> { |
| const { data } = await apiClient.get<{ |
| total_requests: number |
| total_cost: number |
| total_tokens: number |
| }>(`/admin/users/${id}/usage`, { |
| params: { period } |
| }) |
| return data |
| } |
|
|
| |
| |
| |
| export interface BalanceHistoryItem { |
| id: number |
| code: string |
| type: string |
| value: number |
| status: string |
| used_by: number | null |
| used_at: string | null |
| created_at: string |
| group_id: number | null |
| validity_days: number |
| notes: string |
| user?: { id: number; email: string } | null |
| group?: { id: number; name: string } | null |
| } |
|
|
| |
| export interface BalanceHistoryResponse extends PaginatedResponse<BalanceHistoryItem> { |
| total_recharged: number |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| export async function getUserBalanceHistory( |
| id: number, |
| page: number = 1, |
| pageSize: number = 20, |
| type?: string |
| ): Promise<BalanceHistoryResponse> { |
| const params: Record<string, any> = { page, page_size: pageSize } |
| if (type) params.type = type |
| const { data } = await apiClient.get<BalanceHistoryResponse>( |
| `/admin/users/${id}/balance-history`, |
| { params } |
| ) |
| return data |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| export async function replaceGroup( |
| userId: number, |
| oldGroupId: number, |
| newGroupId: number |
| ): Promise<{ migrated_keys: number }> { |
| const { data } = await apiClient.post<{ migrated_keys: number }>( |
| `/admin/users/${userId}/replace-group`, |
| { old_group_id: oldGroupId, new_group_id: newGroupId } |
| ) |
| return data |
| } |
|
|
| export async function bindUserAuthIdentity( |
| userId: number, |
| input: AdminBindAuthIdentityRequest |
| ): Promise<AdminBoundAuthIdentity> { |
| const { data } = await apiClient.post<AdminBoundAuthIdentity>( |
| `/admin/users/${userId}/auth-identities`, |
| input |
| ) |
| return data |
| } |
|
|
| |
| |
| |
| export type PlatformQuotaPlatform = 'anthropic' | 'openai' | 'gemini' | 'antigravity' |
| export type PlatformQuotaWindow = 'daily' | 'weekly' | 'monthly' |
|
|
| export interface PlatformQuotaItem { |
| platform: PlatformQuotaPlatform |
| daily_limit_usd: number | null |
| weekly_limit_usd: number | null |
| monthly_limit_usd: number | null |
| daily_usage_usd: number |
| weekly_usage_usd: number |
| monthly_usage_usd: number |
| daily_window_start?: string | null |
| weekly_window_start?: string | null |
| monthly_window_start?: string | null |
| daily_window_resets_at?: string | null |
| weekly_window_resets_at?: string | null |
| monthly_window_resets_at?: string | null |
| } |
|
|
| export interface PlatformQuotaUpdateItem { |
| platform: PlatformQuotaPlatform |
| daily_limit_usd: number | null |
| weekly_limit_usd: number | null |
| monthly_limit_usd: number | null |
| } |
|
|
| export interface PlatformQuotasResponse { |
| platform_quotas: PlatformQuotaItem[] |
| } |
|
|
| |
| |
| |
| export async function getPlatformQuotas(id: number): Promise<PlatformQuotasResponse> { |
| const { data } = await apiClient.get<PlatformQuotasResponse>( |
| `/admin/users/${id}/platform-quotas` |
| ) |
| return data |
| } |
|
|
| |
| |
| |
| export async function updatePlatformQuotas( |
| id: number, |
| quotas: PlatformQuotaUpdateItem[] |
| ): Promise<PlatformQuotasResponse> { |
| const { data } = await apiClient.put<PlatformQuotasResponse>( |
| `/admin/users/${id}/platform-quotas`, |
| { quotas } |
| ) |
| return data |
| } |
|
|
| |
| |
| |
| export async function resetPlatformQuotaWindow( |
| id: number, |
| platform: PlatformQuotaPlatform, |
| window: PlatformQuotaWindow |
| ): Promise<PlatformQuotasResponse> { |
| const { data } = await apiClient.post<PlatformQuotasResponse>( |
| `/admin/users/${id}/platform-quotas/reset`, |
| { platform, window } |
| ) |
| return data |
| } |
|
|
| export const usersAPI = { |
| list, |
| getById, |
| create, |
| update, |
| delete: deleteUser, |
| updateBalance, |
| updateConcurrency, |
| toggleStatus, |
| getUserApiKeys, |
| getUserUsageStats, |
| getUserBalanceHistory, |
| replaceGroup, |
| bindUserAuthIdentity, |
| getPlatformQuotas, |
| updatePlatformQuotas, |
| resetPlatformQuotaWindow, |
| } |
|
|
| export default usersAPI |
|
|