Loading...

This is taking longer than expected.

Back to the help centre

Team roles and permissions

The owner role, the default role, the roles a team writes for itself, and how a permission is declared for the team guard.

Weblabor Base has one set of roles for the whole application. Weblabor Teams keeps it for the admin panel and adds a set of roles inside each team, on Spatie Permission's teams mode. This guide says which roles a team is born with, how it writes more, and how you declare the permissions they can carry. How the right set is chosen on each request is in The team context.

Two guards

Guard Where it applies Whose roles
web The admin panel at /admin and the switcher at /app. The global roles of the base: admin and whatever you add in /admin/roles.
team Everything under /team. The roles of the team the person is working in.

A permission belongs to one guard. Being an admin of the product says nothing about what the person can do inside a team, and being a team's owner says nothing about the admin panel. The same account can be both.

The roles a team is born with

config/app.php declares them:

'team_owner_role' => 'administrator',
'team_default_role' => 'user',
'team_roles' => [
    'user' => [
        'retrieve members',
    ],
],

When a team is created, every role in team_roles is created inside it with the permissions listed, and the role named in team_owner_role is created with every permission of the team guard and assigned to the creator. Every member added later receives the role named in team_default_role, which has to be one of the keys of team_roles.

Add a key to team_roles and every team created from then on has it. Teams that already exist do not: write a migration that creates the role in each of them when you need that.

The owner

The owner is the person in creator_user_id. Besides holding the owner role, the owner passes every policy check of the team without consulting a permission: the members, the settings, the billing. There is no way to make someone else the owner from the interface; the team was created by one person and stays theirs.

Roles the team writes

/team/roles is a CRUD of the team's roles, scoped to the team: a role created there has the team's id, appears only there, and its name has to be unique inside that team and nowhere else. The form lists every permission of the team guard as checkboxes.

A role can be cloned from the list by a member with create role: the copy keeps the permissions and the team, and gets a name that does not collide.

Deleting a role a member holds leaves that member with no role in the team; assign another one first from the members list.

Declaring a team permission

Permissions are declared once, in config/app.php → permissions, each with its guard:

'permissions' => [
    'dashboard admin' => 'web',
    'dashboard user' => 'web',

    'retrieve members' => 'team',
    'create members' => 'team',
    'update members' => 'team',
    'delete members' => 'team',
    'edit settings' => 'team',
    'manage plans' => 'team',
],

Run php artisan db:seed --class=PermissionSeeder after adding one and it exists for every team, ready to be ticked in a role. With discover_front_permissions on, the seeder also creates retrieve, create, update and delete for every Laravel Front resource, on the guard the resource declares: a resource under app/Front/Resources/Team/ gets them on the team guard. See Build a team-scoped CRUD.

allow_permisisons_deletion deletes on seeding any permission that is no longer declared or discovered, so a permission you stop declaring disappears from every role.

What the shipped permissions guard

Permission What it opens
retrieve members The members list.
create members Adding and inviting members.
update members Changing a member's role.
delete members Removing a member or cancelling an invitation.
edit settings Changing the team's settings. Every member opens the settings screen, since leaving the team is there; only this permission lets them change anything on it.
manage plans The plans, add-ons, billing and payment methods screens, and nothing else: the members, roles, files and space screens ask only for their own permission. Without it, opening a billing screen sends the member back to the dashboard with a message naming the permission.

Checking a permission in your code

Inside a request under /team the context is already the team's, so the base's policies and helpers work as they are:

$this->authorize('viewAny', UserTeam::class);
auth()->user()->hasPermissionTo('edit settings', 'team');

Pass the guard when you call Spatie directly, as in the second line, because the user's default guard is web. In a queued job, a command or a modal loaded outside the request, set the context first; The team context explains how.