kodilab/laravel-batuta

此包已被废弃且不再维护。没有建议的替代包。

Laravel 权限

dev-master 2019-12-06 11:05 UTC

This package is auto-updated.

Last update: 2020-04-08 12:48:03 UTC


README

Build Status

laravel-batuta 是一个 Laravel 包,它提供了一个与 Laravel 提供的 Authorization 系统兼容的权限解决方案。

一些概念

laravel-batuta 使用一些概念,在使用此包之前必须理解。

让我们用一个电子商务项目的例子来说明。您的网站正在销售 商品。那么 item资源 的一个明显例子。在这些 资源 上,我们将能够执行 操作。我们可以为每个资源创建尽可能多的操作。在这种情况下,我们可以列出以下操作(由 verb + resource 组成)

  • 读取商品
  • 写入商品
  • 删除商品
  • 更新商品价格

请注意,我们将 update-pricewrite 中提取出来作为一个独立操作。这允许我们定义可以更新商品但不可更新其价格的用户,可以只更改价格的用户,以及可以执行这两个操作的用户。您可以为每个资源创建哪些操作以及多少操作取决于您的需求!

然后,用户 将对每个 操作 拥有权限。这种权限可以是 true(可以执行该操作),false(不能执行该操作)。如果用户对操作的权限未定义,则默认为 false

为了便于管理权限组,您可以给 用户 分配一个 角色。然后,用户 将在权限未定义时继承分配的角色权限。

总结一下,用户 属于一个(或多个)角色。用户和角色都对 操作 拥有权限。当用户没有权限时,检查用户所属的任何角色是否有此权限。

安装

首先,在您的 composer 配置中添加 laravel-batuta 依赖项

composer require kodilab/laravel-batuta

一旦将依赖项添加到项目中,您必须发布所需的迁移。这些迁移将创建 laravel-batuta 所需的表。还将创建基本的 初始角色。使用以下命令生成迁移文件

php artisan batuta:install

可选地,如果您想修改参数(例如,laravel-batuta 将要创建的表名或初始角色名),您可以生成一个配置文件。您可以使用此命令完成此操作

php artisan batuta:config

这将生成配置文件到您的配置目录(config/batuta.php)。此配置文件包含每个参数的解释。所以,如果您想改变一些东西,在开始之前看看它。

一旦配置符合您的需求,就是时候运行迁移了。

php artisan migrate

恭喜,laravel-batuta 已安装并配置好,可以使用了!

BatutaBuilder

以下部分建议使用 BatutaBuilder。此类提供了一些管理 actionsroles 的辅助方法。重要的是要知道,所有这些方法在底层都直接使用 QueryBuilder,以避免实例化 Eloquent Models。这使得我们可以在 migration 文件中无任何问题地使用 BatutaBuilder

请注意,它们不会触发 Eloquent ORM 事件。如果您想使用 Eloquent ORM 的功能,请使用 Eloquen 提供的 create()delete() 方法来管理 actionsroles

操作

概念部分 中所述,操作代表用户可以对资源执行的操作。在前面的示例中,一个项的操作可以是,例如,createreadwrite。我们可以创建更具体的操作来限制授权,如:update-pricedeleteupdate-images

这些操作总是与一个 resource 相关联。因此,在这种情况下,这些 actions 的名称将是 create itemread itemwrite itemupdate-price itemupdate-images item 等...

创建和删除操作

所有这些操作都必须在 action 表中创建和持久化,才能使用。您可以使用 BatutaBuilder 辅助方法来创建操作。在下面的示例中,我们使用迁移文件,但您可以使用您喜欢的任何方法。

use Kodilab\LaravelBatuta\Builder\BatutaBuilder;

class CreateBatutaPermissionsTables extends Migration
{
    /**
     * Run the migrations.
     */
    public function up()
    {
        BatutaBuilder::createAction('update-price', 'item', 'Can change the item price')
    }

    /**
     * Reverse the migrations.
     */
    public function down()
    {
        BatutaBuilder::removeAction('update-price', 'item');
    }
}

public static function createAction(string $verb, string $resource, string $description = null)

创建一个新的操作。在创建之前,verbresource 将被 slugged。例如,如果 verb='update price' 和资源 Item,则生成的以下 action 为:

  • verb : 'update-price'
  • resource : 'item'
  • name : 'update-price item'

public static function removeAction(string $verb, string $resource = null)

根据操作的 verbresource 删除现有操作。

检索操作

public static function findByName(string $name)

根据名称检索操作

  • string $name: 操作的 name

返回

  • 操作实例或不存在时为 null
Actions::findByName('update-price item');

角色

角色是一组授予的权限。您可以给一个用户分配多个角色,也可以给一个角色分配多个用户(多对多关系)。默认情况下,当用户属于某个角色时,任何未为用户定义的权限将继承该角色的权限。例如,如果update-price item未在用户权限列表中定义,则会检查是否有任何角色授予了update-price item。这种行为可以针对任何用户和角色的案例进行更改(请参阅禁用权限继承)。

初始角色

