I have a NotificationPolicy
with the following code:
<?php
namespace App\Policies;
use App\Notification;
use App\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class NotificationPolicy
{
use HandlesAuthorization;
public function update(User $user, Notification $notification)
{
return $user->id === $notification->user_id;
}
}
I have registered this properly by adding this to the AuthServiceProvider
:
protected $policies = [
Notification::class => NotificationPolicy::class,
];
I have this so that only the logged in user can update their notification by doing things such as setting the archived_at
value or read_at
value to the current timestamp. The policy does work if I use it in the controller, i.e.;
class ArchiveItemController extends Controller
{
public function __invoke(Notification $notification)
{
$this->authorize('update', $notification);
$notification->markAsArchived();
return redirect()->route('inbox.index')->with('success', 'Item has been archived');
}
}
However I don't want to use them in the controllers and would prefer to use them in my routes file. So I have removed this line $this->authorize('update', $notification);
from the controller and I have tried the following but it doesn't work:
Route::prefix('inbox')->middleware(['auth', 'can:employee'])->group(function () {
Route::get('/notification/{notification}/archive', 'User\Account\Inbox\ArchiveItemController')
->name('inbox.item.archive')
->middleware('can:update', 'notification');
});
I've even ran the following but they don't make a difference:
php artisan optimize
php artisan cache:clear
php artisan route:cache
php artisan view:clear
php artisan config:cache
Your middleware declaration is not correct.
You will have to change 'can:update', 'notification'
to 'can:update,notification'
for it to work:
So in the end you would have the following:
Route::prefix('inbox')->middleware(['auth', 'can:employee'])->group(function () {
Route::get('/notification/{notification}/archive', 'User\Account\Inbox\ArchiveItemController')
->name('inbox.item.archive')
->middleware('can:update,notification');
});
If you have cached the routes, you will have to run php artisan route:clear
for the changes to take effect.
From the docs:
Laravel includes a middleware that can authorize actions before the incoming request even reaches your routes or controllers. By default, the
Illuminate\Auth\Middleware\Authorize
middleware is assigned thecan
key in yourApp\Http\Kernel
class. Let's explore an example of using thecan
middleware to authorize that a user can update a blog post:
use App\Post;
Route::put('/post/{post}', function (Post $post) {
// The current user may update the post...
})->middleware('can:update,post');
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, aPost
model will be passed to the policy method. If the user is not authorized to perform the given action, a HTTP response with a403
status code will be generated by the middleware.