77 lines
2.5 KiB
TypeScript
77 lines
2.5 KiB
TypeScript
import {defineStore} from "pinia";
|
|
import {type Ref, ref} from "vue";
|
|
import type {User} from "@/api/auth";
|
|
import {emptyUser, getMyUser, renewToken} from "@/api/auth";
|
|
import {getSecondsTilExpire} from "@/util";
|
|
import {useRouter} from "vue-router";
|
|
|
|
const LOCAL_STORAGE_KEY = "access_token"
|
|
|
|
export const useAuthStore = defineStore("auth", () => {
|
|
const authenticated: Ref<boolean> = ref(false)
|
|
const user: Ref<User> = ref(emptyUser())
|
|
const token: Ref<string> = ref("")
|
|
const tokenRefreshInterval: Ref<number> = ref(0)
|
|
|
|
const router = useRouter()
|
|
|
|
async function logIn(newToken: string, newUser: User) {
|
|
authenticated.value = true
|
|
user.value = newUser
|
|
token.value = newToken
|
|
localStorage.setItem(LOCAL_STORAGE_KEY, token.value)
|
|
tokenRefreshInterval.value = setInterval(tryRefreshToken, 60000)
|
|
// await router.push("/lists")
|
|
}
|
|
|
|
async function logOut() {
|
|
authenticated.value = false
|
|
user.value = emptyUser()
|
|
token.value = ""
|
|
if (tokenRefreshInterval.value) {
|
|
clearInterval(tokenRefreshInterval.value)
|
|
}
|
|
localStorage.removeItem(LOCAL_STORAGE_KEY)
|
|
await router.push("/login")
|
|
}
|
|
|
|
/**
|
|
* Periodically called to renew the access token, if it's close to expiring.
|
|
*/
|
|
async function tryRefreshToken() {
|
|
if (authenticated.value && getSecondsTilExpire(token.value) < 100) {
|
|
try {
|
|
const newToken = await renewToken(token.value)
|
|
token.value = newToken
|
|
localStorage.setItem(LOCAL_STORAGE_KEY, newToken)
|
|
} catch (e: any) {
|
|
console.warn("Failed to renew the access token.", e)
|
|
await logOut()
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tries to log in using an access token stored in the local storage.
|
|
*/
|
|
async function tryLogInFromStoredToken(): Promise<void> {
|
|
if (authenticated.value) return
|
|
const storedToken: string | null = localStorage.getItem(LOCAL_STORAGE_KEY)
|
|
if (storedToken && getSecondsTilExpire(storedToken) > 60) {
|
|
try {
|
|
const storedUser = await getMyUser(storedToken)
|
|
console.log("Logging in using stored token for user: " + storedUser.username)
|
|
await logIn(storedToken, storedUser)
|
|
} catch (e: any) {
|
|
console.warn("Failed to log in using stored token.", e)
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
authenticated, user, token,
|
|
logIn, logOut,
|
|
tryLogInFromStoredToken
|
|
}
|
|
})
|