4

I've created a policy to guard my model. What I'm trying to do is block anyone from editing a thought record that isn't there's.

web.php

Auth::routes();

Route::prefix('/')->middleware(['auth','can:viewAny,App\ThoughtRecord'])->group(function() {

    Route::get('/record/{id}/edit', 'ThoughtRecordController@edit')->middleware('can:isOwner,App\ThoughtRecord');

    Route::patch('/record/{thoughtRecord}','ThoughtRecordController@update')->middleware('can:isOwner,App\ThoughtRecord');

});

ThoughtRecordPolicy.php

public function isOwner(User $user, ThoughtRecord $thoughtRecord)
{
    return $user->id == $thoughtRecord->user_id;

}

The ->middleware(['auth','can:viewAny,App\ThoughtRecord']) works perfectly fine. The middleware on the other routes doesn't though ->middleware('can:isOwner,App\ThoughtRecord') and produces this error:

Error

Symfony\Component\Debug\Exception\FatalThrowableError Too few arguments to function App\Policies\ThoughtRecordPolicy::isOwner(), 1 passed in /Applications/MAMP/htdocs/thought-records/vendor/laravel/framework/src/Illuminate/Auth/Access/Gate.php on line 706 and exactly 2 expected

Edit:

I changed the route to:

Route::get('/record/{thoughtRecord}/edit', 'ThoughtRecordController@edit')->middleware('can:isOwner,thoughtRecord');

Now I'm getting a 403 on a condition that I'm pretty positive is true.

Kyle Corbin Hurst
  • 917
  • 2
  • 10
  • 26

1 Answers1

3

You're incorrectly passing second parameter to the isOwner policy's method.

The following should work:

Route::get('/record/{thoughtRecord}/edit', 'ThoughtRecordController@edit')
   ->middleware('can:isOwner,thoughtRecord');

As per the laravel documentation:

In this example, we're passing the can middleware two arguments. The first is the name of the action we wish to authorize and the second is the route parameter we wish to pass to the policy method. In this case, since we are using implicit model binding, a Post model will be passed to the policy method.

So you basically need to use implicit model binding and pass in the route parameter as the second argument.

Hope it helps!

Tiago Martins Peres
  • 14,289
  • 18
  • 86
  • 145
Zeshan
  • 2,496
  • 3
  • 21
  • 26
  • Thanks. Oddly enough I just tried that. The problem I'm getting now is a 403 on a condition that is true. – Kyle Corbin Hurst Sep 29 '19 at 06:34
  • Ideally it should not. It probably be because of the other middleware `can:viewAny`. Try remove that first and see where the problem is. Try return `true` from the `isOwner` in order to debug where the problem lies. – Zeshan Sep 29 '19 at 06:37
  • 1
    Ahhh wait. I just found out that the problem was on the @edit method on the controller it was passing `$id` as the parameter. Not `ThoughtRecord $thoughtRecord`. This works! – Kyle Corbin Hurst Sep 29 '19 at 06:40