gecche/laravel-policy-builder
构建Eloquent模型允许列表(acl)的简单方法
Requires
- laravel/framework: ^11.0
Requires (Dev)
- codedungeon/phpunit-result-printer: ^0.1.0
- laravel/legacy-factories: ^1.0.4
- mockery/mockery: ^1.6
- orchestra/testbench: ^9.0
- orchestra/testbench-browser-kit: ^9.0
- phpunit/phpunit: ^10.5
This package is not auto-updated.
Last update: 2024-09-17 18:22:58 UTC
README
laravel-policy-builder
根据策略构建Eloquent模型允许列表的简单方便方式。
描述
在许多应用程序中,您使用Laravel的策略来检查用户是否有权处理资源。通常,在这些应用程序中,您还必须根据策略获取允许的资源列表。
使用此包,您将过滤资源列表的业务逻辑直接存储在策略中,并且当使用Eloquent Builder时,通过简单调用方法 acl
来获取此类列表。
文档
版本兼容性
安装
将 gecche/laravel-policy-builder 添加到 composer.json 的需求中
{ "require": { "gecche/laravel-policy-builder": "11.*" } }
此包使用了发现功能。
基本用法
在策略中定义构建模型允许列表的业务逻辑
假设我们有一个 Author
模型类和一个标准的 AuthorPolicy
类来定义能力方法,就像通常一样。
只需直接在 AuthorPolicy
类中添加过滤Author列表的业务逻辑。例如。
class AuthorPolicy { use HandlesAuthorization; /** * * - All authors are allowed to users 1 and 2 * - Only italian authors are allowed to users 3 and 4 * - Only non-italian authors are allowed to other users * * @param \Illuminate\Contracts\Auth\Authenticatable|null $user * @param Builder $builder * @return mixed */ public function acl($user, $builder) { switch ($user->getKey()) { case 1: case 2: return $builder; case 3: case 4: return $builder->where('nation','IT'); default: return $builder->where('nation','<>','IT'); } }
获取用户的允许模型列表
现在,要获取当前认证用户的允许作者列表,只需这样做
Author::acl()->get();
如果您想获取用户3的列表,只需这样做
$userForAcl = User::find(3); Code::acl($userForAcl)->get();
现在列表只返回意大利作者。
默认列表
让我们考虑另一个 Book
模型,对于该模型,其 BookPolicy
中没有定义 acl
方法,或者根本没有 BookPolicy
。
如果我们这样做
Book::acl()->get();
我们为任何用户获取空白的模型列表。
超越基本用法
安装后,除了 acl
Eloquent Builder 宏之外,该包还提供了 PolicyBuilderServiceProvider
(包括 PolicyBuilder
面具),它执行将Eloquent Builder与策略链接的基础机制(通过包装Laravel的 Gate
提供程序),并提供了一些有用的方法。
基本默认构建方法: all
和 none
PolicyBuilder有两个公开方法,即 all
和 none
,它们基本上分别返回所有可用的模型列表(没有任何过滤器)和空列表。
可以通过使用 setAllBuilder
和 setNoneBuilder
方法自定义上述方法的返回值。
在以下示例中,我们使用 PolicyBuilder 的 all
方法更改了之前的 AuthorPolicy
类
但是,我们保留了之前的相同语义。
use Gecche\PolicyBuilder\Facades\PolicyBuilder; use App\Models\Author; class AuthorPolicy { use HandlesAuthorization; /** * * - All authors are allowed to users 1 and 2 * - Only italian authors are allowed to users 3 and 4 * - Only non-italian authors are allowed to other users * * @param \Illuminate\Contracts\Auth\Authenticatable|null $user * @param Builder $builder * @return mixed */ public function acl($user, $builder) { switch ($user->getKey()) { case 1: case 2: return PolicyBuilder::all($builder,Author::class); case 3: case 4: return $builder->where('nation','IT'); default: return $builder->where('nation','<>','IT'); } }
像之前一样,对于用户1和2,如果我们这样做,将返回所有作者的完整列表
Author::acl()->get();
但是,我们可以为PolicyBuilder的 all
方法设置全局不同的语义,例如。
PolicyBuilder::setAllBuilder(function ($builder,$modelClassName = null) { if ($modelClassName == Author::class) { return $builder->where('id','<>',1); } return $builder; });
在上面的示例中,当调用 all
方法时,作者列表中缺少id为1的作者。
同样可以与PolicyBuilder的 none
方法一起使用。
更改“上下文”
通常,用户要么可以访问某个模型,要么不能。但是,在某些“上下文”下,我们需要构建一个与标准列表不同的允许模型列表。
例如,用户可以查看图书馆中所有 Author
模型的完整列表,但不能编辑所有模型。因此,我们还想构建一个用户可以编辑的书籍列表,并且我们将改为使用具有不同业务逻辑的 editing
“上下文”来构建列表。
在这种情况下,只需将“上下文”传递给构建器即可。
//returning the 'editing' list for the authenticated user Author::acl(null,'editing')->get(); //or returning the 'editing' list for user 2 $userForAcl = User::find(2); Author::acl($userForAcl,'editing')->get();
在 AuthorPolicy 中,您必须根据之前为 acl
定义的 aclEditing
方法进行相应的定义。
beforeAcl
策略构建器和策略方法
类似于 Laravel 的 Gate before
方法,PolicyBuilder 有一个 beforeAcl
方法用于注册“beforeAcl”回调。如果注册的回调返回一个 Eloquent Builder,则不需要进一步详细说明,因此不需要任何策略。例如:
/* * - For user 1 (superuser) it returns the full list of models for any model and context * - For all the other registerd users, it returns the full list of models for Book */ PolicyBuilder::beforeAcl(function ($user, $modelClassName, $context, $builder) { if (!$user) { return; } if ($user->getKey() == 1 || $modelClassName == Book::class) { return PolicyBuilder::all($builder,$modelClassName); } return; });
可以在单个策略中放置一个非常相似的 beforeAcl
方法,它将在策略中定义的其他方法之前由 PolicyBuilderServiceProvider
处理。
use Gecche\PolicyBuilder\Facades\PolicyBuilder; use App\Models\Author; class AuthorPolicy { use HandlesAuthorization; public function beforeAcl($user, $context, $builder) { if (is_null($user)) { return PolicyBuilder::none($builder,Author::class); } return null; } ...
在上面的示例中,访客用户对作者没有任何访问权限。