fix: wait until everything is loaded before replacing the current view with the last or login view

This commit is contained in:
kolaente 2022-10-23 16:12:38 +02:00
parent 3f04571e43
commit 6083301d1f
Signed by untrusted user: konrad
GPG Key ID: F40E70337AB24C9B
5 changed files with 36 additions and 19 deletions

View File

@ -61,7 +61,7 @@ const route = useRoute()
const baseStore = useBaseStore() const baseStore = useBaseStore()
const ready = ref(false) const ready = computed(() => baseStore.ready)
const online = useOnline() const online = useOnline()
const error = ref('') const error = ref('')
@ -70,11 +70,11 @@ const showLoading = computed(() => !ready.value && error.value === '')
async function load() { async function load() {
try { try {
await baseStore.loadApp() await baseStore.loadApp()
const redirectTo = getAuthForRoute(route) baseStore.setReady(true)
const redirectTo = await getAuthForRoute(route)
if (typeof redirectTo !== 'undefined') { if (typeof redirectTo !== 'undefined') {
await router.push(redirectTo) await router.push(redirectTo)
} }
ready.value = true
} catch (e: unknown) { } catch (e: unknown) {
error.value = String(e) error.value = String(e)
} }

View File

@ -16,7 +16,7 @@ export function useRenewTokenOnFocus() {
authStore.renewToken() authStore.renewToken()
// Check if the token is still valid if the window gets focus again to maybe renew it // Check if the token is still valid if the window gets focus again to maybe renew it
useEventListener('focus', () => { useEventListener('focus', async () => {
if (!authenticated.value) { if (!authenticated.value) {
return return
} }
@ -26,8 +26,8 @@ export function useRenewTokenOnFocus() {
// If the token expiry is negative, it is already expired and we have no choice but to redirect // If the token expiry is negative, it is already expired and we have no choice but to redirect
// the user to the login page // the user to the login page
if (expiresIn < 0) { if (expiresIn < 0) {
authStore.checkAuth() await authStore.checkAuth()
router.push({name: 'user.login'}) await router.push({name: 'user.login'})
return return
} }

View File

@ -9,6 +9,7 @@ import {setTitle} from '@/helpers/setTitle'
import {useListStore} from '@/stores/lists' import {useListStore} from '@/stores/lists'
import {useAuthStore} from '@/stores/auth' import {useAuthStore} from '@/stores/auth'
import {useBaseStore} from '@/stores/base'
import HomeComponent from '../views/Home.vue' import HomeComponent from '../views/Home.vue'
import NotFoundComponent from '../views/404.vue' import NotFoundComponent from '../views/404.vue'
@ -464,11 +465,18 @@ const router = createRouter({
], ],
}) })
export function getAuthForRoute(route: RouteLocation) { export async function getAuthForRoute(route: RouteLocation) {
const authStore = useAuthStore() const authStore = useAuthStore()
if (authStore.authUser || authStore.authLinkShare) { if (authStore.authUser || authStore.authLinkShare) {
return return
} }
const baseStore = useBaseStore()
// When trying this before the current user was fully loaded we might get a flash of the login screen
// in the user shell. To make shure this does not happen we check if everything is ready before trying.
if (!baseStore.ready) {
return
}
// Check if the user is already logged in and redirect them to the home page if not // Check if the user is already logged in and redirect them to the home page if not
if ( if (
@ -497,7 +505,7 @@ export function getAuthForRoute(route: RouteLocation) {
} }
} }
router.beforeEach((to) => { router.beforeEach(async (to) => {
return getAuthForRoute(to) return getAuthForRoute(to)
}) })

View File

@ -117,7 +117,7 @@ export const useAuthStore = defineStore('auth', {
saveToken(response.data.token, true) saveToken(response.data.token, true)
// Tell others the user is autheticated // Tell others the user is autheticated
this.checkAuth() await this.checkAuth()
} catch (e) { } catch (e) {
if ( if (
e.response && e.response &&
@ -168,7 +168,7 @@ export const useAuthStore = defineStore('auth', {
saveToken(response.data.token, true) saveToken(response.data.token, true)
// Tell others the user is autheticated // Tell others the user is autheticated
this.checkAuth() await this.checkAuth()
} finally { } finally {
this.setIsLoading(false) this.setIsLoading(false)
} }
@ -180,12 +180,12 @@ export const useAuthStore = defineStore('auth', {
password: password, password: password,
}) })
saveToken(response.data.token, false) saveToken(response.data.token, false)
this.checkAuth() await this.checkAuth()
return response.data return response.data
}, },
// Populates user information from jwt token saved in local storage in store // Populates user information from jwt token saved in local storage in store
checkAuth() { async checkAuth() {
// This function can be called from multiple places at the same time and shortly after one another. // This function can be called from multiple places at the same time and shortly after one another.
// To prevent hitting the api too frequently or race conditions, we check at most once per minute. // To prevent hitting the api too frequently or race conditions, we check at most once per minute.
@ -209,7 +209,7 @@ export const useAuthStore = defineStore('auth', {
this.setUser(info) this.setUser(info)
if (authenticated) { if (authenticated) {
this.refreshUserInfo() await this.refreshUserInfo()
} }
} }
@ -218,6 +218,8 @@ export const useAuthStore = defineStore('auth', {
this.setUser(null) this.setUser(null)
this.redirectToProviderIfNothingElseIsEnabled() this.redirectToProviderIfNothingElseIsEnabled()
} }
return Promise.resolve(authenticated)
}, },
redirectToProviderIfNothingElseIsEnabled() { redirectToProviderIfNothingElseIsEnabled() {
@ -335,22 +337,22 @@ export const useAuthStore = defineStore('auth', {
try { try {
await refreshToken(!this.isLinkShareAuth) await refreshToken(!this.isLinkShareAuth)
this.checkAuth() await this.checkAuth()
} catch (e) { } catch (e) {
// Don't logout on network errors as the user would then get logged out if they don't have // Don't logout on network errors as the user would then get logged out if they don't have
// internet for a short period of time - such as when the laptop is still reconnecting // internet for a short period of time - such as when the laptop is still reconnecting
if (e?.request?.status) { if (e?.request?.status) {
this.logout() await this.logout()
} }
} }
}, 5000) }, 5000)
}, },
logout() { async logout() {
removeToken() removeToken()
window.localStorage.clear() // Clear all settings and history we might have saved in local storage. window.localStorage.clear() // Clear all settings and history we might have saved in local storage.
router.push({name: 'user.login'}) await router.push({name: 'user.login'})
this.checkAuth() await this.checkAuth()
}, },
}, },
}) })

