Reputation: 433
I created a policy in laravel 5.3 with this two actions:
class ProjectPolicy {
...
public function index(User $user)
{
return true;
}
public function create(User $user)
{
return true;
}
...
}
and then I tried to make authorization via route group middleware:
Route::group(['middleware' => ['can:index,create,App\Project']], function () {
Route::resource('projects', 'ProjectController');
});
ofcourse I have created Project model and controller correctly, but calling index and create actions always returns 403 forbidden response. where is the problem?
Update:
removing one of actions from route middleware, results correct response. something like this:
Route::group(['middleware' => ['can:index,App\Project']], function () {
Route::resource('projects', 'ProjectController');
});
Upvotes: 6
Views: 5834
Reputation: 812
Spend hours on that ...
If your controller method does not take a Model as parameter, you also have to override the resourceMethodsWithoutModels()
.
protected function resourceAbilityMap()
{
Log::info("Inside resourceAbilityMap()");
return array_merge(parent::resourceAbilityMap(), [
//ControllerMethod => PolicyMethod
'index' => 'index',
'search' => 'search'
]);
}
protected function resourceMethodsWithoutModels(){
return array_merge(parent::resourceMethodsWithoutModels(), [
'search'
]);
}
Upvotes: 5
Reputation: 35170
Looking through the docs the can
middleware doesn't really lend itself to resources. You could use multiple middleware calls on the group but this would mean that your use would require all privileges to access the routes.
Your alternatives are:
Add $this->authorize(new App\Project)
to your index
and create
methods in your controller. Laravel will use reflection to figure out what policy to use based on the method it is called from.
Or
In the __construct()
method of your controller you could use:
$this->authorizeResource(App\Project::class);
This will require you to
create update
, view
and delete
methods inside your Policy class. Each of these methods will be passed User $user, Project $project
e.g.
public function view(User $user, Project $project)
{
return true;
}
FYI, if you leave off the method name with authorize()
or you use authorizeResource()
Laravel will map certain method names to different policy methods i.e. :
[
//ControllerMethod => PolicyMethod
'show' => 'view',
'create' => 'create',
'store' => 'create',
'edit' => 'update',
'update' => 'update',
'destroy' => 'delete',
];
You can override this by adding a resourceAbilityMap()
method to your controller and returning a different array to the one above.
Hope this helps!
Upvotes: 4