Я пытаюсь разрешить пользователю просматривать свой профиль в Laravel 5.4.
UserPolicy.php
public function view(User $authUser, $user) { return true; }
зарегистрированная политика в AuthServiceProvider.php
protected $policies = [ App\Task::class => App\Policies\TaskPolicy::class, App\User::class => App\Policies\UserPolicy::class ];
Маршруты
Route::group(['middleware' => 'auth'], function() { Route::resource('user', 'UserController'); } );
Шаблон клинка
@can ( 'view', $user ) // yes @else // no @endcan
UserController.php
public function profile() { return $this->show(Auth::user()->id); } public function show($id) { $user = User::find($id); return view('user.show', array( 'user'=>$user,'data'=>$this->data ) ); }
Возврат всегда «ложный». То же самое для вызова политики формирует контроллер. Где я ошибаюсь?
Ответ на мой собственный вопрос кажется странным, но я ненавижу его, когда сталкиваюсь с вопросами без последующих действий.
Поэтому после двойной проверки выяснилось, что если я удалю authorizeResource из конструктора
public function __construct() { $this->authorizeResource(User::class); }
и проверить авторизацию в функции контроллера
$this->authorize('view',$user);
все работает. Я, должно быть, пропустил эту часть, когда я добавил $user
в качестве параметра в функции политики. Таким образом, пользователь, который будет просматриваться, никогда не передается в методе authorizeResource
.
Спасибо всем, что нашли время, чтобы помочь мне.
Просто другой подход к пользователям, просматривающим свой профиль.
Во-первых, я создам маршрут для этого
Route::group(['middleware' => 'auth'], function() { Route::get('profile', 'UserController@profile'); });
Тогда в функции profile
я делаю
public function profile() { $user = Auth::user(); return view('profile', compact('user')); }
Таким образом, пользователь автоматически просматривает только свой профиль.
Теперь, если вы хотите разрешить некоторым пользователям просматривать другие профили, вы можете использовать политику. Зачем? Потому что я думаю, что пользователь должен ВСЕГДА просматривать свой профиль. Но не все пользователи должны просматривать другие профили пользователей.
Решение:
Измените второй параметр из @can( 'view', $user )
на @can( 'view', $subject )
и он будет работать.
Зачем:
Потому что вы делаете это неправильно.
public function view(User $user, $subject){ return true; }
Просто внимательно посмотрите на метод просмотра политики, первый параметр – authenticated user
или current user
а второй параметр – $subject
, так как политики организуют логику авторизации вокруг моделей.
Политики – это классы, которые организуют логику авторизации вокруг определенной модели или ресурса. Например, если ваше приложение является блогом, у вас может быть модель Post и соответствующая PostPolicy для авторизации действий пользователя, таких как создание или обновление сообщений.
если вы хотите пойти дальше глубоко внутри него.
https://github.com/laravel/framework/blob/5.3/src/Illuminate/Auth/Access/Gate.php#L353
/** * Resolve the callback for a policy check. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @param string $ability * @param array $arguments * @return callable */ protected function resolvePolicyCallback($user, $ability, array $arguments) { return function () use ($user, $ability, $arguments) { $instance = $this->getPolicyFor($arguments[0]); // If we receive a non-null result from the before method, we will return it // as the final result. This will allow developers to override the checks // in the policy to return a result for all rules defined in the class. if (method_exists($instance, 'before')) { if (! is_null($result = $instance->before($user, $ability, ...$arguments))) { return $result; } } if (strpos($ability, '-') !== false) { $ability = Str::camel($ability); } // If the first argument is a string, that means they are passing a class name // to the policy. We will remove the first argument from this argument list // because the policy already knows what type of models it can authorize. if (isset($arguments[0]) && is_string($arguments[0])) { array_shift($arguments); } if (! is_callable([$instance, $ability])) { return false; } return $instance->{$ability}($user, ...$arguments); }; }
См. Последнюю строку, в которой он вызывает метод с аргументом $ user и $ (в нашем случае Model).
Документы Laravel для авторизации / политики