#Введение
Помимо встроенных сервисов аутентификации, Laravel предоставляет простой способ авторизации действий пользователя в отношении определённого ресурса. Например, даже если пользователь аутентифицирован, он может не иметь права обновлять или удалять определённые модели Eloquent или записи в базе данных, управляемые вашим приложением. Функции авторизации Laravel обеспечивают простой и организованный способ управления такими проверками прав.
Laravel предлагает два основных способа авторизации действий: gates и policies. Можно представить gates и policies как маршруты и контроллеры. Gates обеспечивают простой подход на основе замыканий, тогда как policies, подобно контроллерам, группируют логику вокруг конкретной модели или ресурса. В этой документации мы сначала рассмотрим gates, а затем перейдём к политикам.
Вам не нужно выбирать между использованием исключительно gates или исключительно policies при создании приложения. Большинство приложений, скорее всего, будут содержать смесь gates и policies, и это вполне нормально! Gates лучше подходят для действий, не связанных с конкретной моделью или ресурсом, например, просмотр панели администратора. В то время как policies следует использовать, когда нужно авторизовать действие для конкретной модели или ресурса.
#Gates
#Создание Gates
Gates — отличный способ изучить основы функций авторизации Laravel; однако при создании серьёзных приложений Laravel рекомендуется использовать policies для организации правил авторизации.
Gates — это просто замыкания, которые определяют, авторизован ли пользователь на выполнение данного действия. Обычно gates определяются в методе boot класса App\Providers\AuthServiceProvider с использованием фасада Gate. Gates всегда получают экземпляр пользователя в качестве первого аргумента и могут дополнительно принимать другие аргументы, например, соответствующую модель Eloquent.
В этом примере мы определим gate, который проверяет, может ли пользователь обновить заданную модель App\Models\Post. Gate будет сравнивать id пользователя с user_id пользователя, создавшего пост:
use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Facades\Gate;
/**
* Регистрация сервисов аутентификации / авторизации.
*/
public function boot(): void
{
Gate::define('update-post', function (User $user, Post $post) {
return $user->id === $post->user_id;
});
}
Как и контроллеры, gates могут быть определены с помощью callback-массива класса:
use App\Policies\PostPolicy;
use Illuminate\Support\Facades\Gate;
/**
* Регистрация сервисов аутентификации / авторизации.
*/
public function boot(): void
{
Gate::define('update-post', [PostPolicy::class, 'update']);
}
#Авторизация действий
Для авторизации действия с помощью gates следует использовать методы allows или denies фасада Gate. Обратите внимание, что не нужно явно передавать текущего аутентифицированного пользователя этим методам. Laravel автоматически передаст пользователя в замыкание gate. Обычно методы авторизации gates вызываются в контроллерах приложения перед выполнением действия, требующего авторизации:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
class PostController extends Controller
{
/**
* Обновить указанный пост.
*/
public function update(Request $request, Post $post): RedirectResponse
{
if (! Gate::allows('update-post', $post)) {
abort(403);
}
// Обновить пост...
return redirect('/posts');
}
}
Если вы хотите проверить, имеет ли право выполнить действие пользователь, отличный от текущего аутентифицированного, можно использовать метод forUser фасада Gate:
if (Gate::forUser($user)->allows('update-post', $post)) {
// Пользователь может обновить пост...
}
if (Gate::forUser($user)->denies('update-post', $post)) {
// Пользователь не может обновить пост...
}
Вы можете авторизовать несколько действий одновременно с помощью методов any или none:
if (Gate::any(['update-post', 'delete-post'], $post)) {
// Пользователь может обновить или удалить пост...
}
if (Gate::none(['update-post', 'delete-post'], $post)) {
// Пользователь не может обновить или удалить пост...
}
#Авторизация с выбросом исключений
Если вы хотите попытаться авторизовать действие и автоматически выбросить исключение Illuminate\Auth\Access\AuthorizationException, если пользователь не имеет права на выполнение действия, используйте метод authorize фасада Gate. Исключения AuthorizationException автоматически преобразуются в HTTP-ответ с кодом 403 обработчиком исключений Laravel:
Gate::authorize('update-post', $post);
// Действие авторизовано...
#Передача дополнительного контекста
Методы gate для авторизации возможностей (allows, denies, check, any, none, authorize, can, cannot) и директивы авторизации Blade (@can, @cannot, @canany) могут принимать массив в качестве второго аргумента. Элементы массива передаются как параметры в замыкание gate и могут использоваться для дополнительного контекста при принятии решения об авторизации:
use App\Models\Category;
use App\Models\User;
use Illuminate\Support\Facades\Gate;
Gate::define('create-post', function (User $user, Category $category, bool $pinned) {
if (! $user->canPublishToGroup($category->group)) {
return false;
} elseif ($pinned && ! $user->canPinPosts()) {
return false;
}
return true;
});
if (Gate::check('create-post', [$category, $pinned])) {
// Пользователь может создать пост...
}
#Ответы Gates
До сих пор мы рассматривали gates, возвращающие простые булевы значения. Однако иногда может потребоваться вернуть более подробный ответ, включая сообщение об ошибке. Для этого можно вернуть экземпляр Illuminate\Auth\Access\Response из вашего gate:
use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
Gate::define('edit-settings', function (User $user) {
return $user->isAdmin
? Response::allow()
: Response::deny('Вы должны быть администратором.');
});
Даже при возврате ответа авторизации из gate метод Gate::allows по-прежнему возвращает простое булево значение; однако вы можете использовать метод Gate::inspect для получения полного ответа авторизации, возвращаемого gate:
$response = Gate::inspect('edit-settings');
if ($response->allowed()) {
// Действие авторизовано...
} else {
echo $response->message();
}
При использовании метода Gate::authorize, который выбрасывает исключение AuthorizationException при отсутствии авторизации, сообщение об ошибке из ответа авторизации будет передано в HTTP-ответ:
Gate::authorize('edit-settings');
// Действие авторизовано...
#Настройка HTTP-статуса ответа
Когда действие отклоняется через Gate, возвращается HTTP-ответ с кодом 403; однако иногда полезно вернуть альтернативный HTTP-статус. Вы можете настроить HTTP-статус, возвращаемый при неудачной проверке авторизации, используя статический конструктор denyWithStatus класса Illuminate\Auth\Access\Response:
use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
Gate::define('edit-settings', function (User $user) {
return $user->isAdmin
? Response::allow()
: Response::denyWithStatus(404);
});
Поскольку скрытие ресурсов через ответ с кодом 404 — распространённый паттерн для веб-приложений, для удобства предоставлен метод denyAsNotFound:
use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
Gate::define('edit-settings', function (User $user) {
return $user->isAdmin
? Response::allow()
: Response::denyAsNotFound();
});
#Перехват проверок Gate
Иногда может потребоваться предоставить все права конкретному пользователю. Для этого можно использовать метод before, чтобы определить замыкание, которое будет выполняться перед всеми остальными проверками авторизации:
use App\Models\User;
use Illuminate\Support\Facades\Gate;
Gate::before(function (User $user, string $ability) {
if ($user->isAdministrator()) {
return true;
}
});
Если замыкание before возвращает ненулевой результат, он будет считаться результатом проверки авторизации.
Вы можете использовать метод after для определения замыкания, которое будет выполнено после всех остальных проверок авторизации:
use App\Models\User;
Gate::after(function (User $user, string $ability, bool|null $result, mixed $arguments) {
if ($user->isAdministrator()) {
return true;
}
});
Аналогично методу before, если замыкание after возвращает ненулевой результат, он будет считаться результатом проверки авторизации.
#Встроенная авторизация
Иногда может потребоваться определить, авторизован ли текущий аутентифицированный пользователь на выполнение действия без написания отдельного gate, соответствующего этому действию. Laravel позволяет выполнять такие «встроенные» проверки авторизации с помощью методов Gate::allowIf и Gate::denyIf. Встроенная авторизация не выполняет определённые "before" или "after" хуки авторизации:
use App\Models\User;
use Illuminate\Support\Facades\Gate;
Gate::allowIf(fn (User $user) => $user->isAdministrator());
Gate::denyIf(fn (User $user) => $user->banned());
Если действие не авторизовано или если пользователь не аутентифицирован, Laravel автоматически выбросит исключение Illuminate\Auth\Access\AuthorizationException. Исключения AuthorizationException автоматически преобразуются в HTTP-ответ с кодом 403 обработчиком исключений Laravel.
#Создание политик
#Генерация политик
Политики — это классы, которые организуют логику авторизации вокруг конкретной модели или ресурса. Например, если ваше приложение — блог, у вас может быть модель App\Models\Post и соответствующая политика App\Policies\PostPolicy для авторизации действий пользователя, таких как создание или обновление постов.
Вы можете сгенерировать политику с помощью Artisan-команды make:policy. Сгенерированная политика будет помещена в каталог app/Policies. Если этот каталог отсутствует в вашем приложении, Laravel создаст его автоматически:
php artisan make:policy PostPolicy
Команда make:policy создаст пустой класс политики. Если вы хотите сгенерировать класс с примерами методов политики, связанных с просмотром, созданием, обновлением и удалением ресурса, вы можете указать опцию --model при выполнении команды:
php artisan make:policy PostPolicy --model=Post
#Регистрация политик
После создания класса политики его необходимо зарегистрировать. Регистрация политик позволяет Laravel узнать, какую политику использовать при авторизации действий для данного типа модели.
Включённый в свежие приложения Laravel класс App\Providers\AuthServiceProvider содержит свойство policies, которое сопоставляет ваши модели Eloquent с соответствующими политиками. Регистрация политики указывает Laravel, какую политику использовать при авторизации действий для данной модели Eloquent:
<?php
namespace App\Providers;
use App\Models\Post;
use App\Policies\PostPolicy;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
/**
* Сопоставления политик для приложения.
*
* @var array
*/
protected $policies = [
Post::class => PostPolicy::class,
];
/**
* Регистрация сервисов аутентификации / авторизации приложения.
*/
public function boot(): void
{
// ...
}
}
#Автоматическое обнаружение политик
Вместо ручной регистрации политик моделей Laravel может автоматически обнаруживать политики, если модель и политика следуют стандартным соглашениям Laravel по именованию. В частности, политики должны находиться в каталоге Policies в каталоге с моделями или выше. Например, модели могут располагаться в app/Models, а политики — в app/Policies. В этом случае Laravel будет искать политики сначала в app/Models/Policies, затем в app/Policies. Кроме того, имя политики должно совпадать с именем модели и иметь суффикс Policy. Например, модель User будет соответствовать классу политики UserPolicy.
Если вы хотите определить собственную логику обнаружения политик, вы можете зарегистрировать пользовательский callback для обнаружения политик с помощью метода Gate::guessPolicyNamesUsing. Обычно этот метод вызывается из метода boot вашего AuthServiceProvider:
use Illuminate\Support\Facades\Gate;
Gate::guessPolicyNamesUsing(function (string $modelClass) {
// Вернуть имя класса политики для данной модели...
});
Любые политики, явно сопоставленные в вашем AuthServiceProvider, будут иметь приоритет над потенциально автоматически обнаруженными политиками.
#Написание политик
#Методы политик
После регистрации класса политики вы можете добавить методы для каждого действия, которое она авторизует. Например, определим метод update в PostPolicy, который проверяет, может ли данный App\Models\User обновить конкретный экземпляр App\Models\Post.
Метод update принимает экземпляры User и Post в качестве аргументов и должен возвращать true или false, указывая, авторизован ли пользователь на обновление данного Post. В этом примере мы проверим, совпадает ли id пользователя с user_id поста:
<?php
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
class PostPolicy
{
/**
* Определить, может ли пользователь обновить данный пост.
*/
public function update(User $user, Post $post): bool
{
return $user->id === $post->user_id;
}
}
Вы можете продолжать определять дополнительные методы в политике по мере необходимости для различных действий, которые она авторизует. Например, можно определить методы view или delete для авторизации различных действий с Post, но помните, что вы можете давать методам политики любые имена.
Если вы использовали опцию --model при генерации политики через Artisan, она уже будет содержать методы для действий viewAny, view, create, update, delete, restore и forceDelete.
Все политики разрешаются через service container Laravel, что позволяет автоматически внедрять любые необходимые зависимости через конструктор политики.
#Ответы политик
До сих пор мы рассматривали методы политик, возвращающие простые булевы значения. Однако иногда может потребоваться вернуть более подробный ответ, включая сообщение об ошибке. Для этого можно вернуть экземпляр Illuminate\Auth\Access\Response из метода политики:
use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;
/**
* Определить, может ли пользователь обновить данный пост.
*/
public function update(User $user, Post $post): Response
{
return $user->id === $post->user_id
? Response::allow()
: Response::deny('Вы не являетесь владельцем этого поста.');
}
При возврате ответа авторизации из политики метод Gate::allows по-прежнему возвращает простое булево значение; однако вы можете использовать метод Gate::inspect для получения полного ответа авторизации, возвращаемого gate:
use Illuminate\Support\Facades\Gate;
$response = Gate::inspect('update', $post);
if ($response->allowed()) {
// Действие авторизовано...
} else {
echo $response->message();
}
При использовании метода Gate::authorize, который выбрасывает исключение AuthorizationException при отсутствии авторизации, сообщение об ошибке из ответа авторизации будет передано в HTTP-ответ:
Gate::authorize('update', $post);
// Действие авторизовано...
#Настройка HTTP-статуса ответа
Когда действие отклоняется через метод политики, возвращается HTTP-ответ с кодом 403; однако иногда полезно вернуть альтернативный HTTP-статус. Вы можете настроить HTTP-статус, возвращаемый при неудачной проверке авторизации, используя статический конструктор denyWithStatus класса Illuminate\Auth\Access\Response:
use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;
/**
* Определить, может ли пользователь обновить данный пост.
*/
public function update(User $user, Post $post): Response
{
return $user->id === $post->user_id
? Response::allow()
: Response::denyWithStatus(404);
}
Поскольку скрытие ресурсов через ответ с кодом 404 — распространённый паттерн для веб-приложений, для удобства предоставлен метод denyAsNotFound:
use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;
/**
* Определить, может ли пользователь обновить данный пост.
*/
public function update(User $user, Post $post): Response
{
return $user->id === $post->user_id
? Response::allow()
: Response::denyAsNotFound();
}
#Методы без моделей
Некоторые методы политики принимают только экземпляр текущего аутентифицированного пользователя. Такая ситуация наиболее распространена при авторизации действий create. Например, если вы создаёте блог, вы можете захотеть определить, имеет ли пользователь право создавать вообще какие-либо посты. В таких случаях метод политики должен принимать только пользователя:
/**
* Определить, может ли пользователь создавать посты.
*/
public function create(User $user): bool
{
return $user->role == 'writer';
}
#Гостевые пользователи
По умолчанию все gates и policies автоматически возвращают false, если входящий HTTP-запрос не был инициирован аутентифицированным пользователем. Однако вы можете разрешить этим проверкам авторизации проходить в ваши gates и policies, объявив «опциональную» типизацию или указав значение по умолчанию null для аргумента пользователя:
<?php
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
class PostPolicy
{
/**
* Определить, может ли пользователь обновить данный пост.
*/
public function update(?User $user, Post $post): bool
{
return $user?->id === $post->user_id;
}
}
#Фильтры политик
Для некоторых пользователей может потребоваться разрешить все действия в рамках данной политики. Для этого определите метод before в политике. Метод before будет выполнен перед любыми другими методами политики, давая возможность авторизовать действие до вызова основного метода политики. Эта функция чаще всего используется для авторизации администраторов приложения на выполнение любых действий:
use App\Models\User;
/**
* Выполнить предварительные проверки авторизации.
*/
public function before(User $user, string $ability): bool|null
{
if ($user->isAdministrator()) {
return true;
}
return null;
}
Если вы хотите отклонить все проверки авторизации для определённого типа пользователя, вы можете вернуть false из метода before. Если возвращается null, проверка авторизации будет передана основному методу политики.
Метод before класса политики не будет вызван, если класс не содержит метода с именем, совпадающим с проверяемым правом.
#Авторизация действий с помощью политик
#Через модель User
Модель App\Models\User, включённая в ваше приложение Laravel, содержит два полезных метода для авторизации действий: can и cannot. Методы can и cannot принимают имя действия, которое вы хотите авторизовать, и соответствующую модель. Например, определим, авторизован ли пользователь на обновление заданной модели App\Models\Post. Обычно это делается в методе контроллера:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* Обновить указанный пост.
*/
public function update(Request $request, Post $post): RedirectResponse
{
if ($request->user()->cannot('update', $post)) {
abort(403);
}
// Обновить пост...
return redirect('/posts');
}
}
Если для данной модели зарегистрирована политика, метод can автоматически вызовет соответствующую политику и вернёт булево значение. Если политика не зарегистрирована, метод can попытается вызвать closure-based Gate с соответствующим именем действия.
#Действия, не требующие моделей
Помните, что некоторые действия могут соответствовать методам политики, таким как create, которые не требуют экземпляра модели. В таких случаях вы можете передать имя класса в метод can. Имя класса будет использовано для определения, какую политику применять при авторизации действия:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* Создать пост.
*/
public function store(Request $request): RedirectResponse
{
if ($request->user()->cannot('create', Post::class)) {
abort(403);
}
// Создать пост...
return redirect('/posts');
}
}
#Через помощники контроллера
Помимо полезных методов, предоставляемых модели App\Models\User, Laravel предоставляет удобный метод authorize для любых ваших контроллеров, которые наследуются от базового класса App\Http\Controllers\Controller.
Как и метод can, этот метод принимает имя действия, которое вы хотите авторизовать, и соответствующую модель. Если действие не авторизовано, метод authorize выбросит исключение Illuminate\Auth\Access\AuthorizationException, которое обработчик исключений Laravel автоматически преобразует в HTTP-ответ с кодом 403:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* Обновить указанный блог-пост.
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function update(Request $request, Post $post): RedirectResponse
{
$this->authorize('update', $post);
// Текущий пользователь может обновить блог-пост...
return redirect('/posts');
}
}
#Действия, не требующие моделей
Как уже обсуждалось, некоторые методы политики, такие как create, не требуют экземпляра модели. В таких случаях следует передавать имя класса в метод authorize. Имя класса будет использовано для определения, какую политику применять при авторизации действия:
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
/**
* Создать новый блог-пост.
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function create(Request $request): RedirectResponse
{
$this->authorize('create', Post::class);
// Текущий пользователь может создавать блог-посты...
return redirect('/posts');
}
#Авторизация resource-контроллеров
Если вы используете resource-контроллеры, вы можете воспользоваться методом authorizeResource в конструкторе контроллера. Этот метод добавит соответствующие определения middleware can к методам resource-контроллера.
Метод authorizeResource принимает имя класса модели в качестве первого аргумента и имя параметра маршрута / запроса, содержащего ID модели, в качестве второго аргумента. Убедитесь, что ваш resource-контроллер создан с флагом --model, чтобы иметь необходимые сигнатуры методов и типы:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Post;
class PostController extends Controller
{
/**
* Создать экземпляр контроллера.
*/
public function __construct()
{
$this->authorizeResource(Post::class, 'post');
}
}
Следующие методы контроллера будут сопоставлены с соответствующими методами политики. При маршрутизации запросов к методу контроллера соответствующий метод политики будет автоматически вызван до выполнения метода контроллера:
| Метод контроллера | Метод политики |
|---|---|
| index | viewAny |
| show | view |
| create | create |
| store | create |
| edit | update |
| update | update |
| destroy | delete |
Вы можете использовать команду make:policy с опцией --model для быстрой генерации класса политики для заданной модели: php artisan make:policy PostPolicy --model=Post.
#Через middleware
Laravel включает middleware, который может авторизовать действия до того, как входящий запрос достигнет ваших маршрутов или контроллеров. По умолчанию middleware Illuminate\Auth\Middleware\Authorize назначен ключу can в вашем классе App\Http\Kernel. Рассмотрим пример использования middleware can для авторизации возможности обновления поста:
use App\Models\Post;
Route::put('/post/{post}', function (Post $post) {
// Текущий пользователь может обновить пост...
})->middleware('can:update,post');
В этом примере мы передаём middleware can два аргумента. Первый — имя действия, которое хотим авторизовать, второй — параметр маршрута, который будет передан методу политики. В данном случае, поскольку используется неявное связывание моделей, в метод политики будет передан экземпляр App\Models\Post. Если пользователь не авторизован на выполнение действия, middleware вернёт HTTP-ответ с кодом 403.
Для удобства вы также можете прикрепить middleware can к маршруту с помощью метода can:
use App\Models\Post;
Route::put('/post/{post}', function (Post $post) {
// Текущий пользователь может обновить пост...
})->can('update', 'post');
#Действия, не требующие моделей
Опять же, некоторые методы политики, такие как create, не требуют экземпляра модели. В таких случаях вы можете передать имя класса в middleware. Имя класса будет использовано для определения, какую политику применять при авторизации действия:
Route::post('/post', function () {
// Текущий пользователь может создавать посты...
})->middleware('can:create,App\Models\Post');
Указание полного имени класса в строковом определении middleware может быть громоздким. Поэтому вы можете прикрепить middleware can к маршруту с помощью метода can:
use App\Models\Post;
Route::post('/post', function () {
// Текущий пользователь может создавать посты...
})->can('create', Post::class);
#Через шаблоны Blade
В шаблонах Blade иногда нужно отображать часть страницы только если пользователю разрешено выполнить определённое действие. Например, форму редактирования записи блога стоит показывать только если пользователь действительно может обновить запись. В этом случае можно использовать директивы @can и @cannot:
@can('update', $post)
<!-- Текущий пользователь может обновить запись... -->
@elsecan('create', App\Models\Post::class)
<!-- Текущий пользователь может создавать новые записи... -->
@else
<!-- ... -->
@endcan
@cannot('update', $post)
<!-- Текущий пользователь не может обновить запись... -->
@elsecannot('create', App\Models\Post::class)
<!-- Текущий пользователь не может создавать новые записи... -->
@endcannot
Эти директивы — удобные сокращения для написания условий @if и @unless. Директивы @can и @cannot выше эквивалентны следующим выражениям:
@if (Auth::user()->can('update', $post))
<!-- Текущий пользователь может обновить пост... -->
@endif
@unless (Auth::user()->can('update', $post))
<!-- Текущий пользователь не может обновить пост... -->
@endunless
Вы также можете проверить, авторизован ли пользователь на выполнение любого действия из заданного массива действий. Для этого используйте директиву @canany:
@canany(['update', 'view', 'delete'], $post)
<!-- Текущий пользователь может обновить, просмотреть или удалить пост... -->
@elsecanany(['create'], \App\Models\Post::class)
<!-- Текущий пользователь может создать пост... -->
@endcanany
#Действия, не требующие моделей
Как и большинство других методов авторизации, вы можете передать имя класса директивам @can и @cannot, если действие не требует экземпляра модели:
@can('create', App\Models\Post::class)
<!-- Текущий пользователь может создавать посты... -->
@endcan
@cannot('create', App\Models\Post::class)
<!-- Текущий пользователь не может создавать посты... -->
@endcannot
#Передача дополнительного контекста
При авторизации действий с помощью политик вы можете передать массив в качестве второго аргумента в различные функции и помощники авторизации. Первый элемент массива будет использован для определения вызываемой политики, а остальные элементы массива передаются в метод политики как параметры и могут использоваться для дополнительного контекста при принятии решения об авторизации. Например, рассмотрим следующий метод PostPolicy, который содержит дополнительный параметр $category:
/**
* Определить, может ли пользователь обновить данный пост.
*/
public function update(User $user, Post $post, int $category): bool
{
return $user->id === $post->user_id &&
$user->canUpdateCategory($category);
}
При попытке определить, может ли аутентифицированный пользователь обновить данный пост, мы можем вызвать этот метод политики следующим образом:
/**
* Обновить указанный блог-пост.
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function update(Request $request, Post $post): RedirectResponse
{
$this->authorize('update', [$post, $request->category]);
// Текущий пользователь может обновить блог-пост...
return redirect('/posts');
}