Middleware for routes in vue - express

I want to deny some routes for authorized users, like login page, register page, but I don't know how to make those middlewares
Routes
routes: [
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/register',
name: 'Register',
component: Register
}
]
Function that I use in components
computed: {
isLoggedIn () {
return this.$store.getters.isLoggedIn
}
}

In your router you can do something like this.
All routes marked with meta: { requiresLogin: true} } will be checked in the BeforeEach method. Here we redirect them to the login page.
You can in principle halt the router and show a modal or whatever you like here.
Router
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from '../views/App.vue'
import Login from '../views/login.vue'
import Register from '../views/registser.vue'
Vue.use(VueRouter)
const router = new VueRouter({
routes: [
{ path: '/', name: 'app', component: App, meta: { requiresLogin: true} },
{ path: '/login', name: 'login', component: Login },
{ path: '/register', name: 'register', component: Register },
]
})
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresLogin)) {
if (**USER IS NOT LOGGED IN**) {
next({
path: '/login',
query: {
redirect: to.fullPath,
},
});
} else {
next();
}
} else {
next();
}
})
export default router

Create additional meta field requiresAuth in your routes to specify which route require logged user:
routes: [{
path: '/',
name: 'Dashboard',
component: Dashboard,
children: [{
path: 'settings',
name: 'Settings',
component: Settings,
meta: {
requiresAuth: true
}
}],
meta: {
requiresAuth: true
}
},
{
path: '/login',
name: 'Login',
component: Login
}
],
Then add middleware in main.js:
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth) {
const authUser = JSON.parse(window.localStorage.getItem('authUser')) // your oauth key
if (authUser && authUser.access_token) {
next()
} else {
next({
name: 'Login'
})
}
}
next()
})
new Vue({
el: '#app',
router,
store,
template: '<App/>',
components: {
App
}
})

Related

Vuejs stop rendering component after adding transition in vue router

Vuejs stopped rendering components after I added a transition in the children route of my dashboard layout when I checked the error there was no error and no warnings but whenever I am reloading the page the components render, and the same functionality works in the same application in my login layouts children route when I am going in the network I am getting 304 HTTP error
this is my index router
import { createRouter, createWebHistory } from "vue-router";
// importing Dashboard routes
import DashboardRoutes from "./Dashboard/index.js";
import store from "#/store/store.js";
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: "/",
// redirecting the root to the login welcome page
redirect: { name: "login" },
},
{
// creating a group path for all the login pages
path: "/login",
name: "login",
redirect: { name: "welcome" },
component: () => import("../components/Pages/Login/LoginMain.vue"),
//checking the condition if user is logged in or not and redirecting
beforeEnter: (_, _2, next) => {
if (store.state.login.isLoggedIn) {
next("/dashboard");
} else {
next();
}
},
children: [
{
path: "/welcome",
name: "welcome",
component: () =>
import("../components/Pages/Login/Childrens/WelCome.vue"),
},
{
path: "/austria-login",
name: "austria-login",
component: () =>
import("../components/Pages/Login/Childrens/AustriaLogin.vue"),
},
{
path: "/sms-login",
name: "sms-login",
component: () =>
import("../components/Pages/Login/Childrens/SmsLogin.vue"),
},
{
path: "/enter-tpn",
name: "enter-tpn",
component: () =>
import("../components/Pages/Login/Childrens/EnterTpn.vue"),
//chcking the condition of phone and social security token is entered
beforeEnter: (_, _2, next) => {
if (!store.state.login.phoneVerified) {
next("/sms-login");
} else {
next();
}
},
},
],
},
// using Dashboard Routes
...DashboardRoutes,
],
scrollBehavior(_, _2, savedPosition) {
if (savedPosition) {
window.scrollTo(savedPosition);
} else {
window.scrollTo(0, 0);
}
},
});
export default router;
this is my dashboard children routes
import AppointmentRoutes from "./Appointment"; // importing appointment children routes
import SettingRoutes from "./Setting";
import store from "#/store/store";
const DashboardRoutes = [
{
// router group for all the dashboard views
path: "/dashboardMain",
name: "dashboardMain",
component: () => import("../../components/Pages/DashBoard/IndexMain.vue"),
beforeEnter: (_, _2, next) => {
if (store.state.login.isLoggedIn) {
next();
} else {
next('/login');
}
},
children: [
{
path: "/dashboard",
name: "dashboard",
component: () =>
import("../../components/Pages/DashBoard/Home/DashBoard.vue"),
props: { sidebar: true },
},
// router for appointments
{
path: "/appointments",
name: "PatientAppoinetments",
redirect: { name: "PatientAppointmentsData" },
component: () =>
import(
"../../components/Pages/DashBoard/PatientAppointment/PatientAppointment.vue"
),
props: { sidebar: true },
// children group for appointments components
children: [...AppointmentRoutes],
},
{
path: "/requests",
name: "Requests",
component: () =>
import(
"../../components/Pages/DashBoard/PatientRequests/PatientRequest.vue"
),
},
{
path: "/medications",
name: "Medications",
component: () =>
import(
"../../components/Pages/DashBoard/PatientMedication/PatientMedication.vue"
),
},
{
path: "/questions",
name: "Questions",
component: () =>
import(
"../../components/Pages/DashBoard/PatientQuestionaries/PatientQuestionaries.vue"
),
},
{
path: "/health-status",
name: "HealthStatus",
component: () =>
import(
"../../components/Pages/DashBoard/PatientHealth/PatientHealth.vue"
),
},
{
path: "/diagnostic-center",
name: "PatientDiagnosticCenter",
component: () =>
import(
"../../components/Pages/DashBoard/PatientDiagnostic/PatientDiagnosticCenter.vue"
),
},
{
path: "/vaccination",
name: "PatientVaccination",
component: () =>
import(
"../../components/Pages/DashBoard/PatientVaccination/PatientVaccination.vue"
),
},
{
path: "/setting",
name: "Setting",
redirect: { name: "AccountSetting" },
component: () =>
import("#/components/Pages/DashBoard/Setting/SettingIndex.vue"),
children: [...SettingRoutes],
},
{
path: "/chat",
name: "PatientChat",
redirect: { path: "/chat/gautam" },
component: () =>
import(
"../../components/Pages/DashBoard/PatientChat/PatientChat.vue"
),
// children group for chat page
children: [
{
path: "/chat/:name",
name: "chatMessages",
component: () =>
import(
"../../components/Pages/DashBoard/PatientChat/Children/PatientChatmessages.vue"
),
},
],
},
{
path: "/access-log",
name: "AccessLog",
component: () =>
import("#/components/Pages/DashBoard/AccessLog/AccessLog.vue"),
},
{
path: "/my-profile",
name: "MyProfile",
component: () =>
import("#/components/Pages/DashBoard/MyProfile/MyProfile.vue"),
props: { sidebar: true },
},
],
},
];
export default DashboardRoutes;
and this is DahboardMain where i want to renders my dashboard children pages
but i am getting the blank the black screen children area whenere i am going to any route except page reload
I tried to remove beforeEnter guard from the routes and I also removed all the code from the dashboard layout except router-view but still getting the black screen
enter image description here this is the image of the blank screen
enter image description here this is showing in the network

