php – policy in laravel always unauthorized-ThrowExceptions

Exception or error:

i am try to make policy in Post Model, i follow the documentation but still return always false
in api.php

Route::put('post/{id}','PostController@update')->middleware('auth:api');

in post controller

public function update(Request $request, Post $post,$id){
        $this->authorize('update',$post);

        $request->validate(['content'=>'required']);
        $post = $post->find($id);
        $post->content = $request->content;
        $post->save();

return response()->json($post, 200);
}

in PostPolicy

public function update(User $user, Post $post)
  {
        return $user->id === $post->user_id;
  }

in AuthServiceProvider

protected $policies = [
        'App\Post' => 'App\Policies\PostPolicy',
];

please ignore for model since model is working properly, if i comment $this->authorize in controller is working, but there is no authentication, user can update any thing in model

i test from postman using api using

authorization = Bearer 'api_token'
How to solve:

The reason you’re having this issue is because the update method in the policy expects a loaded instance of the model, however, with your current setup, you’re passing an unloaded/empty instance of the model.

You could get around this by using Route Model Binding. Change {id} in your route to be {post}:

Route::put('post/{post}','PostController@update')->middleware('auth:api');

Then remove the $id argument from your update() method:

public function update(Request $request, Post $post)
{
    $this->authorize('update', $post);

    $request->validate(['content' => 'required']);

    $post->content = $request->content;
    $post->save();

    return response()->json($post, 200);
}

Also, notice now how you’re not having to use find to load the model, this is because Laravel is loading the model for you under-the-hood.

Route model binding works by looking for a param name with the same name as the uri segment i.e. {post} on the route and $post the method argument, and since $post is type-hinted to be a model Laravel knows to use the value of {post} to load (find) the Post model.

Leave a Reply

Your email address will not be published. Required fields are marked *