How to build a flexible role-based access control system in 10 minutes

Dmitry A.
Insider Engineering
5 min readOct 3, 2022

Almost every single web application has some “role play”, in other words — things that should be available only for a certain audience, users, segment of users, etc. Sometimes those requirements are extremely complicated, sometimes it is pretty much enough to have “isAdmin”, “isCustomerSales”, “isPartnerManager” flags to have all control you need.

But what if your system has more to control, let’s say you are developing a SAAS platform which includes several subscription plans or has a multi-level department structure when you need to grant access to certain features only for specific people. In this case having, “isAdmin”, “isPartnerManager” and “isCustomerSales” flags in the database or front-end is definitely not enough. Of course, you can continue struggling with hardcoding these sorts of conditions in every possible place inside your app, but if you want your system to be more flexible and easily customisable there is a simple way to do it.

So enough foreplay, let’s cut to the chase. What we are gonna build here is an advanced role manager that will cover 90% of things your application might need.

Technology we are gonna use in this article:

  • Mysql database
  • Laravel Framework
  • Vue.js framework for FE + @casl/ability npm package

Database

We are going to start building our system with the following database tables:

1/ roles

2/ actions

3/ roleActions

4/ userRoles

I won’t get deep into the Mysql best practices, such as how important is to have your foreign keys set, what Mysql table engine to choose, etc. My goal is to give you an idea of how to build your own structure.

We have a list of roles we need in the “roles” table, a list of actions the user will need to perform in “actions” table, “roleActions” table which binds those two using ManyToMany relation (Since role might have lots of actions and actions can be attached to multiple roles). And finally “userRoles” table with the same ManyToMany type of relations (One user can have more than one role and the role can be assigned to multiple users).

You probably already have your own “users” table, so just specify a relation to ‘userRoles’ and you are good to go.

Applying access rules

So we have set up our database and now we need to send our data to the front end to be able to actually control things we show. It can be done using some API call that will return a list of actions authorised for a user or any other way that you prefer.

In this case, I will proceed with an API route that will compose all actions that are available for my user, based on what kind of roles are assigned.

example from User.php model

Under the hood, I obviously have created all necessary models and relations according to the database structure described above.

So now we have the data coming to the Front End and we need a way to apply our list of available actions to the VueJS app, to do so we need to install the following package https://www.npmjs.com/package/@casl/ability and include it to our VueJs app.

Two things to consider here.

1/ We need to define what sort of action your user is allowed to perform. So let’s make a dedicated file and call it “ability.js”

2/ We need to include our defined actions in VueJs bootstrap file — app.js.

From this point, the Front End application has all the necessary data on what actions we allow users to perform. And we can start adding elements of our “roleplay” where ever we want to limit access to certain features. It can be achieved by using “$can” variable which is accessible from any place within our app, since above we globally registered it in our app.js file.

An example when calling from js code
An example when calling from VueJs template code

Final Words

Our puzzle is completed, and now we have a super flexible way to control access to every single piece of your Front End application. When you embed this tech into our system, you can forget about making changes related to access control, all you need to do is to create a record in “roles” table and attach some necessary actions from “actions” table through “roleActions” table. Same applicable to users, adding a new record on “userRoles” table is enough to set up a new user with a unique set of rules.

--

--