Thursday, February 21, 2019

Create A Middleware to Have The Admin Check in Laravel

Create A Middleware to Have The Admin Check in Laravel

In the previous post “Adding isAdmin() function in Model User in Laravel”, we create an isAdmin function to check the user’s authority in view files. However, we still need a mechanism to check admin authority in the controller file. In Laravel, on of the checking mechanism is “middleware”. It is specified in the controller’s route to prevent unauthorized requests before controllers.

For this case, we need to create an IsAdmin middleware file first at app/Http/Middleware/.

1. Create Middleware app/Http/Middleware/IsAdmin.php

Using artisan make command to create:

$ php artisan make:middleware IsAdmin

The middleware file app/Http/Middleware/IsAdmin.php has been created.

2. Add codes to the middleware file

Adding the checking codes:

<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;

class IsAdmin
{
  /**
   * Handle an incoming request.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \Closure  $next
   * @return mixed
   */
  public function handle($request, Closure $next)
  {
    if (Auth::check() && Auth::user()->isAdmin()) {
      return $next($request); 
    } else {
      return redirect('/');
    }
  }
}

3. Register the middleware IsAdmin.

The next step is to register IsAdmin in the protected function $routeMiddleware of app/Http/kernel.php .

Add the following codes:

'is_admin' => \App\Http\Middleware\IsAdmin::class,

to app/Http/kernel.php:

protected $routeMiddleware = [
  'auth' => \App\Http\Middleware\Authenticate::class,
    :
  'is_admin' => \App\Http\Middleware\IsAdmin::class,              
];

4. Add the middleware before routes that needed to be authorized.

For example, we can add middleware is_admin to the route name products.create:

(before)

route::get('products/create','ProductController@create')
  ->name('products.create');

(after)

route::get('products/create','ProductController@create')
  ->middleware('is_admin')
  ->name('products.create');

Thus, the user must be an administrator to have the right to create a new product.

5. Note: middleware in controller

What if the routes using resources keywords to generate Restful routes and we need to apply middleware to all routes except two of them? (i.e. index and show).

We use the ProductController as an example:

routes/web.php

Route::resource('products', 'ProductController');

There are routes generated by resources:

Method    | URI                     | Route Name      |
-------------------------------------------------------
POST      | products                | products.store  |
GET|HEAD  | products                | products.index  |
GET|HEAD  | products/create         | products.create |
DELETE    | products/{product}      | products.destroy|
PUT|PATCH | products/{product}      | products.update |
GET|HEAD  | products/{product}      | products.show   |
GET|HEAD  | products/{product}/edit | products.edit   |

These routes must apply middleware is_admin except “products.index” and “products.show”. In another word, These routes including “products.store”, “products.create”, “products.destroy”, “products.update” and “products.edit” are allowed by administrator only.

The solution is to put the middleware setting in the app/Http/Controller/ProductController.php to achieve the goal. By adding codes as follows:

public function __construct() {
  $this->middleware('is_admin')->only(['create', 'store', 'edit', 'update', 'destroy']);
}

Note: another keyword is except to exclude the middleware rule.

No comments:

Post a Comment