Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Чим небезпечний Gate::before для суперадміністратора і як його правильно писати?

Gate::before реєструє колбек, який виконується перед усіма перевірками гейтів і політик. Поширений прийом - суперадміністратор, якому дозволено все:

Gate::before(function (User $user, string $ability) {
    if ($user->isSuperAdmin()) {
        return true;
    }
});

Як працює результат:

  • true - дозвіл, жодні гейти й політики далі не викликаються;
  • false - заборона, теж без подальших перевірок;
  • null (нічого не повертати) - звичайна перевірка продовжується.

Пастки:

1. return false замість «нічого».

Gate::before(fn (User $user) => $user->isSuperAdmin());   // помилка!

Для звичайного користувача стрілкова функція повертає false - і всі перевірки в застосунку стають забороненими. Колбек має повертати true або null.

2. Суперадмін може «все» - справді все. true з before дозволяє і дії, які мали б бути заборонені для всіх за бізнес-правилами: видалити оплачене замовлення, змінити закритий фінансовий період, редагувати документ, підписаний іншою стороною. Якщо такі обмеження є, їх варто перевіряти поза гейтами (у сервісі, доменному об'єкті) або виключати в before:

Gate::before(function (User $user, string $ability) {
    if ($user->isSuperAdmin() && ! in_array($ability, ['delete-paid-order', 'impersonate'], true)) {
        return true;
    }
});

3. Ризик облікового запису. Обліковий запис суперадміністратора - найцінніша мішень: обов'язкова двофакторна автентифікація, мінімум таких користувачів, журнал усіх дій.

4. Ознака «суперадміністратора» має бути надійною: поле в базі, яке не змінюється через масове призначення, а не email чи ім'я, що їх можна підробити в іншому контексті.

before у політиці - те саме, але лише для однієї моделі:

class PostPolicy
{
    public function before(User $user, string $ability): ?bool
    {
        return $user->is_moderator ? true : null;
    }
}

Особливість: метод before політики не викликається, якщо в політиці немає методу з назвою перевірюваної дії.

Gate::after - виконується після перевірки; його результат враховується, лише якщо основна перевірка повернула null. Зручно для аудиту рішень.

Тест, який варто мати: звичайний користувач отримує дозвіл на свої дії (захист від пастки з false) і відмову на чужі.

Докладніше в документації: Laravel: перехоплення перевірок гейтів

Схожі питання