Scoped permissions
Sometimes you may need more than just CRUD permissions, or have certain conditions on them. For example, you may not have the permission to update users, but you should be able to update your own profile.
Creating a permission scope
For this example, we will be creating a permission scope where we check if the model is our logged in user:
class WhereIsSelf extends PermissionScope
{
public function check(User $user, ?Model $model): bool
{
return $model && $user->id === $model->id;
}
public function description(): string
{
return __('Only see and update myself');
}
}
Like policies, the first argument in check
is the logged in user, and the second argument is the related model.
To seed this permission scope:
/** @var PermissionCreator $creator */
$creator = app(PermissionCreator::class);
$creator->create('users only self',
'users',
false,
true,
false,
true,
false,
WhereIsSelf::class
);
As you can see, we use true
for view
and update
. This means the permission will only apply for these resource
actions.
Usage
Permission scopes will automatically be used in policies if you use the ExtensivePermissions helpers like:
return $user->canView('users', $model);
If you specifically want to check if the user has a permission scope:
$user->hasPermissionScope(SessionManagement::class, $model)
// OR:
$user->hasPermissionScope(SessionManagement::class)
Scope groups
Scope groups are groups that can be assigned to a ScopedPermission. The best way to explain this, is by example.
Practical example
Let's assume we have a Ticket system, and we have 2 roles: projectmanager
and developer
.
Let's also assume we have 2 mailboxes: support@qlic.nl
and info@qlic.nl
.
Now, developers may only access tickets from support@qlic.nl
, but project managers may read tickets from all inboxes.
We can have the following PermissionScope for this:
class CanReadTickets extends PermissionScope
{
public function check(User $user, ?Model $model): bool
{
return true;
}
public function description(): string
{
return 'Can read tickets';
}
}
Now everyone with this permission can read all tickets. So let's add the inboxes:
public function groups(): array
{
return ['info@qlic.nl', 'support@qlic.nl'];
}
In the interface, a multi-select will now appear where these groups can be assigned to a permission.
Assigning groups
You can assign or revoke a group via PHP:
$role = Role::first();
$role->giveScopeGroup(CanReadTickets::class, ['info@qlic.nl', 'support@qlic.nl']);
$role->revokeScopeGroup(CanReadTickets::class, ['support@qlic.nl']);
It is good practise to give the admin
role every scope group by default. You need to do this manually:
$adminRole = Role::where('name', config('permission.super_admin'))->first();
$adminRole->giveScopeGroup(CanReadTickets::class, ...);
Usage
You can check whether a user has a scope group:
$user->hasPermissionScopeGroup(CanReadTickets::class, 'info@qlic.nl');
Configuring the options
You can display more information for each group in the interface by adding the following method:
public function selectOptions(): array
{
return [
[
'label' => 'Support box',
'value' => 'support@qlic.nl',
'description' => 'My description'
],
[
'label' => 'Info box',
'value' => 'info@qlic.nl',
'description' => 'My description'
],
];
}
By default, you can assign multiple groups to a permission, however you can disable this:
public function canHaveMultipleGroups(): bool
{
return false;
}