2015-06-13 2 views
3

Я хочу создать промежуточное программное обеспечение, чтобы проверить, является ли аутентифицированный пользователь владельцем элемента. Для одной модели, код легко и будет выглядеть примерно так:Laravel 5: multi-model middleware «Owner»

<?php namespace App\Http\Middleware; 

    use Closure; 

    class Owner { 

     public function handle($request, Closure $next) 
     { 
      $id = $request->segments()[1]; //get the id parameter 
      $model = Model::find($id); // find the model from DB 

      if(!$item) 
       return 'not found'; //if item not found 

      //check if authenticated user is owner 
      if($item->user_id == \Auth::id()){ 
       return $next($request); 
      }else{ 
       return 'not allowed'; 
      } 
     } 
    } 

Теперь допустим, у меня есть несколько моделей (ModelX, ModelY, ModelZ), и я не хочу, чтобы переписать промежуточного слоя функции ручки несколько раз , Как бы вставить ссылочную модель в промежуточное программное обеспечение, чтобы оно вмещало несколько моделей из моего приложения?

+0

параметры Middleware? http://laravel.com/docs/5.1/middleware#middleware-parameters – aethergy

ответ

3

Вы можете использовать параметры промежуточного программного обеспечения с привязкой к маршруту/модели. Предположим, что у вас есть ресурс сообщений.

Укажите маршрут. Среднее программное обеспечение получает параметр, описывающий ресурс, который вы хотите проверить.

Route::get('/post/{post}', ['middleware' => 'owner:post', 'as' => 'post', 'uses' => '[email protected]']); 

Тогда вы бы связать свою модель в RouteServiceProvider.php:

$router->bind('post', function ($value) { 
    return Post::where('id', $value)->firstOrFail(); 
}); 

Наконец, вы бы промежуточное программное обеспечение. Важно знать, что привязка становится доступной в объекте запроса в виде $ request-> post. Поскольку вы передаете имя ресурса промежуточному программному обеспечению, он становится третьим параметром в методе дескриптора.

public function handle($request, Closure $next, $resource) 
{ 
    if ($request->{$resource}->user_id == \Auth::id()) { 
     return $next($request); 
    } 
    return response('not allowed.', 401); 
} 

Я полагаю, вы могли бы также программно найти имя ресурса, но с помощью этого метода Вашего имени ресурса и маршрута может быть разными.

+0

Отлично, спасибо! – andrewtweber

2

Вы можете использовать маршрут и middleware parameters:

Вот промежуточное (app/Http/Middleware/AbortIfNotOwner.php):

<?php 

namespace App\Http\Middleware; 

use Closure; 

class AbortIfNotOwner 
{ 
    /** 
    * Handle an incoming request. 
    * 
    * @param \Illuminate\Http\Request $request 
    * @param \Closure $next 
    * @param string $resourceName 
    * @return mixed 
    */ 
    public function handle($request, Closure $next, $resourceName) 
    { 
     $resourceId = $request->route()->parameter($resourceName); 

     $userId = \DB::table($resourceName)->find($resourceId)->user_id; 

     if ($request->user()->id != $userId) { 
      abort(403, 'Unauthorized action.'); 
     } 

     return $next($request); 
    } 
} 

Внутри app\Http\Kernel.php:

protected $routeMiddleware = [ 
    'owner' => 'App\Http\Middleware\AbortIfNotOwner', 
]; 

Внутри файла маршрута (app/Http/routes.php):

Route::group(['middleware' => ['owner:articles']], function() { 
    // your route 
}); 

и необязательно называть его в контроллере:

public function __construct() 
{ 
    $this->middleware('owner:articles', ['only' => ['edit', 'update']]); 
} 
+0

Я предпочитаю это решение. Я собираюсь использовать что-то очень похожее. Благодаря! –