update inbox list

This commit is contained in:
manhlab
2021-04-07 19:25:18 -04:00
parent fda7245f7c
commit 436de2efd6
8576 changed files with 1013325 additions and 3 deletions

View File

@@ -0,0 +1,4 @@
---
title: Basic Usage
weight: 1
---

View File

@@ -0,0 +1,54 @@
---
title: Using artisan commands
weight: 7
---
## Creating roles and permissions with Artisan Commands
You can create a role or permission from the console with artisan commands.
```bash
php artisan permission:create-role writer
```
```bash
php artisan permission:create-permission "edit articles"
```
When creating permissions/roles for specific guards you can specify the guard names as a second argument:
```bash
php artisan permission:create-role writer web
```
```bash
php artisan permission:create-permission "edit articles" web
```
When creating roles you can also create and link permissions at the same time:
```bash
php artisan permission:create-role writer web "create articles|edit articles"
```
## Displaying roles and permissions in the console
There is also a `show` command to show a table of roles and permissions per guard:
```bash
php artisan permission:show
```
## Resetting the Cache
When you use the built-in functions for manipulating roles and permissions, the cache is automatically reset for you, and relations are automatically reloaded for the current model record.
See the Advanced-Usage/Cache section of these docs for detailed specifics.
If you need to manually reset the cache for this package, you may use the following artisan command:
```bash
php artisan permission:cache-reset
```
Again, it is more efficient to use the API provided by this package, instead of manually clearing the cache.

View File

@@ -0,0 +1,97 @@
---
title: Basic Usage
weight: 1
---
First, add the `Spatie\Permission\Traits\HasRoles` trait to your `User` model(s):
```php
use Illuminate\Foundation\Auth\User as Authenticatable;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use HasRoles;
// ...
}
```
This package allows for users to be associated with permissions and roles. Every role is associated with multiple permissions.
A `Role` and a `Permission` are regular Eloquent models. They require a `name` and can be created like this:
```php
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
$role = Role::create(['name' => 'writer']);
$permission = Permission::create(['name' => 'edit articles']);
```
A permission can be assigned to a role using 1 of these methods:
```php
$role->givePermissionTo($permission);
$permission->assignRole($role);
```
Multiple permissions can be synced to a role using 1 of these methods:
```php
$role->syncPermissions($permissions);
$permission->syncRoles($roles);
```
A permission can be removed from a role using 1 of these methods:
```php
$role->revokePermissionTo($permission);
$permission->removeRole($role);
```
If you're using multiple guards the `guard_name` attribute needs to be set as well. Read about it in the [using multiple guards](../multiple-guards) section of the readme.
The `HasRoles` trait adds Eloquent relationships to your models, which can be accessed directly or used as a base query:
```php
// get a list of all permissions directly assigned to the user
$permissionNames = $user->getPermissionNames(); // collection of name strings
$permissions = $user->permissions; // collection of permission objects
// get all permissions for the user, either directly, or from roles, or from both
$permissions = $user->getDirectPermissions();
$permissions = $user->getPermissionsViaRoles();
$permissions = $user->getAllPermissions();
// get the names of the user's roles
$roles = $user->getRoleNames(); // Returns a collection
```
The `HasRoles` trait also adds a `role` scope to your models to scope the query to certain roles or permissions:
```php
$users = User::role('writer')->get(); // Returns only users with the role 'writer'
```
The `role` scope can accept a string, a `\Spatie\Permission\Models\Role` object or an `\Illuminate\Support\Collection` object.
The same trait also adds a scope to only get users that have a certain permission.
```php
$users = User::permission('edit articles')->get(); // Returns only users with the permission 'edit articles' (inherited or directly)
```
The scope can accept a string, a `\Spatie\Permission\Models\Permission` object or an `\Illuminate\Support\Collection` object.
### Eloquent
Since Role and Permission models are extended from Eloquent models, basic Eloquent calls can be used as well:
```php
$all_users_with_all_their_roles = User::with('roles')->get();
$all_users_with_all_direct_permissions = User::with('permissions')->get();
$all_roles_in_database = Role::all()->pluck('name');
$users_without_any_roles = User::doesntHave('roles')->get();
```

View File

