From 2425e6cf2fee23ed352058c641f51fed032de9cc Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Mon, 6 Dec 2021 13:14:42 +0100 Subject: [PATCH] fix(boot): Fix navigation guards so users get redirected after logging in --- package.json | 2 +- src/boot/axios.ts | 7 +++--- src/boot/login.ts | 55 +++++++++++++++++---------------------------- src/pages/Login.vue | 10 ++++++--- 4 files changed, 31 insertions(+), 43 deletions(-) diff --git a/package.json b/package.json index 22a2980..7db11ca 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@capacitor/storage": "^1.2.3", "@flaschengeist/types": "^1.0.0-alpha.10", "@quasar/app": "^3.2.4", - "@quasar/extras": "^1.12.1", + "@quasar/extras": "^1.12.2", "@types/node": "^14.18.0", "@types/webpack": "^5.28.0", "@types/webpack-env": "^1.16.3", diff --git a/src/boot/axios.ts b/src/boot/axios.ts index ec6432d..c406e1c 100644 --- a/src/boot/axios.ts +++ b/src/boot/axios.ts @@ -94,12 +94,11 @@ export default boot(({ router }) => { query: { redirect: next }, }); } else if (e.response && e.response.status == 401) { - void store.handleLoggedOut(); - if (current.name !== 'login') { + store.handleLoggedOut(); + if (current.name != 'login') { await router.push({ name: 'login', - params: { logout: 'logout' }, - query: { redirect: current.path }, + query: { redirect: current.fullPath }, }); } } diff --git a/src/boot/login.ts b/src/boot/login.ts index 1f4e7a7..b2157e2 100644 --- a/src/boot/login.ts +++ b/src/boot/login.ts @@ -3,46 +3,31 @@ */ import { useMainStore, hasPermissions } from '@flaschengeist/api'; import { boot } from 'quasar/wrappers'; -import { RouteRecord } from 'vue-router'; export default boot(({ router }) => { - router.beforeResolve((to, from, next) => { + /** + * Login guard + * Check if user tries to access the secured area and validates token + */ + router.beforeEach((to, from) => { const store = useMainStore(); - // Skip if same path - if (to.path == from.path) return next(); + // Skip loops + if (to.name == 'login' && from.name == 'login') return false; - // Check if secured area or public - if (to.path.startsWith('/in')) { - // Secured area (LOGIN REQUIRED) - // Check login is ok - if (!store.session || store.session.expires <= new Date()) { - void store.handleLoggedOut(); - return next({ name: 'login', query: { redirect: to.fullPath } }); - } - - // Check if special permissions are required - if ( - to.matched.every((record: RouteRecord) => { - if (!('meta' in record) || !('permissions' in record.meta)) return true; - if ((<{ permissions: FG.Permission[] }>record.meta).permissions) { - return hasPermissions((<{ permissions: FG.Permission[] }>record.meta).permissions); - } - }) - ) { - return next(); - } else { - return next({ name: 'login', query: { redirect: to.fullPath } }); - } - } else { - // Public space just handle login loops - if (to.name == 'login' && store.user && !to.params['logout']) { - // Called login while already logged in - return next({ name: 'dashboard' }); - } else { - // We are on the non secured area - return next(); - } + // Secured area '/in/...' requires to be authenticated + if (to.path.startsWith('/in') && (!store.session || store.session.expires <= new Date())) { + store.handleLoggedOut(); + return { name: 'login' }; } }); + + /** + * Permission guard + * Check permissions for route, cancel navigation on errors + */ + router.beforeResolve((to) => { + if (!!to.meta.permissions && !hasPermissions(to.meta.permissions)) + return false; + }); }); diff --git a/src/pages/Login.vue b/src/pages/Login.vue index f5ee75c..cf8eeea 100644 --- a/src/pages/Login.vue +++ b/src/pages/Login.vue @@ -119,10 +119,14 @@ export default defineComponent({ if (status === true) { // On capacitor we set the lifetime to at least two weeks to not annoy users. if (quasar.platform.is.capacitor) - void sessionStore.updateSession(14 * 24 * 60 * 60, mainStore.currentSession.token); + await sessionStore.updateSession(14 * 24 * 60 * 60, mainStore.currentSession.token); // Redirect user to previous page, if any. - const x = router.currentRoute.value.query['redirect']; - void router.push(!!x && typeof x === 'string' ? { path: x } : mainRoute); + const redirect = + router.currentRoute.value.redirectedFrom || 'redirect' in router.currentRoute.value.query + ? { path: router.currentRoute.value.query.redirect as string } + : mainRoute; + + void router.push(redirect); } else { // Login failed, notify and reset form password.value = '';