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-postmụ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ì usercó quyền update bài viết và ngược lại.
2. Sử dụng Gates.
Trong controller:
- Sử dung Method allowsxá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ủauserkhácuserđang đăng nhập:
if (Gate::forUser($user)->allows('update-post', $post)) {
    // The user can update the post...
}
- Sử dụng Method anyvànoneđể 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-posttrướ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ácusertrong 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