Daravelv1.13.0
ENID GitHub

Role dan permission

daravel_permission menyimpan role dan permission di database, di lima tabel milik spatie/laravel-permission v6, sehingga aplikasi Laravel yang memakai Spatie dan aplikasi Daravel bisa berbagi data itu: role yang diberikan salah satunya terlihat oleh yang lain.

dart pub add daravel_permission
// bootstrap/app.dart
import 'package:daravel_permission/daravel_permission.dart';

Application createApp() => Application.configure(basePath: basePath)
    .withPermissions()
    .withMigrations([...migrations, const CreatePermissionTables()])
    // ...
    .create();

CreatePermissionTables membuat roles, permissions, model_has_roles, model_has_permissions, dan role_has_permissions dengan kolom, key, dan nama index dari Spatie, dan tidak melakukan apa pun bila permissions sudah ada, sehingga database yang sudah menjalankan migration Spatie tetap memakainya.

Model#

final class User extends Model with AuthenticatableModel, HasRoles {
  // ...
}

Assignment disimpan dengan morph class model (App\Models\User secara default), sama seperti cara Laravel menyimpannya.

final writer = await Role.create('writer');
await Permission.create('posts.edit');
await writer.givePermissionTo('posts.edit');

await user.assignRole('writer');            // nama, Role, id, atau list
await user.givePermissionTo('posts.publish'); // langsung, tanpa role

await user.hasRole('writer');               // juga 'admin|writer'
await user.hasAnyRole(['admin', 'writer']);
await user.hasAllRoles(['admin', 'writer']);
await user.hasPermissionTo('posts.edit');   // lewat role atau langsung
await user.getRoleNames();                  // ['writer']
await user.getAllPermissions();             // ['posts.edit', 'posts.publish']

await user.syncRoles(['editor']);           // mengganti role-nya
await user.removeRole('editor');
await user.revokePermissionTo('posts.publish');

Seperti di Spatie, hasPermissionTo melempar PermissionDoesNotExist untuk permission yang tidak mungkin dimiliki siapa pun (salah ketik), sedangkan checkPermissionTo menjawab false. Role.create menolak duplikat (RoleAlreadyExists), dan role dari guard lain tidak bisa diberikan (GuardDoesNotMatch); pesannya sama dengan pesan Spatie.

Guard#

Role dan permission dimiliki oleh sebuah guard (guard_name). Nilainya web kecuali PERMISSION_GUARD menentukan lain, karena itulah nama yang dipakai aplikasi Laravel, sehingga barisnya cocok. Model dengan guard lain meng-override-nya:

final class Admin extends Model with AuthenticatableModel, HasRoles {
  @override
  String get guardName => 'admin';
}

await Role.create('admin', guard: 'admin');

Gate dan middleware#

withPermissions() menambahkan hook gate, seperti Gate::before milik Spatie: permission yang dimiliki user membuat Gate.allows('posts.edit'), middleware can:posts.edit, dan authorize() lolos, sedangkan ability lain diteruskan ke definisi gate dan policy Anda.

router.get('/admin', admin.index).middleware(['auth', 'role:admin|editor']);
router.post('/posts', posts.store).middleware(['auth', 'permission:posts.create']);
router.put('/posts/{id}', posts.update).middleware([
  'auth',
  'role_or_permission:admin|posts.edit',
]);

Nama-namanya dipisah dengan | (salah satunya cukup); setelah koma menyusul guard auth (role:admin,token). Penolakan berupa 403 dengan pesan dari Spatie:

{"message": "User does not have the right roles."}

PERMISSION_DISPLAY_ROLE_IN_EXCEPTION dan PERMISSION_DISPLAY_PERMISSION_IN_EXCEPTION menambahkan nama-namanya ke pesan.

PERMISSION_SUPER_ADMIN_ROLE=root membuat sebuah role lolos semua pengecekan gate, pola yang didokumentasikan Spatie; secara default mati.

Wildcard#

Dengan PERMISSION_WILDCARD=true (enable_wildcard_permission dari Spatie), permission dicocokkan per bagian:

Diberikan Mencakup
posts.* atau posts posts.edit, posts.edit.own
posts.edit,delete posts.edit, posts.delete
posts.*.own posts.edit.own, bukan posts.edit.all

Cache#

Role dan permission sebuah model disimpan di memori setelah pengecekan pertama, sehingga pengecekan cukup berupa lookup set, bukan tiga query. Perubahan lewat Daravel (assignRole, givePermissionTo, perintah CLI, ...) langsung berlaku di isolate-nya dan dalam satu detik di semua isolate dan proses lain di mesin yang sama; dengan cache store yang dibagi antarserver (CACHE_STORE=database atau redis), di semua server. Perubahan yang dibuat aplikasi Laravel terlihat dalam PERMISSION_CACHE_TTL (5 menit).

Perintah#

Tambahkan ke bootstrap/commands.dart, dari library tersendiri sehingga server tidak ikut mengompilasi CLI:

import 'package:daravel_permission/commands.dart';

final List<CommandFactory> commands = [...permissionCommands];
Perintah Kegunaan
permission:create-role <name> [--guard] [--permissions=a,b] Membuat role, dan memberinya permission
permission:create-permission <name> [--guard] Membuat permission
permission:assign <id> <role> [--model] [--guard], permission:revoke ... Memberi atau mencabut role (--model adalah tipe yang disimpan, default App\Models\User)
permission:show [--guard] Role terhadap permission
permission:cache-reset Melupakan role dan permission yang di-cache

Bersama Laravel#

bench/interop/permission.sh menjalankan Laravel 12 dengan spatie/laravel-permission 6 dan Daravel di satu database: Laravel menjalankan migration dan memberi role, Daravel membacanya, Daravel memberi role, lalu Laravel membacanya (hasRole, can). Teams (permission.teams) dan key model UUID belum didukung.