mirror of
https://github.com/zyycn/codex-proxy-rs.git
synced 2026-11-14 16:06:02 +00:00
* feat(auth): add API key workspace Add persistent API key sessions and enforce admin/key authorization boundaries. Expose key-scoped quotas, trends, health, and paginated usage records through server-projected data. Share the application shell, system overview, and usage views between admin and key sessions, reorganize frontend domains around view ownership, and omit account, provider, and authentication details from the key workspace. BREAKING CHANGE: Browser authentication now uses /api/auth/* and cpr_session; existing browser sessions must sign in again. Validated frontend lint, type checking, production build, backend workspace tests, and live authenticated key views. Co-authored-by: Codex <noreply@openai.com> * feat(console): refine key workspace experience Unify role-aware console routes and use mode/role in authentication contracts. Reuse request state, stable pagination and performance projections across workspaces. Refine quota cards, usage panels, empty states and key-aware theme previews. Skip session restoration on login and retain form inputs until unmount. Keep the full health timeline grid visible without samples. Co-authored-by: Codex <noreply@openai.com> * feat(key-usage): replace shared workspace with focused usage page Preserve unified admin/key authentication, restore admin pages, and remove the previous client workspace implementation. Add a scoped usage page with metrics, trends, budgets, request logs, and section loading placeholders. Co-authored-by: Codex <noreply@openai.com> --------- Co-authored-by: Zyy <zyycn@users.noreply.github.com> Co-authored-by: Codex <noreply@openai.com>
92 lines
2.4 KiB
TypeScript
92 lines
2.4 KiB
TypeScript
import type { AuthSession } from '@/api'
|
|
|
|
import { defineStore } from 'pinia'
|
|
import { computed, shallowRef } from 'vue'
|
|
|
|
import { login as apiLogin, logout as apiLogout, getAuthStatus } from '@/api'
|
|
import { resetUnauthorizedHandling } from '@/api/request'
|
|
|
|
export const useAuthStore = defineStore('auth', () => {
|
|
const session = shallowRef<AuthSession | null>(null)
|
|
const isAuthenticated = computed(() => session.value !== null)
|
|
const isAdmin = computed(() => session.value?.role === 'admin')
|
|
const sessionChecked = shallowRef(false)
|
|
const loading = shallowRef(false)
|
|
let revision = 0
|
|
let pendingCheck: Promise<boolean> | undefined
|
|
|
|
function checkAuth(): Promise<boolean> {
|
|
if (pendingCheck)
|
|
return pendingCheck
|
|
const currentRevision = revision
|
|
const check = getAuthStatus().then((status) => {
|
|
// 登录或退出之后到达的旧状态响应,不覆盖新会话。
|
|
if (currentRevision === revision) {
|
|
session.value = status.session
|
|
sessionChecked.value = true
|
|
if (status.authenticated)
|
|
resetUnauthorizedHandling()
|
|
}
|
|
return isAuthenticated.value
|
|
}).finally(() => {
|
|
if (pendingCheck === check)
|
|
pendingCheck = undefined
|
|
})
|
|
pendingCheck = check
|
|
return check
|
|
}
|
|
|
|
async function login(payload: Parameters<typeof apiLogin>[0]) {
|
|
if (loading.value)
|
|
return null
|
|
revision += 1
|
|
pendingCheck = undefined
|
|
loading.value = true
|
|
try {
|
|
const result = await apiLogin(payload)
|
|
revision += 1
|
|
pendingCheck = undefined
|
|
session.value = result
|
|
sessionChecked.value = true
|
|
resetUnauthorizedHandling()
|
|
return result
|
|
}
|
|
catch {
|
|
return null
|
|
}
|
|
finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
async function logout() {
|
|
if (loading.value)
|
|
return false
|
|
loading.value = true
|
|
revision += 1
|
|
pendingCheck = undefined
|
|
try {
|
|
await apiLogout()
|
|
invalidateSession()
|
|
return true
|
|
}
|
|
catch {
|
|
// 只有服务端确认撤销后才退出,避免刷新又恢复一个未撤销的会话。
|
|
return false
|
|
}
|
|
finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
function invalidateSession() {
|
|
revision += 1
|
|
pendingCheck = undefined
|
|
session.value = null
|
|
sessionChecked.value = true
|
|
resetUnauthorizedHandling()
|
|
}
|
|
|
|
return { session, isAuthenticated, isAdmin, sessionChecked, loading, checkAuth, login, logout, invalidateSession }
|
|
})
|