webafra/laravel-permission-mongodb

用于Laravel 5.2及以上版本的mongodb权限处理

v1 2023-10-24 08:35 UTC

This package is not auto-updated.

Last update: 2024-09-25 11:03:51 UTC


README

此包允许您在数据库中管理用户权限和角色。它受到了[laravel-permission][link-laravel-permission]的启发。代码和功能完全相同,但与[laravel-mongodb][link-laravel-mongodb]兼容

安装后,您可以执行如下操作

// Adding permissions to a user
$user->givePermissionTo('edit articles');

// Adding permissions via a role
$user->assignRole('writer');

$role->givePermissionTo('edit articles');

如果您使用多个守卫,我们也为您提供了支持。每个守卫都将有自己的权限和角色集合,可以分配给守卫的用户。请参阅README中的使用多个守卫部分。

因为所有权限都将注册在Laravel的gate上,所以您可以使用Laravel默认的can函数来测试用户是否有权限

$user->can('edit articles');

目录

安装

Laravel 兼容性

Laravel

您可以通过Composer安装此包

对于laravel 9.x使用

composer require mostafamaklad/laravel-permission-mongodb

对于laravel 8.x及更早版本使用

composer require mostafamaklad/laravel-permission-mongodb:"^3.1"

您可以使用以下命令发布迁移

php artisan vendor:publish --provider="Webafra\Permission\PermissionServiceProvider" --tag="migrations"
php artisan migrate

您可以使用以下命令发布配置文件

php artisan vendor:publish --provider="Webafra\Permission\PermissionServiceProvider" --tag="config"

发布后,config/permission.php配置文件包含

return [

    'models' => [

        /*
         * When using the "HasRoles" trait from this package, we need to know which
         * Moloquent model should be used to retrieve your permissions. Of course, it
         * is often just the "Permission" model but you may use whatever you like.
         *
         * The model you want to use as a Permission model needs to implement the
         * `Webafra\Permission\Contracts\Permission` contract.
         */

        'permission' => Webafra\Permission\Models\Permission::class,

        /*
         * When using the "HasRoles" trait from this package, we need to know which
         * Moloquent model should be used to retrieve your roles. Of course, it
         * is often just the "Role" model but you may use whatever you like.
         *
         * The model you want to use as a Role model needs to implement the
         * `Webafra\Permission\Contracts\Role` contract.
         */

        'role' => Webafra\Permission\Models\Role::class,

    ],

    'collection_names' => [

        /*
         * When using the "HasRoles" trait from this package, we need to know which
         * table should be used to retrieve your roles. We have chosen a basic
         * default value but you may easily change it to any table you like.
         */

        'roles' => 'roles',

        /*
         * When using the "HasRoles" trait from this package, we need to know which
         * table should be used to retrieve your permissions. We have chosen a basic
         * default value but you may easily change it to any table you like.
         */

        'permissions' => 'permissions',
    ],

    /*
     * By default all permissions will be cached for 24 hours unless a permission or
     * role is updated. Then the cache will be flushed immediately.
     */

    'cache_expiration_time' => 60 * 24,

    /*
     * By default we'll make an entry in the application log when the permissions
     * could not be loaded. Normally this only occurs while installing the packages.
     *
     * If for some reason you want to disable that logging, set this value to false.
     */

    'log_registration_exception' => true,
    
    /*
     * When set to true, the required permission/role names are added to the exception
     * message. This could be considered an information leak in some contexts, so
     * the default setting is false here for optimum safety.
     */
    
    'display_permission_in_exception' => false,
];

Lumen

您可以通过Composer安装此包

composer require mostafamaklad/laravel-permission-mongodb

复制所需文件

cp vendor/mostafamaklad/laravel-permission-mongodb/config/permission.php config/permission.php
cp vendor/mostafamaklad/laravel-permission-mongodb/database/migrations/create_permission_collections.php.stub database/migrations/2018_01_01_000000_create_permission_collections.php

您还需要在config/auth.php中创建另一个配置文件。在Laravel仓库中获取它,或者只需运行以下命令

curl -Ls https://raw.githubusercontent.com/laravel/lumen-framework/5.5/config/auth.php -o config/auth.php

然后,在bootstrap/app.php中注册中间件

$app->routeMiddleware([
    'auth'       => App\Http\Middleware\Authenticate::class,
    'permission' => Webafra\Permission\Middlewares\PermissionMiddleware::class,
    'role'       => Webafra\Permission\Middlewares\RoleMiddleware::class,
]);

以及配置和服务提供者

$app->configure('permission');
$app->register(Webafra\Permission\PermissionServiceProvider::class);

