Tutorial Implementasi User Role and Permission Menggunakan Spatie Pada Laravel (Laravel 9) Dengan Primary Key Uuid


Assalamu'alaikum Wr. Wb.
        Stapie adalah salah satu library atau plugin yang dapat digunakan pada Framework Laravel untuk melakukan tugas-tugas yang membantu server kita, salah satunya yang akan kita bahas pada artikel saya kali ini adalah implementasi user role and permission yand primary key nya menggunakan uuid (Universal Unique Identifier), seperti postingan saya selumnya yang membahas tentang tutorial implementasi JWT (JSON Web Token) pada Laravel saya akan menggunakan Laravel 9 pada tutorial saya kali ini. Langsung saja tutorial implementasi user dan permission pada Laravel adalah sebagai berikut:

  1. Install library Spatie
           
    Pertama-tama yang perlu kita lakukan adalah menginstall plugin atau library Spatie pada project Laravel kita, anda dapat menginstallnya dengan masuk ke direktori root pada project laravel anda dan menggunakan perintah berikut:

             composer require spatie/laravel-permission

  2. Daftarkan provider Spatie (untuk laravel versi lama)
             
    Daftarkan provider Spatie ke file config/app.php, pada laravel versi terbaru anda tidak perlu lagi mendaftarkan plugin Spatie karena sudah otomatis terdaftar, untuk mendaftarkannya masuk ke folder config/app.php cari property 'providers' seperti pada kode berikut:

            'providers' => [
                 // ...
                 Spatie\Permission\PermissionServiceProvider::class,
             ]

  3. Publish file migration dan config untuk Spatie role and permission
             
    Langkah selanjutnya yang perlu kita lakukan untuk menginstall spatie role and permission adalah mempublish file migration dan config dari vendor spatie, untuk melakukannya anda dapat menjalankan perintah beriku:

             php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"

  4. Update file migration permission anda
               
    Jika anda menggunakan uuid sebagai primary key untuk role dan permission nantinya maka anda perlu mengubah beberapa kode pada file migration permission diantaranya adalah sebagai berikut:

               - $table->unsignedBigInteger($columnNames['model_morph_key'])
               + $table->uuid($columnNames['model_morph_key'])


               Schema::create($tableNames['permissions'], function (Blueprint $table) {
                 - $table->bigIncrements('id');
                 + $table->uuid('id');
                   $table->string('name');
                   $table->string('guard_name');
                   $table->timestamps();
                   
                + $table->primary('id');
               });

              Schema::create($tableNames['roles'], function (Blueprint $table) {
                - $table->bigIncrements('id');
               + $table->uuid('id');
                  $table->string('name');
                  $table->string('guard_name');
                  $table->timestamps();
                 
               + $table->primary('id');
              });

               Schema::create($tableNames['model_has_permissions'], function (Blueprint $table) use ($tableNames, $columnNames) {
                - $table->bigIncrements('permission_id');
               + $table->uuid('permission_id');
                   ...

              Schema::create($tableNames['model_has_roles'], function (Blueprint $table) use
    ($tableNames, $columnNames) {
                 - $table->bigIncrements('role_id');
                + $table->uuid('role_id');
                    ...
                   
              Schema::create($tableNames['role_has_permissions'], function (Blueprint $table) use ($tableNames) {
                - $table->bigIncrements('permission_id');
                - $table->bigIncrements('role_id');
                + $table->uuid('permission_id');
                + $table->uuid('role_id');


  5. Configurasi pada file config/permissions.php (Opsional)
             
    Karena saya di sini menggunakan uuid sebagai primary key maka ada sebuah opsi untuk mengubah configurasi 'model_morph_key' pada file config/permissions.php hanya untuk memperjelas saja (semantic), kode konfigurasi kita akan terlihat seperti berikut:

         'column_names' => [   
                /*
                 * Change this if you want to name the related model primary key other than
                 * `model_id`.
                 *
                 * For example, this would be nice if your primary keys are all UUIDs. In
                 * that case, name this `model_uuid`.
                */
                'model_morph_key' => 'model_id',
           ],

  6. Update model Role dan Permission
               Jika kita menggunakan uuid sebagai primary key maka ada yang perlu kita update pada model Role dan Permission Spatie, kita tidak mengubah model Spatie User dan Permission yang berada di folder vendor melainkan membuat Model Spatie Role dan Permission kita sendiri lalu kita extends dengan Model Role dan Permission bawaan Spatie, selain itu kita. juga perlu membuat sebuah trait untuk digunakan untuk menggenrate primary key uuid, untuk membuat model-model tersebut anda dapat menjalankan perintah berikut pada terminal:

              php artisan make:model Role

              php artisan make:model Permission

              Dengan perintah di atas maka akan ada 2 file model Role dan Permission pada directory app/http/middlewares/ yang selanjutnya model Role dan Permission anda akan terlihat seperti berikut:

    trait uuid

         <?php

             namespace App;
             
             use Illuminate\Support\Str;

             trait Uuid
             {

                public static function bootUuidTrait()
               {
                  static::creating(function ($model) {

                  $model->keyType = 'string';

                  $model->incrementing = false;

                  $model->{$model->getKeyName()} = $model->{$model->getKeyName()} ?: (string)
                   Str::orderedUuid();
                 });
               }

               public function getIncrementing()
               {
                  return false;
               }
             
               public function getKeyType()
               {
                 return 'string';
               }
           }

    pada model Role:

          <?php
               
               namespace App\Models;
               
               use Illuminate\Database\Eloquent\Factories\HasFactory;
               use Spatie\Permission\Models\Role as SpatieRole;
               
               class Role extends SpatieRole
              {
                use HasFactory, Uuid;
             
                protected $keyType = 'string';
             
                protected $primaryKey = 'id'; // atau 'uuid' jika primary key yang digunakan bernama 'uuid'
             
                public $incrementing = false; // karena uuid tidak menggunakan $incrementing
             
               /**
                  * The attributes that should be cast to native types.
                  *
                  * @var array
                  */
                protected $casts = [
                    'id' => 'string'
                ];

                public $morphKey = 'model_uuid';

             }

    Pada model Permission:

    <?php
               
               namespace App\Models;
               
               use Illuminate\Database\Eloquent\Factories\HasFactory;
               use Spatie\Permission\Models\Permission as SpatiePermission;
               
               class Permission extends SpatiePermission
              {
                use HasFactory, Uuid;
             
                protected $keyType = 'string';
             
                protected $primaryKey = 'id'; // atau 'uuid' jika primary key yang digunakan bernama 'uuid'
                public $incrementing = false; // karena uuid tidak menggunakan $incrementing
             
             /**
                * The attributes that should be cast to native types.
                *
                * @var array
               */
                 protected $casts = [
                     'id' => 'string'
                 ];

                 public $morphKey = 'model_uuid';

             }


  7. Update konfigurasi model User dan Permission di config/permission.php
               
    Setelah kita membuat Model custom untuk Role dan Permission Spatie maka langkah selanjutnya adalah mengganti model Role dan Permission Spatie dengan  model Role dan Permission Spatie custom kita ke file config/permission.php  sebagai berikut:

    <?php

    use App\Models\Permission;
    use App\Models\Role;

    return [

       'models' => [

           /*
             * When using the "HasPermissions" trait from this package, we need to know which
             * Eloquent model should be used to retrieve your permissions. Of course, it
             * is often just the "Permission" model but you may use whatever you like.
             *
             * The model you want to use as a Permission model needs to implement the
             * `Spatie\Permission\Contracts\Permission` contract.
             */
       
          - 'permission' => Spatie\Permission\Models\Permission::class,
         + 'permission' => Permission::class,

          /*
             * When using the "HasRoles" trait from this package, we need to know which
             * Eloquent model should be used to retrieve your roles. Of course, it
             * is often just the "Role" model but you may use whatever you like.
             *
             * The model you want to use as a Role model needs to implement the
             * `Spatie\Permission\Contracts\Role` contract.
             */
     
          - 'role' => Spatie\Permission\Models\Role::class,
         + 'role' => Role::class,


  8. Mendefinisikan middleware Spatie
               
    Untuk dapat bisa mengimplementasikan middleware spatie pada langkah berikutnya, kita perlu mendaftarkan middleware Spatie di project Laravel kita, untuk kodenya akan terlihat seperti berikut:

    Pada Laravel 9 atau lebih lama:

    protected $routeMiddleware = [
        // ...
        'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
        'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
        'role_or_permission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class,
    ];

    Pada Laravel 10:

    protected $middlewareAliases = [
        // ...
        'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
        'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
        'role_or_permission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class,
    ];
     
  9. Menggunakan middleware Spatie pada route untuk check role dan permission 
               
    Selanjutnya untuk mengimplementasikan Spatie sebagai check permission role dan permission, kita perlu menambahkan middleware ke route atau controller server Laravel kita, contoh kodenya adalah sebagai berikut:

    Pada route:

    Route::get('/', [UserController::class, 'login'])->name('login');

    Route::middleware(['auth:web','role:super-admin'])->group(function(){

        Route::get('/home', [HomeController::class, 'home'])->name('home');

    });

    Atau pasa controller:

    function __construct()
    {
        $this->middleware(['auth:web', 'role:super-admin'], ['except' => ['login']]);
    }

                Dengan kode di atas pada implementasi Spatie pada route maka hanya user dengan role super-admin yang boleh masuk ke controller HomeController dan pada implementasi Spatie pada controller hanya user dengan role super-admin yang boleh masuk ke controller yang menerapkan function __construct() tersebut dengan pengecualian route login boleh megakses controller tanpa autentikasi terlebih dahulu.
                 Selain middleware role, pada kode di atas juga terdapat middleware auth:web yang mana mengacu pada guard web yang mana berarti jika user ingin mengakses controller yang dilindugi oleh middleware auth:web dan role:super-admin maka user perlu login terlebih dahulu, untuk kode untuk melakukan login adalah sebagai berikut:

    $credentials = $request->only('email','password');
    Auth::guard('web')->attempt($credentials);

                 Dengan kode di atas yang ditempatkan pada controller login berarti user sudah diizinkan untuk mengakses HomeController yang dilindugi oleh guard dengan nama web, tetapi karena pada middleware juga menggunakan autentikasi 'role:super-admin' jadi hanya user role super-admin yang boleh mengakses HomeController.
                 Tetapi untuk dapat menggunakan guard web anda perlu mendefinisikan terlebih dahulu guard web tersebut ke model anda yang menggunakan role dan permission milik Spatie ( misal: UserController ), untuk kodenya sebagai berikut:

    protected $guard_name = 'web';





    Sumber: https://spatie.be/docs/laravel-permission/

Posting Komentar

0 Komentar