fix: wait until everything is loaded before replacing the current view with the last or login view
continuous-integration/drone/push Build is passing Details

This commit is contained in:
kolaente 2022-10-23 16:12:38 +02:00
parent 3f04571e43
commit 6083301d1f
Signed by: 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 ready = ref(false)
const ready = computed(() => baseStore.ready)
const online = useOnline()
const error = ref('')
@ -70,11 +70,11 @@ const showLoading = computed(() => !ready.value && error.value === '')
async function load() {
try {
await baseStore.loadApp()
const redirectTo = getAuthForRoute(route)
baseStore.setReady(true)
const redirectTo = await getAuthForRoute(route)
if (typeof redirectTo !== 'undefined') {
await router.push(redirectTo)
}
ready.value = true
} catch (e: unknown) {
error.value = String(e)
}

View File

@ -16,7 +16,7 @@ export function useRenewTokenOnFocus() {
authStore.renewToken()
// 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) {
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
// the user to the login page
if (expiresIn < 0) {
authStore.checkAuth()
router.push({name: 'user.login'})
await authStore.checkAuth()
await router.push({name: 'user.login'})
return
}

View File

@ -9,6 +9,7 @@ import {setTitle} from '@/helpers/setTitle'
import {useListStore} from '@/stores/lists'
import {useAuthStore} from '@/stores/auth'
import {useBaseStore} from '@/stores/base'
import HomeComponent from '../views/Home.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()
if (authStore.authUser || authStore.authLinkShare) {
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
if (
@ -497,7 +505,7 @@ export function getAuthForRoute(route: RouteLocation) {
}
}
router.beforeEach((to) => {
router.beforeEach(async (to) => {
return getAuthForRoute(to)
})

View File

@ -117,7 +117,7 @@ export const useAuthStore = defineStore('auth', {
saveToken(response.data.token, true)
// Tell others the user is autheticated
this.checkAuth()
await this.checkAuth()
} catch (e) {
if (
e.response &&
@ -168,7 +168,7 @@ export const useAuthStore = defineStore('auth', {
saveToken(response.data.token, true)
// Tell others the user is autheticated
this.checkAuth()
await this.checkAuth()
} finally {
this.setIsLoading(false)
}
@ -180,12 +180,12 @@ export const useAuthStore = defineStore('auth', {
password: password,
})
saveToken(response.data.token, false)
this.checkAuth()
await this.checkAuth()
return response.data
},
// 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.
// 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)
if (authenticated) {
this.refreshUserInfo()
await this.refreshUserInfo()
}
}
@ -218,6 +218,8 @@ export const useAuthStore = defineStore('auth', {
this.setUser(null)
this.redirectToProviderIfNothingElseIsEnabled()
}
return Promise.resolve(authenticated)
},
redirectToProviderIfNothingElseIsEnabled() {
@ -335,22 +337,22 @@ export const useAuthStore = defineStore('auth', {
try {
await refreshToken(!this.isLinkShareAuth)
this.checkAuth()
await this.checkAuth()
} catch (e) {
// 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
if (e?.request?.status) {
this.logout()
await this.logout()
}
}
}, 5000)
},
logout() {
async logout() {
removeToken()
window.localStorage.clear() // Clear all settings and history we might have saved in local storage.
router.push({name: 'user.login'})
this.checkAuth()
await router.push({name: 'user.login'})
await this.checkAuth()
},
},
})

View File

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