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 ownPosts
for every action that accesses aPost
(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)?
You can use
authorizeResource()
and override theresourceAbilityMap()
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.