0
votes

I am following a tutorial for making a access level restriction:

https://gist.github.com/amochohan/8cb599ee5dc0af5f4246

I was able to make it work somehow but there's something I need to get working which is not in the tutorial.

Provided I have followed the tutorial. I have setup this resource route:

Route::group(['middleware' => ['auth', 'roles'], 'roles' => ['Administrator']], function()
{
    Route::resource('changeschedule', 'ChangeScheduleController', ['only' => ['index'], 'except' => ['create']]);
});

So what I wanted is just to apply the roles middleware to a resource route but with specific route in that resource only let's say I want to be applied in the index only so I have that route above.

When I go to:

http://localhost/hrs/public/changeschedule

It works fine and the middleware roles is working fine. But why is that when I go to:

http://localhost/hrs/public/changeschedule/create

I am getting

NotFoundHttpException in RouteCollection.php line 161:

So I have a no found route error. Why is that? But when I do

Route::group(['middleware' => ['auth', 'roles'], 'roles' => ['Administrator']], function()
{
    Route::resource('changeschedule', 'ChangeScheduleController');
});

Then it works fine but the middleware is applied to all:

index, create, update, edit, delete

I want it to be in index only.

My code:

Kernel.php

protected $routeMiddleware = [
    'auth'          => \App\Http\Middleware\Authenticate::class,
    'auth.basic'    => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'guest'         => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'roles'         => \App\Http\Middleware\CheckRole::class,
];

CheckRole.php

<?php namespace App\Http\Middleware;

use Closure;

class CheckRole{

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */

    public function handle($request, Closure $next)
    {
        // Get the required roles from the route
        $roles = $this->getRequiredRoleForRoute($request->route());
        // Check if a role is required for the route, and
        // if so, ensure that the user has that role.
        if($request->user()->hasRole($roles) || !$roles)
        {
            return $next($request);
        }
        return response([
            'error' => [
                'code' => 'INSUFFICIENT_ROLE',
                'description' => 'You are not authorized to access this resource.'
            ]
        ], 401);
    }

    private function getRequiredRoleForRoute($route)
    {
        $actions = $route->getAction();
        return isset($actions['roles']) ? $actions['roles'] : null;
    }
}
1

1 Answers

0
votes

You may try this, create a constructor function and add the middleware from there, for example:

public function __construct()
{
    $this->middleware('auth');

    $this->middleware('roles:administrator', ['only' => ['index']]);  
}

Read the documentation.

Update (The third parameter in the middleware::handle method can take the argument):

public function handle($request, Closure $next, $role)
{
    // $role will catch the administrator or whatever you pass
}

You may also check these examples/tutorials on my blog (about middleware).