Files
nl-blogs/client/src/composables/useAuth.ts
2026-06-24 16:50:04 +08:00

112 lines
2.5 KiB
TypeScript

import { ref } from 'vue'
import router from '../router'
const TOKEN_KEY = 'token'
const USER_KEY = 'user'
const EXPIRE_KEY = 'tokenExpireAt'
const sessionExpired = ref(false)
let sessionExpiredHandled = false
let expiryTimer: ReturnType<typeof setTimeout> | null = null
export function useAuth() {
const getToken = () => localStorage.getItem(TOKEN_KEY)
const getTokenExpireAt = (): number => {
const raw = localStorage.getItem(EXPIRE_KEY)
return raw ? Number(raw) : 0
}
const isAuthenticated = (): boolean => {
const token = getToken()
if (!token) return false
const expireAt = getTokenExpireAt()
if (expireAt > 0 && Date.now() >= expireAt) {
return false
}
return true
}
const login = (token: string, user: unknown, expireUnixSeconds: number) => {
localStorage.setItem(TOKEN_KEY, token)
localStorage.setItem(USER_KEY, JSON.stringify(user))
localStorage.setItem(EXPIRE_KEY, String(expireUnixSeconds * 1000))
sessionExpiredHandled = false
sessionExpired.value = false
scheduleExpiryCheck()
}
const logout = (showToast?: (msg: string, type: 'success' | 'error') => void) => {
clearExpiryTimer()
localStorage.removeItem(TOKEN_KEY)
localStorage.removeItem(USER_KEY)
localStorage.removeItem(EXPIRE_KEY)
sessionExpiredHandled = false
sessionExpired.value = false
if (router.currentRoute.value.path !== '/login') {
router.push('/login')
}
if (showToast) {
// noop by default for expiry flow
}
}
const clearExpiryTimer = () => {
if (expiryTimer) {
clearTimeout(expiryTimer)
expiryTimer = null
}
}
const scheduleExpiryCheck = () => {
clearExpiryTimer()
const expireAt = getTokenExpireAt()
if (!expireAt) return
const delay = expireAt - Date.now()
if (delay <= 0) {
handleSessionExpired()
return
}
expiryTimer = setTimeout(() => {
handleSessionExpired()
}, delay)
}
const handleSessionExpired = () => {
if (sessionExpiredHandled) return
sessionExpiredHandled = true
sessionExpired.value = true
}
const confirmSessionExpired = () => {
logout()
}
const getUser = () => {
try {
return JSON.parse(localStorage.getItem(USER_KEY) || '{}')
} catch {
return {}
}
}
return {
sessionExpired,
getToken,
getTokenExpireAt,
isAuthenticated,
login,
logout,
handleSessionExpired,
confirmSessionExpired,
scheduleExpiryCheck,
getUser,
}
}