add: guard in router
This commit is contained in:
@@ -3,9 +3,18 @@
|
|||||||
import { useAuthStore } from '../stores/auth';
|
import { useAuthStore } from '../stores/auth';
|
||||||
import Swal from 'sweetalert2';
|
import Swal from 'sweetalert2';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useCompanyStore } from '../stores/company';
|
||||||
|
import { useVehiclesStore } from '../stores/vehicles';
|
||||||
|
import { useLoadsStore } from '../stores/loads';
|
||||||
|
import { useNotificationsStore } from '../stores/notifications';
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const auth = useAuthStore();
|
const auth = useAuthStore();
|
||||||
|
const company = useCompanyStore();
|
||||||
|
const vehicles = useVehiclesStore();
|
||||||
|
const loads = useLoadsStore();
|
||||||
|
const noty = useNotificationsStore();
|
||||||
|
const router = useRouter();
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
@@ -20,6 +29,11 @@
|
|||||||
}).then(async(result) => {
|
}).then(async(result) => {
|
||||||
if(result.isConfirmed) {
|
if(result.isConfirmed) {
|
||||||
auth.logout();
|
auth.logout();
|
||||||
|
company.clear();
|
||||||
|
vehicles.clear();
|
||||||
|
loads.clear();
|
||||||
|
noty.clear();
|
||||||
|
router.push({name: 'login'});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,13 @@ import App from './App.vue'
|
|||||||
import router from './router'
|
import router from './router'
|
||||||
import i18n from './i18n/i18n'
|
import i18n from './i18n/i18n'
|
||||||
|
|
||||||
|
const pinia = createPinia();
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
app.use(createPinia())
|
|
||||||
app.use(router)
|
app.use(router)
|
||||||
|
app.use(pinia)
|
||||||
|
|
||||||
app.use(i18n)
|
app.use(i18n)
|
||||||
|
|
||||||
|
|
||||||
app.mount('#app')
|
app.mount('#app')
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
import AuthLayout from '../layouts/AuthLayout.vue'
|
import AuthLayout from '../layouts/AuthLayout.vue'
|
||||||
import PublicLayout from '../layouts/PublicLayout.vue'
|
import PublicLayout from '../layouts/PublicLayout.vue'
|
||||||
|
import { useAuthStore } from '../stores/auth';
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
@@ -30,6 +31,11 @@ const router = createRouter({
|
|||||||
name: 'register-company',
|
name: 'register-company',
|
||||||
component: () => import('../views/CompleteRegisterView.vue')
|
component: () => import('../views/CompleteRegisterView.vue')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/:pathMatch(.*)*',
|
||||||
|
name: 'not-found',
|
||||||
|
component: () => import('../views/LoginView.vue'),
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -68,88 +74,121 @@ const router = createRouter({
|
|||||||
path: '/dashboard',
|
path: '/dashboard',
|
||||||
name: 'dashboard',
|
name: 'dashboard',
|
||||||
component: () => import('../layouts/AdminLayout.vue'),
|
component: () => import('../layouts/AdminLayout.vue'),
|
||||||
meta: { requiresAuth: true },
|
meta: {
|
||||||
|
requiresAuth: true,
|
||||||
|
roles: ['manager', 'staff', 'owner']
|
||||||
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'inicio',
|
path: 'inicio',
|
||||||
name: 'home',
|
name: 'home',
|
||||||
|
meta: { permissions: ['role_shipper', 'role_carrier'] },
|
||||||
component: () => import('../views/HomeView.vue'),
|
component: () => import('../views/HomeView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'empresa',
|
path: 'empresa',
|
||||||
name: 'company',
|
name: 'company',
|
||||||
|
meta: { permissions: ['role_shipper', 'role_carrier'] },
|
||||||
component: () => import('../views/MyCompanyView.vue'),
|
component: () => import('../views/MyCompanyView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'profile',
|
path: 'profile',
|
||||||
name: 'profile',
|
name: 'profile',
|
||||||
|
meta: { permissions: ['role_shipper', 'role_carrier'] },
|
||||||
component: () => import('../views/EditProfileView.vue'),
|
component: () => import('../views/EditProfileView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'empresa/:id',
|
path: 'empresa/:id',
|
||||||
name: 'public-users',
|
name: 'public-users',
|
||||||
|
meta: { permissions: ['role_shipper', 'role_carrier'] },
|
||||||
component: () => import('../views/PublicUsersCompanyView.vue'),
|
component: () => import('../views/PublicUsersCompanyView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'ubicaciones',
|
path: 'ubicaciones',
|
||||||
name: 'locations',
|
name: 'locations',
|
||||||
|
meta: { permissions: ['role_shipper', 'role_carrier'] },
|
||||||
component: () => import('../views/LocationsView.vue'),
|
component: () => import('../views/LocationsView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'ofertas',
|
path: 'ofertas',
|
||||||
name: 'published-trucks',
|
name: 'published-trucks',
|
||||||
|
meta: { permissions: ['role_carrier'] },
|
||||||
component: () => import('../views/TrucksPublishedView.vue'),
|
component: () => import('../views/TrucksPublishedView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'usuarios',
|
path: 'usuarios',
|
||||||
name: 'users',
|
name: 'users',
|
||||||
|
meta: { permissions: ['role_shipper', 'role_carrier'] },
|
||||||
component: () => import('../views/UsersView.vue'),
|
component: () => import('../views/UsersView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'calculadora',
|
path: 'calculadora',
|
||||||
name: 'calculator',
|
name: 'calculator',
|
||||||
|
meta: { permissions: ['role_carrier'] },
|
||||||
component: () => import('../views/CalculatorView.vue'),
|
component: () => import('../views/CalculatorView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'reportes',
|
path: 'reportes',
|
||||||
name: 'reports',
|
name: 'reports',
|
||||||
|
meta: { permissions: ['role_shipper', 'role_carrier'] },
|
||||||
component: () => import('../views/ReportsView.vue'),
|
component: () => import('../views/ReportsView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'calendario',
|
path: 'calendario',
|
||||||
name: 'calendar',
|
name: 'calendar',
|
||||||
|
meta: {
|
||||||
|
permissions: ['role_shipper', 'role_carrier'],
|
||||||
|
roles: ['staff', 'manager', 'owner', 'store']
|
||||||
|
},
|
||||||
component: () => import('../views/CalendarView.vue'),
|
component: () => import('../views/CalendarView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'cargas',
|
path: 'cargas',
|
||||||
|
meta: { permissions: ['role_shipper'] },
|
||||||
name: 'published-loads',
|
name: 'published-loads',
|
||||||
component: () => import('../views/LoadsPublishedView.vue'),
|
component: () => import('../views/LoadsPublishedView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'vehiculos',
|
path: 'vehiculos',
|
||||||
name: 'vehicles',
|
name: 'vehicles',
|
||||||
|
meta: { permissions: ['role_carrier'] },
|
||||||
component: () => import('../views/VehiclesView.vue'),
|
component: () => import('../views/VehiclesView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'transportistas',
|
path: 'transportistas',
|
||||||
name: 'carriers',
|
name: 'carriers',
|
||||||
|
meta: { permissions: ['role_shipper'] },
|
||||||
component: () => import('../views/CarriersView.vue'),
|
component: () => import('../views/CarriersView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'embarcadores',
|
path: 'embarcadores',
|
||||||
name: 'shippers',
|
name: 'shippers',
|
||||||
|
meta: { permissions: ['role_carrier'] },
|
||||||
component: () => import('../views/ShippersView.vue'),
|
component: () => import('../views/ShippersView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'buscar-cargas',
|
path: 'buscar-cargas',
|
||||||
name: 'search-loads',
|
name: 'search-loads',
|
||||||
|
meta: { permissions: ['role_carrier'] },
|
||||||
component: () => import('../views/SearchLoadsView.vue'),
|
component: () => import('../views/SearchLoadsView.vue'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'buscar-vehiclulos',
|
path: 'buscar-vehiculos',
|
||||||
name: 'search-vehicles',
|
name: 'search-vehicles',
|
||||||
|
meta: { permissions: ['role_shipper'] },
|
||||||
component: () => import('../views/SearchVehiclesView.vue'),
|
component: () => import('../views/SearchVehiclesView.vue'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '403',
|
||||||
|
name: '403',
|
||||||
|
meta: { permissions: ['role_shipper', 'role_carrier'] },
|
||||||
|
component: () => import('../views/NotFoundView.vue'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/:pathMatch(.*)*',
|
||||||
|
name: 'not-found',
|
||||||
|
component: () => import('../views/HomeView.vue'),
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -158,16 +197,63 @@ const router = createRouter({
|
|||||||
router.beforeEach( async(to, from, next) => {
|
router.beforeEach( async(to, from, next) => {
|
||||||
const requiresAuth = to.matched.some(url => url.meta.requiresAuth)
|
const requiresAuth = to.matched.some(url => url.meta.requiresAuth)
|
||||||
if(requiresAuth === true) {
|
if(requiresAuth === true) {
|
||||||
|
const auth = useAuthStore()
|
||||||
const session = localStorage.getItem('session');
|
const session = localStorage.getItem('session');
|
||||||
//Comprobamos si el usuario esta authenticado
|
const permissions = to.meta.permissions;
|
||||||
|
const roles = to.meta.roles;
|
||||||
|
|
||||||
if(session) {
|
if(session) {
|
||||||
|
await auth.checkSession()
|
||||||
|
const permissionUser = auth?.user?.permissions;
|
||||||
|
const role = auth?.user?.job_role;
|
||||||
|
if (!permissionUser) {
|
||||||
|
return next({name: 'login'}); // Redirige al login si no está autenticado
|
||||||
|
}
|
||||||
|
|
||||||
|
if (permissions && !permissions.includes(permissionUser)) {
|
||||||
|
if(role === 'store') { /// Check if user is store
|
||||||
|
return next({name: 'calendar'});
|
||||||
|
} else {
|
||||||
|
return next({name: 'home'});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(roles && !roles.includes(role)) {
|
||||||
|
return next({name: 'calendar'});
|
||||||
|
}
|
||||||
|
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
next({name: 'login'})
|
return next({name: 'login'})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// router.beforeEach( async(to, from, next) => {
|
||||||
|
// const requiresAuth = to.matched.some(url => url.meta.requiresAuth)
|
||||||
|
// if(requiresAuth === true) {
|
||||||
|
// const session = localStorage.getItem('session');
|
||||||
|
// const role = localStorage.getItem('user');
|
||||||
|
// const permissions = to.meta.permissions;
|
||||||
|
// const auth = useAuthStore()
|
||||||
|
// //Comprobamos si el usuario esta authenticado
|
||||||
|
// if(session) {
|
||||||
|
// if (!role) {
|
||||||
|
// return next({name: 'login'}); // Redirige al login si no está autenticado
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (permissions && !permissions.includes(role)) {
|
||||||
|
// return next({name: 'home'}); // Redirige a una página de acceso denegado si no tiene permisos
|
||||||
|
// }
|
||||||
|
// next();
|
||||||
|
// } else {
|
||||||
|
// return next({name: 'login'})
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// next();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
|
|||||||
@@ -3,9 +3,7 @@ import { ref, onMounted } from "vue";
|
|||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { renewToken } from '../services/auth';
|
import { renewToken } from '../services/auth';
|
||||||
import {useNotificationsStore} from './notifications';
|
import {useNotificationsStore} from './notifications';
|
||||||
import {useCompanyStore} from './company';
|
|
||||||
import { useLoadsStore } from "./loads";
|
import { useLoadsStore } from "./loads";
|
||||||
import { useVehiclesStore } from "./vehicles";
|
|
||||||
import { updateMyUserProfile } from "../services/company";
|
import { updateMyUserProfile } from "../services/company";
|
||||||
|
|
||||||
export const useAuthStore = defineStore('auth', () => {
|
export const useAuthStore = defineStore('auth', () => {
|
||||||
@@ -13,16 +11,14 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const noty = useNotificationsStore();
|
const noty = useNotificationsStore();
|
||||||
const company = useCompanyStore();
|
|
||||||
const loadStore = useLoadsStore();
|
const loadStore = useLoadsStore();
|
||||||
const vehiclesStore = useVehiclesStore();
|
|
||||||
const notyStore = useNotificationsStore();
|
|
||||||
const sesion = ref('')
|
const sesion = ref('')
|
||||||
const checking = ref(false);
|
const checking = ref(false);
|
||||||
const authStatus = ref('checking');
|
const authStatus = ref('checking');
|
||||||
const token = ref('')
|
const token = ref('')
|
||||||
const lang = ref('es');
|
const lang = ref('es');
|
||||||
const user = ref(null);
|
const user = ref(null);
|
||||||
|
const isAuthenticated = ref(false);
|
||||||
const publicNames = [
|
const publicNames = [
|
||||||
'terms-conditions',
|
'terms-conditions',
|
||||||
'notice-privacy',
|
'notice-privacy',
|
||||||
@@ -34,15 +30,10 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
'register-company',
|
'register-company',
|
||||||
]
|
]
|
||||||
|
|
||||||
onMounted( async() => {
|
|
||||||
checkSession();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
const checkSession = async() => {
|
const checkSession = async() => {
|
||||||
const session = localStorage.getItem('session');
|
const session = localStorage.getItem('session');
|
||||||
authStatus.value = 'checking';
|
authStatus.value = 'checking';
|
||||||
if(session && !publicNames.includes(route.name)) {
|
if((session && !publicNames.includes(route.name)) && isAuthenticated.value === false && checking.value === false) {
|
||||||
checking.value = true;
|
checking.value = true;
|
||||||
const resp = await renewToken();
|
const resp = await renewToken();
|
||||||
if(resp.msg === 'success') {
|
if(resp.msg === 'success') {
|
||||||
@@ -53,22 +44,24 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
localStorage.setItem('access', resp.data.accessToken);
|
localStorage.setItem('access', resp.data.accessToken);
|
||||||
localStorage.setItem('id', resp.data.user.company._id);
|
localStorage.setItem('id', resp.data.user.company._id);
|
||||||
checking.value = false;
|
checking.value = false;
|
||||||
|
isAuthenticated.value = true;
|
||||||
} else {
|
} else {
|
||||||
noty.show = true;
|
noty.show = true;
|
||||||
noty.text = 'Sesión ha expirado, ingresa nuevamente';
|
noty.text = 'Sesión ha expirado, ingresa nuevamente';
|
||||||
noty.error = true;
|
noty.error = true;
|
||||||
checking.value = false;
|
checking.value = false;
|
||||||
|
isAuthenticated.value = false;
|
||||||
router.push({name: 'login'});
|
router.push({name: 'login'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
authStatus.value = 'completed';
|
authStatus.value = 'completed';
|
||||||
}
|
}
|
||||||
|
|
||||||
const authenticationPromise = new Promise((resolve) => {
|
// const authenticationPromise = new Promise((resolve) => {
|
||||||
onMounted(() => {
|
// onMounted(() => {
|
||||||
resolve('success');
|
// resolve('success');
|
||||||
});
|
// });
|
||||||
});
|
// });
|
||||||
|
|
||||||
const updateProfile = async(data) => {
|
const updateProfile = async(data) => {
|
||||||
const response = await updateMyUserProfile(data);
|
const response = await updateMyUserProfile(data);
|
||||||
@@ -90,17 +83,7 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
user.value = null;
|
user.value = null;
|
||||||
checking.value = false;
|
checking.value = false;
|
||||||
authStatus.value = 'checking'
|
authStatus.value = 'checking'
|
||||||
notyStore.notifications = [];
|
|
||||||
notyStore.newNoty = false;
|
|
||||||
notyStore.show = false;
|
|
||||||
notyStore.openNotifications = false;
|
|
||||||
notyStore.toggleProfile = false;
|
|
||||||
|
|
||||||
company.clear();
|
|
||||||
loadStore.clear();
|
loadStore.clear();
|
||||||
vehiclesStore.clear();
|
|
||||||
|
|
||||||
router.push({name: 'login'});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -111,8 +94,9 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
checking,
|
checking,
|
||||||
authStatus,
|
authStatus,
|
||||||
checkSession,
|
checkSession,
|
||||||
authenticationPromise,
|
// authenticationPromise,
|
||||||
updateProfile,
|
updateProfile,
|
||||||
lang
|
lang,
|
||||||
|
isAuthenticated
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -34,6 +34,15 @@ export const useNotificationsStore = defineStore('notifications', () => {
|
|||||||
return notifications.value = notifications.value.filter(noty => noty._id !== id);
|
return notifications.value = notifications.value.filter(noty => noty._id !== id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
notifications.value = [];
|
||||||
|
newNoty.value = false;
|
||||||
|
show.value = false;
|
||||||
|
openNotifications.value = false;
|
||||||
|
toggleProfile.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
text,
|
text,
|
||||||
@@ -45,6 +54,7 @@ export const useNotificationsStore = defineStore('notifications', () => {
|
|||||||
removeNoty,
|
removeNoty,
|
||||||
toggleProfile,
|
toggleProfile,
|
||||||
openNotifications,
|
openNotifications,
|
||||||
toggleNotifications
|
toggleNotifications,
|
||||||
|
clear
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
|
|
||||||
localStorage.setItem('id', result.data._id);
|
localStorage.setItem('id', result.data._id);
|
||||||
localStorage.setItem('session', auth.sesion);
|
localStorage.setItem('session', auth.sesion);
|
||||||
// localStorage.setItem('access', auth.token);
|
localStorage.setItem('access', auth.accessToken);
|
||||||
|
|
||||||
const userData = {
|
const userData = {
|
||||||
"first_name" : user.name,
|
"first_name" : user.name,
|
||||||
@@ -109,6 +109,7 @@
|
|||||||
let respUser = await updateMyUserProfile( userData );
|
let respUser = await updateMyUserProfile( userData );
|
||||||
if(respUser.msg === 'success') {
|
if(respUser.msg === 'success') {
|
||||||
auth.user = respUser.data;
|
auth.user = respUser.data;
|
||||||
|
auth.isAuthenticated = true;
|
||||||
} else {
|
} else {
|
||||||
auth.user = userData;
|
auth.user = userData;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
sesion: resp.data.session_token,
|
sesion: resp.data.session_token,
|
||||||
token: resp.data.accessToken,
|
token: resp.data.accessToken,
|
||||||
user: resp.data.user,
|
user: resp.data.user,
|
||||||
|
isAuthenticated: true
|
||||||
})
|
})
|
||||||
} else { // Completar registro
|
} else { // Completar registro
|
||||||
auth.$patch({
|
auth.$patch({
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
})
|
})
|
||||||
|
|
||||||
const getInitialData = async() => {
|
const getInitialData = async() => {
|
||||||
await auth.authenticationPromise;
|
|
||||||
await company.getCompanyData();
|
await company.getCompanyData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
src/views/NotFoundView.vue
Normal file
13
src/views/NotFoundView.vue
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h1>No encontrada</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user