Using a single policy method to cover every action on a resource

I have a resource named Post. Every Post is related to a single User, and a User may have several (or zero) Posts.

I’m using Route::resource to map routes for every possible action on the Post resource to a single resource controller, PostController.

Now, I wish to implement a policy for the Post resource. Aiming to keep everything as simple and fool-proof as possible, I’d like to make the policy as follows:

  • Every user is authorized to make any action that doesn’t require an existing Post (e.g. create).
  • A User is only authorized to access its own Posts for every action that accesses a Post (e.g. edit, update, delete).

What I’m trying to do right now is to create a single policy method called access, which would check that the Post is owned by the User. Then, in my PostController, every method that has a Post object in its parameters (such as edit(Post $post)) would begin with

$this->authorize('access', $post);

However, I don’t like that I need to put those lines manually. If I ever forget one of those, I’ll have a security hole right there.

On the other hand, I have the authorizeResource method, which makes authorization automatic but requires the policy to have several methods so they are mapped to the each of the controller’s methods. Also, I tried to use the Authorize/can middleware, but it didn’t work (maybe because I used it on a Route::resource mapping).

The question is: What would be the cleanest and more secure way to achieve the result I described (i.e. authorizing every possible action that accesses a resource with the exact same rule)?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You can use authorizeResource() and override the resourceAbilityMap() method in your controller. The latter method returns a mapping from controller methods to the policy methods that will be called.

https://github.com/laravel/framework/blob/5.7/src/Illuminate/Foundation/Auth/Access/AuthorizesRequests.php#L105

E.g.

class MyController extends Controller
{
    // ...

    /**
     * Get the map of resource methods to ability names.
     *
     * @return array
     */
    protected function resourceAbilityMap()
    {
        return [
            'edit' => 'access',
            'update' => 'access',
            'destroy' => 'access',
        ];
    }

    // ...
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x