Uncaught error missing param when using named router-link

I am following a YouTube course, and I encountered an error on the last part where I added a button for the EditClient route. I'm getting an Uncaught (in promise) Error: Missing required param "id".
router/index.js:
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import Dashboard from '../views/dashboard/Dashboard.vue'
import MyAccount from '../views/dashboard/MyAccount.vue'
import SignUp from '../views/SignUp.vue'
import Login from '../views/Login.vue'
import Clients from '../views/dashboard/Clients.vue'
import Client from '../views/dashboard/Client.vue'
import AddClient from '../views/dashboard/AddClient.vue'
import EditClient from '../views/dashboard/EditClient.vue'
import EditTeam from '../views/dashboard/EditTeam.vue'
import Invoices from '../views/dashboard/Invoices.vue'
import Invoice from '../views/dashboard/Invoice.vue'
import AddInvoice from '../views/dashboard/AddInvoice.vue'
import store from '../store'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/sign-up',
name: 'SignUp',
component: SignUp
},
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/dashboard',
name: 'Dashboard',
component: Dashboard,
meta: {
requireLogin: true
}
},
{
path: '/dashboard/invoices',
name: 'Invoices',
component: Invoices,
meta: {
requireLogin: true
}
},
{
path: '/dashboard/invoices/add',
name: 'AddInvoice',
component: AddInvoice,
meta: {
requireLogin: true
}
},
{
path: '/dashboard/invoices/:id',
name: 'Invoice',
component: Invoice,
meta: {
requireLogin: true
}
},
{
path: '/dashboard/clients',
name: 'Clients',
component: Clients,
meta: {
requireLogin: true
}
},
{
path: '/dashboard/clients/add',
name: 'AddClient',
component: AddClient,
meta: {
requireLogin: true
}
},
{
path: '/dashboard/clients/:id',
name: 'Client',
component: Client,
meta: {
requireLogin: true
}
},
{
path: '/dashboard/clients/:id/edit',
name: 'EditClient',
component: EditClient,
meta: {
requireLogin: true
}
},
{
path: '/dashboard/my-account',
name: 'MyAccount',
component: MyAccount,
meta: {
requireLogin: true
}
},
{
path: '/dashboard/my-account/edit-team',
name: 'EditTeam',
component: EditTeam,
meta: {
requireLogin: true
}
},
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requireLogin) && !store.state.isAuthenticated) {
next('/login')
}
else {
next()
}
})
export default router
My router link is as follows:
<router-link :to="{ name: 'EditClient', params: { id: client.id }}" class="button is-light mt-4">Edit</router-link>
I have tried, and it works:
<router-link :to="'/dashboard/clients/' + client.id + '/edit'" class="button is-light mt-4">Edit</router-link>
answer by Pylinux from this question.
Although the solution is already acceptable, I would like to know why this is happening in my case.

