Reputation: 576
I am trying to implement a policy to block the edit functionality of a resource.
My route:
Route::resource('imagerequests', 'ImageRequestController');
My ImageRequestPolicy
class ImageRequestPolicy
{
use HandlesAuthorization;
const STATUS_EXECUTING = "executing";
public function edit(ImageRequest $imageRequest)
{
return $imageRequest->status !== self::STATUS_EXECUTING;
}
}
But I can still access the ´imagerequests/{id}/edit´ route
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
ImageRequest::class => ImageRequestPolicy::class,
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
//
}
ImageRequest Model
class ImageRequest extends Model
Edit ImageRequestController method
public function edit($id, ImageRequest $imageRequest)
{
$this->authorize('edit', $imageRequest);
$imageRequest = ImageRequest::findOrFail($id);
$requestTypes = RequestType::all();
$attachments = $this->imageRequestRepository->getAttachmentsListOfImageRequestById($id);
return view('imagerequest.edit', compact('imageRequest', 'requestTypes', 'attachments'));
}
Upvotes: 3
Views: 1333
Reputation: 6544
There is a difference between gates and policies that is somewhat hard to grasp from the documentation. Gates are used to authorize controller methods while resources are responsible to authorize actions regarding models, i.e. actual database records.
So in your case, you should be using gates and not policies. You can still use your existing policy class, but you have to register it differently. Instead of using
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
ImageRequest::class => ImageRequestPolicy::class,
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
}
you should be using
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Gate::resource('imageRequests', App\Policies\ImageRequestPolicy::class);
}
For further reference, have a look at the documentation on gates.
Upvotes: 0
Reputation: 3299
Your edit method is wrong, it's first argument must be the user:
public function edit(User $user, ImageRequest $imageRequest)
{
return $imageRequest->status !== self::STATUS_EXECUTING;
}
Add to your ImageRequestController, edit method:
public function edit(ImageRequest $imageRequest) {
$this->authorize('edit',$imageRequest);
...
}
The $user argument is automaticaly added by laravel.
Also you need to register the policy in AuthServiceProvider.
protected $policies = [
ImageRequest::class => ImageRequestPolicy::class,
];
And ImageRequest must extend Model class. Is it a model or a illuminate\http\request ?
There's something wrong with your controller. You sair your route is:
/imagerequests/26/edit
In your controller you are injecting a new, blank ImageRequest, maybe that's why it's passing the authorize test. Try this:
public function edit($id, ImageRequest $imageRequest)
{
$imageRequest = ImageRequest::findOrFail($id);
$this->authorize('edit', $imageRequest);
$requestTypes = RequestType::all();
$attachments = $this->imageRequestRepository->getAttachmentsListOfImageRequestById($id);
return view('imagerequest.edit', compact('imageRequest', 'requestTypes', 'attachments'));
}
Upvotes: 4
Reputation: 4755
use middleware for protecting routes.
use App\Post;
Route::put('/post/{post}', function (Post $post) {
// The current user may update the post...
})->middleware('can:update,post');
Hope this will help.
Upvotes: 0