User – Role – Permission – Core – Laravel

  1. Assuming we have freshly created following tables
    • users
  2. Now create 2 following models along with its migrations
    • roles table
    • permissions table
      • php artisan make:model Role -m
      • php artisan make:model Permission -m
  3. Migration table of above table (Role and Permission) would be:
Schema::create('permissions', function (Blueprint $table) {
    $table->increments('id');
    $table->string('slug'); //edit-posts
    $table->string('name'); // edit posts
    $table->timestamps();
});

Schema::create('roles', function (Blueprint $table) {
    $table->increments('id');
    $table->string('slug'); //web-developer
    $table->string('name'); //Web Developer
    $table->timestamps();
});

4.  User can have Permission (Pivot Table)

Create migration file for users_permissions

php artisan make:migration create_users_permissions_table --create=users_permissions
Schema would be:
Schema::create('users_permissions', function (Blueprint $table) {
    $table->integer('user_id')->unsigned();
    $table->integer('permission_id')->unsigned();

 //FOREIGN KEY CONSTRAINTS
    $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
    $table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade');
 
//SETTING THE PRIMARY KEYS
    $table->primary(['user_id','permission_id']);
});

5. User can have Role ( Pivot Table)

Create migration file for users_roles

php artisan make:migration create_users_roles_table --create=users_roles
Schema would be:
Schema::create('users_roles', function (Blueprint $table) {
   $table->integer('user_id')->unsigned();
   $table->integer('role_id')->unsigned();

 //FOREIGN KEY CONSTRAINTS
   $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
   $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');

 //SETTING THE PRIMARY KEYS
   $table->primary(['user_id','role_id']);
});

6. Under a particular Role, User may have specific Permission

For example, a user may have the permission for post a topic, and an admin may have the permission to edit or delete a topic. In this case, let’s setup a new table for roles_permissions to handle this complexity.

Create migration file for roles_permissions

php artisan make:migration create_roles_permissions_table --create=roles_permissions

Schema would be:
Schema::create('roles_permissions', function (Blueprint $table) {
 $table->integer('role_id')->unsigned();
 $table->integer('permission_id')->unsigned();

 //FOREIGN KEY CONSTRAINTS
 $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
 $table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade');

 //SETTING THE PRIMARY KEYS
 $table->primary(['role_id','permission_id']);
});

7. Setting Model Relations

Role Model

public function permissions(){ return $this->belongsToMany(Permission::class,'roles_permissions'); }

Permission Model

public function roles(){ return $this->belongsToMany(Role::class,'roles_permissions'); }

8. Creating Trait

Inside of our app directory, let’s create a new directory and name it as Permissions and create a new file namely HasPermissionsTrait.php

<?php
namespace App\Permissions;

use App\Permission;
use App\Role;

trait HasPermissionsTrait {

public function roles() {
return $this->belongsToMany(Role::class,'users_roles');

}


public function permissions() {
return $this->belongsToMany(Permission::class,'users_permissions');

}

public function hasRole( ... $roles ) {
foreach ($roles as $role) {
if ($this->roles->contains('slug', $role)) {
return true;
}
}
return false;
}

protected function hasPermissionTo($permission) {
return $this->hasPermission($permission);
}

protected function hasPermission($permission) {
return (bool) $this->permissions->where('slug', $permission->slug)->count();
}

public function hasPermissionThroughRole($permission) {
foreach ($permission->roles as $role){
if($this->roles->contains($role)) {
return true;
}
}
return false;
}

// public function hasPermissionTo($permission) {
// return $this->hasPermissionThroughRole($permission) || $this->hasPermission($permission);
// }

public function givePermissionsTo(... $permissions) {
$permissions = $this->getAllPermissions($permissions);
dd($permissions);
if($permissions === null) {
return $this;
}
$this->permissions()->saveMany($permissions);
return $this;
}

public function deletePermissions( ... $permissions ) {
$permissions = $this->getAllPermissions($permissions);
$this->permissions()->detach($permissions);
return $this;
}

}

 

9. Service Proivder

We’ll be utilizing the Laravel’s “can” directive to check if the User have Permission. and instead of using $user->hasPermissionTo(), we’ll use $user->can() To do so, we need to create a new PermissionsServiceProvider for authorization.

php artisan make:provider PermissionsServiceProvider

Writing following code inside PermissionsServiceProvider:

public function boot(){
     Permission::get()->map(function($permission){
Gate::define($permission->slug, function($user) use ($permission){
   return $user->hasPermissionTo($permission);
});
     });

Blade::directive('role', function ($role){

return "<?php if(auth()->check() && auth()->user()->hasRole({$role})) { ?>";
});
Blade::directive('endrole', function ($role){
return "<?php } ?>";
}); }

Register above written Service Provider inside “app\config\app.php” :

'providers' => [

      App\Providers\PermissionsServiceProvider::class,

],

10.  Middleware – Role and Permission for Route

php artisan make:middleware RoleMiddleware

Code written inside middleware:

public function handle($request, Closure $next, $role, $permission = null)
{

if(!$request->user()->hasRole($role)){
abort(404);
}
if($permission !== null && !$request->user()->can($permission)) {
abort(404);
}

return $next($request);
}

===========================================

View part ==> verify using role

@role('admin')

<h1>Hello from the admin</h1>

@endrole

Route part==> verify through middleware

Route::group(['middleware' => 'role:admin'], function() {
   Route::get('/admin', function() {
      return 'Welcome Admin';
   });
});

 

Others are:

dd($user->hasRole('developer')); //will return true, if user has role

dd($user->givePermissionsTo('create-tasks')); // will return permission, if not null

dd($user->can('create-tasks')); // will return true, if user has permission

Leave a Reply

Your email address will not be published. Required fields are marked *