默认情况下,当您运行migrations时,laravel-batuta会创建两个初始角色。您可以在运行迁移之前通过更改配置文件中的名称来自定义其角色名称。如果之后想要更改它,则可以通过更新模型或更改数据库中的内容来实现。

这些角色很重要,因为它们都有一些“特殊”的行为

  • 默认角色:默认角色将在创建用户或用户没有角色(至少,必须为用户分配一个角色)时默认分配给用户。这仅在您为用户模型启用角色时发生。此角色不能被删除。

  • 上帝角色:上帝角色是一个特殊角色。属于此角色的每个用户都将被授予执行任何操作的权利。无论您是否更改了该用户或该角色的权限。它将始终拥有全部授权权限。此角色不能被删除。

创建和删除角色

您可以使用BatutaBuilder来管理角色,就像创建操作一样。

use Kodilab\LaravelBatuta\Builder\BatutaBuilder;

class CreateBatutaPermissionsTables extends Migration
{
    /**
     * Run the migrations.
     */
    public function up()
    {
        BatutaBuilder::createRole('editor')
    }

    /**
     * Reverse the migrations.
     */
    public function down()
    {
        BatutaBuilder::removeRole('editor');
    }
}

createRole(string $name)

创建一个新的角色。

removeRole(string $verb, string $resource)

根据名称删除一个现有的角色。

分配和解除用户角色

为了分配角色给用户并解除它们,您必须将HasRoles特性添加到User模型中

class User extends Model
{
    use HasRoles;
}

添加此特性后,您可以使用以下方法

addRole(Role $role)

添加一个新角色,如果尚未添加,则添加到用户中。一旦角色被添加到用户中,它将继承该角色的权限。

  • Role $role:要分配的Role实例。
use Kodilab\LaravelBatuta\Models\Role;

...

$role = Role::find(1);

$user->addRole($role);

public function bulkRoles(array $roleIds, bool $detaching = false)

添加一组角色。

  • array $roleIds:包含Role ID的数组。
  • bool $detaching = false:如果detaching = true,则删除用户分配的先前角色。
$roles = [1, 2];

$user->bulkRoles($roles, true);

public function removeRole(Role $role)

从用户的分配中删除一个角色。

  • Role $role:要分配的Role实例。
$role = Role::find(1);

$user->addRole($role);
$user->removeRole($role);

public function belongsToRole(Role $role)

判断一个角色是否分配给用户

  • Role $role:要分配的Role实例。

返回

  • true:用户属于此角色
  • false:用户不属于此角色
$user->belongsToRole($other);

公共函数 isGod()

返回用户是否属于 god 角色: 返回:

  • true:用户属于 god 角色'
  • false:用户不属于 god 角色'
$user->isGod();

授予权限

尽管 Role 已经准备好使用,但还需要对 User 模型进行更改,以便为用户提供权限。您应该添加 UserPermissions 特性和实现 Permissionable 接口。

class User extends Model implements Permissionable
{
    use UserPermissions;
}

这将向 User 提供处理权限的新方法。

此处列出的方法可用于 RolesUsers

授予用户或角色的权限

updatePermission(Action $action, bool $grant): void

为特定操作授予用户/角色的权限。

  • Kodilab\LaravelBatuta\Models\Action|string $action:动作实例或动作名称
  • bool $granttrue|false
    use Kodilab\LaravelBatuta\Models\Action;

    ...

    $action = Action::findByName('update-price item');

    if (!is_null($action)) {
        $user->updatePermission($action, true);
    }

您可以使用动作 name 而不是动作实例

    $user->updatePermission('update-price item', true);

bulkPermissions(array $permissions, bool $detaching = false): void

为用户/角色授予多个权限。

  • array $permissions:关联数组,其中 key 是动作 idvaluetrue|false
  • bool $detaching = false:如果 detaching = true,则将删除分配给用户的先前权限。
   $permissions = [
       1 => true,
       2 => false
   ];

    $user->bulkPermissions($permissions, true);

检索用户或角色的权限

hasPermission(Action|string $action): bool

返回是否有权限。如果权限未定义,则返回 false。如果正在使用 hasRoles 特性,当权限未定义时,则将检查所属角色的权限。

  • Kodilab\LaravelBatuta\Models\Action|string $action:动作实例或动作名称

返回

  • true:用户可以执行该操作
  • false:用户 不能 执行该操作
    $action = Action::get('update-price item');

    if($user->hasPermission($action)) {
        $item->changePrice();
    }

禁用权限继承

有时您可能想要禁用权限继承(用户从其角色继承权限)。您可以通过添加方法 private function shouldInheritPermissions() 来做到这一点。该方法应根据您是否希望继承权限返回 truefalse。例如

class User extends... {
    ...

    private function shouldInheritPermissions()
    {
        if ($this->id === 1) {
            return false;
        }

        return true;
    }
}

id=1 的用户无论属于哪些角色都不会继承权限。其他用户将按预期继承权限。

重要:属于 god 角色的 用户将不受 shouldInheritPermissions() 方法的影响。