@@ -0,0 +1,91 @@
---
title: Blade directives
weight: 4
---
## Permissions
This package doesn't add any **permission**-specific Blade directives.
Instead, use Laravel's native `@can` directive to check if a user has a certain permission.
```php
@can('edit articles')
//
@endcan
```
or
```php
@if(auth()->user()->can('edit articles') && $some_other_condition)
//
@endif
```
You can use `@can`, `@cannot`, `@canany`, and `@guest` to test for permission-related access.
## Roles
As discussed in the Best Practices section of the docs, **it is strongly recommended to always use permission directives**, instead of role directives.
Additionally, if your reason for testing against Roles is for a Super-Admin, see the *Defining A Super-Admin* section of the docs.
If you actually need to test for Roles, this package offers some Blade directives to verify whether the currently logged in user has all or any of a given list of roles.
Optionally you can pass in the `guard` that the check will be performed on as a second argument.
#### Blade and Roles
Check for a specific role:
```php
@role('writer')
I am a writer!
@else
I am not a writer...
@endrole
```
is the same as
```php
@hasrole('writer')
I am a writer!
@else
I am not a writer...
@endhasrole
```
Check for any role in a list:
```php
@hasanyrole($collectionOfRoles)
I have one or more of these roles!
@else
I have none of these roles...
@endhasanyrole
// or
@hasanyrole('writer|admin')
I am either a writer or an admin or both!
@else
I have none of these roles...
@endhasanyrole
```
Check for all roles:
```php
@hasallroles($collectionOfRoles)
I have all of these roles!
@else
I do not have all of these roles...
@endhasallroles
// or
@hasallroles('writer|admin')
I am both a writer and an admin!
@else
I do not have all of these roles...
@endhasallroles
```
Alternatively, `@unlessrole` gives the reverse for checking a singular role, like this:
```php
@unlessrole('does not have this role')
I do not have the role
@else
I do have the role
@endunlessrole
```

View File

@@ -0,0 +1,67 @@
---
title: Direct Permissions
weight: 2
---
A permission can be given to any user:
```php
$user->givePermissionTo('edit articles');
// You can also give multiple permission at once
$user->givePermissionTo('edit articles', 'delete articles');
// You may also pass an array
$user->givePermissionTo(['edit articles', 'delete articles']);
```
A permission can be revoked from a user:
```php
$user->revokePermissionTo('edit articles');
```
Or revoke & add new permissions in one go:
```php
$user->syncPermissions(['edit articles', 'delete articles']);
```
You can check if a user has a permission:
```php
$user->hasPermissionTo('edit articles');
```
Or you may pass an integer representing the permission id
```php
$user->hasPermissionTo('1');
$user->hasPermissionTo(Permission::find(1)->id);
$user->hasPermissionTo($somePermission->id);
```
You can check if a user has Any of an array of permissions:
```php
$user->hasAnyPermission(['edit articles', 'publish articles', 'unpublish articles']);
```
...or if a user has All of an array of permissions:
```php
$user->hasAllPermissions(['edit articles', 'publish articles', 'unpublish articles']);
```
You may also pass integers to lookup by permission id
```php
$user->hasAnyPermission(['edit articles', 1, 5]);
```
Saved permissions will be registered with the `Illuminate\Auth\Access\Gate` class for the default guard. So you can
check if a user has a permission with Laravel's default `can` function:
```php
$user->can('edit articles');
```

View File

@@ -0,0 +1,83 @@
---
title: Using a middleware
weight: 7
---
## Default Middleware
For checking against a single permission (see Best Practices) using `can`, you can use the built-in Laravel middleware provided by `\Illuminate\Auth\Middleware\Authorize::class` like this:
```php
Route::group(['middleware' => ['can:publish articles']], function () {
//
});
```
## Package Middleware
This package comes with `RoleMiddleware`, `PermissionMiddleware` and `RoleOrPermissionMiddleware` middleware. You can add them inside your `app/Http/Kernel.php` file.
```php
protected $routeMiddleware = [
// ...
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
'role_or_permission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class,
];
```
Then you can protect your routes using middleware rules:
```php
Route::group(['middleware' => ['role:super-admin']], function () {
//
});
Route::group(['middleware' => ['permission:publish articles']], function () {
//
});
Route::group(['middleware' => ['role:super-admin','permission:publish articles']], function () {
//
});
Route::group(['middleware' => ['role_or_permission:super-admin|edit articles']], function () {
//
});
Route::group(['middleware' => ['role_or_permission:publish articles']], function () {
//
});
```
Alternatively, you can separate multiple roles or permission with a `|` (pipe) character:
```php
Route::group(['middleware' => ['role:super-admin|writer']], function () {
//
});
Route::group(['middleware' => ['permission:publish articles|edit articles']], function () {
//
});
Route::group(['middleware' => ['role_or_permission:super-admin|edit articles']], function () {
//
});
```
You can protect your controllers similarly, by setting desired middleware in the constructor:
```php
public function __construct()
{
$this->middleware(['role:super-admin','permission:publish articles|edit articles']);
}
```
```php
public function __construct()
{
$this->middleware(['role_or_permission:super-admin|edit articles']);
}
```

