I am very beginner in JS and VUE. I make mini CMS in Vue and Laravel. I create this router in Vue:
import Vue from 'vue'
import Router from 'vue-router'
// Containers
const TheContainer = () => import('@/containers/TheContainer')
// Views
const Dashboard = () => import('@/views/Dashboard')
....
Vue.use(Router)
let router = new Router({
mode: 'hash', // https://router.vuejs.org/api/#mode
linkActiveClass: 'active',
scrollBehavior: () => ({ y: 0 }),
routes: configRoutes()
})
router.beforeEach((to, from, next) => {
let roles = localStorage.getItem("roles");
if(roles != null){
roles = roles.split(',')
}
if(to.matched.some(record => record.meta.requiresAdmin)) {
if(roles != null && roles.indexOf('admin') >= 0 ){
next()
}else{
next({
path: '/login',
params: { nextUrl: to.fullPath }
})
}
}else if(to.matched.some(record => record.meta.requiresUser)) {
if(roles != null && roles.indexOf('user') >= 0 ){
next()
}else{
next({
path: '/login',
params: { nextUrl: to.fullPath }
})
}
}else{
next()
}
})
export default router
function configRoutes () {
return [
{
path: '/',
redirect: '/dashboard',
name: 'Home',
component: TheContainer,
children: [
{
path: 'dashboard',
name: 'Dashboard',
component: Dashboard
},
]
},
]
}
It's work fine, but I have 2 problems:
If user is login - then first page (and main page) is /dashboard
How can I make it?
Please help me.
What do you think of this:
import Vue from 'vue'
import Router from 'vue-router'
// Containers
const TheContainer = () => import('@/containers/TheContainer')
// Views
const Dashboard = () => import('@/views/Dashboard')
// ....
Vue.use(Router)
let router = new Router({
mode: 'hash', // https://router.vuejs.org/api/#mode
linkActiveClass: 'active',
scrollBehavior: () => ({ y: 0 }),
routes: configRoutes()
})
// routing logic for not-logged-in
// users with a role
const useToLoginObj = (to) => ({
path: '/login',
params: {
nextUrl: to.fullPath
}
})
// DON'T DO THIS IN PRODUCTION!
// secure/security info should
// **NEVER** BE SAVED TO LOCALSTORAGE!!!!!
const fetchUserRoles = () => {
const roles = localStorage.getItem("roles")?.split(',')
return roles
}
// possible roles as keys
// corresponding required meta as value
const rolesDict = {
admin: 'requiresAdmin',
user: 'requiresUser',
}
const getRequiredRole = ({ to, rolesDict }) => {
let requiredRole = null
for (let key in roles) {
// if the required role is already set, then
// don't do anything
if (!requiredRole && to.matched.some(record => record.meta[rolesDict[key]])) {
requiredRole = key
}
}
// if no role is required, then the
// return value is null (falsy)
return requiredRole
}
// if fetched roles include the requiredRole
const routeAuthUser = ({ roles, requiredRole, toLogin, next }) => {
if (!roles.includes(requiredRole)) {
next(toLogin)
} else {
next()
}
}
router.beforeEach((to, from, next) => {
const requiredRole = getRequiredRole({to, rolesDict})
// if requiredRole is falsy (this route
// doesn't require a role), then go
if (!requiredRole) {
next()
} else {
const roles = fetchUserRoles()
const toLogin = useToLoginObj(to)
// if no roles are there, then go to login
if (!roles || !roles.length) {
next(toLogin)
} else {
// user is routed based on her/his role
routeAuthUser({ roles, requiredRole, toLogin, next })
}
}
})
More verbose than the code in question, but
beforeEach routing steps is more logical ("error first" approach)I could not try it out, so there might be errors in the code, but the logic (I think) is clear: break it up to small pieces then construct the logic you want from those small pieces.
Try to find a different solution for storing user roles. localStorage is the least safe (even calling it "the least safe" is an exaggeration) solution for secure data.