Fix #104
This commit is contained in:
@@ -12,13 +12,129 @@ export const useAuthStore = defineStore("auth", {
|
||||
activeTenantData: null as any,
|
||||
loading: true as boolean,
|
||||
notLoggedIn: true,
|
||||
sessionWarningVisible: false,
|
||||
sessionWarningRemainingSeconds: 0,
|
||||
sessionWarningLeadMs: 5 * 60 * 1000,
|
||||
sessionWarningTimer: null as ReturnType<typeof setTimeout> | null,
|
||||
sessionLogoutTimer: null as ReturnType<typeof setTimeout> | null,
|
||||
sessionCountdownTimer: null as ReturnType<typeof setInterval> | null,
|
||||
}),
|
||||
|
||||
actions: {
|
||||
async persist(token) {
|
||||
decodeTokenExpiryMs(token: string) {
|
||||
try {
|
||||
const parts = token.split(".")
|
||||
if (parts.length < 2) return null
|
||||
|
||||
const payload = JSON.parse(atob(parts[1].replace(/-/g, "+").replace(/_/g, "/")))
|
||||
if (!payload?.exp) return null
|
||||
|
||||
return Number(payload.exp) * 1000
|
||||
} catch (err) {
|
||||
console.error("Could not decode token expiry", err)
|
||||
return null
|
||||
}
|
||||
},
|
||||
|
||||
clearSessionTimers() {
|
||||
if (!process.client) return
|
||||
|
||||
if (this.sessionWarningTimer) {
|
||||
clearTimeout(this.sessionWarningTimer)
|
||||
this.sessionWarningTimer = null
|
||||
}
|
||||
|
||||
if (this.sessionLogoutTimer) {
|
||||
clearTimeout(this.sessionLogoutTimer)
|
||||
this.sessionLogoutTimer = null
|
||||
}
|
||||
|
||||
if (this.sessionCountdownTimer) {
|
||||
clearInterval(this.sessionCountdownTimer)
|
||||
this.sessionCountdownTimer = null
|
||||
}
|
||||
},
|
||||
|
||||
startSessionCountdown(expiresAtMs: number) {
|
||||
if (!process.client) return
|
||||
|
||||
if (this.sessionCountdownTimer) {
|
||||
clearInterval(this.sessionCountdownTimer)
|
||||
}
|
||||
|
||||
this.sessionCountdownTimer = setInterval(() => {
|
||||
const remaining = Math.max(0, Math.ceil((expiresAtMs - Date.now()) / 1000))
|
||||
this.sessionWarningRemainingSeconds = remaining
|
||||
|
||||
if (remaining <= 0 && this.sessionCountdownTimer) {
|
||||
clearInterval(this.sessionCountdownTimer)
|
||||
this.sessionCountdownTimer = null
|
||||
}
|
||||
}, 1000)
|
||||
},
|
||||
|
||||
openSessionWarning(expiresAtMs: number) {
|
||||
this.sessionWarningVisible = true
|
||||
this.sessionWarningRemainingSeconds = Math.max(0, Math.ceil((expiresAtMs - Date.now()) / 1000))
|
||||
this.startSessionCountdown(expiresAtMs)
|
||||
},
|
||||
|
||||
scheduleSessionTimers(token?: string | null) {
|
||||
if (!process.client) return
|
||||
|
||||
const tokenToUse = token || useCookie("token").value
|
||||
|
||||
this.clearSessionTimers()
|
||||
this.sessionWarningVisible = false
|
||||
this.sessionWarningRemainingSeconds = 0
|
||||
|
||||
if (!tokenToUse) return
|
||||
|
||||
const expiresAtMs = this.decodeTokenExpiryMs(tokenToUse)
|
||||
if (!expiresAtMs) return
|
||||
|
||||
const now = Date.now()
|
||||
const msUntilLogout = expiresAtMs - now
|
||||
|
||||
if (msUntilLogout <= 0) {
|
||||
void this.logout()
|
||||
return
|
||||
}
|
||||
|
||||
this.sessionLogoutTimer = setTimeout(() => {
|
||||
this.sessionWarningVisible = false
|
||||
void this.logout()
|
||||
}, msUntilLogout)
|
||||
|
||||
const msUntilWarning = msUntilLogout - this.sessionWarningLeadMs
|
||||
|
||||
if (msUntilWarning <= 0) {
|
||||
this.openSessionWarning(expiresAtMs)
|
||||
return
|
||||
}
|
||||
|
||||
this.sessionWarningTimer = setTimeout(() => {
|
||||
this.openSessionWarning(expiresAtMs)
|
||||
}, msUntilWarning)
|
||||
},
|
||||
|
||||
setToken(token: string | null) {
|
||||
useCookie("token").value = token
|
||||
|
||||
if (!token) {
|
||||
this.clearSessionTimers()
|
||||
this.sessionWarningVisible = false
|
||||
this.sessionWarningRemainingSeconds = 0
|
||||
return
|
||||
}
|
||||
|
||||
this.scheduleSessionTimers(token)
|
||||
},
|
||||
|
||||
async persist(token: string | null) {
|
||||
|
||||
console.log("On Web")
|
||||
useCookie("token").value = token // persistieren
|
||||
this.setToken(token)
|
||||
|
||||
},
|
||||
|
||||
@@ -74,8 +190,7 @@ export const useAuthStore = defineStore("auth", {
|
||||
console.log("Token: " + token)
|
||||
|
||||
// 1. WICHTIG: Token sofort ins Cookie schreiben, damit es persistiert wird
|
||||
const tokenCookie = useCookie("token")
|
||||
tokenCookie.value = token
|
||||
this.setToken(token)
|
||||
|
||||
// 2. User Daten laden
|
||||
await this.fetchMe(token)
|
||||
@@ -112,19 +227,22 @@ export const useAuthStore = defineStore("auth", {
|
||||
this.resetState()
|
||||
|
||||
// Token löschen
|
||||
useCookie("token").value = null
|
||||
this.setToken(null)
|
||||
|
||||
// Nur beim expliziten Logout navigieren wir
|
||||
navigateTo("/login")
|
||||
},
|
||||
|
||||
resetState() {
|
||||
this.clearSessionTimers()
|
||||
this.user = null
|
||||
this.permissions = []
|
||||
this.profile = null
|
||||
this.activeTenant = null
|
||||
this.tenants = []
|
||||
this.activeTenantData = null
|
||||
this.sessionWarningVisible = false
|
||||
this.sessionWarningRemainingSeconds = 0
|
||||
},
|
||||
|
||||
async fetchMe(jwt= null) {
|
||||
@@ -162,6 +280,8 @@ export const useAuthStore = defineStore("auth", {
|
||||
this.activeTenantData = me.tenants.find(i => i.id === me.activeTenant)
|
||||
}
|
||||
|
||||
this.scheduleSessionTimers(tokenToUse)
|
||||
|
||||
console.log(this)
|
||||
|
||||
} catch (err: any) {
|
||||
@@ -170,12 +290,27 @@ export const useAuthStore = defineStore("auth", {
|
||||
|
||||
// Stattdessen nur den State sauber machen und Token löschen
|
||||
this.resetState()
|
||||
useCookie("token").value = null
|
||||
this.setToken(null)
|
||||
|
||||
// Wir werfen den Fehler nicht weiter, damit initStore normal durchläuft
|
||||
}
|
||||
},
|
||||
|
||||
async refreshSession() {
|
||||
try {
|
||||
const { token } = await useNuxtApp().$api("/api/auth/refresh", {
|
||||
method: "POST",
|
||||
})
|
||||
|
||||
this.setToken(token)
|
||||
await this.fetchMe(token)
|
||||
this.sessionWarningVisible = false
|
||||
} catch (err) {
|
||||
console.error("JWT refresh failed", err)
|
||||
await this.logout()
|
||||
}
|
||||
},
|
||||
|
||||
async switchTenant(tenant_id: string) {
|
||||
console.log("Auth switchTenant")
|
||||
this.loading = true
|
||||
@@ -188,7 +323,7 @@ export const useAuthStore = defineStore("auth", {
|
||||
const {token} = res
|
||||
|
||||
|
||||
useCookie("token").value = token // persistieren
|
||||
this.setToken(token)
|
||||
|
||||
|
||||
await this.init(token)
|
||||
@@ -198,4 +333,4 @@ export const useAuthStore = defineStore("auth", {
|
||||
return this.permissions.includes(key)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user