Skip to content

Commit

Permalink
Add support for multiple permissions check for users.
Browse files Browse the repository at this point in the history
  • Loading branch information
sammyskills committed Aug 16, 2023
1 parent 78cac54 commit f962bcd
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 33 deletions.
6 changes: 5 additions & 1 deletion docs/authorization.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,14 +111,18 @@ The `Authorizable` trait on the `User` entity provides the following methods to

#### can()

Allows you to check if a user is permitted to do a specific action. The only argument is the permission string. Returns
Allows you to check if a user is permitted to do a specific action or group or actions. The permission string(s) should be passed as the argument(s). Returns
boolean `true`/`false`. Will check the user's direct permissions (**user-level permissions**) first, and then check against all of the user's groups
permissions (**group-level permissions**) to determine if they are allowed.

```php
if ($user->can('users.create')) {
//
}
OR
if ($user->can('users.create', 'users.edit')) {
//
}
```

#### inGroup()
Expand Down
67 changes: 35 additions & 32 deletions src/Authorization/Traits/Authorizable.php
Original file line number Diff line number Diff line change
Expand Up @@ -228,47 +228,50 @@ public function hasPermission(string $permission): bool
* Checks user permissions and their group permissions
* to see if the user has a specific permission.
*
* @param string $permission string consisting of a scope and action, like `users.create`
* @param string $permission string(s) consisting of a scope and action, like `users.create`
*/
public function can(string $permission): bool
public function can(string ...$permissions): bool
{
if (strpos($permission, '.') === false) {
throw new LogicException(
'A permission must be a string consisting of a scope and action, like `users.create`.'
. ' Invalid permission: ' . $permission
);
}

$this->populatePermissions();

$permission = strtolower($permission);
foreach ($permissions as $permission) {
// Permission must contain a scope and action
if (strpos($permission, '.') === false) {
throw new LogicException(
'A permission must be a string consisting of a scope and action, like `users.create`.'
. ' Invalid permission: ' . $permission
);
}

// Check user's permissions
if (in_array($permission, $this->permissionsCache, true)) {
return true;
}
$this->populatePermissions();

// Check the groups the user belongs to
$this->populateGroups();
$permission = strtolower($permission);

if (! count($this->groupCache)) {
return false;
}
// Check user's permissions
if (in_array($permission, $this->permissionsCache, true)) {
return true;
}

$matrix = function_exists('setting')
? setting('AuthGroups.matrix')
: config('AuthGroups')->matrix;
// Check the groups the user belongs to
$this->populateGroups();

foreach ($this->groupCache as $group) {
// Check exact match
if (isset($matrix[$group]) && in_array($permission, $matrix[$group], true)) {
return true;
if (! count($this->groupCache)) {
return false;
}

// Check wildcard match
$check = substr($permission, 0, strpos($permission, '.')) . '.*';
if (isset($matrix[$group]) && in_array($check, $matrix[$group], true)) {
return true;
$matrix = function_exists('setting')
? setting('AuthGroups.matrix')
: config('AuthGroups')->matrix;

foreach ($this->groupCache as $group) {
// Check exact match
if (isset($matrix[$group]) && in_array($permission, $matrix[$group], true)) {
return true;
}

// Check wildcard match
$check = substr($permission, 0, strpos($permission, '.')) . '.*';
if (isset($matrix[$group]) && in_array($check, $matrix[$group], true)) {
return true;
}
}
}

Expand Down
7 changes: 7 additions & 0 deletions tests/Authorization/AuthorizableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,13 @@ public function testCanCascadesToGroupsSimple(): void
$this->assertTrue($this->user->can('admin.access'));
}

public function testCanCascadesToGroupsMultiple(): void
{
$this->user->addGroup('superadmin');

$this->assertTrue($this->user->can('admin.access', 'users.*'));
}

public function testCanCascadesToGroupsWithWildcards(): void
{
$this->user->addGroup('superadmin');
Expand Down

0 comments on commit f962bcd

Please sign in to comment.