# How to add ACL in starter-kit

Import ACL configuration from src/libs/acl in main.js file.

// main.js

import '@/libs/acl'

Do configure the ability.js and config.js files according to your ACL requirement. Initially if there's no ability can be fetched from localStorage then initial ability defined in config.js will be used.

Next thing is we need to take care of is route protection.

# Handling Route Protection

Let's add ACL meta in routes.

add below meta in all routes of starter-kit which shall be visible by everyone (This may differ according to your business logic). In our case we want to make public 404 and login page so we will add meta in those two routes only.

{
  // other route data...
  meta: {
    // other meta....
    action: 'read',
    resource: 'Auth',
  }
}

Now let's add router.beforeEach hook just before we export default router:

WARNING

We updated login route name from auth-login to login in starter-kit. So if you are copying router.beforeEach hook from full package please rename route.

WARNING

getHomeRouteForLoggedInUser is for our demo purpose. Because we have two different route for home location based on user ability.

In your case you can just write next('/') instead of next(next(getHomeRouteForLoggedInUser()))

// New Imports
import { canNavigate } from '@/libs/acl/routeProtection'
import { isUserLoggedIn, getHomeRouteForLoggedInUser } from '@/auth/utils'

// Router Before Each hook for route protection
router.beforeEach((to, _, next) => {
  const isLoggedIn = isUserLoggedIn()

  if (!canNavigate(to)) {
    // Redirect to login if not logged in
    // ! We updated login route name here from `auth-login` to `login` in starter-kit
    if (!isLoggedIn) return next({ name: 'login' })

    // If logged in => not authorized
    return next({ name: 'not-authorized' })
  }

  // Redirect if logged in
  if (to.meta.redirectIfLoggedIn && isLoggedIn) {
    next(getHomeRouteForLoggedInUser())
  }

  return next()
})

Now, we need to add not authorized page as we are redirecting unauthorized user to that page in our router.beforeEach. Copy not authorized page from full-package and update it according to your URL preference. Please make sure you also add route meta we defined earlier so everyone can view it.

// src/router/index.js

{
  path: '/pages/not-authorized',
  name: 'not-authorized',
  // ! Update import path
  component: () => import('@/views/NotAuthorized.vue'),
  meta: {
    layout: 'full',
    action: 'read',
    resource: 'Auth',
  },
},

Now we need to update getHomeRouteForLoggedInUser method for this guide because in our demo we had two different routes where user can go based on it's ability. For simplification we used user's property named role. But be aware role is just for UI purpose in our demo. You need to update getHomeRouteForLoggedInUser method so it can provide your redirection route if user is logged in based on it's ability according to your business logic.

Here, we will assume if we can find userData in localStorage then user is logged in else user is not logged in.

// src/auth/utils.js

export const getHomeRouteForLoggedInUser = () => {
  // ? getUserData is function in this same file
  const userData = getUserData()
  if (userData) return '/'
  return { name: 'auth-login' }
}

Also you need to update not authorized page's loginRoute method which uses getHomeRouteForLoggedInUser because we updated this method.

// src/views/NotAuthorized.vue
// Above file path may differ

loginRoute() {
  return getHomeRouteForLoggedInUser()
},

Now here's come Auth part where you have to update ability once user logs in. For this guide we will just update initial ability in src/libs/acl/config.js file to check route protection.

Now spin up the server and try to visit / route. You will get redirected to login page because user don't have enough ability to view / route.

TIP

name of / route is home

Now let's assume we logged in and updated the ability. For demo purpose we will update the src/libs/acl/config.js file.

For sake of this guide we will provide below ability which will be superuser kind of ability where user can do anything. Please update initialAbility as below:

// src/libs/acl/config.js

export const initialAbility = [
  {
    action: 'manage',
    subject: 'all',
  },
]

Now try to visit the / route and wholla you can visit it.

TIP

As we provided super user kind of ability we didn't had to defined action and resource in other routes.

Certainly, your authenticated user won't be superuser so you need to define action and resource in route meta for other routes as well otherwise our route protection may behave differently.

Let's say we are giving ability of User. Then new ability will be:

// New user ability after login

// `newAbility` will be available from successful Login response
const newAbility = [
  {
    action: 'read',
    subject: 'ACL',
  },
  {
    action: 'read',
    subject: 'Auth',
  },
]

// Update when logged in
this.$ability.update(newAbility)

WARNING

Make sure to provide ability Auth so user can visit route like not authorized, login and any other publicly accessible routes.

In this case as we didn't defined action and resource for other routes. So even if you are logged in you will be redirected to not authorized page. So, make sure you update other route's meta as well.

WARNING

If you try to update ability other than superuser kind for demo/checking purpose browser may give RangeError: Maximum call stack size due to missing user data.

# Hiding/Showing Navigation Item

Please refer to detailed guide on this page.

Last Updated: 11/16/2022, 12:36:59 PM