Policies — Laravel 10 Discovery Training

In this new chapter, we will dive back into the security part and we will see Laravel’s authorization system. Until now we have simply used the middleware system but it is possible to use classes which will allow to define the permissions action by action.

The creation of an access policy will often be done in connection with a model.

php artisan make:policy PostPolicy --model=Post

Then inside the file PostPolicy functions should return false Or true depending on whether or not access to the resource is authorized. It will then be necessary to save the link between the model and the policy by modifying the property $policies in the AuthServiceProvider.

<?php

namespace App\Providers;

use App\Models\Post;
use App\Policies\PostPolicy;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;

class AuthServiceProvider extends ServiceProvider
{

    protected $policies = [
        Post::class => PostPolicy::class,
    ];

    public function boot(): void
    {
        // ...
    }
}

Check permission

Now that our policies are created we can use them to check whether or not the user has access to a resource. This can be done in different ways.

Model User

The model User provides by default has methods to verify user access.

$user->can('update', $post); // true / false
$user->cannot('update', $post); // true /false

Controller

If your Controller inherits the App\Http\Controllers\Controller you will have access to the method authorize which will allow you to see if the user has the right to do the requested action.

<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;

class PostController extends Controller
{
    /**
     * Update the given blog post.
     *
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function update(Request $request, Post $post): RedirectResponse
    {
        $this->authorize('update', $post);
        return redirect('/posts');
    }
}

This method will throw an exception if the user does not have the necessary permissions and the framework will catch it to act accordingly (redirection or display of a JSON response).

Middleware

Laravel also offers special middleware can which allows permission to be checked from the route declaration.

use App\Models\Post;

Route::put('/post/{post}', function (Post $post) {
    // The current user may update the post...
})->middleware('can:update,post');

Blade

In blade views if you want to show or hide a button depending on user permissions you can use the directive @can Or @cannot.

@can('update', $post)
    <!-- L'utilisateur peut modifier l'article... -->
@elsecan('create', App\Models\Post::class)
    <!-- L'utilisateur peut créer un article... -->
@else
    <!-- ... -->
@endcan

@cannot('update', $post)
    <!-- L'utilisateur ne peut pas modifier l'article... -->
@elsecannot('create', App\Models\Post::class)
    <!-- ... -->
@endcannot