From 7f3010869b18df64ad5eb6ebe245238c439f8af9 Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 5 Apr 2022 16:30:53 +0200 Subject: [PATCH 1/4] Router improvements and load roles on login --- src/components/Navbar.vue | 2 +- src/components/UserPanel.vue | 12 ++++++------ src/composables/useRole.js | 16 ++++++++++++++-- src/composables/useSession.js | 10 ++++++++++ src/pages/Customer/Card/CustomerBasicData.vue | 2 +- src/pages/Customer/Card/CustomerCard.vue | 2 +- src/pages/Dashboard/Dashboard.vue | 9 ++------- src/pages/Login/Login.vue | 12 +++++++----- src/router/index.js | 12 ++++++------ src/router/routes.js | 2 +- 10 files changed, 49 insertions(+), 30 deletions(-) diff --git a/src/components/Navbar.vue b/src/components/Navbar.vue index d5382b264..d25fe43a2 100644 --- a/src/components/Navbar.vue +++ b/src/components/Navbar.vue @@ -32,7 +32,7 @@ defineEmits(['toggle-drawer']); - + New customer diff --git a/src/components/UserPanel.vue b/src/components/UserPanel.vue index 679ec6859..1d97bfbc9 100644 --- a/src/components/UserPanel.vue +++ b/src/components/UserPanel.vue @@ -3,14 +3,15 @@ import { onMounted, computed } from 'vue'; import { Dark, useQuasar } from 'quasar'; import { useI18n } from 'vue-i18n'; import { useRouter } from 'vue-router'; -import axios from 'axios'; import { useState } from 'src/composables/useState'; import { useSession } from 'src/composables/useSession'; +import { useRole } from 'src/composables/useRole'; const quasar = useQuasar(); const state = useState(); const session = useSession(); +const role = useRole(); const router = useRouter(); const { t, locale } = useI18n(); @@ -28,11 +29,10 @@ const token = session.getToken(); onMounted(async () => { try { - const { data } = await axios.get('/api/accounts/acl'); - const roles = data.roles.map(userRoles => userRoles.role.name); - - state.setUser(data.user); - state.setRoles(roles); + const stateRoles = state.getRoles().value + if (stateRoles.length === 0) { + await role.fetch(); + } } catch (error) { quasar.notify({ message: t('errors.statusUnauthorized'), diff --git a/src/composables/useRole.js b/src/composables/useRole.js index 8d9ae8b8d..5cf4c3e29 100644 --- a/src/composables/useRole.js +++ b/src/composables/useRole.js @@ -1,9 +1,20 @@ import { useState } from './useState'; +import axios from 'axios'; + + +const state = useState(); export function useRole() { + async function fetch() { + const { data } = await axios.get('/api/accounts/acl'); + const roles = data.roles.map(userRoles => userRoles.role.name); + + state.setUser(data.user); + state.setRoles(roles); + } + function hasAny(roles) { - const { getRoles } = useState(); - const roleStore = getRoles(); + const roleStore = state.getRoles(); for (const role of roles) { if (roleStore.value.indexOf(role) !== -1) return true; @@ -13,6 +24,7 @@ export function useRole() { } return { + fetch, hasAny, }; } diff --git a/src/composables/useSession.js b/src/composables/useSession.js index 3a60c33b9..e52829ba7 100644 --- a/src/composables/useSession.js +++ b/src/composables/useSession.js @@ -1,4 +1,5 @@ import { useState } from './useState'; +import { useRole } from './useRole'; export function useSession() { function getToken() { @@ -29,6 +30,14 @@ export function useSession() { }); } + async function login(token, keepLogin) { + const { fetch } = useRole(); + + setToken({ token, keepLogin }); + + await fetch(); + } + function isLoggedIn() { const localToken = localStorage.getItem('token'); const sessionToken = sessionStorage.getItem('token'); @@ -40,6 +49,7 @@ export function useSession() { getToken, setToken, destroy, + login, isLoggedIn, }; } diff --git a/src/pages/Customer/Card/CustomerBasicData.vue b/src/pages/Customer/Card/CustomerBasicData.vue index 97af8c637..b4e913ad5 100644 --- a/src/pages/Customer/Card/CustomerBasicData.vue +++ b/src/pages/Customer/Card/CustomerBasicData.vue @@ -1,3 +1,3 @@ \ No newline at end of file diff --git a/src/pages/Customer/Card/CustomerCard.vue b/src/pages/Customer/Card/CustomerCard.vue index d386fb094..152c8cfdc 100644 --- a/src/pages/Customer/Card/CustomerCard.vue +++ b/src/pages/Customer/Card/CustomerCard.vue @@ -4,7 +4,7 @@ - + Descriptor diff --git a/src/pages/Dashboard/Dashboard.vue b/src/pages/Dashboard/Dashboard.vue index 3b1ac8f33..f02d33f3f 100644 --- a/src/pages/Dashboard/Dashboard.vue +++ b/src/pages/Dashboard/Dashboard.vue @@ -1,13 +1,9 @@ @@ -19,9 +15,8 @@ const isSalesPerson = computed(() => hasAny(['salesPerson'])); rounded class="bg-orange text-white q-mb-lg" > - {{ isSalesPerson }} + Employee notification message diff --git a/src/pages/Login/Login.vue b/src/pages/Login/Login.vue index 2c18a4283..a49222ab4 100644 --- a/src/pages/Login/Login.vue +++ b/src/pages/Login/Login.vue @@ -32,17 +32,19 @@ async function onSubmit() { password: password.value, }); - session.setToken({ - token: data.token, - keepLogin: keepLogin.value, - }); + await session.login(data.token, keepLogin.value); quasar.notify({ message: t('login.loginSuccess'), type: 'positive', }); - await router.push({ path: '/dashboard' }); + const currentRoute = router.currentRoute.value; + if (currentRoute.query && currentRoute.query.redirect) { + router.push(currentRoute.query.redirect); + } else { + router.push({ name: 'Dashboard' }); + } } catch (error) { if (axios.isAxiosError(error)) { const errorCode = error.response && error.response.status; diff --git a/src/router/index.js b/src/router/index.js index 476d34a81..221671eb0 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -36,18 +36,18 @@ export default route(function (/* { store, ssrContext } */) { Router.beforeEach((to, from, next) => { const { isLoggedIn } = session; - if (!isLoggedIn && to.name !== 'Login') { - next({ path: '/login', query: { redirect: to.fullPath } }); + if (!isLoggedIn() && to.name !== 'Login') { + next({ name: 'Login', query: { redirect: to.fullPath } }); } else { - const pathRoutes = to.matched; - const droles = pathRoutes.every(route => { + const matches = to.matched; + const hasRequiredRoles = matches.every(route => { const meta = route.meta; - if (meta.roles) + if (meta && meta.roles) return role.hasAny(meta.roles) return true; }); - if (droles) { + if (hasRequiredRoles) { next(); } else { next({ path: '/' }); diff --git a/src/router/routes.js b/src/router/routes.js index e40a9ef89..d4b63df1d 100644 --- a/src/router/routes.js +++ b/src/router/routes.js @@ -6,7 +6,7 @@ const routes = [ path: '/login', name: 'Login', meta: { title: 'logIn' }, - component: () => import('../pages/Login/Login.vue'), + component: () => import('../pages/Login/Login.vue') }, { path: '/', From 9a9bcc5e51bc3f21da9be89ad132b8be8121bff8 Mon Sep 17 00:00:00 2001 From: joan Date: Tue, 5 Apr 2022 16:32:30 +0200 Subject: [PATCH 2/4] Removed empty line --- src/composables/useRole.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/composables/useRole.js b/src/composables/useRole.js index 5cf4c3e29..664dc2f66 100644 --- a/src/composables/useRole.js +++ b/src/composables/useRole.js @@ -1,7 +1,6 @@ import { useState } from './useState'; import axios from 'axios'; - const state = useState(); export function useRole() { From 20604a2441f6511c38b6392a5dbba80da6fc798a Mon Sep 17 00:00:00 2001 From: carlosjr Date: Wed, 6 Apr 2022 08:46:34 +0200 Subject: [PATCH 3/4] front unit test fixed after login enhancement --- src/components/__tests__/UserPanel.spec.js | 4 ++-- src/pages/Login/__tests__/Login.spec.js | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/__tests__/UserPanel.spec.js b/src/components/__tests__/UserPanel.spec.js index 7b8b3ba51..3d5182890 100644 --- a/src/components/__tests__/UserPanel.spec.js +++ b/src/components/__tests__/UserPanel.spec.js @@ -12,7 +12,7 @@ jest.mock('vue-router', () => ({ describe('UserPanel', () => { describe('onMounted', () => { - it('should define the user into state', async () => { + it.only('should define the user into state', async () => { const userMock = { user: { id: 1, @@ -30,7 +30,7 @@ describe('UserPanel', () => { expect(vm.state.getUser().value).toEqual(expectedUser); }); - xit('should logout and notify the expected error', async () => { + it('should logout and notify the expected error', async () => { jest.spyOn(axios, 'get').mockRejectedValue(new Error('error')); const { vm } = createWrapper(UserPanel); diff --git a/src/pages/Login/__tests__/Login.spec.js b/src/pages/Login/__tests__/Login.spec.js index 1778a6002..36323d1ed 100644 --- a/src/pages/Login/__tests__/Login.spec.js +++ b/src/pages/Login/__tests__/Login.spec.js @@ -7,6 +7,7 @@ const mockPush = jest.fn(); jest.mock('vue-router', () => ({ useRouter: () => ({ push: mockPush, + currentRoute: { value: 'myCurrentRoute' } }), })); @@ -18,6 +19,7 @@ describe('Login', () => { it('should successfully set the token into session', async () => { jest.spyOn(axios, 'post').mockResolvedValue({ data: { token: 'token' } }); + jest.spyOn(axios, 'get').mockResolvedValue({ data: { roles: [], user: { id: 1 } } }); jest.spyOn(vm.quasar, 'notify') expect(vm.session.getToken()).toEqual(''); From 565b91b235bc600dfaf9c5d6c39f9a3d07129ee9 Mon Sep 17 00:00:00 2001 From: carlosjr Date: Wed, 6 Apr 2022 08:50:53 +0200 Subject: [PATCH 4/4] cypress tests working after updating file paths --- cypress.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cypress.json b/cypress.json index a8b2f0d73..59e0ef6cc 100644 --- a/cypress.json +++ b/cypress.json @@ -1,15 +1,15 @@ { "baseUrl": "http://localhost:8080/", - "fixturesFolder": "test/cypress/fixtures", - "integrationFolder": "test/cypress/integration", - "pluginsFile": "test/cypress/plugins/index.js", - "screenshotsFolder": "test/cypress/screenshots", - "supportFile": "test/cypress/support/index.js", - "videosFolder": "test/cypress/videos", + "fixturesFolder": "tests/cypress/fixtures", + "integrationFolder": "tests/cypress/integration", + "pluginsFile": "tests/cypress/plugins/index.js", + "screenshotsFolder": "tests/cypress/screenshots", + "supportFile": "tests/cypress/support/index.js", + "videosFolder": "tests/cypress/videos", "video": true, "component": { "componentFolder": "src", "testFiles": "**/*.spec.js", - "supportFile": "test/cypress/support/unit.js" + "supportFile": "tests/cypress/support/unit.js" } }