Laravel

laravel roles and permissions without package

The article "Laravel Roles and Permissions Without Package" on aidigitalcode.com explains how to implement role-based access control in Laravel without relying on third-party packages. This approach offers developers more control over the implementation process and helps avoid potential issues associated with using external packages. By following the steps outlined in the article, developers can create the necessary models, tables, and middleware to establish role-based access control in their Laravel application.

Step 1: Create the Role Model

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
   // Attributes
   protected $fillable = ['name', 'label'];
   // Relationships
   public function permissions()
   {
       return $this->belongsToMany(Permission::class);
   }
   // Grant permission to a role
   public function givePermissionTo(Permission $permission)
   {
       return $this->permissions()->save($permission);
   }
}


Step 2: Create the Permission Model

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Permission extends Model
{
   // Attributes
   protected $fillable = ['name', 'label'];
   // Relationships
   public function roles()
   {
       return $this->belongsToMany(Role::class);
   }
}


Step 3: Create the HasRoles Trait

<?php
namespace App\Models;
trait HasRoles
{
   // Relationships
   public function roles()
   {
       return $this->belongsToMany(Role::class);
   }
   // Assign a role to the user
   public function assignRole($role)
   {
       return $this->roles()->save(
           Role::whereName($role)->firstOrFail()
       );
   }
   // Check if the user has the given role
   public function hasRole($role)
   {
       if (is_string($role)) {
           return $this->roles->contains('name', $role);
       }
       if (is_array($role)) {
           foreach ($role as $r) {
               if ($this->hasRole($r)) {
                   return true;
               }
           }
           return false;
       }
       return !!$role->intersect($this->roles)->count();
   }
   // Check if the user has the given permission
   public function hasPermission(Permission $permission)
   {
       return $this->hasRole($permission->roles);
   }
}


Step 4: Add the HasRoles Trait to the User Model

use HasRoles;

Step 5: Create the Migration for Roles and Permissions

php artisan make:migration create_roles_permissions_tables

Update the migration file create_roles_permissions_tables with the following code:

<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateRolesPermissionsTables extends Migration
{
   // Run the migrations
   public function up()
   {
       Schema::create('roles', function (Blueprint $table) {
           $table->bigIncrements('id');
           $table->string('name');
           $table->string('label')->nullable();
           $table->timestamps();
       });
       Schema::create('permissions', function (Blueprint $table) {
           $table->bigIncrements('id');
           $table->string('name');
           $table->string('label')->nullable();
           $table->timestamps();
       });
       Schema::create('permission_role', function (Blueprint $table) {
           $table->unsignedBigInteger('permission_id');
           $table->unsignedBigInteger('role_id');
           $table->foreign('permission_id')
               ->references('id')
               ->on('permissions')
               ->onDelete('cascade');
           $table->foreign('role_id')
               ->references('id')
               ->on('roles')
               ->onDelete('cascade');
           $table->primary(['permission_id', 'role_id']);
       });
       Schema::create('role_user', function (Blueprint $table) {
           $table->unsignedBigInteger('role_id');
           $table->unsignedBigInteger('user_id');
           $table->foreign('role_id')
               ->references('id')
               ->on('roles')
               ->onDelete('cascade');
           $table->foreign('user_id')
               ->references('id')
               ->on('users')
               ->onDelete('cascade');
           $table->primary(['role_id', 'user_id']);
       });
   }
   // Reverse the migrations
   public function down()
   {
       Schema::drop('permission_role');
       Schema::drop('role_user');
       Schema::drop('roles');
       Schema::drop('permissions');
   }
}


Run the migration to create the roles and permissions tables:

php artisan migrate

Step 6: Create the Role Checker Middleware
Create the CheckRole middleware file app/Http/Middleware/CheckRole.php:

<?php
namespace App\Http\Middleware;
use Closure;
class CheckRole
{
   // Handle an incoming request
   public function handle($request, Closure $next, $role)
   {
       if ($request->user()->hasRole($role) || !$role) {
           return $next($request);
       }
       abort(403, 'This action is unauthorized.');
   }
}


Add the CheckRole middleware in app/Http/Kernel.php:

protected $routeMiddleware = [
   // ...
   'role' => \App\Http\Middleware\CheckRole::class,
];

Once you have completed these steps, you will have the necessary files and configurations for role and permission management in your Laravel application.

To create a role and assign permissions:

$role = Role::findOrFail($id);
$permission = Permission::whereName($permission_name)->first();
$role->givePermissionTo($permission);

To assign roles to a user:

$user = User::findOrFail($id);
$user->assignRole('role_name');

To check a user's role:

if (Auth::check() && Auth::user()->hasRole('admin')) {
  // Perform admin actions here
} else {
  // Perform other actions here
}

To check roles and permissions in route middleware:

Route::group(['middleware' => ['auth', 'role:admin']], function () {
  // Routes for admin role only
});
Route::group(['middleware' => ['auth', 'can:write_user']], function () {
  // Routes for users with write_user permission
});

To check permissions:

if ($user->can('permission-name')) {
  // Perform actions requiring permission
}

These modifications incorporate the code snippets and instructions from the article, making it easier for Laravel developers to implement role-based access control in their applications.

Leave A Comment