Commit 69786b01 by Alexander Makarov

Merge pull request #2974 from yiisoft/decouple-bizrules-from-auth-items

RBAC: decoupled rules from assignments and items, implemented php manager
parents c5ad45c7 57498582
......@@ -121,24 +121,47 @@ class PhpManager extends \yii\rbac\PhpManager
}
```
Now create custom rule class:
```php
namespace app\rbac;
use yii\rbac\Rule;
class NotGuestRule extends Rule
{
public function execute($params, $data)
{
return !Yii::$app->user->isGuest;
}
}
```
Then create permissions hierarchy in `@app/data/rbac.php`:
```php
<?php
use yii\rbac\Item;
use app\rbac\NotGuestRule;
$notGuest = new NotGuestRule();
return [
'rules' => [
$rule->name => serialize($notGuest),
],
'items' => [
// HERE ARE YOUR MANAGEMENT TASKS
'manageThing0' => ['type' => Item::TYPE_OPERATION, 'description' => '...', 'bizRule' => NULL, 'data' => NULL],
'manageThing1' => ['type' => Item::TYPE_OPERATION, 'description' => '...', 'bizRule' => NULL, 'data' => NULL],
'manageThing2' => ['type' => Item::TYPE_OPERATION, 'description' => '...', 'bizRule' => NULL, 'data' => NULL],
'manageThing3' => ['type' => Item::TYPE_OPERATION, 'description' => '...', 'bizRule' => NULL, 'data' => NULL],
'manageThing0' => ['type' => Item::TYPE_OPERATION, 'description' => '...', 'ruleName' => NULL, 'data' => NULL],
'manageThing1' => ['type' => Item::TYPE_OPERATION, 'description' => '...', 'ruleName' => NULL, 'data' => NULL],
'manageThing2' => ['type' => Item::TYPE_OPERATION, 'description' => '...', 'ruleName' => NULL, 'data' => NULL],
'manageThing3' => ['type' => Item::TYPE_OPERATION, 'description' => '...', 'ruleName' => NULL, 'data' => NULL],
// AND THE ROLES
'guest' => [
'type' => Item::TYPE_ROLE,
'description' => 'Guest',
'bizRule' => NULL,
'ruleName' => NULL,
'data' => NULL
],
......@@ -149,7 +172,7 @@ return [
'guest',
'manageThing0', // User can edit thing0
],
'bizRule' => 'return !Yii::$app->user->isGuest;',
'ruleName' => $notGuest->name,
'data' => NULL
],
......@@ -160,7 +183,7 @@ return [
'user', // Can manage all that user can
'manageThing1', // and also thing1
],
'bizRule' => NULL,
'ruleName' => NULL,
'data' => NULL
],
......@@ -171,7 +194,7 @@ return [
'moderator', // can do all the stuff that moderator can
'manageThing2', // and also manage thing2
],
'bizRule' => NULL,
'ruleName' => NULL,
'data' => NULL
],
......@@ -182,10 +205,10 @@ return [
'admin', // can do all that admin can
'manageThing3', // and also thing3
],
'bizRule' => NULL,
'ruleName' => NULL,
'data' => NULL
],
],
];
```
......
......@@ -79,6 +79,7 @@ Yii Framework 2 Change Log
- Enh #46: Added Image extension based on [Imagine library](http://imagine.readthedocs.org) (tonydspaniard)
- Enh #364: Improve Inflector::slug with `intl` transliteration. Improved transliteration char map. (tonydspaniard)
- Enh #497: Removed `\yii\log\Target::logUser` and added `\yii\log\Target::prefix` to support customizing message prefix (qiangxue)
- Enh #499: Decoupled `Rule` from RBAC `Item` (samdark, qiangxue)
- Enh #797: Added support for validating multiple columns by `UniqueValidator` and `ExistValidator` (qiangxue)
- Enh #802: Added support for retrieving sub-array element or child object property through `ArrayHelper::getValue()` (qiangxue, cebe)
- Enh #938: Added `yii\web\View::renderAjax()` and `yii\web\Controller::renderAjax()` (qiangxue)
......
......@@ -27,9 +27,9 @@ class Assignment extends Object
*/
public $manager;
/**
* @var string the business rule associated with this assignment
* @var string name of the rule associated with this assignment
*/
public $bizRule;
public $ruleName;
/**
* @var mixed additional data for this assignment
*/
......
......@@ -38,19 +38,27 @@ class DbManager extends Manager
* with a DB connection object.
*/
public $db = 'db';
/**
* @var string the name of the table storing authorization items. Defaults to 'auth_item'.
* @var string the name of the table storing authorization items. Defaults to "auth_item".
*/
public $itemTable = '{{%auth_item}}';
/**
* @var string the name of the table storing authorization item hierarchy. Defaults to 'auth_item_child'.
* @var string the name of the table storing authorization item hierarchy. Defaults to "auth_item_child".
*/
public $itemChildTable = '{{%auth_item_child}}';
/**
* @var string the name of the table storing authorization item assignments. Defaults to 'auth_assignment'.
* @var string the name of the table storing authorization item assignments. Defaults to "auth_assignment".
*/
public $assignmentTable = '{{%auth_assignment}}';
/**
* @var string the name of the table storing rules. Defaults to "auth_rule".
*/
public $ruleTable = '{{%auth_rule}}';
private $_usingSqlite;
/**
......@@ -69,7 +77,7 @@ class DbManager extends Manager
* @param mixed $userId the user ID. This should can be either an integer or a string representing
* the unique identifier of a user. See [[\yii\web\User::id]].
* @param string $itemName the name of the operation that need access check
* @param array $params name-value pairs that would be passed to biz rules associated
* @param array $params name-value pairs that would be passed to rules associated
* with the tasks and roles assigned to the user. A param with name 'userId' is added to this array,
* which holds the value of `$userId`.
* @return boolean whether the operations can be performed by the user.
......@@ -87,7 +95,7 @@ class DbManager extends Manager
* @param mixed $userId the user ID. This should can be either an integer or a string representing
* the unique identifier of a user. See [[\yii\web\User::id]].
* @param string $itemName the name of the operation that need access check
* @param array $params name-value pairs that would be passed to biz rules associated
* @param array $params name-value pairs that would be passed to rules associated
* with the tasks and roles assigned to the user. A param with name 'userId' is added to this array,
* which holds the value of `$userId`.
* @param Assignment[] $assignments the assignments to the specified user
......@@ -102,13 +110,13 @@ class DbManager extends Manager
if (!isset($params['userId'])) {
$params['userId'] = $userId;
}
if ($this->executeBizRule($item->bizRule, $params, $item->data)) {
if ($this->executeRule($item->ruleName, $params, $item->data)) {
if (in_array($itemName, $this->defaultRoles)) {
return true;
}
if (isset($assignments[$itemName])) {
$assignment = $assignments[$itemName];
if ($this->executeBizRule($assignment->bizRule, $params, $assignment->data)) {
if ($this->executeRule($assignment->ruleName, $params, $assignment->data)) {
return true;
}
}
......@@ -208,7 +216,7 @@ class DbManager extends Manager
public function getItemChildren($names)
{
$query = new Query;
$rows = $query->select(['name', 'type', 'description', 'biz_rule', 'data'])
$rows = $query->select(['name', 'type', 'description', 'rule_name', 'data'])
->from([$this->itemTable, $this->itemChildTable])
->where(['parent' => $names, 'name' => new Expression('child')])
->createCommand($this->db)
......@@ -223,7 +231,7 @@ class DbManager extends Manager
'name' => $row['name'],
'type' => $row['type'],
'description' => $row['description'],
'bizRule' => $row['biz_rule'],
'ruleName' => $row['rule_name'],
'data' => $data,
]);
}
......@@ -233,15 +241,16 @@ class DbManager extends Manager
/**
* Assigns an authorization item to a user.
*
* @param mixed $userId the user ID (see [[\yii\web\User::id]])
* @param string $itemName the item name
* @param string $bizRule the business rule to be executed when [[checkAccess()]] is called
* @param string $ruleName the business rule to be executed when [[checkAccess()]] is called
* for this particular authorization item.
* @param mixed $data additional data associated with this assignment
* @return Assignment the authorization assignment information.
* @throws InvalidParamException if the item does not exist or if the item has already been assigned to the user
*/
public function assign($userId, $itemName, $bizRule = null, $data = null)
public function assign($userId, $itemName, $ruleName = null, $data = null)
{
if ($this->usingSqlite() && $this->getItem($itemName) === null) {
throw new InvalidParamException("The item '$itemName' does not exist.");
......@@ -250,7 +259,7 @@ class DbManager extends Manager
->insert($this->assignmentTable, [
'user_id' => $userId,
'item_name' => $itemName,
'biz_rule' => $bizRule,
'rule_name' => $ruleName,
'data' => $data === null ? null : serialize($data),
])
->execute();
......@@ -259,7 +268,7 @@ class DbManager extends Manager
'manager' => $this,
'userId' => $userId,
'itemName' => $itemName,
'bizRule' => $bizRule,
'ruleName' => $ruleName,
'data' => $data,
]);
}
......@@ -329,7 +338,7 @@ class DbManager extends Manager
'manager' => $this,
'userId' => $row['user_id'],
'itemName' => $row['item_name'],
'bizRule' => $row['biz_rule'],
'ruleName' => $row['rule_name'],
'data' => $data,
]);
} else {
......@@ -359,7 +368,7 @@ class DbManager extends Manager
'manager' => $this,
'userId' => $row['user_id'],
'itemName' => $row['item_name'],
'bizRule' => $row['biz_rule'],
'ruleName' => $row['rule_name'],
'data' => $data,
]);
}
......@@ -371,11 +380,11 @@ class DbManager extends Manager
* Saves the changes to an authorization assignment.
* @param Assignment $assignment the assignment that has been changed.
*/
public function saveAssignment($assignment)
public function saveAssignment(Assignment $assignment)
{
$this->db->createCommand()
->update($this->assignmentTable, [
'biz_rule' => $assignment->bizRule,
'rule_name' => $assignment->ruleName,
'data' => $assignment->data === null ? null : serialize($assignment->data),
], [
'user_id' => $assignment->userId,
......@@ -403,12 +412,12 @@ class DbManager extends Manager
->where(['type' => $type])
->createCommand($this->db);
} elseif ($type === null) {
$command = $query->select(['name', 'type', 'description', 't1.biz_rule', 't1.data'])
$command = $query->select(['name', 'type', 'description', 't1.rule_name', 't1.data'])
->from([$this->itemTable . ' t1', $this->assignmentTable . ' t2'])
->where(['user_id' => $userId, 'name' => new Expression('item_name')])
->createCommand($this->db);
} else {
$command = $query->select(['name', 'type', 'description', 't1.biz_rule', 't1.data'])
$command = $query->select(['name', 'type', 'description', 't1.rule_name', 't1.data'])
->from([$this->itemTable . ' t1', $this->assignmentTable . ' t2'])
->where(['user_id' => $userId, 'type' => $type, 'name' => new Expression('item_name')])
->createCommand($this->db);
......@@ -423,7 +432,7 @@ class DbManager extends Manager
'name' => $row['name'],
'type' => $row['type'],
'description' => $row['description'],
'bizRule' => $row['biz_rule'],
'ruleName' => $row['rule_name'],
'data' => $data,
]);
}
......@@ -437,23 +446,24 @@ class DbManager extends Manager
* It has three types: operation, task and role.
* Authorization items form a hierarchy. Higher level items inheirt permissions representing
* by lower level items.
*
* @param string $name the item name. This must be a unique identifier.
* @param integer $type the item type (0: operation, 1: task, 2: role).
* @param string $description description of the item
* @param string $bizRule business rule associated with the item. This is a piece of
* @param string $rule business rule associated with the item. This is a piece of
* PHP code that will be executed when [[checkAccess()]] is called for the item.
* @param mixed $data additional data associated with the item.
* @return Item the authorization item
* @throws Exception if an item with the same name already exists
*/
public function createItem($name, $type, $description = '', $bizRule = null, $data = null)
public function createItem($name, $type, $description = '', $rule = null, $data = null)
{
$this->db->createCommand()
->insert($this->itemTable, [
'name' => $name,
'type' => $type,
'description' => $description,
'biz_rule' => $bizRule,
'rule_name' => $rule,
'data' => $data === null ? null : serialize($data),
])
->execute();
......@@ -463,7 +473,7 @@ class DbManager extends Manager
'name' => $name,
'type' => $type,
'description' => $description,
'bizRule' => $bizRule,
'ruleName' => $rule,
'data' => $data,
]);
}
......@@ -512,7 +522,7 @@ class DbManager extends Manager
'name' => $row['name'],
'type' => $row['type'],
'description' => $row['description'],
'bizRule' => $row['biz_rule'],
'ruleName' => $row['rule_name'],
'data' => $data,
]);
} else {
......@@ -525,7 +535,7 @@ class DbManager extends Manager
* @param Item $item the item to be saved.
* @param string $oldName the old item name. If null, it means the item name is not changed.
*/
public function saveItem($item, $oldName = null)
public function saveItem(Item $item, $oldName = null)
{
if ($this->usingSqlite() && $oldName !== null && $item->getName() !== $oldName) {
$this->db->createCommand()
......@@ -544,7 +554,7 @@ class DbManager extends Manager
'name' => $item->getName(),
'type' => $item->type,
'description' => $item->description,
'biz_rule' => $item->bizRule,
'rule_name' => $item->ruleName,
'data' => $item->data === null ? null : serialize($item->data),
], [
'name' => $oldName === null ? $item->getName() : $oldName,
......@@ -604,4 +614,67 @@ class DbManager extends Manager
{
return $this->_usingSqlite;
}
/**
* Removes the specified rule.
*
* @param string $name the name of the rule to be removed
* @return boolean whether the rule exists in the storage and has been removed
*/
public function removeRule($name)
{
return $this->db->createCommand()->delete($this->ruleTable, ['name' => $name])->execute();
}
/**
* Saves the changes to the rule.
*
* @param Rule $rule the rule that has been changed.
*/
public function insertRule(Rule $rule)
{
$this->db->createCommand()->insert($this->ruleTable, ['name' => $rule->name, 'data' => serialize($rule)])->execute();
}
/**
* Updates existing rule.
*
* @param string $name the name of the rule to update
* @param Rule $rule new rule
*/
public function updateRule($name, Rule $rule)
{
$this->db->createCommand()->update($this->ruleTable, ['name' => $rule->name, 'data' => serialize($rule)], ['name' => $name])->execute();
}
/**
* Returns rule given its name.
*
* @param string $name name of the rule.
* @return Rule
*/
public function getRule($name)
{
$query = new Query;
$query->select(['data'])->from($this->ruleTable)->where(['name' => $name]);
$row = $query->createCommand($this->db)->queryOne();
return $row === false ? null : unserialize($row['data']);
}
/**
* Returns all rules.
*
* @return Rule[]
*/
public function getRules()
{
$query = new Query();
$rows = $query->from($this->ruleTable)->createCommand($this->db)->queryAll();
$rules = [];
foreach ($rows as $row) {
$rules[$row['name']] = unserialize($row['data']);
}
return $rules;
}
}
......@@ -40,9 +40,9 @@ class Item extends Object
*/
public $description;
/**
* @var string the business rule associated with this item
* @var string name of the rule associated with this item
*/
public $bizRule;
public $ruleName;
/**
* @var mixed the additional data associated with this item
*/
......@@ -66,7 +66,7 @@ class Item extends Object
public function checkAccess($itemName, $params = [])
{
Yii::trace('Checking permission: ' . $this->_name, __METHOD__);
if ($this->manager->executeBizRule($this->bizRule, $params, $this->data)) {
if ($this->manager->executeRule($this->ruleName, $params, $this->data)) {
if ($this->_name == $itemName) {
return true;
}
......@@ -146,17 +146,18 @@ class Item extends Object
/**
* Assigns this item to a user.
*
* @param mixed $userId the user ID (see [[\yii\web\User::id]])
* @param string $bizRule the business rule to be executed when [[checkAccess()]] is called
* @param Rule $rule the rule to be executed when [[checkAccess()]] is called
* for this particular authorization item.
* @param mixed $data additional data associated with this assignment
* @return Assignment the authorization assignment information.
* @throws \yii\base\Exception if the item has already been assigned to the user
* @see Manager::assign
*/
public function assign($userId, $bizRule = null, $data = null)
public function assign($userId, Rule $rule = null, $data = null)
{
return $this->manager->assign($userId, $this->_name, $bizRule, $data);
return $this->manager->assign($userId, $this->_name, $rule, $data);
}
/**
......
......@@ -44,17 +44,12 @@ use yii\base\InvalidParamException;
abstract class Manager extends Component
{
/**
* @var boolean Enable error reporting for bizRules.
*/
public $showErrors = false;
/**
* @var array list of role names that are assigned to all users implicitly.
* These roles do not need to be explicitly assigned to any user.
* When calling [[checkAccess()]], these roles will be checked first.
* For performance reason, you should minimize the number of such roles.
* A typical usage of such roles is to define an 'authenticated' role and associate
* it with a biz rule which checks if the current user is authenticated.
* it with a rule which checks if the current user is authenticated.
* And then declare 'authenticated' in this property so that it can be applied to
* every authenticated user.
*/
......@@ -63,48 +58,52 @@ abstract class Manager extends Component
/**
* Creates a role.
* This is a shortcut method to [[Manager::createItem()]].
*
* @param string $name the item name
* @param string $description the item description.
* @param string $bizRule the business rule associated with this item
* @param string $ruleName name of the rule associated with this item
* @param mixed $data additional data to be passed when evaluating the business rule
* @return Item the authorization item
*/
public function createRole($name, $description = '', $bizRule = null, $data = null)
public function createRole($name, $description = '', $ruleName = null, $data = null)
{
return $this->createItem($name, Item::TYPE_ROLE, $description, $bizRule, $data);
return $this->createItem($name, Item::TYPE_ROLE, $description, $ruleName, $data);
}
/**
* Creates a task.
* This is a shortcut method to [[Manager::createItem()]].
*
* @param string $name the item name
* @param string $description the item description.
* @param string $bizRule the business rule associated with this item
* @param string $ruleName name of the rule associated with this item
* @param mixed $data additional data to be passed when evaluating the business rule
* @return Item the authorization item
*/
public function createTask($name, $description = '', $bizRule = null, $data = null)
public function createTask($name, $description = '', $ruleName = null, $data = null)
{
return $this->createItem($name, Item::TYPE_TASK, $description, $bizRule, $data);
return $this->createItem($name, Item::TYPE_TASK, $description, $ruleName, $data);
}
/**
* Creates an operation.
* This is a shortcut method to [[Manager::createItem()]].
*
* @param string $name the item name
* @param string $description the item description.
* @param string $bizRule the business rule associated with this item
* @param string $ruleName name of the rule associated with this item
* @param mixed $data additional data to be passed when evaluating the business rule
* @return Item the authorization item
*/
public function createOperation($name, $description = '', $bizRule = null, $data = null)
public function createOperation($name, $description = '', $ruleName = null, $data = null)
{
return $this->createItem($name, Item::TYPE_OPERATION, $description, $bizRule, $data);
return $this->createItem($name, Item::TYPE_OPERATION, $description, $ruleName, $data);
}
/**
* Returns roles.
* This is a shortcut method to [[Manager::getItems()]].
*
* @param mixed $userId the user ID. If not null, only the roles directly assigned to the user
* will be returned. Otherwise, all roles will be returned.
* @return Item[] roles (name => AuthItem)
......@@ -117,6 +116,7 @@ abstract class Manager extends Component
/**
* Returns tasks.
* This is a shortcut method to [[Manager::getItems()]].
*
* @param mixed $userId the user ID. If not null, only the tasks directly assigned to the user
* will be returned. Otherwise, all tasks will be returned.
* @return Item[] tasks (name => AuthItem)
......@@ -129,6 +129,7 @@ abstract class Manager extends Component
/**
* Returns operations.
* This is a shortcut method to [[Manager::getItems()]].
*
* @param mixed $userId the user ID. If not null, only the operations directly assigned to the user
* will be returned. Otherwise, all operations will be returned.
* @return Item[] operations (name => AuthItem)
......@@ -139,16 +140,21 @@ abstract class Manager extends Component
}
/**
* Executes the specified business rule.
* @param string $bizRule the business rule to be executed.
* Executes the specified rule.
*
* @param string $ruleName name of the rule to be executed.
* @param array $params parameters passed to [[Manager::checkAccess()]].
* @param mixed $data additional data associated with the authorization item or assignment.
* @return boolean whether the business rule returns true.
* If the business rule is empty, it will still return true.
* @return boolean whether the rule execution returns true.
* If the rule is empty, it will still return true.
*/
public function executeBizRule($bizRule, $params, $data)
public function executeRule($ruleName, $params, $data)
{
return $bizRule === '' || $bizRule === null || ($this->showErrors ? eval($bizRule) != 0 : @eval($bizRule) != 0);
$rule = $this->getRule($ruleName);
if ($rule) {
return $rule->execute($params, $data);
}
return true;
}
/**
......@@ -170,7 +176,7 @@ abstract class Manager extends Component
* @param mixed $userId the user ID. This should be either an integer or a string representing
* the unique identifier of a user. See [[\yii\web\User::id]].
* @param string $itemName the name of the operation that we are checking access to
* @param array $params name-value pairs that would be passed to biz rules associated
* @param array $params name-value pairs that would be passed to rules associated
* with the tasks and roles assigned to the user.
* @return boolean whether the operations can be performed by the user.
*/
......@@ -182,22 +188,24 @@ abstract class Manager extends Component
* It has three types: operation, task and role.
* Authorization items form a hierarchy. Higher level items inheirt permissions representing
* by lower level items.
*
* @param string $name the item name. This must be a unique identifier.
* @param integer $type the item type (0: operation, 1: task, 2: role).
* @param string $description description of the item
* @param string $bizRule business rule associated with the item. This is a piece of
* PHP code that will be executed when [[checkAccess()]] is called for the item.
* @param string $ruleName name of the rule associated with the item.
* @param mixed $data additional data associated with the item.
* @throws \yii\base\Exception if an item with the same name already exists
* @return Item the authorization item
*/
abstract public function createItem($name, $type, $description = '', $bizRule = null, $data = null);
abstract public function createItem($name, $type, $description = '', $ruleName = null, $data = null);
/**
* Removes the specified authorization item.
* @param string $name the name of the item to be removed
* @return boolean whether the item exists in the storage and has been removed
*/
abstract public function removeItem($name);
/**
* Returns the authorization items of the specific type and user.
* @param mixed $userId the user ID. Defaults to null, meaning returning all items even if
......@@ -207,18 +215,20 @@ abstract class Manager extends Component
* @return Item[] the authorization items of the specific type.
*/
abstract public function getItems($userId = null, $type = null);
/**
* Returns the authorization item with the specified name.
* @param string $name the name of the item
* @return Item the authorization item. Null if the item cannot be found.
*/
abstract public function getItem($name);
/**
* Saves an authorization item to persistent storage.
* @param Item $item the item to be saved.
* @param string $oldName the old item name. If null, it means the item name is not changed.
*/
abstract public function saveItem($item, $oldName = null);
abstract public function saveItem(Item $item, $oldName = null);
/**
* Adds an item as a child of another item.
......@@ -227,6 +237,7 @@ abstract class Manager extends Component
* @throws \yii\base\Exception if either parent or child doesn't exist or if a loop has been detected.
*/
abstract public function addItemChild($itemName, $childName);
/**
* Removes a child from its parent.
* Note, the child item is not deleted. Only the parent-child relationship is removed.
......@@ -235,6 +246,7 @@ abstract class Manager extends Component
* @return boolean whether the removal is successful
*/
abstract public function removeItemChild($itemName, $childName);
/**
* Returns a value indicating whether a child exists within a parent.
* @param string $itemName the parent item name
......@@ -242,6 +254,7 @@ abstract class Manager extends Component
* @return boolean whether the child exists
*/
abstract public function hasItemChild($itemName, $childName);
/**
* Returns the children of the specified item.
* @param mixed $itemName the parent item name. This can be either a string or an array.
......@@ -252,15 +265,17 @@ abstract class Manager extends Component
/**
* Assigns an authorization item to a user.
*
* @param mixed $userId the user ID (see [[\yii\web\User::id]])
* @param string $itemName the item name
* @param string $bizRule the business rule to be executed when [[checkAccess()]] is called
* @param string $ruleName name of the rule to be executed when [[checkAccess()]] is called
* for this particular authorization item.
* @param mixed $data additional data associated with this assignment
* @return Assignment the authorization assignment information.
* @throws \yii\base\Exception if the item does not exist or if the item has already been assigned to the user
*/
abstract public function assign($userId, $itemName, $bizRule = null, $data = null);
abstract public function assign($userId, $itemName, $ruleName = null, $data = null);
/**
* Revokes an authorization assignment from a user.
* @param mixed $userId the user ID (see [[\yii\web\User::id]])
......@@ -268,12 +283,14 @@ abstract class Manager extends Component
* @return boolean whether removal is successful
*/
abstract public function revoke($userId, $itemName);
/**
* Revokes all authorization assignments from a user.
* @param mixed $userId the user ID (see [[\yii\web\User::id]])
* @return boolean whether removal is successful
*/
abstract public function revokeAll($userId);
/**
* Returns a value indicating whether the item has been assigned to the user.
* @param mixed $userId the user ID (see [[\yii\web\User::id]])
......@@ -281,6 +298,7 @@ abstract class Manager extends Component
* @return boolean whether the item has been assigned to the user.
*/
abstract public function isAssigned($userId, $itemName);
/**
* Returns the item assignment information.
* @param mixed $userId the user ID (see [[\yii\web\User::id]])
......@@ -296,19 +314,60 @@ abstract class Manager extends Component
* returned if there is no item assigned to the user.
*/
abstract public function getAssignments($userId);
/**
* Removes the specified rule.
* @param string $name the name of the rule to be removed
* @return boolean whether the rule exists in the storage and has been removed
*/
abstract public function removeRule($name);
/**
* Inserts new rule.
*
* @param Rule $rule the rule that needs to be stored.
*/
abstract public function insertRule(Rule $rule);
/**
* Updates existing rule.
*
* @param string $name the name of the rule to update
* @param Rule $rule new rule
*/
abstract public function updateRule($name, Rule $rule);
/**
* Returns rule given its name.
*
* @param string $name name of the rule.
* @return Rule
*/
abstract public function getRule($name);
/**
* Returns all rules.
*
* @return Rule[]
*/
abstract public function getRules();
/**
* Saves the changes to an authorization assignment.
* @param Assignment $assignment the assignment that has been changed.
*/
abstract public function saveAssignment($assignment);
abstract public function saveAssignment(Assignment $assignment);
/**
* Removes all authorization data.
*/
abstract public function clearAll();
/**
* Removes all authorization assignments.
*/
abstract public function clearAssignments();
/**
* Saves authorization data into persistent storage.
* If any change is made to the authorization data, please make
......
......@@ -43,6 +43,7 @@ class PhpManager extends Manager
private $_items = []; // itemName => item
private $_children = []; // itemName, childName => child
private $_assignments = []; // userId, itemName => assignment
private $_rules = []; // ruleName => rule
/**
......@@ -62,7 +63,7 @@ class PhpManager extends Manager
* @param mixed $userId the user ID. This can be either an integer or a string representing
* @param string $itemName the name of the operation that need access check
* the unique identifier of a user. See [[\yii\web\User::id]].
* @param array $params name-value pairs that would be passed to biz rules associated
* @param array $params name-value pairs that would be passed to rules associated
* with the tasks and roles assigned to the user. A param with name 'userId' is added to
* this array, which holds the value of `$userId`.
* @return boolean whether the operations can be performed by the user.
......@@ -78,14 +79,14 @@ class PhpManager extends Manager
if (!isset($params['userId'])) {
$params['userId'] = $userId;
}
if ($this->executeBizRule($item->bizRule, $params, $item->data)) {
if ($this->executeRule($item->ruleName, $params, $item->data)) {
if (in_array($itemName, $this->defaultRoles)) {
return true;
}
if (isset($this->_assignments[$userId][$itemName])) {
/** @var Assignment $assignment */
$assignment = $this->_assignments[$userId][$itemName];
if ($this->executeBizRule($assignment->bizRule, $params, $assignment->data)) {
if ($this->executeRule($assignment->ruleName, $params, $assignment->data)) {
return true;
}
}
......@@ -181,15 +182,16 @@ class PhpManager extends Manager
/**
* Assigns an authorization item to a user.
*
* @param mixed $userId the user ID (see [[\yii\web\User::id]])
* @param string $itemName the item name
* @param string $bizRule the business rule to be executed when [[checkAccess()]] is called
* @param string $ruleName the business rule to be executed when [[checkAccess()]] is called
* for this particular authorization item.
* @param mixed $data additional data associated with this assignment
* @return Assignment the authorization assignment information.
* @throws InvalidParamException if the item does not exist or if the item has already been assigned to the user
*/
public function assign($userId, $itemName, $bizRule = null, $data = null)
public function assign($userId, $itemName, $ruleName = null, $data = null)
{
if (!isset($this->_items[$itemName])) {
throw new InvalidParamException("Unknown authorization item '$itemName'.");
......@@ -200,7 +202,7 @@ class PhpManager extends Manager
'manager' => $this,
'userId' => $userId,
'itemName' => $itemName,
'bizRule' => $bizRule,
'ruleName' => $ruleName,
'data' => $data,
]);
}
......@@ -314,16 +316,17 @@ class PhpManager extends Manager
* It has three types: operation, task and role.
* Authorization items form a hierarchy. Higher level items inheirt permissions representing
* by lower level items.
*
* @param string $name the item name. This must be a unique identifier.
* @param integer $type the item type (0: operation, 1: task, 2: role).
* @param string $description description of the item
* @param string $bizRule business rule associated with the item. This is a piece of
* @param string $rule business rule associated with the item. This is a piece of
* PHP code that will be executed when [[checkAccess()]] is called for the item.
* @param mixed $data additional data associated with the item.
* @return Item the authorization item
* @throws Exception if an item with the same name already exists
*/
public function createItem($name, $type, $description = '', $bizRule = null, $data = null)
public function createItem($name, $type, $description = '', $rule = null, $data = null)
{
if (isset($this->_items[$name])) {
throw new Exception('Unable to add an item whose name is the same as an existing item.');
......@@ -334,7 +337,7 @@ class PhpManager extends Manager
'name' => $name,
'type' => $type,
'description' => $description,
'bizRule' => $bizRule,
'ruleName' => $rule,
'data' => $data,
]);
}
......@@ -377,7 +380,7 @@ class PhpManager extends Manager
* @param string $oldName the old item name. If null, it means the item name is not changed.
* @throws InvalidParamException if an item with the same name already taken
*/
public function saveItem($item, $oldName = null)
public function saveItem(Item $item, $oldName = null)
{
if ($oldName !== null && ($newName = $item->getName()) !== $oldName) { // name changed
if (isset($this->_items[$newName])) {
......@@ -410,7 +413,7 @@ class PhpManager extends Manager
* Saves the changes to an authorization assignment.
* @param Assignment $assignment the assignment that has been changed.
*/
public function saveAssignment($assignment)
public function saveAssignment(Assignment $assignment)
{
}
......@@ -427,7 +430,7 @@ class PhpManager extends Manager
$items[$name] = [
'type' => $item->type,
'description' => $item->description,
'bizRule' => $item->bizRule,
'ruleName' => $item->ruleName,
'data' => $item->data,
];
if (isset($this->_children[$name])) {
......@@ -443,14 +446,19 @@ class PhpManager extends Manager
/** @var Assignment $assignment */
if (isset($items[$name])) {
$items[$name]['assignments'][$userId] = [
'bizRule' => $assignment->bizRule,
'ruleName' => $assignment->ruleName,
'data' => $assignment->data,
];
}
}
}
$this->saveToFile($items, $this->authFile);
$rules = [];
foreach ($this->_rules as $name => $rule) {
$rules[$name] = serialize($rule);
}
$this->saveToFile(['items' => $items, 'rules' => $rules], $this->authFile);
}
/**
......@@ -460,20 +468,21 @@ class PhpManager extends Manager
{
$this->clearAll();
$items = $this->loadFromFile($this->authFile);
$data = $this->loadFromFile($this->authFile);
foreach ($items as $name => $item) {
if (isset($data['items'])) {
foreach ($data['items'] as $name => $item) {
$this->_items[$name] = new Item([
'manager' => $this,
'name' => $name,
'type' => $item['type'],
'description' => $item['description'],
'bizRule' => $item['bizRule'],
'ruleName' => $item['ruleName'],
'data' => $item['data'],
]);
}
foreach ($items as $name => $item) {
foreach ($data['items'] as $name => $item) {
if (isset($item['children'])) {
foreach ($item['children'] as $childName) {
if (isset($this->_items[$childName])) {
......@@ -487,7 +496,7 @@ class PhpManager extends Manager
'manager' => $this,
'userId' => $userId,
'itemName' => $name,
'bizRule' => $assignment['bizRule'],
'ruleName' => $assignment['ruleName'],
'data' => $assignment['data'],
]);
}
......@@ -495,6 +504,13 @@ class PhpManager extends Manager
}
}
if (isset($data['rules'])) {
foreach ($data['rules'] as $name => $ruleData) {
$this->_rules[$name] = unserialize($ruleData);
}
}
}
/**
* Removes all authorization data.
*/
......@@ -562,4 +578,70 @@ class PhpManager extends Manager
{
file_put_contents($file, "<?php\nreturn " . var_export($data, true) . ";\n", LOCK_EX);
}
/**
* Removes the specified rule.
*
* @param string $name the name of the rule to be removed
* @return boolean whether the rule exists in the storage and has been removed
*/
public function removeRule($name)
{
if (isset($this->_rules[$name])) {
unset($this->_rules[$name]);
return true;
} else {
return false;
}
}
/**
* Saves the changes to the rule.
*
* @param Rule $rule the rule that has been changed.
*/
public function insertRule(Rule $rule)
{
$this->_rules[$rule->name] = $rule;
}
/**
* Updates existing rule.
*
* @param string $name the name of the rule to update
* @param Rule $rule new rule
*/
public function updateRule($name, Rule $rule)
{
if ($rule->name !== $name) {
unset($this->_rules[$name]);
}
$this->_rules[$rule->name] = $rule;
}
/**
* Returns rule given its name.
*
* @param string $name name of the rule.
* @return Rule
*/
public function getRule($name)
{
if (!isset($this->_rules[$name])) {
return null;
}
return $this->_rules[$name];
}
/**
* Returns all rules.
*
* @return Rule[]
*/
public function getRules()
{
return $this->_rules;
}
}
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\rbac;
use yii\base\Object;
/**
* Rule represents a business constraint that may be assigned and the applied to
* an authorization item or assignment.
*
* @author Alexander Makarov <sam@rmcreative.ru>
* @since 2.0
*/
abstract class Rule extends Object
{
/**
* @var string name of the rule
*/
public $name;
/**
* Executes the rule.
*
* @param array $params parameters passed to [[Manager::checkAccess()]].
* @param mixed $data additional data associated with the authorization item or assignment.
* @return boolean whether the rule execution returns true.
*/
abstract public function execute($params, $data);
}
......@@ -12,15 +12,24 @@
drop table if exists [auth_assignment];
drop table if exists [auth_item_child];
drop table if exists [auth_item];
drop table if exists [auth_rule];
create table [auth_rule]
(
[name] varchar(64) not null,
[data] text,
primary key ([name])
);
create table [auth_item]
(
[name] varchar(64) not null,
[type] integer not null,
[description] text,
[biz_rule] text,
[rule_name] varchar(64),
[data] text,
primary key ([name]),
foreign key ([rule_name]) references [auth_rule] ([name]) on delete set null on update cascade,
key [type] ([type])
);
......@@ -37,8 +46,9 @@ create table [auth_assignment]
(
[item_name] varchar(64) not null,
[user_id] varchar(64) not null,
[biz_rule] text,
[rule_name] varchar(64),
[data] text,
primary key ([item_name],[user_id]),
foreign key ([item_name]) references [auth_item] ([name]) on delete cascade on update cascade
primary key ([item_name], [user_id]),
foreign key ([item_name]) references [auth_item] ([name]) on delete cascade on update cascade,
foreign key ([rule_name]) references [auth_rule] ([name]) on delete set null on update cascade
);
......@@ -12,15 +12,24 @@
drop table if exists `auth_assignment`;
drop table if exists `auth_item_child`;
drop table if exists `auth_item`;
drop table if exists `auth_rule`;
create table `auth_rule`
(
`name` varchar(64) not null,
`data` text,
primary key (`name`)
) engine InnoDB;
create table `auth_item`
(
`name` varchar(64) not null,
`type` integer not null,
`description` text,
`biz_rule` text,
`rule_name` varchar(64),
`data` text,
primary key (`name`),
foreign key (`rule_name`) references `auth_rule` (`name`) on delete set null on update cascade,
key `type` (`type`)
) engine InnoDB;
......@@ -28,7 +37,7 @@ create table `auth_item_child`
(
`parent` varchar(64) not null,
`child` varchar(64) not null,
primary key (`parent`,`child`),
primary key (`parent`, `child`),
foreign key (`parent`) references `auth_item` (`name`) on delete cascade on update cascade,
foreign key (`child`) references `auth_item` (`name`) on delete cascade on update cascade
) engine InnoDB;
......@@ -37,8 +46,9 @@ create table `auth_assignment`
(
`item_name` varchar(64) not null,
`user_id` varchar(64) not null,
`biz_rule` text,
`rule_name` varchar(64),
`data` text,
primary key (`item_name`,`user_id`),
foreign key (`item_name`) references `auth_item` (`name`) on delete cascade on update cascade
primary key (`item_name`, `user_id`),
foreign key (`item_name`) references `auth_item` (`name`) on delete cascade on update cascade,
foreign key (`rule_name`) references `auth_rule` (`name`) on delete set null on update cascade
) engine InnoDB;
\ No newline at end of file
......@@ -12,15 +12,24 @@
drop table if exists "auth_assignment";
drop table if exists "auth_item_child";
drop table if exists "auth_item";
drop table if exists "auth_rule";
create table "auth_rule"
(
"name" varchar(64) not null,
"data" text,
primary key ("name")
);
create table "auth_item"
(
"name" varchar(64) not null,
"type" integer not null,
"description" text,
"biz_rule" text,
"rule_name" varchar(64),
"data" text,
primary key ("name"),
foreign key ("rule_name") references "auth_rule" ("name") on delete set null on update cascade,
key "type" ("type")
);
......@@ -37,8 +46,9 @@ create table "auth_assignment"
(
"item_name" varchar(64) not null,
"user_id" varchar(64) not null,
"biz_rule" text,
"rule_name" varchar(64),
"data" text,
primary key ("item_name","user_id"),
foreign key ("item_name") references "auth_item" ("name") on delete cascade on update cascade
foreign key ("item_name") references "auth_item" ("name") on delete cascade on update cascade,
foreign key ("rule_name") references "auth_rule" ("name") on delete set null on update cascade
);
......@@ -12,15 +12,24 @@
drop table if exists "auth_assignment";
drop table if exists "auth_item_child";
drop table if exists "auth_item";
drop table if exists "auth_rule";
create table "auth_rule"
(
"name" varchar(64) not null,
"data" text,
primary key ("name")
);
create table "auth_item"
(
"name" varchar(64) not null,
"type" integer not null,
"description" text,
"biz_rule" text,
"rule_name" varchar(64),
"data" text,
primary key ("name")
primary key ("name"),
foreign key ("rule_name") references "auth_rule" ("name") on delete set null on update cascade
);
create index auth_item_type_idx on "auth_item" ("type");
......@@ -38,8 +47,9 @@ create table "auth_assignment"
(
"item_name" varchar(64) not null,
"user_id" varchar(64) not null,
"biz_rule" text,
"rule_name" varchar(64),
"data" text,
primary key ("item_name","user_id"),
foreign key ("item_name") references "auth_item" ("name") on delete cascade on update cascade
foreign key ("item_name") references "auth_item" ("name") on delete cascade on update cascade,
foreign key ("rule_name") references "auth_rule" ("name") on delete set null on update cascade
);
......@@ -9,36 +9,47 @@
* @since 2.0
*/
drop table if exists 'auth_assignment';
drop table if exists 'auth_item_child';
drop table if exists 'auth_item';
drop table if exists "auth_assignment";
drop table if exists "auth_item_child";
drop table if exists "auth_item";
drop table if exists "auth_rule";
create table 'auth_item'
create table "auth_rule"
(
"name" varchar(64) not null,
"data" text,
primary key ("name")
);
create table "auth_item"
(
"name" varchar(64) not null,
"type" integer not null,
"description" text,
"biz_rule" text,
"rule_name" varchar(64),
"data" text,
primary key ("name"),
key "type" ("type")
foreign key ("rule_name") references "auth_rule" ("name") on delete set null on update cascade
);
create table 'auth_item_child'
create index "auth_item_type_idx" on "auth_item" ("type");
create table "auth_item_child"
(
"parent" varchar(64) not null,
"child" varchar(64) not null,
primary key ("parent","child"),
foreign key ("parent") references 'auth_item' ("name") on delete cascade on update cascade,
foreign key ("child") references 'auth_item' ("name") on delete cascade on update cascade
foreign key ("parent") references "auth_item" ("name") on delete cascade on update cascade,
foreign key ("child") references "auth_item" ("name") on delete cascade on update cascade
);
create table 'auth_assignment'
create table "auth_assignment"
(
"item_name" varchar(64) not null,
"user_id" varchar(64) not null,
"biz_rule" text,
"rule_name" varchar(64),
"data" text,
primary key ("item_name","user_id"),
foreign key ("item_name") references 'auth_item' ("name") on delete cascade on update cascade
foreign key ("item_name") references "auth_item" ("name") on delete cascade on update cascade,
foreign key ("rule_name") references "auth_rule" ("name") on delete set null on update cascade
);
<?php
namespace yiiunit\framework\rbac;
use yii\rbac\Rule;
/**
* Checks if authorID matches userID passed via params
*/
class AuthorRule extends Rule
{
public $name = 'isAuthor';
public $reallyReally = false;
/**
* @inheritdoc
*/
public function execute($params, $data)
{
return $params['authorID'] == $params['userID'];
}
}
\ No newline at end of file
<?php
namespace yiiunit\framework\rbac;
use yii\db\Connection;
use yii\rbac\DbManager;
/**
* DbManagerTestCase
*/
abstract class DbManagerTestCase extends ManagerTestCase
{
protected $database;
protected $driverName = 'mysql';
/**
* @var Connection
*/
protected $db;
protected function setUp()
{
parent::setUp();
$databases = $this->getParam('databases');
$this->database = $databases[$this->driverName];
$pdo_database = 'pdo_'.$this->driverName;
if (!extension_loaded('pdo') || !extension_loaded($pdo_database)) {
$this->markTestSkipped('pdo and '.$pdo_database.' extension are required.');
}
$this->auth = new DbManager(['db' => $this->getConnection()]);
$this->auth->init();
$this->prepareData();
}
protected function tearDown()
{
parent::tearDown();
if ($this->db) {
$this->db->close();
}
$this->destroyApplication();
}
/**
* @param boolean $reset whether to clean up the test database
* @param boolean $open whether to open and populate test database
* @throws \yii\base\InvalidParamException
* @throws \yii\db\Exception
* @throws \yii\base\InvalidConfigException
* @return \yii\db\Connection
*/
public function getConnection($reset = true, $open = true)
{
if (!$reset && $this->db) {
return $this->db;
}
$db = new Connection;
$db->dsn = $this->database['dsn'];
if (isset($this->database['username'])) {
$db->username = $this->database['username'];
$db->password = $this->database['password'];
}
if (isset($this->database['attributes'])) {
$db->attributes = $this->database['attributes'];
}
if ($open) {
$db->open();
$lines = explode(';', file_get_contents(\Yii::getAlias('@yii/rbac/schema-'.$this->driverName.'.sql')));
foreach ($lines as $line) {
if (trim($line) !== '') {
$db->pdo->exec($line);
}
}
}
$this->db = $db;
return $db;
}
}
......@@ -8,7 +8,7 @@ use yiiunit\TestCase;
abstract class ManagerTestCase extends TestCase
{
/** @var \yii\rbac\PhpManager|\yii\rbac\DbManager */
/** @var \yii\rbac\Manager */
protected $auth;
public function testCreateItem()
......@@ -16,24 +16,24 @@ abstract class ManagerTestCase extends TestCase
$type = Item::TYPE_TASK;
$name = 'editUser';
$description = 'edit a user';
$bizRule = 'checkUserIdentity()';
$ruleName = 'isAuthor';
$data = [1, 2, 3];
$item = $this->auth->createItem($name, $type, $description, $bizRule, $data);
$item = $this->auth->createItem($name, $type, $description, $ruleName, $data);
$this->assertTrue($item instanceof Item);
$this->assertEquals($item->type, $type);
$this->assertEquals($item->name, $name);
$this->assertEquals($item->description, $description);
$this->assertEquals($item->bizRule, $bizRule);
$this->assertEquals($item->ruleName, $ruleName);
$this->assertEquals($item->data, $data);
// test shortcut
$name2 = 'createUser';
$item2 = $this->auth->createRole($name2, $description, $bizRule, $data);
$item2 = $this->auth->createRole($name2, $description, $ruleName, $data);
$this->assertEquals($item2->type, Item::TYPE_ROLE);
// test adding an item with the same name
$this->setExpectedException('\yii\base\Exception');
$this->auth->createItem($name, $type, $description, $bizRule, $data);
$this->auth->createItem($name, $type, $description, $ruleName, $data);
}
public function testGetItem()
......@@ -98,11 +98,11 @@ abstract class ManagerTestCase extends TestCase
public function testAssign()
{
$auth = $this->auth->assign('new user', 'createPost', 'rule', 'data');
$auth = $this->auth->assign('new user', 'createPost', 'isAuthor', 'data');
$this->assertTrue($auth instanceof Assignment);
$this->assertEquals($auth->userId, 'new user');
$this->assertEquals($auth->itemName, 'createPost');
$this->assertEquals($auth->bizRule, 'rule');
$this->assertEquals($auth->ruleName, 'isAuthor');
$this->assertEquals($auth->data, 'data');
$this->setExpectedException('\yii\base\Exception');
......@@ -168,14 +168,79 @@ abstract class ManagerTestCase extends TestCase
$this->auth->addItemChild('readPost', 'readPost');
}
public function testExecuteBizRule()
public function testGetRule()
{
$this->assertTrue($this->auth->executeBizRule(null, [], null));
$this->assertTrue($this->auth->executeBizRule('return 1 == true;', [], null));
$this->assertTrue($this->auth->executeBizRule('return $params[0] == $params[1];', [1, '1'], null));
if (!defined('HHVM_VERSION')) { // invalid code crashes on HHVM
$this->assertFalse($this->auth->executeBizRule('invalid;', [], null));
$rule = $this->auth->getRule('isAuthor');
$this->assertInstanceOf('yii\rbac\Rule', $rule);
$this->assertEquals('isAuthor', $rule->name);
$rule = $this->auth->getRule('nonExisting');
$this->assertNull($rule);
}
public function testInsertRule()
{
$ruleName = 'isReallyReallyAuthor';
$rule = new AuthorRule(['name' => $ruleName, 'reallyReally' => true]);
$this->auth->insertRule($rule);
/** @var AuthorRule $rule */
$rule = $this->auth->getRule($ruleName);
$this->assertEquals($ruleName, $rule->name);
$this->assertEquals(true, $rule->reallyReally);
}
public function testUpdateRule()
{
$rule = $this->auth->getRule('isAuthor');
$rule->name = "newName";
$rule->reallyReally = false;
$this->auth->updateRule('isAuthor', $rule);
/** @var AuthorRule $rule */
$rule = $this->auth->getRule('isAuthor');
$this->assertEquals(null, $rule);
$rule = $this->auth->getRule('newName');
$this->assertEquals("newName", $rule->name);
$this->assertEquals(false, $rule->reallyReally);
$rule->reallyReally = true;
$this->auth->updateRule('newName', $rule);
$rule = $this->auth->getRule('newName');
$this->assertEquals(true, $rule->reallyReally);
}
public function testGetRules()
{
$rule = new AuthorRule(['name' => 'isReallyReallyAuthor', 'reallyReally' => true]);
$this->auth->insertRule($rule);
$rules = $this->auth->getRules();
$ruleNames = [];
foreach ($rules as $rule) {
$ruleNames[] = $rule->name;
}
$this->assertContains('isReallyReallyAuthor', $ruleNames);
$this->assertContains('isAuthor', $ruleNames);
}
public function testRemoveRule()
{
$this->auth->removeRule('isAuthor');
$rules = $this->auth->getRules();
$this->assertEmpty($rules);
}
public function testExecuteRule()
{
$this->assertTrue($this->auth->executeRule(null, [], null));
$this->assertTrue($this->auth->executeRule('isAuthor', ['userID' => 1, 'authorID' => 1], null));
$this->assertFalse($this->auth->executeRule('isAuthor', ['userID' => 1, 'authorID' => 2], null));
}
public function testCheckAccess()
......@@ -231,12 +296,14 @@ abstract class ManagerTestCase extends TestCase
protected function prepareData()
{
$this->auth->insertRule(new AuthorRule());
$this->auth->createOperation('createPost', 'create a post');
$this->auth->createOperation('readPost', 'read a post');
$this->auth->createOperation('updatePost', 'update a post');
$this->auth->createOperation('deletePost', 'delete a post');
$task = $this->auth->createTask('updateOwnPost', 'update a post by author himself', 'return $params["authorID"] == $params["userID"];');
$task = $this->auth->createTask('updateOwnPost', 'update a post by author himself', 'isAuthor');
$task->addChild('updatePost');
$role = $this->auth->createRole('reader');
......
<?php
namespace yiiunit\framework\rbac;
/**
* MySQLManagerTest
*/
class MySQLManagerTest extends DbManagerTestCase
{
}
<?php
namespace yiiunit\framework\rbac;
/**
* PgSQLManagerTest
*/
class PgSQLManagerTest extends DbManagerTestCase
{
protected $driverName = 'pgsql';
}
......@@ -7,6 +7,7 @@ use yii\rbac\PhpManager;
/**
* @group rbac
* @property \yii\rbac\PhpManager $auth
*/
class PhpManagerTest extends ManagerTestCase
{
......
<?php
namespace yiiunit\framework\rbac;
/**
* SqliteManagerTest
*/
class SqliteManagerTest extends DbManagerTestCase
{
protected $driverName = 'sqlite';
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment