From ec02b9827296623f049444b5ef572806cd933603 Mon Sep 17 00:00:00 2001 From: Alexandro Uc Santos Date: Fri, 24 Nov 2023 21:07:42 -0600 Subject: [PATCH] add: guard in router --- index.html | 6 +- package-lock.json | 181 ++++++++++++++++- package.json | 1 + src/App.vue | 10 +- src/assets/main.css | 3 - src/components/ui/LoadingModal.vue | 50 +++++ src/components/ui/Notification.vue | 2 +- src/helpers/validations.js | 2 + src/layouts/AdminLayout.vue | 304 ++++++++++++++++++++++++++++- src/router/index.js | 61 +++++- src/services/auth.js | 59 ++++++ src/stores/auth.js | 55 ++++++ src/views/CalendarView.vue | 13 ++ src/views/CompleteRegisterView.vue | 99 ++++++++++ src/views/LoadsView.vue | 13 ++ src/views/LoginView.vue | 76 +++++--- src/views/UsersView.vue | 13 ++ src/views/VehiclesView.vue | 13 ++ 18 files changed, 914 insertions(+), 47 deletions(-) create mode 100644 src/components/ui/LoadingModal.vue create mode 100644 src/stores/auth.js create mode 100644 src/views/CalendarView.vue create mode 100644 src/views/CompleteRegisterView.vue create mode 100644 src/views/LoadsView.vue create mode 100644 src/views/UsersView.vue create mode 100644 src/views/VehiclesView.vue diff --git a/index.html b/index.html index 3721c05..0f706c1 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,10 @@ + Eta viaporte @@ -12,8 +16,8 @@ - + diff --git a/package-lock.json b/package-lock.json index 940d3f2..21e7932 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "axios": "^1.6.2", "pinia": "^2.1.7", + "sass": "^1.69.5", "vue": "^3.3.4", "vue-multiselect": "^3.0.0-beta.3", "vue-router": "^4.2.5" @@ -507,6 +508,18 @@ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.8.tgz", "integrity": "sha512-8PGwybFwM4x8pcfgqEQFy70NaQxASvOC5DJwLQfpArw1UDfUXrJkdxD3BhVTMS+0Lef/TU7YO0Jvr0jJY8T+mw==" }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -522,6 +535,51 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -588,6 +646,17 @@ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/follow-redirects": { "version": "1.15.3", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", @@ -624,7 +693,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -634,6 +702,60 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/immutable": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", + "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/magic-string": { "version": "0.30.5", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", @@ -681,11 +803,30 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/pinia": { "version": "2.1.7", "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.7.tgz", @@ -768,6 +909,17 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/rollup": { "version": "3.29.4", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", @@ -784,6 +936,22 @@ "fsevents": "~2.3.2" } }, + "node_modules/sass": { + "version": "1.69.5", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.69.5.tgz", + "integrity": "sha512-qg2+UCJibLr2LCVOt3OlPhr/dqVHWOa9XtZf2OjbLs/T4VPSJ00udtgJxH3neXZm+QqX8B+3cU7RaLqp1iVfcQ==", + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -792,6 +960,17 @@ "node": ">=0.10.0" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/vite": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.0.tgz", diff --git a/package.json b/package.json index c2ac9d7..2ec4eea 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "dependencies": { "axios": "^1.6.2", "pinia": "^2.1.7", + "sass": "^1.69.5", "vue": "^3.3.4", "vue-multiselect": "^3.0.0-beta.3", "vue-router": "^4.2.5" diff --git a/src/App.vue b/src/App.vue index 253b52a..a0fa7c1 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,3 +1,7 @@ + + - - \ No newline at end of file diff --git a/src/assets/main.css b/src/assets/main.css index dc9245b..f315452 100644 --- a/src/assets/main.css +++ b/src/assets/main.css @@ -2,9 +2,6 @@ body { margin: 0px 0px; padding: 0px; } -.bg-body{ - background-color: red; -} .w-lg-45{ width: 45%; diff --git a/src/components/ui/LoadingModal.vue b/src/components/ui/LoadingModal.vue new file mode 100644 index 0000000..0a7b714 --- /dev/null +++ b/src/components/ui/LoadingModal.vue @@ -0,0 +1,50 @@ + + + + + \ No newline at end of file diff --git a/src/components/ui/Notification.vue b/src/components/ui/Notification.vue index 6078e07..b5e6e31 100644 --- a/src/components/ui/Notification.vue +++ b/src/components/ui/Notification.vue @@ -28,7 +28,7 @@ .content-noty { width: 100%; max-width: 500px; - padding: 14px 20px; + padding: 16px 32px; background-color: white; border-radius: 8px; diff --git a/src/helpers/validations.js b/src/helpers/validations.js index 8ae70fa..02bd606 100644 --- a/src/helpers/validations.js +++ b/src/helpers/validations.js @@ -8,6 +8,8 @@ export const validateEmail = (email) => { export const messagesError = (msg) => { switch (msg) { + case 'Invalid credentials': + return 'Email y/o password incorrectos'; case 'Email is not registered!': return 'No se encontro una cuenta con este email'; case 'Wrong OTP': diff --git a/src/layouts/AdminLayout.vue b/src/layouts/AdminLayout.vue index ee9a402..f75c256 100644 --- a/src/layouts/AdminLayout.vue +++ b/src/layouts/AdminLayout.vue @@ -1,11 +1,305 @@ - - - \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js index a3258fc..061d8c3 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -1,6 +1,5 @@ import { createRouter, createWebHistory } from 'vue-router' import AuthLayout from '../layouts/AuthLayout.vue' -import LoginView from '../views/LoginView.vue' const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -25,21 +24,77 @@ const router = createRouter({ name: 'recovery', component: () => import('../views/RecoveryPasswordView.vue'), }, + { + path: 'empresa', + name: 'company', + component: () => import('../views/CompleteRegisterView.vue') + } ] }, { path: '/dashboard', name: 'dashboard', component: () => import('../layouts/AdminLayout.vue'), + meta: { requiresAuth: true }, children: [ { path: 'inicio', - name: 'inicio', + name: 'home', component: () => import('../views/HomeView.vue'), }, + { + path: 'usuarios', + name: 'users', + component: () => import('../views/UsersView.vue'), + }, + { + path: 'calendario', + name: 'calendar', + component: () => import('../views/CalendarView.vue'), + }, + { + path: 'cargas', + name: 'loads', + component: () => import('../views/LoadsView.vue'), + }, + { + path: 'vehiculos', + name: 'vehicles', + component: () => import('../views/VehiclesView.vue'), + }, ] } ] -}) +}); + +router.beforeEach( async(to, from, next) => { + const requiresAuth = to.matched.some(url => url.meta.requiresAuth) + const session = localStorage.getItem('session'); + // console.log('--------------- SE EJECUTA -----------------'); + // console.log(session); + // console.log('--------------- FIN -----------------'); + if(requiresAuth) { + //Comprobamos si el usuario esta authenticado + if(session) { + // try { + // const resp = await renewToken(); + // if(resp.msg == 'success') { + // next(); + // } else { + // next({name: 'login'}) + // } + // } catch (error) { + // console.log(error); + // next({name: 'login'}) + // } + next(); + } else { + next({name: 'login'}) + } + } else { + // No esta protegido + next(); + } +}); export default router diff --git a/src/services/auth.js b/src/services/auth.js index 06aca62..d22719a 100644 --- a/src/services/auth.js +++ b/src/services/auth.js @@ -1,6 +1,65 @@ import api from "../lib/axios"; import {messagesError} from '../helpers/validations'; +export const login = async(body) => { + try { + const endpoint = "/account/authorize"; + const {data} = await api.post(endpoint, body); + console.log(data); + console.log(data.accessToken); + if(data.accessToken !== null){ + if(data.user.job_role !== 'driver'){ + //TODO: Guardar token y datos del usuario + return { + msg: 'success', + data + }; + } else { + //Remover datos de sesion + return 'Rol no autorizado'; + } + } else { + return { + msg: "email y/o password incorrectos", + data: null + }; + } + } catch (error) { + const errStr = error.response.data.error ?? 'Algo salio mal, intente más tarde'; + return { + msg: messagesError(errStr), + data: null + }; + } +} + +export const renewToken = async() => { + const session = localStorage.getItem('session'); + try { + const endpoint = `/account/authorize/${session}`; + const {data} = await api.get(endpoint); + console.log(data.user); + if(data.accessToken !== null){ + return { + msg: 'success', + data + }; + } else { + return { + msg: "Sesion expiro", + data: null + }; + } + } catch (error) { + const errStr = error.response.data.error ?? 'Algo salio mal, intente más tarde'; + return { + msg: 'Sesion expiro', + data: null + }; + } +} + + export const regiter = async(body) => { try { const endpoint = "/account/signup"; diff --git a/src/stores/auth.js b/src/stores/auth.js new file mode 100644 index 0000000..296687b --- /dev/null +++ b/src/stores/auth.js @@ -0,0 +1,55 @@ +import { defineStore } from "pinia"; +import { ref, onMounted } from "vue"; +import { useRouter } from 'vue-router'; +import { renewToken } from '../services/auth'; +import {useNotificationsStore} from './notifications'; + +export const useAuthStore = defineStore('auth', () => { + + const router = useRouter(); + const noty = useNotificationsStore(); + const sesion = ref('') + const checking = ref(false); + const token = ref('') + const user = ref(null) + + onMounted( async() => { + console.log('Se ejecuta onMounted auth'); + checkSession(); + }); + + const checkSession = async() => { + checking.value = true; + const resp = await renewToken(); + if(resp.msg === 'success') { + localStorage.setItem('session', resp.data.session_token); + sesion.value = resp.data.session_token; + token.value = resp.data.accessToken; + user.value = resp.data.user; + checking.value = false; + } else { + noty.show = true; + noty.text = 'Sesión ha expirado, ingresa nuevamente'; + noty.error = true; + checking.value = false; + router.push({name: 'login'}); + } + } + + const logout = () => { + + localStorage.removeItem('session'); + router.push({name: 'login'}); + sesion.value = ''; + token.value = ''; + user.value = null; + } + + return { + sesion, + logout, + token, + user, + checking + } +}); \ No newline at end of file diff --git a/src/views/CalendarView.vue b/src/views/CalendarView.vue new file mode 100644 index 0000000..953acbf --- /dev/null +++ b/src/views/CalendarView.vue @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/src/views/CompleteRegisterView.vue b/src/views/CompleteRegisterView.vue new file mode 100644 index 0000000..658acea --- /dev/null +++ b/src/views/CompleteRegisterView.vue @@ -0,0 +1,99 @@ + + + + + + + + \ No newline at end of file diff --git a/src/views/LoadsView.vue b/src/views/LoadsView.vue new file mode 100644 index 0000000..4d4c588 --- /dev/null +++ b/src/views/LoadsView.vue @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/src/views/LoginView.vue b/src/views/LoginView.vue index 4e97612..3dced71 100644 --- a/src/views/LoginView.vue +++ b/src/views/LoginView.vue @@ -4,14 +4,19 @@ import NotificationBadge from '../components/ui/NotificationBadge.vue'; import {validateEmail} from '../helpers/validations'; import Spiner from '../components/ui/Spiner.vue'; -import { RouterLink } from 'vue-router'; + import { login } from '../services/auth'; + import { RouterLink, useRouter } from 'vue-router'; + import { useAuthStore } from '../stores/auth'; const form = reactive({ - email: '', - password: '', + email: 'alexandro.uc.santos@gmail.com', + password: 'Password0', }); + const router = useRouter(); + const auth = useAuthStore(); + const loading = ref(false); const msgError = ref(''); const msgSuccess = ref(''); @@ -31,7 +36,24 @@ import { RouterLink } from 'vue-router'; email: form.email, password: form.password } - console.log(data); + const resp = await login(data); + if(resp.msg === 'success') { + console.log(resp.data.user); + if(resp.data.user.first_name && resp.data.user.last_name) { + localStorage.setItem('session', resp.data.session_token); + router.push({name: 'home'}); + auth.$patch({ + sesion: resp.data.session_token, + token: resp.data.accessToken, + user: resp.data.user, + }) + } else { + router.push({name: 'company'}); + } + } else { + msgError.value = resp.msg; + } + clearMessages(); loading.value = false; } } @@ -59,29 +81,29 @@ import { RouterLink } from 'vue-router';

Iniciar sesión

Bienvenido de vuelta! Ingresa tu email y contraseña

-
- - - - - - - -

¿Olvidaste tu contreseña? Ingresa aqui

-

¿No tienes una cuenta? Registrate aqui

+
+ + + + + + + +

¿Olvidaste tu contreseña? Ingresa aqui

+

¿No tienes una cuenta? Registrate aqui

diff --git a/src/views/UsersView.vue b/src/views/UsersView.vue new file mode 100644 index 0000000..6bf3930 --- /dev/null +++ b/src/views/UsersView.vue @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/src/views/VehiclesView.vue b/src/views/VehiclesView.vue new file mode 100644 index 0000000..adb8a67 --- /dev/null +++ b/src/views/VehiclesView.vue @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file