Why does the router link not work the first time?

I have a grpc application, there is authorization. When you start a project, you must be logged in. I decided to add under the login button if you are not registered. But the router does not work. Only at the entrance, go to the registration page. Please help to understand what is the mistake? Why is seemingly blocked?
routes.js
const routes = [
{
path: "/",
component: () => import("layouts/MainLayout"),
children: [
{
path: "",
component: () => import("pages/Index"),
meta: { requireAuth: true }
},
{
path: "/logs",
component: () => import("pages/Logs"),
meta: { requireAuth: true, admin: true }
}
]
},
{
path: "/",
component: () => import("layouts/AuthLayout"),
children: [
{
path: "/welcome",
component: () => import("pages/Auth"),
meta: { guest: true }
},
{
path: "/register",
component: () => import("pages/Register"),
meta: { guest: true }
}
]
}
];
I tried many things, like in Auth.vue:
<q-item to='/register'>Sign Up</q-item>
<router-link tag="a" :to="{path:'/register'}" replace>Go</router-link>
<span #click="callSomeFunc()">Register</span>
...
methods: {
callSomeFunc() {
this.$router.push({ path: "/register" });
}
My router-view in App.vue
for more information github repo
You have duplicate routes in your config - the path / is used on 2 routes. You should fix this.
To prevent unauthorized users to see your protected pages you can add a global navigation guard to your router through the beforeEach hook:
import VueRouter from 'vue-router';
const routes = [
{
path: "/",
component: () => import("layouts/MainLayout"),
meta: { requireAuth: true },
children: [
{
path: "",
component: () => import("pages/Index"),
},
{
path: "logs",
component: () => import("pages/Logs"),
meta: { admin: true }
}
]
},
{
path: "/login",
component: () => import("layouts/AuthLayout"),
children: [
{
path: "",
component: () => import("pages/Auth"),
},
{
path: "/register",
component: () => import("pages/Register"),
}
]
}
];
const router = new VueRouter({
routes
});
router.beforeEach((to, from, next) =>
{
if (to.matched.some(route => route.meta.requireAuth))
{
if (userNotLogged) next('/login');
else next();
}
else next();
});
export default router;
You may also consider reading a more verbose tutorial, e.g. https://www.digitalocean.com/community/tutorials/how-to-set-up-vue-js-authentication-and-route-handling-using-vue-router

How to create child routes in vue js using Vue-Router and Laravel?

My application was working fine, until I changed my router.js file slightly to have child routes, and now my app is breaking, I can't see anything on any routes.
I get this error:
app.js:191 Uncaught TypeError: Cannot read property 'bind' of undefined
I can see that it points to this line:
var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);
in this file /public/js/app.js inside this block of code:
// on error function for async loading
__webpack_require__.oe = function(err) { console.error(err); throw err; };
var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || [];
var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);
jsonpArray.push = webpackJsonpCallback;
jsonpArray = jsonpArray.slice();
for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);
/******/ var parentJsonpFunction = oldJsonpFunction;
Has anyone come across something like this? I tried searching on google and there wasn't that much about it, I found something that said they updated their cli#3.0.0-rc.5 to rc.6 and it solved it for that 1 person, but that didn't solve it for me.
Working router.js:
import Vue from 'vue';
import VueRouter from 'vue-router';
import Dashboard from './views/Dashboard';
import Login from './views/Login';
import Register from './views/Register';
import Forms from './views/Forms';
import CandidateProfileCreate from './views/candidate/CandidateProfileCreate';
import CandidateProfileIndex from './views/candidate/CandidateProfileIndex';
Vue.use(VueRouter);
const routes = [
{
path: '/',
name: 'dashboard',
component: Dashboard
},
{
path: '/candidate-profile/create',
name: 'candidate-profile-create',
component: CandidateProfileCreate
},
{
path: '/candidate-profile',
name: 'candidate-profile',
component: CandidateProfileIndex
},
{
path: '/login',
name: 'login',
component: Login
},
{
path: '/register',
name: 'register',
component: Register
},
{
path: '/forms',
name: 'forms',
component: Forms
}
]
const router = new VueRouter({
mode: 'history',
routes: routes,
linkActiveClass: 'active'
});
export default router;
Getting error, router.js:
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from './views/Home';
Vue.use(VueRouter);
const routes = [
{
path: '/home',
component: Home,
children: [
{
path: '',
name: 'dashboard',
component: () => import('./views/Dashboard.vue')
},
{
path: 'candidate-profile',
name: 'candidate-profile-index',
component: () => import('./views/candidate/CandidateProfileIndex')
},
{
path: '/candidate-profile/create',
name: 'candidate-profile-create',
component: () => import('./views/candidate/CandidateProfileCreate')
},
],
},
{
path: '/login',
name: 'login',
component: () => import('./views/Login.vue')
},
{
path: '/register',
name: 'register',
component: () => import('./views/Register.vue')
},
{
path: '/forms',
name: 'forms',
component: () => import('./views/Forms.vue')
}
]
const router = new VueRouter({
mode: 'history',
routes: routes,
linkActiveClass: 'active'
});
export default router;
You must create children in object you want.
Like this
if you put path of father element to his children
this page will be open when page create
{
path: '/home',
component: Home,
children: [
{
path: '/home',
name: 'dashboard',
component: () => import('./views/Dashboard.vue')
},
{
path: 'candidate-profile',
name: 'candidate-profile-index',
component: () => import('./views/candidate/CandidateProfileIndex')
},
{
path: '/candidate-profile/create',
name: 'candidate-profile-create',
component: () => import('./views/candidate/CandidateProfileCreate')
},
],
},