View File

@@ -0,0 +1,60 @@
---
title: Using multiple guards
weight: 6
---
When using the default Laravel auth configuration all of the core methods of this package will work out of the box, no extra configuration required.
However, when using multiple guards they will act like namespaces for your permissions and roles. Meaning every guard has its own set of permissions and roles that can be assigned to their user model.
### The Downside To Multiple Guards
Note that this package requires you to register a permission name for each guard you want to authenticate with. So, "edit-article" would have to be created multiple times for each guard your app uses. An exception will be thrown if you try to authenticate against a non-existing permission+guard combination. Same for roles.
> **Tip**: If your app uses only a single guard, but is not `web` (Laravel's default, which shows "first" in the auth config file) then change the order of your listed guards in your `config/auth.php` to list your primary guard as the default and as the first in the list of defined guards. While you're editing that file, best to remove any guards you don't use, too.
### Using permissions and roles with multiple guards
When creating new permissions and roles, if no guard is specified, then the **first** defined guard in `auth.guards` config array will be used.
```php
// Create a manager role for users authenticating with the admin guard:
$role = Role::create(['guard_name' => 'admin', 'name' => 'manager']);
// Define a `publish articles` permission for the admin users belonging to the admin guard
$permission = Permission::create(['guard_name' => 'admin', 'name' => 'publish articles']);
// Define a *different* `publish articles` permission for the regular users belonging to the web guard
$permission = Permission::create(['guard_name' => 'web', 'name' => 'publish articles']);
```
To check if a user has permission for a specific guard:
```php
$user->hasPermissionTo('publish articles', 'admin');
```
> **Note**: When determining whether a role/permission is valid on a given model, it checks against the first matching guard in this order (it does NOT check role/permission for EACH possibility, just the first match):
- first the guardName() method if it exists on the model;
- then the `$guard_name` property if it exists on the model;
- then the first-defined guard/provider combination in the `auth.guards` config array that matches the logged-in user's guard;
- then the `auth.defaults.guard` config (which is the user's guard if they are logged in, else the default in the file).
### Assigning permissions and roles to guard users
You can use the same core methods to assign permissions and roles to users; just make sure the `guard_name` on the permission or role matches the guard of the user, otherwise a `GuardDoesNotMatch` or `Role/PermissionDoesNotExist` exception will be thrown.
### Using blade directives with multiple guards
You can use all of the blade directives offered by this package by passing in the guard you wish to use as the second argument to the directive:
```php
@role('super-admin', 'admin')
I am a super-admin!
@else
I am not a super-admin...
@endrole
```

View File

@@ -0,0 +1,169 @@
---
title: Example App
weight: 90
---
## Creating A Demo App
If you want to just try out the features of this package you can get started with the following.
The examples on this page are primarily added for assistance in creating a quick demo app for troubleshooting purposes, to post the repo on github for convenient sharing to collaborate or get support.
If you're new to Laravel or to any of the concepts mentioned here, you can learn more in the [Laravel documentation](https://laravel.com/docs/) and in the free videos at Laracasts such as this series: https://laracasts.com/series/laravel-6-from-scratch/
### Initial setup:
```sh
cd ~/Sites
laravel new mypermissionsdemo
cd mypermissionsdemo
git init
git add .
git commit -m "Fresh Laravel Install"
# Environment
cp -n .env.example .env
sed -i '' 's/DB_CONNECTION=mysql/DB_CONNECTION=sqlite/' .env
sed -i '' 's/DB_DATABASE=laravel/#DB_DATABASE=laravel/' .env
touch database/database.sqlite
# Package
composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
git add .
git commit -m "Add Spatie Laravel Permissions package"
php artisan migrate:fresh
# Add `HasRoles` trait to User model
sed -i '' $'s/use Notifiable;/use Notifiable;\\\n use \\\\Spatie\\\\Permission\\\\Traits\\\\HasRoles;/' app/User.php
git add . && git commit -m "Add HasRoles trait"
# Add Laravel's basic auth scaffolding
composer require laravel/ui --dev
php artisan ui bootstrap --auth
# npm install && npm run prod
git add . && git commit -m "Setup auth scaffold"
```
### Add some basic permissions
- Add a new file, `/database/seeds/PermissionsDemoSeeder.php` such as the following (You could create it with `php artisan make:seed` and then edit the file accordingly):
```php
<?php
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Spatie\Permission\PermissionRegistrar;
class PermissionsDemoSeeder extends Seeder
{
/**
* Create the initial roles and permissions.
*
* @return void
*/
public function run()
{
// Reset cached roles and permissions
app()[PermissionRegistrar::class]->forgetCachedPermissions();
// create permissions
Permission::create(['name' => 'edit articles']);
Permission::create(['name' => 'delete articles']);
Permission::create(['name' => 'publish articles']);
Permission::create(['name' => 'unpublish articles']);
// create roles and assign existing permissions
$role1 = Role::create(['name' => 'writer']);
$role1->givePermissionTo('edit articles');
$role1->givePermissionTo('delete articles');
$role2 = Role::create(['name' => 'admin']);
$role2->givePermissionTo('publish articles');
$role2->givePermissionTo('unpublish articles');
$role3 = Role::create(['name' => 'super-admin']);
// gets all permissions via Gate::before rule; see AuthServiceProvider
// create demo users
$user = Factory(App\User::class)->create([
'name' => 'Example User',
'email' => 'test@example.com',
]);
$user->assignRole($role1);
$user = Factory(App\User::class)->create([
'name' => 'Example Admin User',
'email' => 'admin@example.com',
]);
$user->assignRole($role2);
$user = Factory(App\User::class)->create([
'name' => 'Example Super-Admin User',
'email' => 'superadmin@example.com',
]);
$user->assignRole($role3);
}
}
```
- re-migrate and seed the database:
```sh
composer dump-autoload
php artisan migrate:fresh --seed --seeder=PermissionsDemoSeeder
```
### Grant Super-Admin access
Super-Admins are a common feature. Using the following approach allows that when your Super-Admin user is logged in, all permission-checks in your app which call `can()` or `@can()` will return true.
- Add a Gate::before check in your `AuthServiceProvider`:
```diff
public function boot()
{
$this->registerPolicies();
//
+ // Implicitly grant "Super Admin" role all permission checks using can()
+ Gate::before(function ($user, $ability) {
+ if ($user->hasRole('Super-Admin')) {
+ return true;
+ }
+ });
}
```
### Application Code
The permissions created in the seeder above imply that there will be some sort of Posts or Article features, and that various users will have various access control levels to manage/view those objects.
Your app will have Models, Controllers, routes, Views, Factories, Policies, Tests, middleware, and maybe additional Seeders.
You can see examples of these in the demo app at https://github.com/drbyte/spatie-permissions-demo/
## Sharing
To share your app on Github for easy collaboration:
- create a new public repository on Github, without any extras like readme/etc.
- follow github's sample code for linking your local repo and uploading the code. It will look like this:
```sh
git remote add origin git@github.com:YOURUSERNAME/REPONAME.git
git push -u origin master
```
The above only needs to be done once.
- then add the rest of your code by making new commits:
```sh
git add .
git commit -m "Explain what your commit is about here"
git push origin master
```
Repeat the above process whenever you change code that you want to share.
Those are the basics!

View File

@@ -0,0 +1,140 @@
---
title: Using permissions via roles
weight: 3
---
A role can be assigned to any user:
```php
$user->assignRole('writer');
// You can also assign multiple roles at once
$user->assignRole('writer', 'admin');
// or as an array
$user->assignRole(['writer', 'admin']);
```
A role can be removed from a user:
```php
$user->removeRole('writer');
```
Roles can also be synced:
```php
// All current roles will be removed from the user and replaced by the array given
$user->syncRoles(['writer', 'admin']);
```
You can determine if a user has a certain role:
```php
$user->hasRole('writer');
// or at least one role from an array of roles:
$user->hasRole(['editor', 'moderator']);
```
You can also determine if a user has any of a given list of roles:
```php
$user->hasAnyRole(['writer', 'reader']);
// or
$user->hasAnyRole('writer', 'reader');
```
You can also determine if a user has all of a given list of roles:
```php
$user->hasAllRoles(Role::all());
```
The `assignRole`, `hasRole`, `hasAnyRole`, `hasAllRoles` and `removeRole` functions can accept a
string, a `\Spatie\Permission\Models\Role` object or an `\Illuminate\Support\Collection` object.
A permission can be given to a role:
```php
$role->givePermissionTo('edit articles');
```
You can determine if a role has a certain permission:
```php
$role->hasPermissionTo('edit articles');
```
A permission can be revoked from a role:
```php
$role->revokePermissionTo('edit articles');
```
The `givePermissionTo` and `revokePermissionTo` functions can accept a
string or a `Spatie\Permission\Models\Permission` object.
Permissions are inherited from roles automatically.
Additionally, individual permissions can be assigned to the user too.
For instance:
```php
$role = Role::findByName('writer');
$role->givePermissionTo('edit articles');
$user->assignRole('writer');
$user->givePermissionTo('delete articles');
```
In the above example, a role is given permission to edit articles and this role is assigned to a user.
Now the user can edit articles and additionally delete articles. The permission of 'delete articles' is the user's direct permission because it is assigned directly to them.
When we call `$user->hasDirectPermission('delete articles')` it returns `true`,
but `false` for `$user->hasDirectPermission('edit articles')`.
This method is useful if one builds a form for setting permissions for roles and users in an application and wants to restrict or change inherited permissions of roles of the user, i.e. allowing to change only direct permissions of the user.
You can check if the user has All or Any of a set of permissions directly assigned:
```php
// Check if the user has All direct permissions
$user->hasAllDirectPermissions(['edit articles', 'delete articles']);
// Check if the user has Any permission directly
$user->hasAnyDirectPermission(['create articles', 'delete articles']);
```
By following the previous example, when we call `$user->hasAllDirectPermissions(['edit articles', 'delete articles'])`
it returns `true`, because the user has all these direct permissions.
When we call
`$user->hasAnyDirectPermission('edit articles')`, it returns `true` because the user has one of the provided permissions.
You can list all of these permissions:
```php
// Direct permissions
$user->getDirectPermissions() // Or $user->permissions;
// Permissions inherited from the user's roles
$user->getPermissionsViaRoles();
// All permissions which apply on the user (inherited and direct)
$user->getAllPermissions();
```
All these responses are collections of `Spatie\Permission\Models\Permission` objects.
If we follow the previous example, the first response will be a collection with the `delete article` permission and
the second will be a collection with the `edit article` permission and the third will contain both.
If we follow the previous example, the first response will be a collection with the `delete article` permission and
the second will be a collection with the `edit article` permission and the third will contain both.
### NOTE about using permission names in policies
When calling `authorize()` for a policy method, if you have a permission named the same as one of those policy methods, your permission "name" will take precedence and not fire the policy. For this reason it may be wise to avoid naming your permissions the same as the methods in your policy. While you can define your own method names, you can read more about the defaults Laravel offers in Laravel's documentation at https://laravel.com/docs/authorization#writing-policies

View File

@@ -0,0 +1,49 @@
---
title: Defining a Super-Admin
weight: 5
---
We strongly recommend that a Super-Admin be handled by setting a global `Gate::before` or `Gate::after` rule which checks for the desired role.
Then you can implement the best-practice of primarily using permission-based controls (@can and $user->can, etc) throughout your app, without always having to check for "is this a super-admin" everywhere. Best not to use role-checking (ie: `hasRole`) when you have Super Admin features like this.
## `Gate::before`
If you want a "Super Admin" role to respond `true` to all permissions, without needing to assign all those permissions to a role, you can use Laravel's `Gate::before()` method. For example:
```php
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
$this->registerPolicies();
// Implicitly grant "Super Admin" role all permissions
// This works in the app by using gate-related functions like auth()->user->can() and @can()
Gate::before(function ($user, $ability) {
return $user->hasRole('Super Admin') ? true : null;
});
}
}
```
NOTE: `Gate::before` rules need to return `null` rather than `false`, else it will interfere with normal policy operation. [See more.](https://laracasts.com/discuss/channels/laravel/policy-gets-never-called#reply=492526)
Jeffrey Way explains the concept of a super-admin (and a model owner, and model policies) in the [Laravel 6 Authorization Filters](https://laracasts.com/series/laravel-6-from-scratch/episodes/51) video and some related lessons in that chapter.
## `Gate::after`
Alternatively you might want to move the Super Admin check to the `Gate::after` phase instead, particularly if your Super Admin shouldn't be allowed to do things your app doesn't want "anyone" to do, such as writing more than 1 review, or bypassing unsubscribe rules, etc.
The following code snippet is inspired from [Freek's blog article](https://murze.be/when-to-use-gateafter-in-laravel) where this topic is discussed further.
```php
// somewhere in a service provider
Gate::after(function ($user, $ability) {
return $user->hasRole('Super Admin'); // note this returns boolean
});
```

View File

@@ -0,0 +1,68 @@
---
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}.
> NOTE: You must actually create the permissions (eg: `posts.create.1`) before you can assign them, and must also create any wildcard permission patterns (eg: `posts.create.*`) before you can check for them.
### Using Wildcards
Each part can also contain wildcards (*). So let's say we assign the following permission to a user:
```php
Permission::create(['name'=>'posts.*']);
$user->givePermissionTo('posts.*');
// is the same as
Permission::create(['name'=>'posts']);
$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.