Laravel извлекает записи модели только в том случае, если они принадлежат аутентифицированному пользователю.

Я использую Laravel 5.4 и имею модель под названием Order. Для проверки я создал двух пользователей и два Ордена, каждый из которых имеет один Орден.

Я только что увидел, что могу получить заказ того, кто не является моим текущим пользователем. Я получаю список собственных заказов пользователя, используя Auth::user()->orders. Но для того, чтобы показать детали конкретного заказа, я делаю это:

/**
 * Display the specified resource.
 *
 * @param  int  $id
 * @return \Illuminate\Http\Response
 */
public function show($id)
{
    $order = CustomerOrder::findOrFail($id)->with('products')->get();
    return view('order.show')
        ->with('order', $order);
}

Что мне здесь не хватает? Есть ли промежуточное программное обеспечение или что-то, чтобы сообщить приложению, чтобы разрешить доступ только к заказам, связанным с аутентифицированным пользователем?

Изменить: я попытался сделать это с помощью политики OrderPolicy (CRUD).

view() Функция Политики:

/**
 * Determine whether the user can view the customerOrder.
 *
 * @param  \App\User  $user
 * @param  \App\CustomerOrder  $customerOrder
 * @return mixed
 */
public function view(User $user, CustomerOrder $customerOrder)
{
    return $user->id === $customerOrder->user_id;
}

И я зарегистрировал его в AuthServiceProvider.php:

protected $policies = [
    'App\Model' => 'App\Policies\ModelPolicy',
    Adress::class => AdressPolicy::class, //Doesn't work either
    Order::class => OrderPolicy::class
];

Я все еще могу проверить Заказ для другого пользователя.


person xTheWolf    schedule 29.03.2017    source источник
comment
Ради интереса, зачем минусовать нормальный вопрос?   -  person xTheWolf    schedule 29.03.2017


Ответы (4)


У вас есть несколько вариантов. Наилучший вариант в моем варианте - использование Policies. Документацию для этого можно найти здесь:

https://laravel.com/docs/5.4/authorization

В качестве альтернативы do может сделать что-то вроде:

/**
 * Display the specified resource.
 *
 * @param  int  $id
 * @return \Illuminate\Http\Response
 */
public function show($id)
{
    $user = request()->user();

    $order = $user->orders()->with('products')->find($id)->get();

    return view('order.show', compact('order'));
}

С функцией отношений заказов в вашей пользовательской модели.


Обновленный ответ

С помощью политики, которую вы указали, и вашего маршрута ресурсов вы сможете сделать:

/**
 * Display the specified resource.
 *
 * @param  int  $id
 * @return \Illuminate\Http\Response
 */
public function show(CustomerOrder $order)
{
    $this->authorize('view', $order);

    return view('order.show', compact('order'));
}
person Jono20201    schedule 29.03.2017
comment
Итак, я попробовал Policies. Теперь у меня есть OrderPolicy, я зарегистрировал его в AuthServiceProvider и сделал: public function view(User $user, CustomerOrder $customerOrder) { return $user->id === $customerOrder->user_id; } но все равно не работает, я все еще могу проверить другие заказы. Я сделал что-то не так? - person xTheWolf; 29.03.2017
comment
@Scarwolf Обновите свой вопрос, указав новый код, пожалуйста. - person Jono20201; 29.03.2017
comment
@AlexeyMezenin Пожалуйста, уточните, почему? - person Jono20201; 29.03.2017
comment
@Jono20201 Готово - person xTheWolf; 29.03.2017
comment
@Scarwolf Можешь тоже поделиться своим маршрутом? - person Jono20201; 29.03.2017
comment
Это от CRUD-контроллера Route::resource('order', 'OrderController'); - person xTheWolf; 29.03.2017
comment
@Scarwolf Попробуйте мой обновленный ответ. Используя политики и неявную привязку, вы сможете добиться действительно чистого решения для этого. - person Jono20201; 29.03.2017
comment
@Jono20201 Спасибо. Но это дает мне это действие является несанкционированным. хотя мой идентификатор пользователя равен 1, а отношение user_id в таблице заказов также равно 1. Может что-то не так с политикой? - person xTheWolf; 29.03.2017
comment
Хорошо, заработало. Забудьте импортировать мою модель в AuthServiceProvider - person xTheWolf; 29.03.2017
comment
@Scarwolf Рад слышать, что у тебя все получилось. Удивительно, как много работы Laravel иногда делает за вас. - person Jono20201; 29.03.2017

Другим способом было бы использовать определенную связь и указать, чтобы она извлекала только ту, у которой есть идентификатор $id. Как это:

$customerOrder = auth()->user()->orders()->with('products')->find($id);
person DevK    schedule 29.03.2017
comment
@Scarwolf, если ваша цель — получить заказ по идентификатору, но только если он принадлежит пользователю, используйте код из этого ответа. - person Alexey Mezenin; 29.03.2017
comment
@devk, ты забыл добавить with('products') часть. - person Alexey Mezenin; 29.03.2017
comment
@ Jono20201 Так и есть. Он ограничивает запрос результатами, принадлежащими аутентифицированному пользователю. Для этого он использует отношение к пользовательской модели. У Алексея: Это правда - person DevK; 29.03.2017
comment
@devk идеально. +1 - person Alexey Mezenin; 29.03.2017
comment
Это тоже будет работать, но я чувствую, что если разработчики Laravel добавят Политики для этого, я пойду по этому пути. Спасибо за ваш ответ! - person xTheWolf; 29.03.2017
comment
@devk Извините, я не комментировал ваш ответ, я отвечал на комментарий Алексея, который позже был удален. - person Jono20201; 29.03.2017

Если вы хотите получить заказы, принадлежащие аутентифицированному пользователю, сделайте следующее:

CustomerOrder::where('user_id', auth()->user()->id)->with('products')->find($id);
person Alexey Mezenin    schedule 29.03.2017
comment
@AlexeyMezenin Вот и сравняйтесь. Код делает то, о чем просил автор (я думаю). Я думаю, что автор хочет получить заказ только с id $id, не все пользователи заказывают. Но он не дал этого понять (->findOrFail($id)->get() - я не знаю, почему ->get() в конце. - person DevK; 29.03.2017
comment
@dev спасибо, я понял, чего хочет ОП. Исправил и мой код. - person Alexey Mezenin; 29.03.2017
comment
Следует отметить, что этот ответ далеко не идеален, поскольку он требует от разработчика не забывать выполнять поиск по user_id. Отношения инициируют поиск по заказам, принадлежащим данному пользователю, и устраняют риск забыть добавить где. - person Computer User; 07.08.2018

Помните,
сначала вы создаете политику.
Во-вторых, вы регистрируете его.
В-третьих, вы используете что-то вроде $this->authorize('view', $order); в обычном контроллере.
Вы пропустили третий шаг. Документацию можно найти здесь: [https://laravel.com/docs/5.8/authorization#authorizing-actions-using-policies][1]

person Pooria Honarmand    schedule 31.05.2019