From ad9be84b9c20aed3f3ee46dabe4a747ad97fbdc9 Mon Sep 17 00:00:00 2001 From: wbuezas Date: Sun, 22 Dec 2024 21:53:44 -0300 Subject: [PATCH] Renew token improvements --- src/boot/axios.js | 16 +++++++-- src/pages/Login/LoginView.vue | 11 ++---- src/router/index.js | 38 ++++++++++---------- src/stores/user.js | 67 +++++++++++++++++++++-------------- 4 files changed, 76 insertions(+), 56 deletions(-) diff --git a/src/boot/axios.js b/src/boot/axios.js index 9d86aea4..1235d58e 100644 --- a/src/boot/axios.js +++ b/src/boot/axios.js @@ -4,7 +4,7 @@ import { useUserStore } from '@/stores/user'; import axios from 'axios'; import useNotify from '@/composables/useNotify.js'; import { useAppStore } from '@/stores/app'; - +import { Router } from 'src/router'; const { notify } = useNotify(); // Be careful when using SSR for cross-request state pollution // due to creating a Singleton instance here; @@ -22,6 +22,8 @@ const onRequestError = error => { }; const onResponseError = error => { + const userStore = useUserStore(); + let message = error.message; const response = error.response; @@ -33,7 +35,14 @@ const onResponseError = error => { notify(message, 'negative'); - return Promise.reject(error); + if (userStore.isLoggedIn && response?.status === 401) { + if (!Router) return; + + Router.push({ name: 'login' }); + userStore.destroy(false); + } else if (!userStore.isLoggedIn) { + return Promise.reject(error); + } }; export default boot(({ app }) => { @@ -41,7 +50,8 @@ export default boot(({ app }) => { const appStore = useAppStore(); function addToken(config) { if (userStore.token) { - config.headers.Authorization = userStore.token; + if (!config.headers.Authorization) + config.headers.Authorization = userStore.token; config.headers['Accept-Language'] = appStore.siteLang; } return config; diff --git a/src/pages/Login/LoginView.vue b/src/pages/Login/LoginView.vue index ac9cf77a..3e95f630 100644 --- a/src/pages/Login/LoginView.vue +++ b/src/pages/Login/LoginView.vue @@ -4,7 +4,7 @@ import { useI18n } from 'vue-i18n'; import { useUserStore } from 'stores/user'; import useNotify from 'src/composables/useNotify.js'; -import { useRouter, useRoute } from 'vue-router'; +import { useRoute } from 'vue-router'; import { storeToRefs } from 'pinia'; import { useAppStore } from 'src/stores/app'; @@ -14,7 +14,6 @@ const { locale } = useI18n({ useScope: 'global' }); const userStore = useUserStore(); const appStore = useAppStore(); const route = useRoute(); -const router = useRouter(); const { siteLang, localeOptions } = storeToRefs(appStore); const email = ref(null); @@ -45,20 +44,14 @@ onMounted(() => { } }); -const onLogin = async () => { - await userStore.fetchUser(); - await router.push({ name: 'home' }); -}; - const login = async () => { await userStore.login(email.value, password.value, remember.value); - await onLogin(); }; const loginAsGuest = async () => { userStore.isGuest = true; localStorage.setItem('hederaGuest', true); - await onLogin(); + await userStore.onLogin(); }; diff --git a/src/router/index.js b/src/router/index.js index ab2967a8..07bdc997 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -18,25 +18,27 @@ import routes from './routes'; * with the Router instance. */ +const createHistory = process.env.SERVER + ? createMemoryHistory + : process.env.VUE_ROUTER_MODE === 'history' + ? createWebHistory + : createWebHashHistory; + +const Router = createRouter({ + scrollBehavior: () => ({ left: 0, top: 0 }), + routes, + + // Leave this as is and make changes in quasar.conf.js instead! + // quasar.conf.js -> build -> vueRouterMode + // quasar.conf.js -> build -> publicPath + history: createHistory( + process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE + ) +}); + +export { Router }; + export default route(function (/* { store, ssrContext } */) { - const createHistory = process.env.SERVER - ? createMemoryHistory - : process.env.VUE_ROUTER_MODE === 'history' - ? createWebHistory - : createWebHashHistory; - - const Router = createRouter({ - scrollBehavior: () => ({ left: 0, top: 0 }), - routes, - - // Leave this as is and make changes in quasar.conf.js instead! - // quasar.conf.js -> build -> vueRouterMode - // quasar.conf.js -> build -> publicPath - history: createHistory( - process.env.MODE === 'ssr' ? void 0 : process.env.VUE_ROUTER_BASE - ) - }); - Router.beforeEach((to, from, next) => { const userStore = useUserStore(); const allowedRoutes = ['login', 'recoverPassword']; diff --git a/src/stores/user.js b/src/stores/user.js index b27737e2..d45c3c3b 100644 --- a/src/stores/user.js +++ b/src/stores/user.js @@ -25,7 +25,8 @@ export const useUserStore = defineStore('user', () => { const storage = computed(() => keepLogin.value ? localStorage : sessionStorage ); - const isLoggedIn = computed(() => !!storage.value.getItem(TOKEN)); + + const isLoggedIn = computed(() => !!token.value); const init = async _router => { router = _router; @@ -87,9 +88,9 @@ export const useUserStore = defineStore('user', () => { let destroyTokenPromises = []; try { if (destroyTokens) { - const { data: isValidToken } = await api.get( - 'VnUsers/validateToken' - ); + const response = await api.get('VnUsers/validateToken'); + const isValidToken = response?.data; + if (isValidToken) { destroyTokenPromises = Object.entries(tokens).map( ([key, url]) => destroyToken(url, storage.value, key) @@ -101,6 +102,7 @@ export const useUserStore = defineStore('user', () => { sessionStorage.clear(); await Promise.allSettled(destroyTokenPromises); user.value = null; + $reset(); stopRenewer(); } }; @@ -117,30 +119,43 @@ export const useUserStore = defineStore('user', () => { }; const fetchMultimediaToken = async data => { - const { - data: { multimediaToken } - } = await api.get('VnUsers/ShareToken', { - headers: { Authorization: data.token } - }); - return multimediaToken; + try { + const response = await api.get('VnUsers/ShareToken', { + headers: { Authorization: data.token } + }); + const multimediaToken = response?.data?.multimediaToken; + return multimediaToken; + } catch (error) { + throw new Error('Error fetching multimedia token'); + } + }; + + const onLogin = async () => { + await fetchUser(); + router.push({ name: 'home' }); }; const login = async (username, password, remember) => { - const params = { user: username, password }; - const { data } = await api.post('Accounts/login', params); + try { + const params = { user: username, password }; + const { data } = await api.post('Accounts/login', params); - const multimediaToken = await fetchMultimediaToken(data); - if (!multimediaToken) return; + const multimediaToken = await fetchMultimediaToken(data); + if (!multimediaToken) return; - keepLogin.value = remember; - setSession({ - created: Date.now(), - tokenMultimedia: multimediaToken.id, - username, - ...data - }); - await fetchTokenConfig(); - startInterval(); + keepLogin.value = remember; + setSession({ + created: Date.now(), + tokenMultimedia: multimediaToken.id, + username, + ...data + }); + await fetchTokenConfig(); + startInterval(); + await onLogin(); + } catch (error) { + throw new Error('Error logging in'); + } }; const tryAutoLogin = async () => { @@ -161,7 +176,6 @@ export const useUserStore = defineStore('user', () => { await api.post('Accounts/logout'); } catch (e) {} destroy(); - $reset(); useAppStore().onLogout(); }; @@ -192,8 +206,8 @@ export const useUserStore = defineStore('user', () => { }); setToken({ - _token: tokenData.data.id, - _tokenMultimedia: tokenMultimedia.data.id + _token: tokenData?.data?.id || '', + _tokenMultimedia: tokenMultimedia?.data?.id || '' }); }; @@ -272,6 +286,7 @@ export const useUserStore = defineStore('user', () => { const $reset = () => { token.value = ''; + tokenMultimedia.value = ''; isGuest.value = false; user.value = null; supplantedUser.value = null;