9

I got this handle in a middleware called rolMiddleware:

public function handle($request, Closure $next, $roles)
{
    //dd($request->user());
    foreach ($roles as $rol) {
        if ($request->user()->getTipoUsuario($request->user()->tipo_usuario_id)->getNombreTipoUsuario() == $rol) {
            return $next($request);
        }
    }
    abort(403, "¡No hay autorizacion!");
}

But $roles is an array, here is the route where I use the middleware:

Route::get('/mid', ['middleware' => 'roles:super admin', function () {
    return "done";
}]);

and the error that gives me is:

ErrorException in RolMiddleware.php line 22:
Invalid argument supplied for foreach()

You may thing that I do not need an array because I am only using it in super admin, for that route I only need super admin, but there would be routes that can be for super admin and the admin of an area.

6 Answers 6

29

In laravel , you can separate your parameters which you want to pass to middleware using comma , as follows:

Route::get('/mid', ['middleware' => 'roles:super,admin', function () {
//                                              ^ note this
    return "done";
}]);

note that, this won't send parameters as an array, so you can't loop over $roles unless you use your passed parameters as ellipsis parameters as follows :

public function handle($request, Closure $next, ...$roles)

rather, you will need to use a single parameter for each role:

public function handle($request, Closure $next, $role1, $role2) // .... and so on
Sign up to request clarification or add additional context in comments.

1 Comment

That ellipsis parameters is all I need. $roles becomes array. Thank you very much.
4

Route:

Route::get('/access', ['middleware' => 'hasroles:super,admin', function () {
}]);

passing one parameter to check user have created permission in my cause

Route::middleware('admin')->namespace('Admin')->prefix('admin')->group(function(){
    Route::get('/home', 'MainController@getIndex')->name('admin.index')->middleware("hasrole:create");

Middleware:

1.Using Parameters

public function handle($request, Closure $next, $parm1, $parm2){}

2.Using var-arg

public function handle($request, Closure $next, $parm1, $parm2){}
public function handle($request, Closure $next, ...$parm1){}

Two-way Middleware Use

1: Register routeMiddleware

// Within App\Http\Kernel Class...
protected $routeMiddleware = [
    'hasrole' => \Illuminate\Auth\Middleware\HasRole::class,

Using:

Route::get('admin/profile', function () {
})->middleware('hasrole'); 

2: Not Register in routeMiddleware

Using:

use App\Http\Middleware\HasRole;

Route::get('admin/profile', function () {
    //
})->middleware(HasRole::class);

Comments

3

Send parameter as string like as

Route::prefix('panel')->middleware('auth:admin|editor')->group(function (){
    Route::get('/', [SiteController::class, 'index'])->name('site.index');
}

Program in middleware to sense this string as array

if (in_array(Auth::user()->rule, explode('|', $access))) {
   return $next($request);
} else {
   return redirect()->route('site.denied');
}

Comments

1

You can use explode function within middleware for converting string to array.

Controller:

public function __construct()
{
    $this->middleware('RoleCheck:admin|user')->except(['index', 'show']);
}

Middleware:

public function handle(Request $request, Closure $next, $roles)
{   
    $user = Auth::user();
    $roles = explode("|", $roles); // convert $roles to array
    foreach ($roles as $role) {
        if ($user->hasRole($role))
            return $next($request);
    }

    return redirect('login');
}

Comments

0

I don't exactly understand what your functions do, but you can try something like this:

public function handle($request, Closure $next, $roles)
{
    if(is_array($roles)){
        //dd($request->user());
        foreach ($roles as $rol) {
            if ($request->user()->getTipoUsuario($request->user()->tipo_usuario_id)->getNombreTipoUsuario() == $rol) {
                return $next($request);
            }
        }
    }else{
        if($request->user()->getTipoUsuario($request->user()->tipo_usuario_id)->getNombreTipoUsuario() == $roles)
            return $next($request);
    }
    abort(403, "¡No hay autorizacion!");
}

Comments

0

You should always have return $next($request); at the end of a middleware file... Some of these examples fail to do that.

Here's how your routes will be (web.php file):

Route::middleware('auth')->group(function () {
Route::middleware('CheckRole:super-admin')->group(function () {
//super-admin only routes here
});

Route::middleware('CheckRole:user')->group(function () {
//user only routes here
});
});

To add more roles to the above code, just put CheckRole:super-admin,user you can keep going with commas for the specific group.

The middlewares below will automatically keep anyone without permission out of the areas specified above, and only when a user is logged in

Make sure to add the below middleware to:

App\Http\Kernel.php

Under protected $middlewareAliases = [ Put the following line:

'CheckRole' => \App\Http\Middleware\CheckRole::class,

Your middleware will be:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

class CheckRole
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
     */
    public function handle(Request $request, Closure $next, ...$roles): Response
    {
        if ($request->user()) {

            $userRole = Auth::user()->role->value('name');

            if (! in_array($userRole, $roles)) {
                
                abort(403, 'Your account permissions do not allow access to the requested page');

            }

        }

        return $next($request);
    }
}

This assumes you only have 1 role for 1 user. If you have multiple roles for 1 user, that would be a different check in your middleware code

If you have multiple Roles for multiple Users, you can use this middleware:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;

class CheckRole
{
    /**
     * Handle an incoming request.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
     */
    public function handle(Request $request, Closure $next, ...$roles): Response
    {
        if ($request->user()) {

            $userRoles = Auth::user()->roles
                ->pluck('name')
                ->toArray();

            if (! array_intersect($userRoles, $roles)) {
                
                abort(403, 'Your account permissions do not allow access to the requested page');

            }

        }

        return $next($request);
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.