Roles and Permissions - Step 1 - Using Roles and Permissions to Secure your System

As the systems you build become more sophisticated you will find it necessary to implement more elaborate security based on the different roles the users of your system are acting in. In the tennisclub example we have been using there could reasonably be a number of roles including, System Admin, Club Secretary, Club Coach and Club Member. A system administrator is generally a super user who can access all parts of the system, it's always necessary to have one super user to access all functional componenets in case some aspect of the system becomes blocked or broken. A club secretary might reasonably be expected to assign members into different roles - for example if a new coach was appointed they could assign them into that role. A coach might get certain privileges to block book courts or delete bookings where as ordinary members might only be able to book two hours at at time. No matter what the system, there will be users, roles and permissions.

Laravel, as we know, has built in user-registration and authorisation. It also provides all the mechanism to programatically lock down aspects of your application using system of "gates" and "guards". While this is useful and robust it involves writing a lot of code and does not save information regarding roles and permissions in the database. This means role assignment and permission assignment to roles requires a programmer. This is not ideal as, for many systems, these features would be expected to regularly managed by system admins without a code change.

Luckily there are a number of laravel packages to address this. By far the most popular of these is maintatined by a Belgian WebDesign Company called Spatie and is called Laravel-Permission. There is good documentation and support available for this package and a good well established community of users. This makes it the best bet as a proven established security package. The following posts will desribe how to:

  • install the Spatie - Laravel Permission Package on your system
  • How to build a Simple User interface for the Spatie packages allowing non-programmer users to assign roles and permissions
  • How to lock down the application so that only users acting in certain roles can gain access to certain routes
Installing Spatie - Laravel-permission

To install laravel permission using composer in the root folder of your application as follows

php composer.phar require spatie/laravel-permission 

Next, to add this to the list of laravel service providers, edit the file config/app.php and add the following line of code to the bottom of the list of service providers in the 'providers' array

Spatie\Permission\PermissionServiceProvider::class,

The line should go into the list as follows

Next you have to create and publish the migration file. The migration file is the one which will create the database tables assoicated with maintaining the roles and permissions and the relationships between the users roles and permissions. We'll talk about these table a bit more in the next post. For now, we create the migration file by publishing it with the following line

php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" 

This will create the migration file as follows.

Before proceeding you should clear your application cache by removing any caching of configuration as follows

php artisan config:clear

Before we can run the migration to create the database tables, there are some slight adjustments we have to make. Firstly, in Laravel 5.4 the charater set used was switched to utf8mb4. This uses longer length fields and keys to, among other things, support emojis. One issue with this is that it does not play nicely with older versions of MySQL or versions using MariaDB as and engine. To get around this problem we need to modify app/Providers/appServiceProvider.php and include the following modifications which will reset the default String Length. Add the following line at the top of the file with the use clauses

use Illuminate\Support\Facades\Schema;

Add this line to the boot function

Schema::defaultStringLength(191);

It's possible you have already made these changes in an early example/post. If so you can proceed to the migration. Make sure the appServiceProvider.php file looks as follows

User HasRoles

To all the User class which ships with Laravel to use Spatie's roles we need to make some slight modifications to that class. Edit the file app\Models\User.php and add the following line at the top to allow the User to use the Spatie HasRoles Trait from its namespace

use Spatie\Permission\Traits\HasRoles;

Now add two other lines two instruct the class to use that trait and to set the guard_name to 'web' (guard names are discussed in more detail later)

use HasRoles;
protected $guard_name = 'web';

These lines appear as follows in the app\User.php class

Next, we need to make a slight modification to the migration file which was published by Spatie before we run the migration. We need to make it so that the tables created by the migrations for the roles and permissions tables set the field for guard_name to be both nullable and have a default value of 'web'. The reason for this will be explained in the next section. To do this, open up the file in the database folder which looks like 2021_02_10_170535_create_permission_tables.php. Your date and timestamp at the beginning of the filename will be different to the one mentioned here - don't worry about this. Add

->nullable()->default('web');

To the ends of the fields settings for gaurd_name in both the roles and permissions tables.

This should look like the following

You are now clear to run the migration which will create the database tables which will support Spatie - Laravel-permission. To do this run the command:

php artisan migrate

This will produce the following result

Now if you refresh your database under your preferred MySQL client (mine is HeidiSQL) you will notice a range of new tables in your application

You now have Spatie Laravel-permission installed and ready to use. In the next post we'll see how to create a simple UI to access these database tables and create new roles and permissions and assign them to appropriate users.

Leave a Reply