Как авторизоваться в зависимости от запроса?

В настоящее время я добавляю разрешения/роли/авторизацию в приложение Laravel.

В базе данных приложения есть пользователи, компании и продукты. У компаний много пользователей, и продукт принадлежит компании.

Теперь я хочу авторизовать пользователей компании, чтобы создать продукт для своей компании.

В моем ProductController.php у меня есть что-то вроде этого:

public function create(Request $request)
{
    $company = Company::findOrFail($request->get('company_id'));
    return view('product.create', compact('company');
}

Одним из вариантов было бы использовать Gate::authorize() после получения компании и передать $company методу авторизации.

Вопрос: Но как мне это решить, если я не хочу использовать Gate::authorize(). Итак, на случай, если я захочу использовать политики?

Еще Вопрос: Вижу несколько способов авторизации: Gate::authorize(), политики, StoreProduct's authorize(), ... Какой из них использовать? Должен ли я всегда реализовывать событие authorize() StoreProduct, например, если я использую политики?


person rakete    schedule 07.10.2019    source источник
comment
Пользователь и продукт принадлежат только одной компании?   -  person Bryan    schedule 08.10.2019
comment
@rakete вы можете создать permission, например manage product, или отдельные, например create product и update product и т. д. Пользовательские Request классы, чтобы проверить, есть ли у пользователя разрешение. Дайте мне знать, если вы заинтересованы в этом подходе, и я добавлю пример кода.   -  person Mike Ross    schedule 08.10.2019
comment
У компании @Bryan много пользователей. Продукт имеет одна компания.   -  person rakete    schedule 08.10.2019
comment
@MikeRoss Хм, я уже создал разрешения. Проверить разрешение не проблема. Проблема в том, что модель, которая решает, авторизован ли пользователь (компания пользователя), будет передана как company_id.   -  person rakete    schedule 08.10.2019
comment
Если ваш пользователь принадлежит только одной компании, я бы полагался на отношение (при условии, что у вас есть принадлежность в модели User): $company = $request->user()->company;   -  person adam    schedule 08.10.2019
comment
Да, конечно... Но как я могу получить доступ к $request из ProductPolicy?   -  person rakete    schedule 08.10.2019
comment
Gate::authorize() использует политики, и authorize() тоже их использует. Покажите, пожалуйста, ваш маршрут для этого метода создания и политику для него.   -  person Styx    schedule 16.10.2019


Ответы (1)


У вас может быть возможность create для ProductPolicy принимать экземпляр компании в качестве аргумента, а затем вы можете проверить, принадлежит ли пользователь этой компании в политике:

use App\Company;
use App\User;

class ProductPolicy
{
    public function create(User $user, Company $company)
    {
        return $user->company_id === $company->id;
    }

    ...
}

Вы можете вызвать authorize в своем контроллере, чтобы использовать ProductPolicy для авторизации пользователя. Эти методы авторизации могут принимать массив в качестве второго аргумента, который позволяет вам отправлять дополнительные данные [первым аргументом будет модель для политики, в этом случае она не принимает экземпляр, но нам все равно нужно знать, какая модель политика, которую мы хотим, поэтому она принимает имя класса]. Это проверит возможность create политики для продукта и передаст ей дополнительное значение $company:

use App\Company;
use App\Product;
...
public function create(Request $request)
{
    $company = Company::findOrFail($request->input('company_id'));

    $this->authorize('create', [Product::class, $company]);

    return view('product.create', compact('company');
}

Не забудьте зарегистрировать Политику для модели Продукта.

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

person lagbox    schedule 16.10.2019