Spatie Permission: The Ultimate Laravel Security Toolkit


Laravel

Author: Steve Alila
Reviewer: Deepak Prasad

Laravel is a widely used PHP web application framework that is known for its flexibility and robustness. One of the key aspects of any web application is access control, which is where Laravel's roles and permissions come in. Roles and permissions allow you to control access to different parts of your application, ensuring that users can only access the functionality that they are authorized to.

One popular tool for implementing roles and permissions in Laravel is the Spatie Laravel Permission package. This package provides a simple and flexible way to manage roles and permissions in your Laravel application, allowing you to easily define roles, assign permissions to those roles, and then assign roles to users.

With the Spatie Laravel Permission package, you can quickly and easily implement a robust access control system in your Laravel application, without having to spend hours writing custom code. In this article, we'll explore how to use the Spatie Laravel Permission package to manage roles and permissions in your Laravel application, including how to assign roles to users and how to check a user's permissions in your code.

You could implement the Laravel role and permission system from scratch or use libraries like Spatie, as shown below.

 

Install Spatie Permission Package

These commands are used in Laravel to install and configure the Spatie Laravel Permission package. The composer require command installs the package, while php artisan vendor:publish publishes the configuration file of the package to your application. Finally, php artisan optimize:clear clears the cached bootstrap files of your Laravel application. These commands together provide a simple and efficient way to install, configure, and optimize the Spatie Laravel Permission package, which allows you to manage roles and permissions in your Laravel application.

// install the Spatie Permission package in your Laravel application
composer require spatie/laravel-permission

// publish the configuration file of the Spatie Laravel Permission package to the Laravel application
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"

//  clear the cached bootstrap files of your Laravel application
php artisan optimize:clear

We install the library using composer. Next, we publish the migration and the config file with the default role and permission tables (explained in the configuration section). Lastly, we clear the config cache as the library requires us to.

 

Configuration

The config/permission.php file should be configured with the following tables:

  • roles: Holds the roles' names.
  • permissions: Holds the permissions' names.
  • model_has_permissions: Holds the User model's permissions.
  • model_has_roles: Holds the User model's roles.
  • role_has_permissions: Holds each role's permissions.

Now you can update the Model with HasRoles trait.

app/Models/User.php

The use statement at the top of the file imports the HasRoles trait from the Spatie package. The HasRoles trait adds methods and attributes to the User model that allow you to check whether a user has a particular role, assign a role to a user, and revoke a role from a user.

<?php
...
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable, HasRoles;
  ...
}

The HasRoles trait simplifies interacting with the Role and Permission models with eloquent. The respective (Role and Permission) classes are eloquent models. You create their instances using an associative array with a key called name and value of your choice.

First, you need to import the models into the current file.

use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;

before using them.

$adminRole = Role::create(['name' => 'Admin']);
$permissions = Permission::all();

You can also configure the middleware and use it, as follows.

configure

// app/Http/Kernel.php (Laravel 10)
<?php
...  
class Kernel extends HttpKernel
{
   ...
    protected $middlewareAliases = [
        ...
        'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
        'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
        'role_or_permission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class,
    ];
}

Spatie Permission: The Ultimate Laravel Security Toolkit

 

This code defines a Laravel route that is accessed when the URL /admin is requested using the HTTP GET method.

The route returns the admin.index view when accessed.

The middleware method is used to define middleware that should be applied to this route. In this case, three middleware are applied: auth, verified, and role:Admin.

The auth middleware ensures that only authenticated users can access this route, while the verified middleware checks whether the user's email has been verified. Finally, the role:Admin middleware checks whether the authenticated user has the Admin role.

Route::get('/admin', function () {
    return view('admin.index');
})->middleware(['auth', 'verified', 'role:Admin'])->name('admin.index');

The role:admin middleware from 'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class permits only users with Admin role to access the 'admin.index' view via the /admin route.

You can create the roles in the codebase or let the application users do it. Similarly, you can create default roles like admin using database seeders.

Here is an example.

 

Creating and assigning Laravel role and permission

Let's create some roles and permissions using database seeders.

php artisan make:seeder RolePermissionSeeder

We create a database seeder called RolePermissionSeeder. Next, open the database/seeders/RolePermissionSeeder.php file and create the permissions and roles.

This code demonstrates how to use the Spatie Laravel Permission package to seed the database with roles and permissions in a Laravel application. In the run() method, several permissions are created for actions such as creating, editing, and deleting users and posts. These permissions are then assigned to an Admin role using the givePermissionTo() method.

<?php

...
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;