How to properly use the meta props on vue router?

I'm trying to handle route middleware of the children route, but I got this error
Uncaught TypeError: route.children.some is not a function
The documentation are only shows the example for a single route but in this case, I have a children route that needs to be restricted.
Please take a look at my router configuration:
import Vue from 'vue'
import Router from 'vue-router'
import store from './store/index'
import Home from './views/home/Index.vue'
Vue.use(Router)
let router = new Router({
mode: 'history',
base: process.env.VUE_APP_BASE_URL,
linkActiveClass: 'is-active',
linkExactActiveClass: 'is-exact-active',
routes: [{
path: '/',
name: 'home',
component: Home,
meta: {
requiresAuth: true
}
},
{
path: '/login',
name: 'login',
// route level code-splitting
// this generates a separate chunk (login.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import('./views/auth/Login.vue'),
meta: {
requiresGuest: true
}
},
{
path: '/register',
name: 'register',
component: () => import('./views/auth/Register.vue'),
meta: {
requiresGuest: true
}
},
{
path: '/forgot-password',
name: 'forgot-password',
component: () => import('./views/auth/extras/ForgotPassword.vue'),
meta: {
requiresGuest: true
}
},
{
path: '/database',
name: 'database',
component: () => import('./views/database/Index.vue'),
meta: {
requiresAuth: true
}
},
{
path: '/third-parties',
name: 'third-parties',
component: () => import('./views/third-parties/Index.vue'),
meta: {
requiresAuth: true
}
},
{
path: '/editor',
name: 'editor',
meta: {
requiresAuth: true,
requiresAdmin: true,
requiresEditor: true,
},
children: {
path: ':appSlug/layout-editor/:pageSlug',
name: 'layout-editor',
component: () => import('./views/editor/Index.vue'),
}
},
]
})
router.beforeEach((to, from, next) => {
const isLoggedIn = store.getters['auth/isLoggedIn'];
// Role getters
const isAdmin = (store.getters['auth/isAdmin'] == 'admin') || (store.getters['auth/isAdmin'] == 'super-admin');
const isEditor = store.getters['auth/isEditor'] == 'editor';
// Redirect to the login page if the user is not logged in
// and the route meta record is requires auth
if (to.matched.some(record => record.meta.requiresAuth) && !isLoggedIn) {
next('/login')
}
// Redirect to the homepage page if the user is logged in
// and the route meta record is requires guest
if (to.matched.some(record => record.meta.requiresGuest) && isLoggedIn) {
next('/')
}
// Redirect to the preview page if the user is logged in
// but has no role assigned or the role is user
if (to.matched.some(record => (
record.meta.requiresAuth &&
record.meta.requiresAdmin &&
record.meta.requiresEditor)) && !isAdmin && !isEditor) {
next('/preview')
}
// Pass any access if not match two conditions above
next()
})
export default router
Could somebody please explain it? Why I getting this error and how to fix it?
Thanks in advance.
I just found the answer, kinda silly tho.. I forgot to put square brackets on the children props. Now it's working as I expected.
fix:
{
path: '/editor',
name: 'editor',
meta: {
requiresAuth: true,
requiresAdmin: true,
requiresEditor: true,
},
children: [{
path: ':appSlug/layout-editor/:pageSlug',
name: 'layout-editor',
component: () => import('./views/editor/Index.vue'),
}]
},