diff --git a/src/components/misc/ready.vue b/src/components/misc/ready.vue index d9493c0489..e00e7a63bb 100644 --- a/src/components/misc/ready.vue +++ b/src/components/misc/ready.vue @@ -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) } diff --git a/src/composables/useRenewTokenOnFocus.ts b/src/composables/useRenewTokenOnFocus.ts index 06305984e8..c5ed0fa653 100644 --- a/src/composables/useRenewTokenOnFocus.ts +++ b/src/composables/useRenewTokenOnFocus.ts @@ -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 } diff --git a/src/router/index.ts b/src/router/index.ts index d836fc6b46..06120f6f03 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -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) }) diff --git a/src/stores/auth.ts b/src/stores/auth.ts index 7bece3482d..13d354a49b 100644 --- a/src/stores/auth.ts +++ b/src/stores/auth.ts @@ -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() }, }, }) diff --git a/src/stores/base.ts b/src/stores/base.ts index 83be641334..d00ad57bf5 100644 --- a/src/stores/base.ts +++ b/src/stores/base.ts @@ -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 }, }, })