Laravel 10 Authorization Policy Tutorial step by step | All about Laravel Policy

By Ved Prakash N | Feb 22, 2024 | Laravel
Share : Whatsapp

https://www.fundaofwebit.com/post/laravel-10-authorization-policy-tutorial-step-by-step-with-example

Laravel 10 Policy Tutorial step by step | All about Laravel Policy Tutorial


In this post, we will learn how to create a Laravel Policy and use Laravel Policy in our application.

What are Laravel Policies?

Laravel Policies provide a convenient way to authorize user actions on resources. These resources could be Eloquent models or any other objects in your application. Policies help centralize authorization logic and make it easy to manage access control rules. Instead of scattering authorization checks throughout your codebase, you can encapsulate them within dedicated policy classes.


Step 1: Create a Policy

You may generate a policy using the make:policy Artisan command

php artisan make:policy PostPolicy

Suppose you would like to generate a class with example policy methods related to viewing, creating, updating, and deleting the resource. In that case, you may provide a --model option when executing the command:

php artisan make:policy PostPolicy --model=Post


Step 2: Registering Policies

You need to register your policies in the AuthServiceProvider. This class is located in the app/Providers directory.

In the AuthServiceProvider, you'll find a $policies property where you can map your models to their respective policies. For example:

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


Step 3: Define Policy Methods | Writing Policies

Inside the PostPolicy class, you can define methods that correspond to different actions users can perform on posts.

For example, you might create methods like view, create, update, and delete. These methods should return a Boolean value indicating whether the user is authorized to act. Here's an example of a methods in PostPolicy: 

Open the PostPolicy.php file in path - app/ Policies/ PostPolicy.php

<?php

namespace App\Policies;

use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;

class PostPolicy
{
    /**
     * Determine whether the user can view any models.
     */
    public function viewAny(User $user): bool
    {
        return true;
    }

    /**
     * Determine whether the user can view the model.
     */
    public function view(User $user, Post $post): bool
    {
        return $user->id == $post->user_id;
    }

    /**
     * Determine whether the user can create models.
     */
    public function create(User $user): bool
    {
        if($user->role == 'writer'){
            return true;
        }else{
            return false;
        }
    }

    /**
     * Determine whether the user can update the model.
     */
    public function update(User $user, Post $post): bool
    {
        return $user->id == $post->user_id;
    }

    /**
     * Determine whether the user can delete the model.
     */
    public function delete(User $user, Post $post): bool
    {
        return $user->id == $post->user_id;
    }
}


Policy Filters

For certain users, you may wish to authorize all actions within a given policy.

To accomplish this, define a "before" method on the policy. The before method will be executed before any other methods on the policy, giving you an opportunity to authorize the action before the intended policy method is actually called. This feature is most commonly used for authorizing application administrators to perform any action:

class PostPolicy
{
    public function before(User $user, string $ability): bool|null
    {
        if ($user->isAdministrator()) {
            return true;
        }

        return null;
    }

    //...
}


Step 4: Use Policies in Controllers

Open your PostController or any other controller as per your requirement and use the below code for the policy i.e. $this->authorize():

The authorize method checks if the current user is authorized to access the post using the all method defined in the PostPolicy.

<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function index()
    {
        $this->authorize('viewAny', Post::class);
        //...
    }

    public function create()
    {
        $this->authorize('create', Post::class);
        //...
    }

    public function show(Post $post)
    {
        $this->authorize('view', $post);
        //...
    }

    public function store(Request $request)
    {
        $this->authorize('create', Post::class);
        //...
    }

    public function edit(Post $post)
    {
        $this->authorize('update', $post);
        //...
    }

    public function update(Request $request, Post $post)
    {
        $this->authorize('update', $post);
        //...
    }

    public function destroy(Post $post)
    {
        $this->authorize('delete', $post);
        //...
    }
}


Step 5: Use Policies in Blade Templates

@can is a shortcut of @if condition

@can('update', $post)
    <!-- The current user can update the post... -->
@elsecan('create', App\Models\Post::class)
    <!-- The current user can create new posts... -->
@else
    <!-- ... -->
@endcan
@can('create', App\Models\Post::class)
    <!-- The current user can create posts... -->
@endcan


@cannot is a shortcut of @unless condition

@cannot('update', $post)
    <!-- The current user cannot update the post... -->
@elsecannot('create', App\Models\Post::class)
    <!-- The current user cannot create new posts... -->
@endcannot
@cannot('create', App\Models\Post::class)
    <!-- The current user can't create posts... -->
@endcannot


Instead of @can & @unless how can use in this way:

@if (Auth::user()->can('update', $post))
    <!-- The current user can update the post... -->
@endif
@unless (Auth::user()->can('update', $post))
    <!-- The current user cannot update the post... -->
@endunless


That's It.