Skip to main content

Black Friday 2025! Only until December 1st: coupon FRIDAY25 for 40% off Yearly/Lifetime membership!

Read more here

Roles/Permissions DB: Enums and Seeders

Premium
3:38

In this course section, let's get to a more complex example with Teams and Roles.


Scenario

Imagine a scenario for managing clinics. The application has roles in a hierarchy: master admin > super admin > admin > user.

The idea comes from a real comment on our YouTube channel:

We've tried to re-create that scenario in this demo project:

  • master admin has access to everything
  • super admin is a clinic owner who can have multiple clinics
  • admin: a manager of each clinic
  • users: finally, "regular" users are also split into three roles: staff, doctors, and patients.

We will continue the same Task Management project as in the previous lessons and use the Spatie Permissions package with the Teams function enabled. In this case, the Team will represent a Clinic.

Here's the plan of this project:

  • We define Roles and their Permissions
  • We add the Teams and their CRUD Management
  • We add the User Management and who has permission for it
  • Then, finally, we add the Tasks CRUD with permissions
  • All covered by tests, traditionally

Roles and Permissions: Enums and Seeders

First, I created an Enum file listing all the roles:

php artisan make:enum Role

app/Enums/Role.php:

namespace App\Enums;
 
enum Role: string
{
case Patient = 'patient';
case Doctor = 'doctor';
case Staff = 'staff';
case ClinicAdmin = 'clinic-admin';
case ClinicOwner = 'clinic-owner';
case MasterAdmin = 'master-admin';
}

Why Enum? To avoid typos in the string names, when typing "clinic-owner" somewhere else in the code and mistyping it as "clinicowner" or "clinic_owner". So, we will only reference role names via their Enum values. Consistency.

Similarly, Enum for Permissions.

app/Enums/Permission.php:

namespace App\Enums;
 
enum Permission: string
{
case LIST_TEAM = 'list-team';
case CREATE_TEAM = 'create-team';
 
case LIST_USER = 'list-user';
case CREATE_USER = 'create-user';
 
case LIST_TASK = 'list-task';
case CREATE_TASK = 'create-task';
case EDIT_TASK = 'edit-task';
case DELETE_TASK = 'delete-task';
 
case SWITCH_TEAM = 'switch-team';
}

Next, we immediately use that Enum in practice: we seed all those roles and permissions into DB.

php artisan make:seeder RoleAndPermissionSeeder

Now, which role can do what?

Here's the table I came up with as I understand the roles in a typical clinic:

All that role/permission list is available in this seeder's private method...

The Full Lesson is Only for Premium Members

Want to access all of our courses? (31 h 16 min)

You also get:

55 courses
Premium tutorials
Access to repositories
Private Discord
Get Premium for $129/year or $29/month

Already a member? Login here

Comments & Discussion

M
M ✓ Link copied!

If your Seeder uses "use WithoutModelEvents;", then you should refresh the cached permissions to avoid the following error "There is no permission named list-task for guard web."

        // Reset cached roles and permissions
        app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();

        // dd(PermissionEnum::cases(), RoleEnum::cases());
        foreach (PermissionEnum::cases() as $permission) {
            \Spatie\Permission\Models\Permission::create(['name' => $permission->value]);
        }

        // update cache
        app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();
 

ref: https://github.com/spatie/laravel-permission/discussions/2708

M
Modestas ✓ Link copied!

Makes sense! Thanks for the link