Авторизація

Вступ

На додаток до надання вбудованих служб автентифікації, Laravel також забезпечує простий спосіб авторизації дій користувача щодо заданого ресурсу. Наприклад, навіть якщо користувач автентифікований, він може не мати дозволу на оновлення або видалення певних моделей Eloquent або записів бази даних, якими керує ваш застосунок. Функції авторизації Laravel забезпечують легкий, організований спосіб управління такими перевірками авторизації.

Laravel надає два основні способи авторизації дій: ворота та політики. Думайте про ворота та політики як про маршрути та контролери. Ворота забезпечують простий підхід до авторизації на основі замикань, тоді як політики, як і контролери, групують логіку навколо певної моделі або ресурсу. У цій документації ми спочатку розглянемо ворота, а потім вивчимо політики.

Вам не потрібно вибирати між виключним використанням воріт або виключним використанням політик при створенні застосунку. Більшість застосунків, швидше за все, міститимуть певну суміш воріт і політик, і це цілком нормально! Ворота найбільш застосовні до дій, які не пов'язані з жодною моделлю або ресурсом, таких як перегляд панелі адміністратора. На противагу цьому, політики слід використовувати, коли ви бажаєте авторизувати дію для конкретної моделі або ресурсу.

Gates

Написання Gates

Ворота є чудовим способом вивчити основи функцій авторизації Laravel; однак, при створенні надійних застосунків Laravel слід розглянути можливість використання політик для організації ваших правил авторизації.

Gates - це просто замикання, які визначають, чи авторизований користувач виконати певну дію. Зазвичай, gates визначаються в методі boot класу App\Providers\AppServiceProvider з використанням фасаду Gate. Gates завжди отримують екземпляр користувача як свій перший аргумент і можуть додатково отримувати інші аргументи, такі як відповідна модель Eloquent.

У цьому прикладі ми визначимо ворота, щоб визначити, чи може користувач оновити дану модель App\Models\Post. Ворота досягнуть цього, порівнюючи 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;
});
}

Як і контролери, шлюзи також можуть бути визначені за допомогою масиву зворотних викликів класу:

use App\Policies\PostPolicy;
use Illuminate\Support\Facades\Gate;
 
/**
* Ініціалізувати будь-які сервіси застосунку.
*/
public function boot(): void
{
Gate::define('update-post', [PostPolicy::class, 'update']);
}

Авторизація дій

Щоб авторизувати дію за допомогою воріт, ви повинні використовувати методи allows або denies, надані фасадом Gate. Зверніть увагу, що вам не потрібно передавати поточного автентифікованого користувача до цих методів. Laravel автоматично подбає про передачу користувача у замикання воріт. Зазвичай методи авторизації воріт викликаються у контролерах вашого застосунку перед виконанням дії, яка потребує авторизації:

<?php
 
namespace App\Http\Controllers;
 
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 автоматично перетворюються на 403 HTTP-відповідь у 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])) {
    // Користувач може створити пост...
}

Відповіді Gate

До цього ми розглядали лише шлюзи, які повертають прості булеві значення. Однак іноді ви можете захотіти повернути більш детальну відповідь, включаючи повідомлення про помилку. Для цього ви можете повернути 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::deny('You must be an administrator.');
});

Навіть коли ви повертаєте відповідь авторизації з вашого шлюзу, метод Gate::allows все одно поверне просте булеве значення; однак, ви можете використовувати метод Gate::inspect, щоб отримати повну відповідь авторизації, повернуту шлюзом:

$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;
    }
});

Значення, що повертаються замиканнями after, не перевизначать результат перевірки авторизації, якщо тільки шлюз або політика не повернули null.

Вбудована Авторизація

Іноді ви можете захотіти визначити, чи має поточний автентифікований користувач право виконати певну дію, без написання спеціального шлюзу, що відповідає цій дії. Laravel дозволяє виконувати такі типи "вбудованих" перевірок авторизації за допомогою методів Gate::allowIf та Gate::denyIf. Вбудована авторизація не виконує жодних визначених "до" або "після" хуків авторизації:

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 автоматично перетворюються на 403 HTTP-відповідь обробником виключень 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. Зокрема, політики повинні бути в каталозі Policies на рівні або вище каталогу, що містить ваші моделі. Наприклад, моделі можуть бути розміщені в каталозі app/Models, а політики можуть бути розміщені в каталозі app/Policies. У цій ситуації Laravel перевірятиме наявність політик у app/Models/Policies, а потім у app/Policies. Крім того, назва політики повинна відповідати назві моделі та мати суфікс Policy. Отже, модель User відповідатиме класу політики UserPolicy.

Якщо ви хочете визначити власну логіку виявлення політик, ви можете зареєструвати власний зворотний виклик для виявлення політик, використовуючи метод Gate::guessPolicyNamesUsing. Зазвичай цей метод слід викликати з методу boot вашого застосунку AppServiceProvider:

use Illuminate\Support\Facades\Gate;
 
Gate::guessPolicyNamesUsing(function (string $modelClass) {
    // Повернути ім'я класу політики для даної моделі...
});

Ручна реєстрація політик

Використовуючи фасад Gate, ви можете вручну реєструвати політики та їх відповідні моделі в методі boot вашого застосунку AppServiceProvider:

use App\Models\Order;
use App\Policies\OrderPolicy;
use Illuminate\Support\Facades\Gate;
 
/**
* Ініціалізувати будь-які сервіси застосунку.
*/
public function boot(): void
{
Gate::policy(Order::class, OrderPolicy::class);
}

Альтернативно, ви можете розмістити атрибут UsePolicy у класі моделі, щоб повідомити Laravel про відповідну політику моделі:

<?php
 
namespace App\Models;
 
