From 0e17d652dc4dd94fe93b7909df117cedf6758374 Mon Sep 17 00:00:00 2001 From: Misbahul D Munir Date: Tue, 5 Apr 2016 04:52:04 +0700 Subject: [PATCH] Enhanced RBAC Rule assignment * #11254 Enhanced RBAC Rule assignment * Enhanced RBAC Rule assignment --- framework/CHANGELOG.md | 1 + framework/rbac/BaseManager.php | 10 +++++ tests/framework/rbac/ActionRule.php | 16 ++++++++ tests/framework/rbac/ManagerTestCase.php | 64 ++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+) create mode 100644 tests/framework/rbac/ActionRule.php diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 9ca353c..49faf33 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -48,6 +48,7 @@ Yii Framework 2 Change Log - Enh #11137: Added weak ETag support to `yii\filters\HttpCache`. It could be turned on via setting `$weakEtag` to `true` (particleflux) - Enh #11139: `yii\validators\EachValidator` injects specific attribute value in error message parameters (silverfire) - Enh #11187: migrate command now generates phpdoc for table migrations (Faryshta) +- Enh #11254: Added ability to attach RBAC rule using class name (mdmunir) - Enh: Added `StringHelper::countWords()` that given a string returns number of words in it (samdark) - Chg: HTMLPurifier dependency updated to `~4.6` (samdark) - Chg #10726: Added `yii\rbac\ManagerInterface::canAddChild()` (dkhlystov, samdark) diff --git a/framework/rbac/BaseManager.php b/framework/rbac/BaseManager.php index d9c0c03..666b0df 100644 --- a/framework/rbac/BaseManager.php +++ b/framework/rbac/BaseManager.php @@ -115,6 +115,11 @@ abstract class BaseManager extends Component implements ManagerInterface public function add($object) { if ($object instanceof Item) { + if ($object->ruleName && $this->getRule($object->ruleName) === null) { + $rule = \Yii::createObject($object->ruleName); + $rule->name = $object->ruleName; + $this->addRule($rule); + } return $this->addItem($object); } elseif ($object instanceof Rule) { return $this->addRule($object); @@ -143,6 +148,11 @@ abstract class BaseManager extends Component implements ManagerInterface public function update($name, $object) { if ($object instanceof Item) { + if ($object->ruleName && $this->getRule($object->ruleName) === null) { + $rule = \Yii::createObject($object->ruleName); + $rule->name = $object->ruleName; + $this->addRule($rule); + } return $this->updateItem($name, $object); } elseif ($object instanceof Rule) { return $this->updateRule($name, $object); diff --git a/tests/framework/rbac/ActionRule.php b/tests/framework/rbac/ActionRule.php new file mode 100644 index 0000000..2db99f4 --- /dev/null +++ b/tests/framework/rbac/ActionRule.php @@ -0,0 +1,16 @@ +action === 'all' || $this->action === $params['action']; + } +} diff --git a/tests/framework/rbac/ManagerTestCase.php b/tests/framework/rbac/ManagerTestCase.php index f6978fd..1c38bae 100644 --- a/tests/framework/rbac/ManagerTestCase.php +++ b/tests/framework/rbac/ManagerTestCase.php @@ -387,4 +387,68 @@ abstract class ManagerTestCase extends TestCase $this->assertNotEmpty($this->auth->getRules()); $this->assertNotEmpty($this->auth->getRoles()); } + + public function testAssignRule() + { + $auth = $this->auth; + $userId = 3; + + $auth->removeAll(); + $role = $auth->createRole('Admin'); + $auth->add($role); + $auth->assign($role, $userId); + $this->assertTrue($auth->checkAccess($userId, 'Admin')); + + // with normal register rule + $auth->removeAll(); + $rule = new ActionRule(); + $auth->add($rule); + $role = $auth->createRole('Reader'); + $role->ruleName = $rule->name; + $auth->add($role); + $auth->assign($role, $userId); + $this->assertTrue($auth->checkAccess($userId, 'Reader', ['action' => 'read'])); + $this->assertFalse($auth->checkAccess($userId, 'Reader', ['action' => 'write'])); + + // using rule class name + $auth->removeAll(); + $role = $auth->createRole('Reader'); + $role->ruleName = 'yiiunit\framework\rbac\ActionRule'; + $auth->add($role); + $auth->assign($role, $userId); + $this->assertTrue($auth->checkAccess($userId, 'Reader', ['action' => 'read'])); + $this->assertFalse($auth->checkAccess($userId, 'Reader', ['action' => 'write'])); + + // using DI + \Yii::$container->set('write_rule', ['class' => 'yiiunit\framework\rbac\ActionRule', 'action' => 'write']); + \Yii::$container->set('delete_rule', ['class' => 'yiiunit\framework\rbac\ActionRule', 'action' => 'delete']); + \Yii::$container->set('all_rule', ['class' => 'yiiunit\framework\rbac\ActionRule', 'action' => 'all']); + + $role = $auth->createRole('Writer'); + $role->ruleName = 'write_rule'; + $auth->add($role); + $auth->assign($role, $userId); + $this->assertTrue($auth->checkAccess($userId, 'Writer', ['action' => 'write'])); + $this->assertFalse($auth->checkAccess($userId, 'Writer', ['action' => 'update'])); + + $role = $auth->createRole('Deleter'); + $role->ruleName = 'delete_rule'; + $auth->add($role); + $auth->assign($role, $userId); + $this->assertTrue($auth->checkAccess($userId, 'Deleter', ['action' => 'delete'])); + $this->assertFalse($auth->checkAccess($userId, 'Deleter', ['action' => 'update'])); + + $role = $auth->createRole('Author'); + $role->ruleName = 'all_rule'; + $auth->add($role); + $auth->assign($role, $userId); + $this->assertTrue($auth->checkAccess($userId, 'Author', ['action' => 'update'])); + + // update role and rule + $role = $auth->getRole('Reader'); + $role->name = 'AdminPost'; + $role->ruleName = 'all_rule'; + $auth->update('Reader', $role); + $this->assertTrue($auth->checkAccess($userId, 'AdminPost', ['action' => 'print'])); + } }