Удобное правило валидации проверки доступа в Laravel 5



Я работал над несколькими проектами Laravel и почти в каждом проекте есть необходимость в системе управления доступом. Наиболее простым примером является проверка того, принадлежит ли некоторый ресурс пользователю. Например, представьте, у вас есть сайт для фрилансеров, где пользователи могут управлять своими проектами, учётом рабочего времени, заказами и т. д. Когда пользователь хочет отправить новый таймлог для некоторого проекта, он должен выбрать этот проект из выпадающего меню и заполнить оставшуюся часть формы. Когда он посылает эту форму к API, нам необходимо проверить этот запрос.
Допустим, что выпадающее меню имеет свойство “PROJECT_ID” с установленным значением:
$rules = [
    // другие правила
    'project_id' => 'required|exists:projects,id',
    // другие правила
];

Проблема

Следующим важным шагом является проверка того, принадлежит ли этот проект аутентефицированному пользователю. Для этого у вас есть множество вариантов. Например, вы можете использовать класс Illuminate\Auth\Access\Gate и в нём определить возможности пользователя (см. больше), или вы можете написать свой собственный контроллер валидации. В моем случае, я бы хотел иметь что-то, что требует значительно меньшее количество кода и может быть использовано для валидации. Это решило бы сразу 2 проблемы:
  1. Код многоразового использования, который может быть применен к почти каждому ресурсу;
  2. Лёгкое нахождение ошибок в отношении неавторизованных запросов.

Решение

В большинстве случаев, чтобы проверить, принадлежит ли некоторый ресурс пользователю, я могу сделать что-то вроде этого:
$rules = [
    // other rules
    'project_id' => 'required|exists:projects,id|belongs_to_user:projects',
    // other rules
];
Правило belongs_to_user делает проверку, существует ли данный ID проекта в таблице projects. Так же он проверяет, что user_id - это идентификатор аутентефицированного пользователя. Для добавления этого пользовательского правила, нам необходимо создать пользовательский класс сервис-провайдера с помощью следующей команды:
php artisan make:provider CustomValidationServiceProvider
Следующий шаг заключается в регистрации нашего нового сервис-провайдера. Это может быть сделано путем открытия файла Config/app.php и добавления App\Providers\CustomValidationServiceProvider::class в массив providers. После этого, новый файл будет создан в директории app/Providers. Откройте вновь созданный файл и добавьте следующий код в тело метода boot:
public function boot()
{
    Validator::extend('belongs_to_user', function($attribute, $value, $parameters, $validator) {
        $table = $parameters[0];
        $primary_key_field = isset($parameters[1]) ? $parameters[1] : 'id';
        $user_foreign_key_field = isset($parameters[2]) ? $parameters[2] : 'user_id';

        return DB::table($table)->where($primary_key_field, '=', $value)->first()->$user_foreign_key_field == Auth::user()->id;
    });
}
Если вы посмотрите на код, то обнаружите 2 необязательных параметра. Один параметр нужен для задания пользовательского поля, содержащего первичный ключ для нашего ресурса (если поле первичного ключа не “ID”). Другой параметр нужен для задания пользовательского поля, содержащего внешний ключ (если вы не используете user_id в качестве внешнего ключа для таблицы users).
На этом урок заканчивается, спасибо за прочтение!
Ссылка на оригинал