-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Add wildcard permissions #1381
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Add wildcard permissions #1381
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
--- | ||
title: Wildcard permissions | ||
weight: 3 | ||
--- | ||
|
||
Wildcard permissions can be enabled in the permission config file: | ||
|
||
```php | ||
// config/permission.php | ||
'enable_wildcard_permission' => true, | ||
``` | ||
|
||
When enabled, wildcard permissions offers you a flexible representation for a variety of permission schemes. The idea | ||
behind wildcard permissions is inspired by the default permission implementation of | ||
[Apache Shiro](https://shiro.apache.org/permissions.html). | ||
|
||
A wildcard permission string is made of one or more parts separated by dots (.). | ||
|
||
```php | ||
$permission = 'posts.create.1'; | ||
``` | ||
|
||
The meaning of each part of the string depends on the application layer. | ||
|
||
> You can use as many parts as you like. So you are not limited to the three-tiered structure, even though | ||
this is the common use-case, representing {resource}.{action}.{target}. | ||
|
||
### Using Wildcards | ||
|
||
Each part can also contain wildcards (*). So let's say we assign the following permission to a user: | ||
|
||
```php | ||
$user->givePermissionTo('posts.*'); | ||
// is the same as | ||
$user->givePermissionTo('posts'); | ||
``` | ||
|
||
Everyone who is assigned to this permission will be allowed every action on posts. It is not necessary to use a | ||
wildcard on the last part of the string. This is automatically assumed. | ||
|
||
```php | ||
// will be true | ||
$user->can('posts.create'); | ||
$user->can('posts.edit'); | ||
$user->can('posts.delete'); | ||
``` | ||
|
||
### Subparts | ||
|
||
Besides the use of parts and wildcards, subparts can also be used. Subparts are divided with commas (,). This is a | ||
powerful feature that lets you create complex permission schemes. | ||
|
||
```php | ||
// user can only do the actions create, update and view on both resources posts and users | ||
$user->givePermissionTo('posts,users.create,update,view'); | ||
|
||
// user can do the actions create, update, view on any available resource | ||
$user->givePermissionTo('*.create,update,view'); | ||
|
||
// user can do any action on posts with ids 1, 4 and 6 | ||
$user->givePermissionTo('posts.*.1,4,6'); | ||
``` | ||
|
||
> As said before, the meaning of each part is determined by the application layer! So, you are free to use each part as you like. And you can use as many parts and subparts as you want. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?php | ||
|
||
namespace Spatie\Permission\Exceptions; | ||
|
||
use InvalidArgumentException; | ||
|
||
class WildcardPermissionInvalidArgument extends InvalidArgumentException | ||
{ | ||
public static function create() | ||
{ | ||
return new static('Wildcard permission must be string, permission id or permission instance'); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?php | ||
|
||
namespace Spatie\Permission\Exceptions; | ||
|
||
use InvalidArgumentException; | ||
|
||
class WildcardPermissionNotProperlyFormatted extends InvalidArgumentException | ||
{ | ||
public static function create(string $permission) | ||
{ | ||
return new static("Wildcard permission `{$permission}` is not properly formatted."); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
<?php | ||
|
||
namespace Spatie\Permission; | ||
|
||
use Illuminate\Support\Collection; | ||
use Spatie\Permission\Exceptions\WildcardPermissionNotProperlyFormatted; | ||
|
||
class WildcardPermission | ||
{ | ||
/** @var string */ | ||
const WILDCARD_TOKEN = '*'; | ||
|
||
/** @var string */ | ||
const PART_DELIMITER = '.'; | ||
|
||
/** @var string */ | ||
const SUBPART_DELIMITER = ','; | ||
|
||
/** @var string */ | ||
protected $permission; | ||
|
||
/** @var Collection */ | ||
protected $parts; | ||
|
||
/** | ||
* @param string $permission | ||
*/ | ||
public function __construct(string $permission) | ||
{ | ||
$this->permission = $permission; | ||
$this->parts = collect(); | ||
|
||
$this->setParts(); | ||
} | ||
|
||
/** | ||
* @param string|WildcardPermission $permission | ||
* | ||
* @return bool | ||
*/ | ||
public function implies($permission): bool | ||
{ | ||
if (is_string($permission)) { | ||
$permission = new self($permission); | ||
} | ||
|
||
$otherParts = $permission->getParts(); | ||
|
||
$i = 0; | ||
foreach ($otherParts as $otherPart) { | ||
if ($this->getParts()->count() - 1 < $i) { | ||
return true; | ||
} | ||
|
||
if (! $this->parts->get($i)->contains(self::WILDCARD_TOKEN) | ||
&& ! $this->containsAll($this->parts->get($i), $otherPart)) { | ||
return false; | ||
} | ||
|
||
$i++; | ||
} | ||
|
||
for ($i; $i < $this->parts->count(); $i++) { | ||
if (! $this->parts->get($i)->contains(self::WILDCARD_TOKEN)) { | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* @param Collection $part | ||
* @param Collection $otherPart | ||
* | ||
* @return bool | ||
*/ | ||
protected function containsAll(Collection $part, Collection $otherPart): bool | ||
{ | ||
foreach ($otherPart->toArray() as $item) { | ||
if (! $part->contains($item)) { | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* @return Collection | ||
*/ | ||
public function getParts(): Collection | ||
{ | ||
return $this->parts; | ||
} | ||
|
||
/** | ||
* Sets the different parts and subparts from permission string. | ||
* | ||
* @return void | ||
*/ | ||
protected function setParts(): void | ||
{ | ||
if (empty($this->permission) || $this->permission == null) { | ||
throw WildcardPermissionNotProperlyFormatted::create($this->permission); | ||
} | ||
|
||
$parts = collect(explode(self::PART_DELIMITER, $this->permission)); | ||
|
||
$parts->each(function ($item, $key) { | ||
$subParts = collect(explode(self::SUBPART_DELIMITER, $item)); | ||
|
||
if ($subParts->isEmpty() || $subParts->contains('')) { | ||
throw WildcardPermissionNotProperlyFormatted::create($this->permission); | ||
} | ||
|
||
$this->parts->add($subParts); | ||
}); | ||
|
||
if ($this->parts->isEmpty()) { | ||
throw WildcardPermissionNotProperlyFormatted::create($this->permission); | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.