forked from verdnatura/salix-front
Merge pull request 'Router improvements and load roles on login' (#8) from router-improvements into dev
Reviewed-on: verdnatura/salix-front#8
This commit is contained in:
commit
aada44755c
14
cypress.json
14
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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ defineEmits(['toggle-drawer']);
|
|||
<q-icon name="arrow_drop_down" size="s" />
|
||||
<q-menu>
|
||||
<q-list style="min-width: 150px">
|
||||
<q-item clickable>
|
||||
<q-item :to="{ path: '/customer/create' }" clickable>
|
||||
<q-item-section>New customer</q-item-section>
|
||||
</q-item>
|
||||
<q-item clickable>
|
||||
|
|
|
@ -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'),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,9 +1,19 @@
|
|||
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 +23,7 @@ export function useRole() {
|
|||
}
|
||||
|
||||
return {
|
||||
fetch,
|
||||
hasAny,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<template>
|
||||
<q-card>asd</q-card>
|
||||
<q-card>Basic Data</q-card>
|
||||
</template>
|
|
@ -4,7 +4,7 @@
|
|||
<q-card square>
|
||||
<router-link :to="{ path: '/customer/list' }">
|
||||
<q-icon name="arrow_back" size="md" color="primary" />
|
||||
</router-link>
|
||||
</router-link>Descriptor
|
||||
</q-card>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { useRole } from '/src/composables/useRole';
|
||||
import { ref } from 'vue';
|
||||
|
||||
const slide = ref('style');
|
||||
const slideText = 'Description text';
|
||||
|
||||
const { hasAny } = useRole();
|
||||
|
||||
const isSalesPerson = computed(() => hasAny(['salesPerson']));
|
||||
|
||||
</script>
|
||||
|
||||
|
@ -19,9 +15,8 @@ const isSalesPerson = computed(() => hasAny(['salesPerson']));
|
|||
rounded
|
||||
class="bg-orange text-white q-mb-lg"
|
||||
>
|
||||
{{ isSalesPerson }}
|
||||
Employee notification message
|
||||
<template #action>
|
||||
<q-btn flat label="Turn ON Wifi" />
|
||||
<q-btn flat label="Dismiss" />
|
||||
</template>
|
||||
</q-banner>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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('');
|
||||
|
|
|
@ -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: '/' });
|
||||
|
|
|
@ -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: '/',
|
||||
|
|
Loading…
Reference in New Issue