Laravel Gates

Gates là simply closures, xác định xem người dùng có quyền hay không với một hành động cụ thể. Gates được sử dụng cả ở template blade, routes, controller. Gates sẽ không gắn với model cụ thể nào, gate sẽ sử dụng các thông tin truyền vào với tham số đầu tiên là user.

Laravel Gates

Tổng quan về Gates:

  • Gates là simply closures, xác định xem người dùng có quyền hay không với một hành động cụ thể.
  • Gates được sử dụng cả ở template blade, routes, controller. Gates sẽ không gắn với model cụ thể nào, gate sẽ sử dụng các thông tin truyền vào với tham số đầu tiên là user.
  • Gates được viết (định nghĩa) ở App\Providers\AuthServiceProvider.

1. Khởi tạo Gates:

  • Khởi tạo Gates trong App\Providers\AuthServiceProvider:
<?php namespace App\Providers;

    use App\Models\User;
    use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
    use Illuminate\Support\Facades\Gate;

    class AuthServiceProvider extends ServiceProvider
    {
        /**
         * The policy mappings for the application.
         *
         * @var array
         */
        protected $policies = [
            'App\Models\Model' => 'App\Policies\ModelPolicy',
        ];

        /**
         * Register any authentication / authorization services.
         *
         * @return void
         */
        public function boot()
        {
            $this->registerPolicies();
            $this->setGates();
        }

        private function setGates()
        {
            Gate::define('update-post', function (User $user,  Post $post) {
                return $user->id === $post->user_id;
            });
        }
    }
  • Định nghĩa một gate là update-post mục đính xác định xem user có quyền update bài viết hay không.
  • Tham số đầu tiên truyền vào được mặc định là user đang đăng nhập, tiếp theo truyền vào các tham số ở đây là bài viết muốn cập nhật.
  • Hàm trả về giá trị true hoặc fales nếu true thì user có quyền update bài viết và ngược lại.

2. Sử dụng Gates.

Trong controller:

  • Sử dung Method allows xác định xem Gate có cho phép hành động diễn ra hay không:
if (Gate::allows('update-post', $post)){ 
// Update the post... 
} 
  • Sử dụng Method denies để từ chối hành động diễn ra:
if (Gate::denies('update-post', $post)) {
    // The user can't update the post...
}
  • Sử dụng Method forUser để kiểm tra quyền của user khác user đang đăng nhập:
if (Gate::forUser($user)->allows('update-post', $post)) {
    // The user can update the post...
}
  • Sử dụng Method anynone để sử dụng nhiều Gate kiểm tra một hành động xem có được phép diễn ra hay không:
if (Gate::any(['update-post', 'delete-post'], $post)) {
    // The user can update or delete the post...
}

if (Gate::none(['update-post', 'delete-post'], $post)) {
    // The user can't update or delete the post...
}
  • Ngoài ra còn một số method khác check, authorize, inspect, can, cannot.

Trong Middleware:

Route::post('/update-post', [App\Http\Controllers\PostController::class, 'update'])->can('update-post');
  • Trong ví dụ trên kiểm tra user có quyền update-post trước khi tới rquest tới controller.

Trong Blade Templates:

@can('update-post', $post)
    <!-- The current user can update the post... -->
@endcan
  • Ở đây màn hình chỉ hiển thị các bài viết mà user đang đăng nhập có quyền cập nhật.

3. Kết luận.

  • Chúng ta đã tìm hiểu thêm một công cụ giúp giải quyết bài toán phân quyền trong Laravel ngoài Middleware và Policy.
  • Gates thường được sử dụng ở tầng Controller, giúp kiểm soát quyền của các user trong hệ thống một cách dễ dàng (logic phần quyền được viết tập chung ở AuthServiceProvider).


Tài liệu tham khảo:
https://laravel.com/docs/8.x/authorization#gates
https://www.php.net/manual/en/class.closure.php