Skip to content

Roles and Abilities

Adding roles and abilities to users is extremely easy. You do not have to create a role or an ability in advance. Simply pass the name of the role/ability, and Warden will create it if it doesn’t exist.

Let’s create a role called admin and give it the ability to ban-users from our site:

Warden::allow('admin')->to('ban-users');

That’s it. Behind the scenes, Warden will create both a Role model and an Ability model for you.

Note: Roles and abilities are scoped to the configured guard (default: web). For applications using multiple guards, see Multi-Guard Support.

If you want to add additional attributes to the role/ability, such as a human-readable title, you can manually create them using the role and ability methods:

$admin = Warden::role()->firstOrCreate([
'name' => 'admin',
'title' => 'Administrator',
]);
$ban = Warden::ability()->firstOrCreate([
'name' => 'ban-users',
'title' => 'Ban users',
]);
Warden::allow($admin)->to($ban);

To give the admin role to a user, simply tell Warden that the given user should be assigned the admin role:

Warden::assign('admin')->to($user);

Alternatively, you can call the assign method directly on the user:

$user->assign('admin');

Sometimes you might want to give a user an ability directly, without using a role:

Warden::allow($user)->to('ban-users');

You can accomplish the same directly off of the user:

$user->allow('ban-users');

You can assign roles to multiple users by ID:

Warden::assign('admin')->to([1, 2, 3]);

Re-sync a user’s abilities:

Warden::sync($user)->abilities($abilities);

Re-sync a user’s roles:

Warden::sync($user)->roles($roles);

Allow a user or role to do everything:

Warden::allow($user)->everything();
Warden::allow('admin')->everything();

Allow a specific ability on everything:

Warden::allow($user)->to('view')->everything();

Allow a user to manage a model (all abilities):

Warden::allow($user)->toManage(Post::class);
Warden::allow($user)->toManage($post);

Sometimes you need permissions that are only valid within a specific boundary, such as a team, organization, or workspace. Warden supports boundary-scoped permissions through the within() method:

Grant an ability that only applies within a specific boundary:

// Simple ability within a team boundary
Warden::allow($user)->within($team)->to('view-invoices');
// Model class ability within an organization boundary
Warden::allow($user)->within($organization)->to('edit', Post::class);
// Specific model instance ability within a workspace boundary
Warden::allow($user)->within($workspace)->to('delete', $invoice);

You can also assign roles within a specific boundary:

// User is an admin, but only within this team
Warden::assign('admin')->within($team)->to($user);
// User is an editor, but only within this organization
Warden::assign('editor')->within($organization)->to($user);

Forbid abilities within a specific boundary:

// User cannot delete invoices within this team
Warden::forbid($user)->within($team)->to('delete-invoices');
// User cannot edit this specific post within this organization
Warden::forbid($user)->within($organization)->to('edit', $post);

Boundary-scoped permissions are completely independent from global permissions. A user can have different abilities in different boundaries:

// Global permission - can view all invoices
Warden::allow($user)->to('view-invoices');
// Team-specific permission - can edit invoices in Team A
Warden::allow($user)->within($teamA)->to('edit-invoices');
// Different team permission - can delete invoices in Team B
Warden::allow($user)->within($teamB)->to('delete-invoices');

In the example above:

  • The user can view invoices globally (everywhere)
  • The user can edit invoices only within Team A
  • The user can delete invoices only within Team B

Boundary morphs use the same polymorphic relationship types as actors. You can configure the morph type in your config/warden.php:

'boundary_morph_type' => env('WARDEN_BOUNDARY_MORPH_TYPE', 'morph'),

Supported values:

  • 'morph' - Standard integer IDs (default)
  • 'ulidMorph' - ULID primary keys
  • 'uuidMorph' - UUID primary keys

Note: This configuration must be set before running migrations, as it determines the database schema structure.