现在,运行您的迁移

php artisan migrate

使用方法

首先,将Webafra\Permission\Traits\HasRoles特性添加到您的User模型中

use Illuminate\Auth\Authenticatable;
use Jenssegers\Mongodb\Eloquent\Model as Model;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Webafra\Permission\Traits\HasRoles;

class User extends Model implements AuthenticatableContract, AuthorizableContract
{
    use Authenticatable, Authorizable, HasRoles;

    // ...
}

注意:如果您需要在其他模型中使用HasRoles特性,例如Page,您还需要将protected $guard_name = 'web';添加到该模型中,否则您将遇到错误

use Jenssegers\Mongodb\Eloquent\Model as Model;
use Webafra\Permission\Traits\HasRoles;

class Page extends Model
{
    use HasRoles;

    protected $guard_name = 'web'; // or whatever guard you want to use

    // ...
}

此包允许用户与权限和角色关联。每个角色都与多个权限相关联。《Role》和《Permission》是常规Moloquent模型。它们需要一个《name》,可以像这样创建

use Webafra\Permission\Models\Role;
use Webafra\Permission\Models\Permission;

$role = Role::create(['name' => 'writer']);
$permission = Permission::create(['name' => 'edit articles']);

可以使用以下方法之一将权限分配给角色

$role->givePermissionTo($permission);
$permission->assignRole($role);

可以使用以下方法之一将多个权限同步到角色

$role->syncPermissions($permissions);
$permission->syncRoles($roles);

可以使用以下方法之一从角色中删除权限

$role->revokePermissionTo($permission);
$permission->removeRole($role);

如果您使用多个守卫,则需要设置guard_name属性。请参阅README中的使用多个守卫部分。

HasRoles特性为您的模型添加了Moloquent关系,可以直接访问或用作基础查询

// get a list of all permissions directly assigned to the user
$permissions = $user->permissions; // Returns a collection

// get all permissions inherited by the user via roles
$permissions = $user->getAllPermissions(); // Returns a collection

// get all permissions names
$permissions = $user->getPermissionNames(); // Returns a collection

// get a collection of all defined roles
$roles = $user->roles->pluck('name'); // Returns a collection

// get all role names
$roles = $user->getRoleNames() // Returns a collection;

HasRoles 特性还为您模型添加了一个 role 范围,以便将查询范围限定在特定的角色或权限上。

$users = User::role('writer')->get(); // Returns only users with the role 'writer'
$users = User::permission('edit articles')->get(); // Returns only users with the permission 'edit articles'

此范围可以接受一个字符串、一个 \Webafra\Permission\Models\Role 对象、一个 \Webafra\Permission\Models\Permission 对象或一个 \Illuminate\Support\Collection 对象。

使用“直接”权限

可以授予具有 HasRoles 特性的任何用户权限

$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']);

也可以从用户中撤销权限

$user->revokePermissionTo('edit articles');

或者一次性撤销并添加新的权限

$user->syncPermissions(['edit articles', 'delete articles']);

可以测试用户是否有权限

$user->hasPermissionTo('edit articles');

...或者测试用户是否有多个权限

$user->hasAnyPermission(['edit articles', 'publish articles', 'unpublish articles']);

保存的权限将与默认守卫的 Illuminate\Auth\Access\Gate 类注册。因此,您可以使用 Laravel 的默认 can 函数来测试用户是否有权限

$user->can('edit articles');

通过角色使用权限

可以将角色分配给任何用户

$user->assignRole('writer');

// You can also assign multiple roles at once
$user->assignRole('writer', 'admin');
// or as an array
$user->assignRole(['writer', 'admin']);

可以从用户中移除角色

$user->removeRole('writer');

角色也可以进行同步

// All current roles will be removed from the user and replaced by the array given
$user->syncRoles(['writer', 'admin']);

可以确定用户是否有特定的角色

$user->hasRole('writer');

也可以确定用户是否有给定列表中的任何角色

$user->hasAnyRole(Role::all());

也可以确定用户是否有给定列表中的所有角色

$user->hasAllRoles(Role::all());

assignRolehasRolehasAnyRolehasAllRolesremoveRole 函数可以接受一个字符串、一个 \Webafra\Permission\Models\Role 对象或一个 \Illuminate\Support\Collection 对象。

可以授予角色权限

$role->givePermissionTo('edit articles');

可以确定角色是否有特定的权限

$role->hasPermissionTo('edit articles');

可以从角色中撤销权限

$role->revokePermissionTo('edit articles');

