auto-logout after session expired
This commit is contained in:
@ -81,7 +81,8 @@
|
|||||||
"created": "Položka byla vytvořena.",
|
"created": "Položka byla vytvořena.",
|
||||||
"saved": "Změny byly uloženy.",
|
"saved": "Změny byly uloženy.",
|
||||||
"updated": "Změny byly aplikovány.",
|
"updated": "Změny byly aplikovány.",
|
||||||
"deleted": "Položka byla smazána."
|
"deleted": "Položka byla smazána.",
|
||||||
|
"sessionExpired": "Relace vypršela. Přihlas se znovu."
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"loadDay": "Nepodařilo se načíst den.",
|
"loadDay": "Nepodařilo se načíst den.",
|
||||||
|
|||||||
@ -81,7 +81,8 @@
|
|||||||
"created": "Element wurde erstellt.",
|
"created": "Element wurde erstellt.",
|
||||||
"saved": "Änderungen wurden gespeichert.",
|
"saved": "Änderungen wurden gespeichert.",
|
||||||
"updated": "Änderungen wurden übernommen.",
|
"updated": "Änderungen wurden übernommen.",
|
||||||
"deleted": "Element wurde gelöscht."
|
"deleted": "Element wurde gelöscht.",
|
||||||
|
"sessionExpired": "Sitzung ist abgelaufen. Bitte melde dich erneut an."
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"loadDay": "Tag konnte nicht geladen werden.",
|
"loadDay": "Tag konnte nicht geladen werden.",
|
||||||
|
|||||||
@ -81,7 +81,8 @@
|
|||||||
"created": "Item was created.",
|
"created": "Item was created.",
|
||||||
"saved": "Changes were saved.",
|
"saved": "Changes were saved.",
|
||||||
"updated": "Changes were applied.",
|
"updated": "Changes were applied.",
|
||||||
"deleted": "Item was deleted."
|
"deleted": "Item was deleted.",
|
||||||
|
"sessionExpired": "Session expired. Please sign in again."
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"loadDay": "Failed to load the day.",
|
"loadDay": "Failed to load the day.",
|
||||||
|
|||||||
@ -81,7 +81,8 @@
|
|||||||
"created": "Elemento creado.",
|
"created": "Elemento creado.",
|
||||||
"saved": "Cambios guardados.",
|
"saved": "Cambios guardados.",
|
||||||
"updated": "Cambios aplicados.",
|
"updated": "Cambios aplicados.",
|
||||||
"deleted": "Elemento eliminado."
|
"deleted": "Elemento eliminado.",
|
||||||
|
"sessionExpired": "La sesión ha caducado. Inicia sesión de nuevo."
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"loadDay": "No se pudo cargar el día.",
|
"loadDay": "No se pudo cargar el día.",
|
||||||
|
|||||||
@ -81,7 +81,8 @@
|
|||||||
"created": "Položka bola vytvorená.",
|
"created": "Položka bola vytvorená.",
|
||||||
"saved": "Zmeny boli uložené.",
|
"saved": "Zmeny boli uložené.",
|
||||||
"updated": "Zmeny boli aplikované.",
|
"updated": "Zmeny boli aplikované.",
|
||||||
"deleted": "Položka bola zmazaná."
|
"deleted": "Položka bola zmazaná.",
|
||||||
|
"sessionExpired": "Relácia vypršala. Prihlás sa znova."
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"loadDay": "Nepodarilo sa načítať deň.",
|
"loadDay": "Nepodarilo sa načítať deň.",
|
||||||
|
|||||||
@ -5,12 +5,37 @@ import App from './App.vue'
|
|||||||
import i18n from './i18n'
|
import i18n from './i18n'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
import { pinia } from './stores'
|
import { pinia } from './stores'
|
||||||
|
import { useAuthStore } from './stores/auth'
|
||||||
import { useThemeStore } from './stores/theme'
|
import { useThemeStore } from './stores/theme'
|
||||||
|
import { useUIStore } from './stores/ui'
|
||||||
|
import { SESSION_EXPIRED_EVENT } from './utils/error'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
const themeStore = useThemeStore(pinia)
|
const themeStore = useThemeStore(pinia)
|
||||||
|
const authStore = useAuthStore(pinia)
|
||||||
|
const uiStore = useUIStore(pinia)
|
||||||
themeStore.initialize()
|
themeStore.initialize()
|
||||||
|
|
||||||
|
const handleSessionExpired = async () => {
|
||||||
|
const wasAuthenticated = authStore.isAuthenticated
|
||||||
|
authStore.clearSession()
|
||||||
|
|
||||||
|
if (wasAuthenticated) {
|
||||||
|
uiStore.info(String(i18n.global.t('ux.toast.sessionExpired')))
|
||||||
|
}
|
||||||
|
|
||||||
|
await router.isReady()
|
||||||
|
if (router.currentRoute.value.name !== 'auth') {
|
||||||
|
await router.replace({ name: 'auth' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.addEventListener(SESSION_EXPIRED_EVENT, () => {
|
||||||
|
void handleSessionExpired()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
app.component('font-awesome-icon', FontAwesomeIcon)
|
app.component('font-awesome-icon', FontAwesomeIcon)
|
||||||
app.use(pinia)
|
app.use(pinia)
|
||||||
app.use(router)
|
app.use(router)
|
||||||
|
|||||||
@ -1,4 +1,46 @@
|
|||||||
export const toErrorMessage = (error: unknown, fallback: string): string => {
|
export const SESSION_EXPIRED_EVENT = 'auth:session-expired'
|
||||||
|
|
||||||
|
const TOKEN_ERROR_MESSAGES = new Set(['Invalid or expired token'])
|
||||||
|
const SESSION_EXPIRED_EVENT_THROTTLE_MS = 500
|
||||||
|
|
||||||
|
let lastSessionExpiredEventAt = 0
|
||||||
|
|
||||||
|
const resolveErrorMessage = (error: unknown): string => {
|
||||||
|
if (typeof error === 'string') {
|
||||||
|
return error
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error instanceof Error && typeof error.message === 'string') {
|
||||||
|
return error.message
|
||||||
|
}
|
||||||
|
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
const emitSessionExpiredEvent = () => {
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const now = Date.now()
|
||||||
|
if (now - lastSessionExpiredEventAt < SESSION_EXPIRED_EVENT_THROTTLE_MS) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
lastSessionExpiredEventAt = now
|
||||||
|
window.dispatchEvent(new Event(SESSION_EXPIRED_EVENT))
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isSessionExpiredError = (error: unknown): boolean => {
|
||||||
|
return TOKEN_ERROR_MESSAGES.has(resolveErrorMessage(error))
|
||||||
|
}
|
||||||
|
|
||||||
|
export const toErrorMessage = (error: unknown, fallback: string): string => {
|
||||||
|
if (isSessionExpiredError(error)) {
|
||||||
|
emitSessionExpiredEvent()
|
||||||
|
return fallback
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof error === 'string' && error.length > 0) {
|
if (typeof error === 'string' && error.length > 0) {
|
||||||
return error
|
return error
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user