use App\Policies\OrderPolicy;
use Illuminate\Database\Eloquent\Attributes\UsePolicy;
use Illuminate\Database\Eloquent\Model;
 
#[UsePolicy(OrderPolicy::class)]
class Order extends Model
{
    //
}

Написання Політик

Методи Політики

Після того як клас політики було зареєстровано, ви можете додати методи для кожної дії, яку він авторизує. Наприклад, давайте визначимо метод 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.

Всі політики вирішуються через 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('You do not own this post.');
}

Коли повертаєте відповідь авторизації з вашої політики, метод Gate::allows все ще буде повертати просте булеве значення; однак, ви можете використовувати метод Gate::inspect, щоб отримати повну відповідь авторизації, повернену шлюзом:

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';
}

Гостьові користувачі

За замовчуванням, всі шлюзи та політики автоматично повертають false, якщо вхідний HTTP-запит не був ініційований автентифікованим користувачем. Однак, ви можете дозволити цим перевіркам авторизації проходити через ваші шлюзи та політики, оголосивши "необов'язкову" підказку типу або надавши значення за замовчуванням 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\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 спробує викликати Gate на основі замикання, що відповідає заданій назві дії.

Дії, які не потребують моделей

Пам'ятайте, деякі дії можуть відповідати методам політики, таким як create, які не потребують екземпляра моделі. У таких ситуаціях ви можете передати ім'я класу методу can. Ім'я класу буде використано для визначення, яку політику використовувати при авторизації дії:

<?php
 
namespace App\Http\Controllers;
 
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');
    }
}

Через фасад Gate

На додаток до корисних методів, наданих моделі App\Models\User, ви завжди можете авторизувати дії за допомогою методу authorize фасаду Gate.

Як і метод can, цей метод приймає назву дії, яку ви бажаєте авторизувати, та відповідну модель. Якщо дія не авторизована, метод authorize викине виключення Illuminate\Auth\Access\AuthorizationException, яке обробник виключень Laravel автоматично перетворить на HTTP-відповідь зі статус-кодом 403:

<?php
 
namespace App\Http\Controllers;
 
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
 
class PostController extends Controller
{
    /**
     * Оновіть даний блог-пост.
     *
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function update(Request $request, Post $post): RedirectResponse
    {
        Gate::authorize('update', $post);
 
        // Поточний користувач може оновити публікацію в блозі...
 
        return redirect('/posts');
    }
}

Дії, які не потребують моделей

Як обговорювалося раніше, деякі методи політики, такі як create, не вимагають екземпляра моделі. У таких ситуаціях ви повинні передати ім'я класу методу authorize. Ім'я класу буде використано для визначення, яку політику використовувати при авторизації дії:

use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
 
/**
 * Створити новий блог-пост.
 *
 * @throws \Illuminate\Auth\Access\AuthorizationException
 */
public function create(Request $request): RedirectResponse
{
    Gate::authorize('create', Post::class);
 
    // Поточний користувач може створювати пости в блозі...
 
    return redirect('/posts');
}

Через Middleware

Laravel включає middleware, яке може авторизувати дії до того, як вхідний запит навіть досягне ваших маршрутів або контролерів. За замовчуванням, middleware Illuminate\Auth\Middleware\Authorize може бути прикріплене до маршруту за допомогою can псевдоніму middleware, яке автоматично реєструється Laravel. Давайте розглянемо приклад використання middleware can для авторизації того, що користувач може оновити пост:

use App\Models\Post;
 
Route::put('/post/{post}', function (Post $post) {
    // Поточний користувач може оновити публікацію...
})->middleware('can:update,post');

У цьому прикладі ми передаємо can middleware два аргументи. Перший - це назва дії, яку ми хочемо авторизувати, а другий - це параметр маршруту, який ми хочемо передати методу політики. У цьому випадку, оскільки ми використовуємо неявне зв'язування моделей, модель App\Models\Post буде передана методу політики. Якщо користувач не має дозволу на виконання даної дії, middleware поверне HTTP-відповідь зі статус-кодом 403.

Для зручності, ви також можете прикріпити can middleware до вашого маршруту, використовуючи метод 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 може стати громіздким. З цієї причини ви можете вибрати прикріплення can middleware до вашого маршруту, використовуючи метод 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
{
    Gate::authorize('update', [$post, $request->category]);
 
    // Поточний користувач може оновити публікацію в блозі...
 
    return redirect('/posts');
}

Авторизація & Inertia

Хоча авторизація завжди повинна оброблятися на сервері, часто може бути зручно надати вашому фронтенд-застосунку дані авторизації, щоб правильно відобразити інтерфейс користувача вашого застосунку. Laravel не визначає обов'язкову конвенцію для надання інформації про авторизацію фронтенду, що працює на Inertia.

Однак, якщо ви використовуєте один з стартових комплектів Laravel на базі Inertia, ваш застосунок вже містить middleware HandleInertiaRequests. У методі share цього middleware ви можете повертати спільні дані, які будуть надані всім сторінкам Inertia у вашому застосунку. Ці спільні дані можуть служити зручним місцем для визначення інформації про авторизацію для користувача:

<?php
 
namespace App\Http\Middleware;
 
use App\Models\Post;
use Illuminate\Http\Request;
use Inertia\Middleware;
 
class HandleInertiaRequests extends Middleware
{
    // ...
 
    /**
     * Визначте властивості, які спільно використовуються за замовчуванням.
     *
     * @return array<string, mixed>
     */
    public function share(Request $request)
    {
        return [
            ...parent::share($request),
            'auth' => [
                'user' => $request->user(),
                'permissions' => [
                    'post' => [
                        'create' => $request->user()->can('create', Post::class),
                    ],
                ],
            ],
        ];
    }
}