givePermissionTorevokePermissionTo 函数可以接受一个字符串或一个 Webafra\Permission\Models\Permission 对象。

权限会自动从角色继承。此外,也可以为用户分配单个权限。

例如

$role = Role::findByName('writer');
$role->givePermissionTo('edit articles');

$user->assignRole('writer');

$user->givePermissionTo('delete articles');

在上面的示例中,一个角色被授予编辑文章的权限,并将该角色分配给一个用户。现在该用户可以编辑文章,并且还可以删除文章。delete articles 权限是用户的直接权限,因为它直接分配给了他们。当我们调用 $user->hasDirectPermission('delete articles') 时,它返回 true,但 false 对于 $user->hasDirectPermission('edit articles')

如果在一个应用程序中构建一个用于设置角色和用户权限的表单,并且想要限制或更改用户角色的继承权限,这种方法很有用,即仅允许更改用户的直接权限。

可以列出所有这些权限

// 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();

所有这些响应都是 Webafra\Permission\Models\Permission 对象的集合。

如果遵循前面的示例,第一个响应将包含 delete article 权限的集合,第二个将包含 edit article 权限的集合,第三个将包含两者。

使用Blade指令

此包还添加了用于验证当前登录用户是否具有给定列表中的所有或任何角色的 Blade 指令。

可选地,可以将要执行的检查的 guard 作为第二个参数传递。

Blade 和 Roles

测试特定角色

@role('writer')
    I am a writer!
@else
    I am not a writer...
@endrole

等同于

@hasrole('writer')
    I am a writer!
@else
    I am not a writer...
@endhasrole

测试列表中的任何角色

@hasanyrole(Role::all())
    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

测试所有角色

@hasallroles(Role::all())
    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

Blade 和 Permissions

此包不会添加任何与权限特定的 Blade 指令。相反,请使用 Laravel 的原生 @can 指令来检查用户是否有特定的权限。

@can('edit articles')
  //
@endcan

@if(auth()->user()->can('edit articles') && $some_other_condition)
  //
@endif

使用多个守卫

当使用默认的 Laravel 身份验证配置时,所有上述方法都将正常工作,无需额外配置。

然而,当使用多个守卫时,它们将像命名空间一样作用于您的权限和角色。这意味着每个守卫都有自己的权限和角色集,可以分配给其用户模型。

使用多个守卫的权限和角色

在创建新的权限和角色时,如果没有指定守卫,则将使用auth.guards配置数组中定义的第一个守卫。当为特定的守卫创建权限和角色时,您必须在模型上指定它们的guard_name

// Create a superadmin role for the admin users

$user->hasPermissionTo('publish articles', 'admin');

注意:在确定给定模型上的角色/权限是否有效时,它将按照以下顺序选择守卫:首先检查模型的$guard_name属性;然后是配置中的守卫(通过提供者);接着是auth.guards配置数组中定义的第一个守卫;最后是auth.defaults.guard配置。

将权限和角色分配给守卫用户

您可以使用与上述通过角色使用权限中描述的相同方法来分配用户权限和角色。只需确保权限或角色上的guard_name与用户的守卫匹配,否则将抛出GuardDoesNotMatch异常。

使用多个守卫的Blade指令

您可以通过将希望使用的守卫作为指令的第二个参数传递,来使用使用blade指令中列出的所有blade指令。

@role('super-admin', 'admin')
    I am a super-admin!
@else
    I am not a super-admin...
@endrole

使用中间件

此包附带RoleMiddlewarePermissionMiddleware中间件。您可以在app/Http/Kernel.php文件中添加它们。

protected $routeMiddleware = [
    // ...
    'role' => \Webafra\Permission\Middlewares\RoleMiddleware::class,
    'permission' => \Webafra\Permission\Middlewares\PermissionMiddleware::class,
];

然后您可以使用中间件规则来保护您的路由。

Route::group(['middleware' => ['role:super-admin']], function () {
    //
});

Route::group(['middleware' => ['permission:publish articles']], function () {
    //
});

Route::group(['middleware' => ['role:super-admin','permission:publish articles']], function () {
    //
});

您可以通过在构造函数中设置所需的中间件以类似的方式保护控制器。

public function __construct()
{
    $this->middleware(['role:super-admin','permission:publish articles|edit articles']);
}

您可以在Laravel异常处理器中添加一些内容。

public function render($request, Exception $exception)
{
    if ($exception instanceof \Webafra\Permission\Exceptions\UnauthorizedException) {
        // Code here ...
    }

    return parent::render($request, $exception);
}

使用Artisan命令

您可以使用Artisan命令从控制台创建角色或权限。

