112 lines
2.5 KiB
TypeScript
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,
|
|
}
|
|
}
|