From 4d8148953071cc1ca9fb01153c3bb0b7f482de5b Mon Sep 17 00:00:00 2001 From: Pranav C Date: Wed, 13 Nov 2024 07:30:14 +0000 Subject: [PATCH] refactor: token generation with token (WIP) --- .../nc-gui/composables/useApi/interceptors.ts | 5 ++ .../nc-gui/composables/useGlobal/actions.ts | 52 +++++++++++-------- .../nc-gui/composables/useGlobal/types.ts | 4 +- 3 files changed, 37 insertions(+), 24 deletions(-) diff --git a/packages/nc-gui/composables/useApi/interceptors.ts b/packages/nc-gui/composables/useApi/interceptors.ts index d194a5a590..b9a1a06b38 100644 --- a/packages/nc-gui/composables/useApi/interceptors.ts +++ b/packages/nc-gui/composables/useApi/interceptors.ts @@ -137,6 +137,11 @@ export function addAxiosInterceptors(api: Api) { }) } + try { + const token = await state.refreshToken() + refreshTokenPromiseRes(token) + } catch (e) {} + // Try request again with new token return axiosInstance .post('/auth/token/refresh', null, { diff --git a/packages/nc-gui/composables/useGlobal/actions.ts b/packages/nc-gui/composables/useGlobal/actions.ts index 5187b77d2f..b738b6a372 100644 --- a/packages/nc-gui/composables/useGlobal/actions.ts +++ b/packages/nc-gui/composables/useGlobal/actions.ts @@ -1,8 +1,10 @@ import { getActivePinia } from 'pinia' +import { useStorage } from '@vueuse/core' import type { Actions, AppInfo, State } from './types' import type { NcProjectType } from '#imports' export function useGlobalActions(state: State): Actions { + const isTokenRefreshInProgress = useStorage(TOKEN_REFRESH_PROGRESS_KEY, false) const isTokenUpdatedTab = useState('isTokenUpdatedTab', () => false) const setIsMobileMode = (isMobileMode: boolean) => { @@ -45,7 +47,7 @@ export function useGlobalActions(state: State): Actions { /** Sign in by setting the token in localStorage * keepProps - is for keeping any existing role info if user id is same as previous user * */ - const signIn: Actions['signIn'] = async (newToken, keepProps = false) => { + const signIn: Actions['signIn'] = (newToken, keepProps = false) => { isTokenUpdatedTab.value = true state.token.value = newToken @@ -63,30 +65,36 @@ export function useGlobalActions(state: State): Actions { } /** manually try to refresh token */ - const refreshToken = async () => { + const refreshToken = async ({ + axiosInstance = nuxtApp.$api.instance, + skipSignOut = false, + }: { + axiosInstance?: any + skipSignOut?: boolean + } = {}) => { const nuxtApp = useNuxtApp() const t = nuxtApp.vueApp.i18n.global.t - - return new Promise((resolve) => { - nuxtApp.$api.instance - .post('/auth/token/refresh', null, { - withCredentials: true, - }) - .then((response) => { - if (response.data?.token) { - signIn(response.data.token, true) - } - }) - .catch(async () => { - if (state.token.value && state.user.value) { - await signOut({ - skipApiCall: true, - }) - message.error(t('msg.error.youHaveBeenSignedOut')) - } + isTokenRefreshInProgress.value = true + try { + const response = await axiosInstance.post('/auth/token/refresh', null, { + withCredentials: true, + }) + if (response.data?.token) { + signIn(response.data.token, true) + return response.data.token + } + return null + } catch (e) { + if (state.token.value && state.user.value && !skipSignOut) { + await signOut({ + skipApiCall: true, }) - .finally(() => resolve(true)) - }) + message.error(t('msg.error.youHaveBeenSignedOut')) + } + return null + } finally { + isTokenRefreshInProgress.value = false + } } const loadAppInfo = async () => { diff --git a/packages/nc-gui/composables/useGlobal/types.ts b/packages/nc-gui/composables/useGlobal/types.ts index 9946ea88cb..19ccb0c655 100644 --- a/packages/nc-gui/composables/useGlobal/types.ts +++ b/packages/nc-gui/composables/useGlobal/types.ts @@ -91,8 +91,8 @@ export interface SignOutParams { export interface Actions { signOut: (signOutParams?: SignOutParams) => Promise - signIn: (token: string, keepProps?: boolean) => Promise - refreshToken: () => void + signIn: (token: string, keepProps?: boolean) => void + refreshToken: () => Promise loadAppInfo: () => void setIsMobileMode: (isMobileMode: boolean) => void navigateToProject: (params: { workspaceId?: string; baseId?: string; type?: NcProjectType; query?: any }) => void