php artisan permission:create-role writer
php artisan permission:create-permission 'edit articles'

在为特定守卫创建权限和角色时,您可以将守卫名称作为第二个参数指定。

php artisan permission:create-role writer web
php artisan permission:create-permission 'edit articles' web

单元测试

在您应用程序的测试中,如果您在测试的setUp()中不作为部分生成角色和权限,那么您可能会遇到一个鸡生蛋的困境,其中角色和权限未在门(因为您的测试在门注册完成后创建它们)中注册。解决这个问题很简单:在测试中,只需添加一个setUp()指令以重新注册权限,如下所示

public function setUp()
{
    // first include all the normal setUp operations
    parent::setUp();

    // now re-register all the roles and permissions
    $this->app->make(\Webafra\Permission\PermissionRegistrar::class)->registerPermissions();
}

数据库播种

关于数据库填充的两个注意事项

  1. 在填充之前最好清除webafra.permission.cache,以避免缓存冲突错误。这可以通过Artisan命令(见故障排除:缓存部分)或直接在填充器类中完成(见下面示例)。

  2. 下面是一个示例填充器,它清除缓存、创建权限,然后将权限分配给角色

use Illuminate\Database\Seeder;
use Webafra\Permission\Models\Role;
use Webafra\Permission\Models\Permission;

class RolesAndPermissionsSeeder extends Seeder
{
    public function run()
    {
        // Reset cached roles and permissions
        app()['cache']->forget('webafra.permission.cache');
        
        // create permissions
        Permission::firstOrCreate(['name' => 'edit articles']);
        Permission::firstOrCreate(['name' => 'delete articles']);
        Permission::firstOrCreate(['name' => 'publish articles']);
        Permission::firstOrCreate(['name' => 'unpublish articles']);
        
        // create roles and assign existing permissions
        $role = Role::firstOrCreate(['name' => 'writer']);
        $role->givePermissionTo('edit articles');
        $role->givePermissionTo('delete articles');
        
        $role = Role::firstOrCreate(['name' => 'admin']);
        $role->givePermissionTo(['publish articles', 'unpublish articles']);
    }
}

扩展

如果您需要扩展现有的RolePermission模型,请注意

  • 您的Role模型需要继承自Webafra\Permission\Models\Role模型
  • 您的Permission模型需要继承自Webafra\Permission\Models\Permission模型

如果您需要扩展或替换现有的RolePermission模型,只需记住以下事项

  • 您的Role模型需要实现Webafra\Permission\Contracts\Role合同
  • 您的Permission模型需要实现Webafra\Permission\Contracts\Permission合同

在两种情况下,无论是扩展还是替换,您都需要在配置中指定您的新模型。为此,您必须在发布配置后使用此命令更新配置文件中的models.rolemodels.permission

php artisan vendor:publish --provider="Webafra\Permission\PermissionServiceProvider" --tag="config"

缓存

角色和权限数据被缓存以提高性能。

当您使用用于操作角色和权限的提供的方法时,缓存会自动为您重置。

$user->assignRole('writer');
$user->removeRole('writer');
$user->syncRoles(params);
$role->givePermissionTo('edit articles');
$role->revokePermissionTo('edit articles');
$role->syncPermissions(params);
$permission->assignRole('writer');
$permission->removeRole('writer');
$permission->syncRoles(params);

然而,如果您直接在数据库中而不是调用提供的方法直接操作权限/角色数据,那么除非您手动重置缓存,否则您将看不到应用程序中的更改。

手动重置缓存

要手动重置此包的缓存,请运行

php artisan cache:forget webafra.permission.cache

缓存标识符

注意:如果您正在使用缓存服务,如 redismemcached,并且服务器上还运行着其他网站,可能会遇到缓存冲突。为了安全起见,您应该在 /config/cache.php 文件中为每个应用程序设置独特的缓存 prefix。这将防止其他应用程序意外地使用/修改您的缓存数据。

需要UI吗?

由于我们基于 [laravel-permission][link-laravel-permission]。该包默认不包含任何界面,您需要自己构建。要开始,请查看 这篇详细的教程,作者是 Caleb Oki

变更日志

有关最近更改的更多信息,请参阅 CHANGELOG

测试

composer test

贡献

有关详细信息,请参阅 CONTRIBUTINGCONDUCT

安全

如果您发现任何安全问题,请通过电子邮件 webafra@gmail.com 而不是使用问题跟踪器。

鸣谢

  • [Mostafa MAN][link-author]
  • [所有贡献者][link-contributors]

许可

MIT 许可证(MIT)。有关更多信息,请参阅 许可证文件