View File

@ -11,6 +11,7 @@ import type {IList} from '@/modelTypes/IList'
export interface RootStoreState { export interface RootStoreState {
loading: boolean, loading: boolean,
ready: boolean,
currentList: IList | null, currentList: IList | null,
background: string, background: string,
@ -26,6 +27,7 @@ export interface RootStoreState {
export const useBaseStore = defineStore('base', { export const useBaseStore = defineStore('base', {
state: () : RootStoreState => ({ state: () : RootStoreState => ({
loading: false, loading: false,
ready: false,
// This is used to highlight the current list in menu for all list related views // This is used to highlight the current list in menu for all list related views
currentList: new ListModel({ currentList: new ListModel({
@ -95,6 +97,10 @@ export const useBaseStore = defineStore('base', {
setLogoVisible(visible: boolean) { setLogoVisible(visible: boolean) {
this.logoVisible = visible this.logoVisible = visible
}, },
setReady(ready: boolean) {
this.ready = ready
},
async handleSetCurrentList({list, forceUpdate = false} : {list: IList | null, forceUpdate: boolean}) { async handleSetCurrentList({list, forceUpdate = false} : {list: IList | null, forceUpdate: boolean}) {
if (list === null) { if (list === null) {
@ -133,7 +139,8 @@ export const useBaseStore = defineStore('base', {
async loadApp() { async loadApp() {
await checkAndSetApiUrl(window.API_URL) await checkAndSetApiUrl(window.API_URL)
useAuthStore().checkAuth() await useAuthStore().checkAuth()
this.ready = true
}, },
}, },
}) })