class RolePermissionSeeder extends Seeder
{
    public function run(): void
    {
        // permission
            // on users
        Permission::create(['name' => 'create-users']);
        Permission::create(['name' => 'edit-users']);
        Permission::create(['name' => 'delete-users']);
            // on posts
        Permission::create(['name' => 'create-posts']);
        Permission::create(['name' => 'edit-posts']);
        Permission::create(['name' => 'delete-posts']);

        // role
        $adminRole = Role::create(['name' => 'Admin']);
        
        $adminRole->givePermissionTo([
            'create-users',
            'delete-users',
            'create-posts',
            'edit-posts',
            'delete-posts',
        ]);
    }
}

 

database/seeders/DatabaseSeeder.php

The run() method in the class calls two methods to create and populate data in the database. The first method uses the User model's factory method to create 10 sample users and insert them into the database. The factory() method is a convenient way to generate fake data for testing purposes.

The second method in the run() method calls the RolePermissionSeeder class, which seeds the database with roles and permissions. This is typically used in applications that use role-based access control to restrict user access to certain parts of the application.

<?php
...
class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        \App\Models\User::factory(10)->create();
        $this->call(RolePermissionSeeder::class);
    }
}

Apart from 10 users, we have configured the database to create the permissions and Admin role in the respective tables. Let's seed the database with changes.

php artisan migrate --seed

Spatie Permission: The Ultimate Laravel Security Toolkit

Now we can retrieve users and assign them permissions.

 

routes/web.php

This code assigns the "Admin" role to the first user in the database and then dumps the role names assigned to that user using the dd() function, which stands for "dump and die".

The assignRole() method is provided by the HasRoles trait of the User model, which is included at the top of the code snippet. It accepts a role name as a parameter and assigns that role to the user. In this case, the "Admin" role is assigned.

The getRoleNames() method is also provided by the HasRoles trait and returns an array of the names of all the roles assigned to the user. The dd() function is used to dump this array to the browser and then terminate the script execution, allowing you to see the output.

<?php
use App\Models\User;
use Illuminate\Support\Facades\Route;

Route::get('/', function () {
    $user1 = User::first();
    $user1->assignRole('Admin');
    dd($user1->getRoleNames());

    return view('welcome');
});

We get the first database user and make him an admin. That means s(he) can create and delete users or create, edit and delete posts as defined in the RolePermissionSeeder.php file.

 $adminRole->givePermissionTo([
   'create-users',
   'delete-users',
   'create-posts',
   'edit-posts',
   'delete-posts',
 ]);

Laravel role and permission

getRoleNames is one of the methods to read or assign permissions and roles to users. For example, we can permit the Admin to edit users.

$role = Role::findByName('Admin');
$role->givePermissionTo('edit-users');

We can also remove a role or revoke permission. The first part of the code removes the Admin role from the first user in the database, and the second part of the code revokes the edit-users permission from the Admin role. By using these methods, you can control access to different parts of your application and manage the roles and permissions of your users, ensuring that they only have access to the functionality that they are authorized to.

# role
$user1 = User::first();
$user1->removeRole('Admin');
# permission
$role = Role::findByName('Admin');
$role->revokePermissionTo('edit-users');

 

Display resources depending on Laravel role and permission

Depending on the set roles and permissions, you can hide or show a part of a view. For example, you can display a button in Blade using the @role or @can directives if the logged-in user has the matching role or permission.

The @role directive checks if the user has the Admin role and displays an Admin button if they do. The @can directive checks if the user has the edit-users permission and displays an Edit button if they do. By using these directives, the code provides a simple way to control access to different parts of your application based on a user's role or permissions.

<!-- role --->
@role('Admin')
    <button><a href="{{ route('admin.index', $user->id) }}">Admin</a></button>
@endrole
<!-- permission --->
@can('edit-users')
    <button><a href="{{ route('/edit', $user->id) }}">Edit</a></button>
@endcan

The user will only see the Admin and Edit buttons if they have the Admin role and 'edit-users' permission.

 

Conclusion

In summary, Spatie Laravel Permission is a popular package for adding role-based access control to Laravel applications. By using this package, you can define roles and permissions for different parts of your application, and assign those roles and permissions to users. This allows you to control access to different parts of your application based on the user's role, improving the security and usability of your application.

To use the Spatie Laravel Permission package, you can install it via Composer and run database migrations to set up the necessary tables. You can then define roles and permissions in your application's code and assign them to users. Laravel's middleware feature can be used to restrict access to certain routes based on the user's role. By using the HasRoles trait in the User model, you can easily check whether a user has a particular role, assign a role to a user, and revoke a role from a user.

 

Steve Alila

Steve Alila

He specializes in web design, WordPress development, and data analysis, with proficiency in Python, JavaScript, and data extraction tools. Additionally, he excels in web API development, AI integration, and data presentation using Matplotlib and Plotly. You can connect with him on his LinkedIn profile.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

Leave a Comment