Search code examples
laravelauthenticationmiddlewarelaravel-fortify

User roles and permissions. Laravel Fortify (and not only)


Is there any ready-made functionality in the Fortify package for setting user roles and permissions (regular user, admin, main admin, etc.)? If not, what is the correct way to implement it yourself? Alternatively, create middleware and an is_admin field in the users table. And do the check:

if(Auth::user()->is_admin != 1){
    return redirect()->route('index');
}

Route:

Route::group(['middleware' => 'id_admin'], function(){
    Route::get('/admin-panel', [AdminController::class, 'admin_panel'])->name('admin_panel');
});

It's easy if I have 2 user roles (0 is normal user, 1 is administrator). But what if I have a regular user, an admin (can edit, update, delete products, categories, etc.), and a CEO (can give and take away admin rights, edit users' data and delete users)? Is it worth creating a second middleware to check is_ceo?

And with second middleware route:

Route::group(['middleware' => 'id_admin'], function(){
    Route::get('/admin-panel', [AdminController::class, 'admin_panel'])->name('admin_panel');
    Route::group(['middleware' => 'id_ceo'], function(){
        Route::get('/ceo-panel', [AdminController::class, 'ceo_panel'])->name('ceo_panel');
    });
});

Is it correct way?


Solution

  • Because Fortify has no solution for roles, so I had to write the functionality myself.

    Using this answer I found a solution for my case. I have 3 permission levels.

    0 - regular user,

    1 - administrator,

    2 - CEO.

    In my User model I wrote this:

    public function hasRole(){
          if($this->role === 2){
            return 1&&2;
          }else if($this->role === 1){
            return 1;
          }else{
            return redirect()->back();
          }
        }
    

    A Role middleware:

    <?php
    
    namespace App\Http\Middleware;
    
    use Closure;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Auth;
    
    class Role
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
         public const Admin = '1';
         public const CEO = '2';
         public function handle(Request $request, Closure $next, ... $roles){
             $user = Auth::user();
             
             $role = Auth::user()->role;
    
             if (!in_array($user->hasRole(), $roles)) {
               return redirect()->back();
            }
    
            return $next($request);
         }
    
    }
    

    App\Http\Kernel.php:

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

    Routes:

    Route::group(['middleware' => 'auth'], function(){
    
      Route::group(['middleware' => 'role:Admin,CEO'], function(){
    
          Route::get('/ceo-panel', [AdminController::class, 'ceo_panel'])->middleware('role:CEO')->name('ceo_panel');
    
          Route::get('/admin-panel', [AdminController::class, 'admin_panel'])->name('admin_panel');
    
      });
    
    });
    

    Hope somebody will find this useful!