thomas-miceli / voters
检查和验证复杂的特定用户权限。
1.0
2021-04-28 22:18 UTC
Requires
- php: >=7.4
Requires (Dev)
- phpunit/phpunit: ^9.2
This package is auto-updated.
Last update: 2024-09-29 05:36:36 UTC
README
有助于检查复杂的用户权限。
灵感来源于 Symfony 投票系统。
安装
$ composer require thomas-miceli/voters
使用
要检查用户动作(例如查看或编辑)的特定权限 $attribute(例如文章),无论是否有 $subject(例如文章),每个注册的投票者都会被调用,并检查他们是否可以对该权限进行投票。每个有资格的投票者都会投票决定用户是否可以拥有该权限。
为我们的博客设置权限。
创建权限对象
<?php $permission = new \ThomasMiceli\Voter\Permission; $permission->addVoter(new ArticleVoter); // register the voter for this permission object $user = ... $article = ... $permission->can($user, ArticleVoter::VIEW, $article); // check if our user can view the article $permission->can($user, ArticleVoter::EDIT, $article); // check if our user can edit the article
创建投票者
<?php /* This voter determine what the user can do with an article from our blog. */ class ArticleVoter implements \ThomasMiceli\Voter\Voter { const VIEW = 'view'; const EDIT = 'edit'; // if the voter can vote for the requested attribute... public function canVote(string $attribute, $subject = null): bool { return in_array($attribute, [self::EDIT, self::VIEW]) && $subject instanceof Article; } // ...if yes, the voter will determinate and return the permission for this attribute public function vote(?\ThomasMiceli\Voter\VoterUser $user, string $attribute, $subject = null): bool { /** @var Article $subject */ switch ($attribute) { // if the user is connected, he can read the article case self::VIEW: return $user !== null; // if the user is the author, he can modify the article case self::EDIT: return $subject->getAuthor() === $user; } // the user has not the permission for other attributes return false; } }
策略
当多个投票者有资格对属性进行投票时,可以设置不同的策略来决定权限。
<?php $permission = new \ThomasMiceli\Voter\Permission(new \ThomasMiceli\Voter\Strategy\AffirmativeStrategy); // default strategy // $permission::can() returns true if at least one of the registered voters approved the attribute $permission = new \ThomasMiceli\Voter\Permission(new \ThomasMiceli\Voter\Strategy\VetoStrategy); // $permission::can() returns true if all the registered voters approved the attribute $permission = new \ThomasMiceli\Voter\Permission(new \ThomasMiceli\Voter\Strategy\MajorityStrategy); // $permission::can() returns true if at least half plus one of the registered voters approved the attribute
我们可以使用工厂静态方法以获得更好的可读性。
<?php $permission = \ThomasMiceli\Voter\Permission::affirmative(); $permission = \ThomasMiceli\Voter\Permission::veto(); $permission = \ThomasMiceli\Voter\Permission::majority();
我们可以创建自己的策略,并将其设置到权限中...
<?php class CustomStrategy implements \ThomasMiceli\Voter\Strategy\VoterStrategy { // the permission is granted if at least 4 voters voted true for an attribute public function can(?\ThomasMiceli\Voter\VoterUser $user, array $voters, string $attribute, $subject): bool { $approvals = 0; foreach ($voters as $voter) { if ($voter->canVote($attribute, $subject)) { $vote = $voter->vote($user, $attribute, $subject); //ConsoleLogger::debug($voter, $vote, $attribute, $user, $subject); if ($vote) { ++$approvals; } } } return $approvals > 3; } }
...然后使用它。
<?php $permission = new \ThomasMiceli\Voter\Permission(new CustomStrategy);
我们甚至可以轻松创建通用的投票者,允许定义应该有多少投票者批准属性。
<?php $permission = new \ThomasMiceli\Voter\Permission(new \ThomasMiceli\Voter\Strategy\GenericStrategy(40, 5)); $permission = \ThomasMiceli\Voter\Permission::generic(40, 5); // at least 40% and 5 voters should have approved the attribute