Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Policies - How to Pass Multiple Arguments to function

I'm trying to authorize a users character to delete/update post. I was using policies to do so, but I could only pass one parameter to the policy function. If I pass more than the user and another variable, the variable isn't passed into the function.

Models: User has many characters, a character can post multiple posts. So for authorization purposes, I would have to compare the post's character_id with the current character's id...-

Per the docs, you can pass more multiples to the Gate Facade:

Gate::define('delete-comment', function ($user, $post, $comment) {
    //
});

But I couldn't find anyway to do so with policies. What I had to do was to inject the Request object to get the object needed for authorization. Basically I wouldn't even need the User Object.

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

Using the Request object works, but it feels very hacky. Is there a nicer way to achieve this?

edit:

In the CharacterLocationController I have a method show and I want to authorize the action before showing the resource.

public function show(Request $request, Character $character, Location $location)
{
    $this->authorize([$location, $character]);
    ...
}

The policy is registered like this: 'App\Location' => 'App\Policies\LocationPolicy' in the AuthServiceProvider

I dumped the array passed to the policy function, and it only outputs the $location.

public function show(User $user, $data) {
    dd($data); // expecting location and character
    return !$location->private || $location->authorized->contains($this->character);
}
like image 275
Johannes Avatar asked Apr 07 '16 17:04

Johannes


1 Answers

I think there is possibly some confusion here on what functions are doing what.

When you use

Gate::define('delete-comment', function ($user, $post, $comment) {
    //
});

Or in the CommentPolicy

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

All you are doing is defining the rules. At this point, we aren't worried about passing anything, only that the objects we received can or should be able to interact with each other. The only difference between these two is when using policies, it's just an easy way to abstract all your rules into one simple and easy to read class. If you have an app with potentially hundreds of tables and models, it will get confusing fast if you have these rules littered all over your app so policies would help to keep them all organized.

It's when you are actually checking if someone has permission to do something when you should be passing these items along. For example, when you do the following,

if (Gate::allows('delete-comment', [$post, $comment])) {
    // 
}

Or if in the CommentController

$this->authorize('delete', [$post, $comment]);

That is what controls which parameters are going to be passed to the policy or the Gate::define method. According to the docs, the $user parameter is already added for you so in this case, you only need to worry about passing the correct $post and $comment being modified.

like image 161
user1669496 Avatar answered Nov 02 '22 08:11

user1669496