大美食品 / permissions
此包已被废弃且不再维护。没有建议的替代包。
2.0.1
2019-07-15 15:27 UTC
Requires
- php: >=7.1
- nette/security: ^2.4
- nette/utils: ^2.4
Requires (Dev)
- damejidlo/coding-standard: ^0.10.0
- mockery/mockery: ^1.2
- nette/tester: ^2.2
This package is auto-updated.
Last update: 2020-01-16 15:01:26 UTC
README
动机
此库的目的是为 isAllowed
评估添加特定于用户的数据。断言回调直接将 IUser
作为第一个参数传递。
这解决了Nette中本地ACL的最大“问题”
$callback = function (IUser $user, $queriedRole, $queriedResource) { return $user->getEntity()->getId() === $queriedResource->getEntity()->getCreatorId(); }; // god can destroy world, but only the one he created $authorizator->allow('god', 'world', 'destroy', $callback);
此库的另一个方面是将授权者与 Nette\Security\User
分离,因为这绝对不是用户的责任来提供此功能。
免责声明
此库被编写得尽可能类似于Nette中的 Permission
类。然而,规则的评估是从头开始编写的。
因此
- 不实现
Nette\Security\IAuthorizator
(由于不同的isAllowed
方法API,无法实现), - 可能会显著 较慢(但编写得很漂亮),
- 无法保证其行为完全相同。
安装
composer require damejidlo/permission
配置
AccessList
和 Neon
你自己的 AccessList
服务的示例实现。
class AccessList extends Authorizator { /** * @param string[][] $roles */ public function addRoles(array $roles) { foreach ($roles as $role => $parentRoles) { $this->addRole($role, $parentRoles); } } /** * @param @param string[] $resources */ public function addResources(array $resources) { foreach ($resources as $resource) { $this->addResource($resource); } } /** * @param string[][][] $directives */ public function addDirectives(array $directives) { foreach ($directives as $resource => $resourceDirectives) { foreach ($resourceDirectives as $privilege => $privilegeDirectives) { foreach ($privilegeDirectives as $roleIdentifier => $directiveType) { $this->createDirective($directiveType, $roleIdentifier, $resource, $privilege); } } } } public function someStuff() { $callback = function (IUser $user, $queriedRole, $queriedResource) { return $user->getEntity()->getId() === $queriedResource->getEntity()->getCreatorId(); }; // god can destroy world, but only the one he created $authorizator->allow('god', 'world', 'destroy', $callback); } }
然后只需将其添加到你的 config.neon
parameters: acl: roles: writer: [] reviewer: [writer] resources: - article directives: article: create: writer: allow publish: reviewer: allow services: acl: class: YourProject\Security\AccessList setup: - addRoles(%acl.roles%) - addResources(%acl.resources%) - addDirectives(%acl.directives%) - someStuff() # here we can do some "cool stuff"
创建你的 AclUser
class AclUser extends Object implements IUser { // Implement `getRoles` method }
创建你自己的 Nette\Security\User
你需要创建你自己的 User
服务
class MyLoggedUser extends \Nette\Security\User { /** * @param IUserStorage $storage * @param IAuthenticator|NULL $authenticator */ public function __construct(IUserStorage $storage, IAuthenticator $authenticator = NULL) { parent::__construct($storage, $authenticator); // No IAuthorizator here !!! } /** * @inheritdoc */ public function isAllowed($resource = IAuthorizator::ALL, $privilege = IAuthorizator::ALL) { throw new LogicException('Use Damejidlo\ACL\Authorizator directly. User shouldn\'t have such a responsibility'); } /** * @inheritdoc */ public function isInRole($role) { throw new LogicException('Use Damejidlo\ACL\Authorizator directly. User shouldn\'t have such a responsibility'); } /** * @return AclUser */ public function getAclUser() { $entity = $this->getEntity(); // depens on your implementation return new AclUser($entity, $this->getRoles()); } }
services: user: Some\Namespace\MyLoggedUser
将你的授权者加载到模板中
最好的方法是创建你自己的 TemplateFactory
。然后在 createTemplate
方法中调用
/** * @param Control|NULL $control * @return Template */ public function createTemplate(Control $control = NULL) { $template = parent::createTemplate($control); // Some stuff (helper registration, etc...) $template->setParameters([ 'authorizator' => $this->authorizator, ]); return $template; }
用法
现在,开始获利!
// In some Presenter public function handleDestroy($worldId) { $world = $this->worldFinder->findWorld($worldId); $resource = new WorldResource($world); $permission = 'destroy'; if (!$this->authorizator->isAllowed($this->user->getAclUser(), $resource, $permission) { throw new NotAllowedException($resource, $permission); } }