Files
codex-proxy-rs/frontend/src/stores/modules/auth.ts
T
f0484c4e11 chore(frontend): upgrade ESLint config to v10 and migrate formatting (#522)
* chore(deps-dev): bump @antfu/eslint-config in /frontend

Bumps [@antfu/eslint-config](https://github.com/antfu/eslint-config) from 9.5.1 to 10.0.0.
- [Release notes](https://github.com/antfu/eslint-config/releases)
- [Commits](https://github.com/antfu/eslint-config/compare/v9.5.1...v10.0.0)

---
updated-dependencies:
- dependency-name: "@antfu/eslint-config"
  dependency-version: 10.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore(frontend): migrate formatting to ESLint v10

Co-authored-by: Codex <noreply@openai.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Zyy <zyycn@users.noreply.github.com>
Co-authored-by: Codex <noreply@openai.com>
2026-10-26 11:34:32 +08:00

128 lines
3.5 KiB
TypeScript

import type { AuthSession } from '@/api'
import { defineStore } from 'pinia'
import { computed, shallowRef } from 'vue'
import { login as apiLogin, logout as apiLogout, getAuthStatus, refreshAuthSession } from '@/api'
import { resetUnauthorizedHandling } from '@/api/request'
export const useAuthStore = defineStore('auth', () => {
const session = shallowRef<AuthSession | null>(null)
// 登录身份变化使关联数据失效,正常续期只更新会话有效期。
const sessionGeneration = shallowRef(0)
const isAuthenticated = computed(() => session.value !== null)
const isAdmin = computed(() => session.value?.role === 'admin')
const sessionChecked = shallowRef(false)
const loading = shallowRef(false)
let revision = 0
const pendingCheck = shallowRef<Promise<boolean>>()
const checking = computed(() => pendingCheck.value !== undefined)
function checkAuth(): Promise<boolean> {
if (pendingCheck.value)
return pendingCheck.value
const check = loadSession(async () => {
const status = await getAuthStatus()
return status.authenticated
? status
: refreshAuthSession()
}).finally(() => {
if (pendingCheck.value === check)
pendingCheck.value = undefined
})
pendingCheck.value = check
return check
}
function refreshSession() {
// 并发续期由请求层协调,不能复用只读状态检查来释放失败请求
return loadSession(refreshAuthSession)
}
function loadSession(load: typeof getAuthStatus): Promise<boolean> {
const currentRevision = ++revision
return load().then((status) => {
// 登录或退出之后到达的旧状态响应,不覆盖新会话。
if (currentRevision === revision) {
const wasAuthenticated = isAuthenticated.value
const previousRole = session.value?.role
session.value = status.session
if (previousRole !== status.session?.role)
sessionGeneration.value += 1
sessionChecked.value = true
if (status.authenticated && !wasAuthenticated)
resetUnauthorizedHandling()
}
return isAuthenticated.value
})
}
async function login(payload: Parameters<typeof apiLogin>[0]) {
if (loading.value)
return null
revision += 1
pendingCheck.value = undefined
loading.value = true
try {
const result = await apiLogin(payload)
revision += 1
pendingCheck.value = undefined
session.value = result
sessionGeneration.value += 1
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.value = undefined
try {
await apiLogout()
invalidateSession()
return true
}
catch {
// 只有服务端确认撤销后才退出,避免刷新又恢复一个未撤销的会话。
return false
}
finally {
loading.value = false
}
}
function invalidateSession() {
revision += 1
pendingCheck.value = undefined
session.value = null
sessionGeneration.value += 1
sessionChecked.value = true
resetUnauthorizedHandling()
}
return {
session,
sessionGeneration,
isAuthenticated,
isAdmin,
sessionChecked,
loading,
checking,
checkAuth,
refreshSession,
login,
logout,
invalidateSession,
}
})