mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-24 10:39:03 +08:00
Merge pull request #4104 from yiisoft/rbac-phpmanager-adjusment
\yii\rbac\PhpManager adjustments
This commit is contained in:
@@ -121,6 +121,12 @@ Yii Framework 2 Change Log
|
||||
- Improved overall slug results.
|
||||
- Added note about the fact that intl is required for non-latin languages to requirements checker.
|
||||
- Enh #4028: Added ability to `yii\widgets\Menu` to encode each item's label separately (creocoder, umneeq)
|
||||
- Enh #4072: `\yii\rbac\PhpManager` adjustments (samdark)
|
||||
- Data is now stored in three separate files for items, assignments and rules. File format is simpler.
|
||||
- Removed `authFile`. Added `itemFile`, `assignmentFile` and `ruleFile`.
|
||||
- `createdAt` and `updatedAt` are now properly filled with corresponding file modification time.
|
||||
- `save()` and `load()` are now protected instead of public.
|
||||
- Added unit test for saving and loading data.
|
||||
- Enh #4080: Added proper handling and support of the symlinked directories in `FileHelper`, added $options parameter in `FileHelper::removeDirectory()` (resurtm)
|
||||
- Enh #4086: changedAttributes of afterSave Event now contain old values (dizews)
|
||||
- Enh: Added support for using sub-queries when building a DB query with `IN` condition (qiangxue)
|
||||
|
||||
@@ -74,6 +74,54 @@ Upgrade from Yii 2.0 Beta
|
||||
* `mail` component was renamed to `mailer`, `yii\log\EmailTarget::$mail` was renamed to `yii\log\EmailTarget::$mailer`.
|
||||
Please update all references in the code and config files.
|
||||
|
||||
* `\yii\rbac\PhpManager` now stores data in three separate files instead of one. In order to convert old file to
|
||||
new ones save the following code as `convert.php` that should be placed in the same directory your `rbac.php` is in:
|
||||
|
||||
```php
|
||||
<?php
|
||||
$oldFile = 'rbac.php';
|
||||
$itemsFile = 'items.php';
|
||||
$assignmentsFile = 'assignments.php';
|
||||
$rulesFile = 'rules.php';
|
||||
|
||||
$oldData = include $oldFile;
|
||||
|
||||
function saveToFile($data, $fileName) {
|
||||
$out = var_export($data, true);
|
||||
$out = "<?php\nreturn " . $out . ";";
|
||||
$out = str_replace(['array (', ')'], ['[', ']'], $out);
|
||||
file_put_contents($fileName, $out);
|
||||
}
|
||||
|
||||
$items = [];
|
||||
$assignments = [];
|
||||
if (isset($oldData['items'])) {
|
||||
foreach ($oldData['items'] as $name => $data) {
|
||||
if (isset($data['assignments'])) {
|
||||
foreach ($data['assignments'] as $userId => $assignmentData) {
|
||||
$assignments[$userId] = $assignmentData['roleName'];
|
||||
}
|
||||
unset($data['assignments']);
|
||||
}
|
||||
$items[$name] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
$rules = [];
|
||||
if (isset($oldData['rules'])) {
|
||||
$rules = $oldData['rules'];
|
||||
}
|
||||
|
||||
saveToFile($items, $itemsFile);
|
||||
saveToFile($assignments, $assignmentsFile);
|
||||
saveToFile($rules, $rulesFile);
|
||||
|
||||
echo "Done!\n";
|
||||
```
|
||||
|
||||
Run it once, delete `rbac.php`. If you've configured `authFile` property, remove the line from config and instead
|
||||
configure `itemFile`, `assignmentFile` and `ruleFile`.
|
||||
|
||||
* Static helper `yii\helpers\Security` has been converted into an application component. You should change all usage of
|
||||
its methods to a new syntax, for example: instead of `yii\helpers\Security::hashData()` use `Yii::$app->getSecurity()->hashData()`.
|
||||
Default encryption and hash parameters has been upgraded. If you need to decrypt/validate data that was encrypted/hashed
|
||||
|
||||
@@ -13,8 +13,6 @@ use yii\base\Object;
|
||||
/**
|
||||
* Assignment represents an assignment of a role to a user.
|
||||
*
|
||||
* It includes additional assignment information including [[ruleName]] and [[data]].
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @author Alexander Kochetov <creocoder@gmail.com>
|
||||
* @since 2.0
|
||||
|
||||
@@ -26,34 +26,52 @@ use yii\helpers\VarDumper;
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @author Alexander Kochetov <creocoder@gmail.com>
|
||||
* @author Christophe Boulain <christophe.boulain@gmail.com>
|
||||
* @author Alexander Makarov <sam@rmcreative.ru>
|
||||
* @since 2.0
|
||||
*/
|
||||
class PhpManager extends BaseManager
|
||||
{
|
||||
/**
|
||||
* @var string the path of the PHP script that contains the authorization data.
|
||||
* @var string the path of the PHP script that contains the authorization items.
|
||||
* This can be either a file path or a path alias to the file.
|
||||
* Make sure this file is writable by the Web server process if the authorization needs to be changed online.
|
||||
* @see loadFromFile()
|
||||
* @see saveToFile()
|
||||
*/
|
||||
public $authFile = '@app/data/rbac.php';
|
||||
public $itemFile = '@app/rbac/items.php';
|
||||
/**
|
||||
* @var string the path of the PHP script that contains the authorization assignments.
|
||||
* This can be either a file path or a path alias to the file.
|
||||
* Make sure this file is writable by the Web server process if the authorization needs to be changed online.
|
||||
* @see loadFromFile()
|
||||
* @see saveToFile()
|
||||
*/
|
||||
public $assignmentFile = '@app/rbac/assignments.php';
|
||||
|
||||
/**
|
||||
* @var string the path of the PHP script that contains the authorization rules.
|
||||
* This can be either a file path or a path alias to the file.
|
||||
* Make sure this file is writable by the Web server process if the authorization needs to be changed online.
|
||||
* @see loadFromFile()
|
||||
* @see saveToFile()
|
||||
*/
|
||||
public $ruleFile = '@app/rbac/rules.php';
|
||||
/**
|
||||
* @var Item[]
|
||||
*/
|
||||
private $_items = []; // itemName => item
|
||||
protected $items = []; // itemName => item
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $_children = []; // itemName, childName => child
|
||||
protected $children = []; // itemName, childName => child
|
||||
/**
|
||||
* @var Assignment[]
|
||||
*/
|
||||
private $_assignments = []; // userId, itemName => assignment
|
||||
protected $assignments = []; // userId, itemName => assignment
|
||||
/**
|
||||
* @var Rule[]
|
||||
*/
|
||||
private $_rules = []; // ruleName => rule
|
||||
protected $rules = []; // ruleName => rule
|
||||
|
||||
|
||||
/**
|
||||
@@ -64,7 +82,9 @@ class PhpManager extends BaseManager
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
$this->authFile = Yii::getAlias($this->authFile);
|
||||
$this->itemFile = Yii::getAlias($this->itemFile);
|
||||
$this->assignmentFile = Yii::getAlias($this->assignmentFile);
|
||||
$this->ruleFile = Yii::getAlias($this->ruleFile);
|
||||
$this->load();
|
||||
}
|
||||
|
||||
@@ -82,7 +102,7 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function getAssignments($userId)
|
||||
{
|
||||
return isset($this->_assignments[$userId]) ? $this->_assignments[$userId] : [];
|
||||
return isset($this->assignments[$userId]) ? $this->assignments[$userId] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,12 +120,12 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
protected function checkAccessRecursive($user, $itemName, $params, $assignments)
|
||||
{
|
||||
if (!isset($this->_items[$itemName])) {
|
||||
if (!isset($this->items[$itemName])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* @var $item Item */
|
||||
$item = $this->_items[$itemName];
|
||||
$item = $this->items[$itemName];
|
||||
Yii::trace($item instanceof Role ? "Checking role: $itemName" : "Checking permission : $itemName", __METHOD__);
|
||||
|
||||
if (!$this->executeRule($user, $item, $params)) {
|
||||
@@ -116,7 +136,7 @@ class PhpManager extends BaseManager
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach ($this->_children as $parentName => $children) {
|
||||
foreach ($this->children as $parentName => $children) {
|
||||
if (isset($children[$itemName]) && $this->checkAccessRecursive($user, $parentName, $params, $assignments)) {
|
||||
return true;
|
||||
}
|
||||
@@ -130,7 +150,7 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function addChild($parent, $child)
|
||||
{
|
||||
if (!isset($this->_items[$parent->name], $this->_items[$child->name])) {
|
||||
if (!isset($this->items[$parent->name], $this->items[$child->name])) {
|
||||
throw new InvalidParamException("Either '{$parent->name}' or '{$child->name}' does not exist.");
|
||||
}
|
||||
|
||||
@@ -144,11 +164,11 @@ class PhpManager extends BaseManager
|
||||
if ($this->detectLoop($parent, $child)) {
|
||||
throw new InvalidCallException("Cannot add '{$child->name}' as a child of '{$parent->name}'. A loop has been detected.");
|
||||
}
|
||||
if (isset($this->_children[$parent->name][$child->name])) {
|
||||
if (isset($this->children[$parent->name][$child->name])) {
|
||||
throw new InvalidCallException("The item '{$parent->name}' already has a child '{$child->name}'.");
|
||||
}
|
||||
$this->_children[$parent->name][$child->name] = $this->_items[$child->name];
|
||||
$this->save();
|
||||
$this->children[$parent->name][$child->name] = $this->items[$child->name];
|
||||
$this->saveItems();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -165,10 +185,10 @@ class PhpManager extends BaseManager
|
||||
if ($child->name === $parent->name) {
|
||||
return true;
|
||||
}
|
||||
if (!isset($this->_children[$child->name], $this->_items[$parent->name])) {
|
||||
if (!isset($this->children[$child->name], $this->items[$parent->name])) {
|
||||
return false;
|
||||
}
|
||||
foreach ($this->_children[$child->name] as $grandchild) {
|
||||
foreach ($this->children[$child->name] as $grandchild) {
|
||||
/* @var $grandchild Item */
|
||||
if ($this->detectLoop($parent, $grandchild)) {
|
||||
return true;
|
||||
@@ -183,9 +203,9 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function removeChild($parent, $child)
|
||||
{
|
||||
if (isset($this->_children[$parent->name][$child->name])) {
|
||||
unset($this->_children[$parent->name][$child->name]);
|
||||
$this->save();
|
||||
if (isset($this->children[$parent->name][$child->name])) {
|
||||
unset($this->children[$parent->name][$child->name]);
|
||||
$this->saveItems();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -197,7 +217,7 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function hasChild($parent, $child)
|
||||
{
|
||||
return isset($this->_children[$parent->name][$child->name]);
|
||||
return isset($this->children[$parent->name][$child->name]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,18 +225,18 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function assign($role, $userId, $ruleName = null, $data = null)
|
||||
{
|
||||
if (!isset($this->_items[$role->name])) {
|
||||
if (!isset($this->items[$role->name])) {
|
||||
throw new InvalidParamException("Unknown role '{$role->name}'.");
|
||||
} elseif (isset($this->_assignments[$userId][$role->name])) {
|
||||
} elseif (isset($this->assignments[$userId][$role->name])) {
|
||||
throw new InvalidParamException("Authorization item '{$role->name}' has already been assigned to user '$userId'.");
|
||||
} else {
|
||||
$this->_assignments[$userId][$role->name] = new Assignment([
|
||||
$this->assignments[$userId][$role->name] = new Assignment([
|
||||
'userId' => $userId,
|
||||
'roleName' => $role->name,
|
||||
'createdAt' => time(),
|
||||
]);
|
||||
$this->save();
|
||||
return $this->_assignments[$userId][$role->name];
|
||||
$this->saveAssignments();
|
||||
return $this->assignments[$userId][$role->name];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,9 +245,9 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function revoke($role, $userId)
|
||||
{
|
||||
if (isset($this->_assignments[$userId][$role->name])) {
|
||||
unset($this->_assignments[$userId][$role->name]);
|
||||
$this->save();
|
||||
if (isset($this->assignments[$userId][$role->name])) {
|
||||
unset($this->assignments[$userId][$role->name]);
|
||||
$this->saveAssignments();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -239,11 +259,11 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function revokeAll($userId)
|
||||
{
|
||||
if (isset($this->_assignments[$userId]) && is_array($this->_assignments[$userId])) {
|
||||
foreach ($this->_assignments[$userId] as $itemName => $value) {
|
||||
unset($this->_assignments[$userId][$itemName]);
|
||||
if (isset($this->assignments[$userId]) && is_array($this->assignments[$userId])) {
|
||||
foreach ($this->assignments[$userId] as $itemName => $value) {
|
||||
unset($this->assignments[$userId][$itemName]);
|
||||
}
|
||||
$this->save();
|
||||
$this->saveAssignments();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -255,7 +275,7 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function getAssignment($roleName, $userId)
|
||||
{
|
||||
return isset($this->_assignments[$userId][$roleName]) ? $this->_assignments[$userId][$roleName] : null;
|
||||
return isset($this->assignments[$userId][$roleName]) ? $this->assignments[$userId][$roleName] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -265,7 +285,7 @@ class PhpManager extends BaseManager
|
||||
{
|
||||
$items = [];
|
||||
|
||||
foreach ($this->_items as $name => $item) {
|
||||
foreach ($this->items as $name => $item) {
|
||||
/* @var $item Item */
|
||||
if ($item->type == $type) {
|
||||
$items[$name] = $item;
|
||||
@@ -281,15 +301,15 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function removeItem($item)
|
||||
{
|
||||
if (isset($this->_items[$item->name])) {
|
||||
foreach ($this->_children as &$children) {
|
||||
if (isset($this->items[$item->name])) {
|
||||
foreach ($this->children as &$children) {
|
||||
unset($children[$item->name]);
|
||||
}
|
||||
foreach ($this->_assignments as &$assignments) {
|
||||
foreach ($this->assignments as &$assignments) {
|
||||
unset($assignments[$item->name]);
|
||||
}
|
||||
unset($this->_items[$item->name]);
|
||||
$this->save();
|
||||
unset($this->items[$item->name]);
|
||||
$this->saveItems();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -301,7 +321,7 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function getItem($name)
|
||||
{
|
||||
return isset($this->_items[$name]) ? $this->_items[$name] : null;
|
||||
return isset($this->items[$name]) ? $this->items[$name] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -310,10 +330,10 @@ class PhpManager extends BaseManager
|
||||
public function updateRule($name, $rule)
|
||||
{
|
||||
if ($rule->name !== $name) {
|
||||
unset($this->_rules[$name]);
|
||||
unset($this->rules[$name]);
|
||||
}
|
||||
$this->_rules[$rule->name] = $rule;
|
||||
$this->save();
|
||||
$this->rules[$rule->name] = $rule;
|
||||
$this->saveRules();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -322,7 +342,7 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function getRule($name)
|
||||
{
|
||||
return isset($this->_rules[$name]) ? $this->_rules[$name] : null;
|
||||
return isset($this->rules[$name]) ? $this->rules[$name] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -330,7 +350,7 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function getRules()
|
||||
{
|
||||
return $this->_rules;
|
||||
return $this->rules;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -340,7 +360,7 @@ class PhpManager extends BaseManager
|
||||
{
|
||||
$roles = [];
|
||||
foreach ($this->getAssignments($userId) as $name => $assignment) {
|
||||
$roles[$name] = $this->_items[$assignment->roleName];
|
||||
$roles[$name] = $this->items[$assignment->roleName];
|
||||
}
|
||||
|
||||
return $roles;
|
||||
@@ -358,8 +378,8 @@ class PhpManager extends BaseManager
|
||||
}
|
||||
$permissions = [];
|
||||
foreach (array_keys($result) as $itemName) {
|
||||
if (isset($this->_items[$itemName]) && $this->_items[$itemName] instanceof Permission) {
|
||||
$permissions[$itemName] = $this->_items[$itemName];
|
||||
if (isset($this->items[$itemName]) && $this->items[$itemName] instanceof Permission) {
|
||||
$permissions[$itemName] = $this->items[$itemName];
|
||||
}
|
||||
}
|
||||
return $permissions;
|
||||
@@ -373,8 +393,8 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
protected function getChildrenRecursive($name, &$result)
|
||||
{
|
||||
if (isset($this->_children[$name])) {
|
||||
foreach ($this->_children[$name] as $child) {
|
||||
if (isset($this->children[$name])) {
|
||||
foreach ($this->children[$name] as $child) {
|
||||
$result[$child->name] = true;
|
||||
$this->getChildrenRecursive($child->name, $result);
|
||||
}
|
||||
@@ -398,8 +418,8 @@ class PhpManager extends BaseManager
|
||||
|
||||
$permissions = [];
|
||||
foreach (array_keys($result) as $itemName) {
|
||||
if (isset($this->_items[$itemName]) && $this->_items[$itemName] instanceof Permission) {
|
||||
$permissions[$itemName] = $this->_items[$itemName];
|
||||
if (isset($this->items[$itemName]) && $this->items[$itemName] instanceof Permission) {
|
||||
$permissions[$itemName] = $this->items[$itemName];
|
||||
}
|
||||
}
|
||||
return $permissions;
|
||||
@@ -410,7 +430,7 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function getChildren($name)
|
||||
{
|
||||
return isset($this->_children[$name]) ? $this->_children[$name] : [];
|
||||
return isset($this->children[$name]) ? $this->children[$name] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -418,10 +438,10 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function removeAll()
|
||||
{
|
||||
$this->_children = [];
|
||||
$this->_items = [];
|
||||
$this->_assignments = [];
|
||||
$this->_rules = [];
|
||||
$this->children = [];
|
||||
$this->items = [];
|
||||
$this->assignments = [];
|
||||
$this->rules = [];
|
||||
$this->save();
|
||||
}
|
||||
|
||||
@@ -448,9 +468,9 @@ class PhpManager extends BaseManager
|
||||
protected function removeAllItems($type)
|
||||
{
|
||||
$names = [];
|
||||
foreach ($this->_items as $name => $item) {
|
||||
foreach ($this->items as $name => $item) {
|
||||
if ($item->type == $type) {
|
||||
unset($this->_items[$name]);
|
||||
unset($this->items[$name]);
|
||||
$names[$name] = true;
|
||||
}
|
||||
}
|
||||
@@ -458,25 +478,25 @@ class PhpManager extends BaseManager
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->_assignments as $i => $assignment) {
|
||||
foreach ($this->assignments as $i => $assignment) {
|
||||
if (isset($names[$assignment->roleName])) {
|
||||
unset($this->_assignments[$i]);
|
||||
unset($this->assignments[$i]);
|
||||
}
|
||||
}
|
||||
foreach ($this->_children as $name => $children) {
|
||||
foreach ($this->children as $name => $children) {
|
||||
if (isset($names[$name])) {
|
||||
unset($this->_children[$name]);
|
||||
unset($this->children[$name]);
|
||||
} else {
|
||||
foreach ($children as $childName => $item) {
|
||||
if (isset($names[$childName])) {
|
||||
unset($children[$childName]);
|
||||
}
|
||||
}
|
||||
$this->_children[$name] = $children;
|
||||
$this->children[$name] = $children;
|
||||
}
|
||||
}
|
||||
|
||||
$this->save();
|
||||
$this->saveItems();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -484,11 +504,11 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function removeAllRules()
|
||||
{
|
||||
foreach ($this->_items as $item) {
|
||||
foreach ($this->items as $item) {
|
||||
$item->ruleName = null;
|
||||
}
|
||||
$this->_rules = [];
|
||||
$this->save();
|
||||
$this->rules = [];
|
||||
$this->saveRules();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -496,8 +516,8 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
public function removeAllAssignments()
|
||||
{
|
||||
$this->_assignments = [];
|
||||
$this->save();
|
||||
$this->assignments = [];
|
||||
$this->saveAssignments();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -505,14 +525,14 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
protected function removeRule($rule)
|
||||
{
|
||||
if (isset($this->_rules[$rule->name])) {
|
||||
unset($this->_rules[$rule->name]);
|
||||
foreach ($this->_items as $item) {
|
||||
if (isset($this->rules[$rule->name])) {
|
||||
unset($this->rules[$rule->name]);
|
||||
foreach ($this->items as $item) {
|
||||
if ($item->ruleName === $rule->name) {
|
||||
$item->ruleName = null;
|
||||
}
|
||||
}
|
||||
$this->save();
|
||||
$this->saveRules();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -524,8 +544,8 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
protected function addRule($rule)
|
||||
{
|
||||
$this->_rules[$rule->name] = $rule;
|
||||
$this->save();
|
||||
$this->rules[$rule->name] = $rule;
|
||||
$this->saveRules();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -534,25 +554,25 @@ class PhpManager extends BaseManager
|
||||
*/
|
||||
protected function updateItem($name, $item)
|
||||
{
|
||||
$this->_items[$item->name] = $item;
|
||||
$this->items[$item->name] = $item;
|
||||
if ($name !== $item->name) {
|
||||
if (isset($this->_items[$item->name])) {
|
||||
if (isset($this->items[$item->name])) {
|
||||
throw new InvalidParamException("Unable to change the item name. The name '{$item->name}' is already used by another item.");
|
||||
}
|
||||
if (isset($this->_items[$name])) {
|
||||
unset ($this->_items[$name]);
|
||||
if (isset($this->items[$name])) {
|
||||
unset ($this->items[$name]);
|
||||
|
||||
if (isset($this->_children[$name])) {
|
||||
$this->_children[$item->name] = $this->_children[$name];
|
||||
unset ($this->_children[$name]);
|
||||
if (isset($this->children[$name])) {
|
||||
$this->children[$item->name] = $this->children[$name];
|
||||
unset ($this->children[$name]);
|
||||
}
|
||||
foreach ($this->_children as &$children) {
|
||||
foreach ($this->children as &$children) {
|
||||
if (isset($children[$name])) {
|
||||
$children[$item->name] = $children[$name];
|
||||
unset ($children[$name]);
|
||||
}
|
||||
}
|
||||
foreach ($this->_assignments as &$assignments) {
|
||||
foreach ($this->assignments as &$assignments) {
|
||||
if (isset($assignments[$name])) {
|
||||
$assignments[$item->name] = $assignments[$name];
|
||||
unset($assignments[$name]);
|
||||
@@ -560,7 +580,7 @@ class PhpManager extends BaseManager
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->save();
|
||||
$this->saveItems();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -577,9 +597,9 @@ class PhpManager extends BaseManager
|
||||
$item->updatedAt = $time;
|
||||
}
|
||||
|
||||
$this->_items[$item->name] = $item;
|
||||
$this->items[$item->name] = $item;
|
||||
|
||||
$this->save();
|
||||
$this->saveItems();
|
||||
|
||||
return true;
|
||||
|
||||
@@ -588,95 +608,63 @@ class PhpManager extends BaseManager
|
||||
/**
|
||||
* Loads authorization data from persistent storage.
|
||||
*/
|
||||
public function load()
|
||||
protected function load()
|
||||
{
|
||||
$this->_children = [];
|
||||
$this->_rules = [];
|
||||
$this->_assignments = [];
|
||||
$this->_items = [];
|
||||
$this->children = [];
|
||||
$this->rules = [];
|
||||
$this->assignments = [];
|
||||
$this->items = [];
|
||||
|
||||
$data = $this->loadFromFile($this->authFile);
|
||||
$items = $this->loadFromFile($this->itemFile);
|
||||
$itemsMtime = @filemtime($this->itemFile);
|
||||
$assignments = $this->loadFromFile($this->assignmentFile);
|
||||
$assignmentsMtime = @filemtime($this->assignmentFile);
|
||||
$rules = $this->loadFromFile($this->ruleFile);
|
||||
|
||||
if (isset($data['items'])) {
|
||||
foreach ($data['items'] as $name => $item) {
|
||||
foreach ($items as $name => $item) {
|
||||
$class = $item['type'] == Item::TYPE_PERMISSION ? Permission::className() : Role::className();
|
||||
|
||||
$this->_items[$name] = new $class([
|
||||
$this->items[$name] = new $class([
|
||||
'name' => $name,
|
||||
'description' => isset($item['description']) ? $item['description'] : null,
|
||||
'ruleName' => isset($item['ruleName']) ? $item['ruleName'] : null,
|
||||
'data' => isset($item['data']) ? $item['data'] : null,
|
||||
'createdAt' => isset($item['createdAt']) ? $item['createdAt'] : null,
|
||||
'updatedAt' => isset($item['updatedAt']) ? $item['updatedAt'] : null,
|
||||
'createdAt' => $itemsMtime,
|
||||
'updatedAt' => $itemsMtime,
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($data['items'] as $name => $item) {
|
||||
foreach ($items as $name => $item) {
|
||||
if (isset($item['children'])) {
|
||||
foreach ($item['children'] as $childName) {
|
||||
if (isset($this->_items[$childName])) {
|
||||
$this->_children[$name][$childName] = $this->_items[$childName];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($item['assignments'])) {
|
||||
foreach ($item['assignments'] as $userId => $assignment) {
|
||||
$this->_assignments[$userId][$name] = new Assignment([
|
||||
'userId' => $userId,
|
||||
'roleName' => $assignment['roleName'],
|
||||
'createdAt' => isset($assignment['createdAt']) ? $assignment['createdAt'] : null,
|
||||
]);
|
||||
if (isset($this->items[$childName])) {
|
||||
$this->children[$name][$childName] = $this->items[$childName];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($data['rules'])) {
|
||||
foreach ($data['rules'] as $name => $ruleData) {
|
||||
$this->_rules[$name] = unserialize($ruleData);
|
||||
foreach ($assignments as $userId => $role) {
|
||||
$this->assignments[$userId][$role] = new Assignment([
|
||||
'userId' => $userId,
|
||||
'roleName' => $role,
|
||||
'createdAt' => $assignmentsMtime,
|
||||
]);
|
||||
}
|
||||
|
||||
foreach ($rules as $name => $ruleData) {
|
||||
$this->rules[$name] = unserialize($ruleData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves authorization data into persistent storage.
|
||||
*/
|
||||
public function save()
|
||||
protected function save()
|
||||
{
|
||||
$items = [];
|
||||
foreach ($this->_items as $name => $item) {
|
||||
/* @var $item Item */
|
||||
$items[$name] = array_filter([
|
||||
'type' => $item->type,
|
||||
'description' => $item->description,
|
||||
'ruleName' => $item->ruleName,
|
||||
'data' => $item->data,
|
||||
]);
|
||||
if (isset($this->_children[$name])) {
|
||||
foreach ($this->_children[$name] as $child) {
|
||||
/* @var $child Item */
|
||||
$items[$name]['children'][] = $child->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->_assignments as $userId => $assignments) {
|
||||
foreach ($assignments as $name => $assignment) {
|
||||
/* @var $assignment Assignment */
|
||||
if (isset($items[$name])) {
|
||||
$items[$name]['assignments'][$userId] = [
|
||||
'roleName' => $assignment->roleName,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$rules = [];
|
||||
foreach ($this->_rules as $name => $rule) {
|
||||
$rules[$name] = serialize($rule);
|
||||
}
|
||||
|
||||
$this->saveToFile(['items' => $items, 'rules' => $rules], $this->authFile);
|
||||
$this->saveItems();
|
||||
$this->saveAssignments();
|
||||
$this->saveRules();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -706,4 +694,57 @@ class PhpManager extends BaseManager
|
||||
{
|
||||
file_put_contents($file, "<?php\nreturn " . VarDumper::export($data) . ";\n", LOCK_EX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves items data into persistent storage.
|
||||
*/
|
||||
protected function saveItems()
|
||||
{
|
||||
$items = [];
|
||||
foreach ($this->items as $name => $item) {
|
||||
/* @var $item Item */
|
||||
$items[$name] = array_filter(
|
||||
[
|
||||
'type' => $item->type,
|
||||
'description' => $item->description,
|
||||
'ruleName' => $item->ruleName,
|
||||
'data' => $item->data,
|
||||
]
|
||||
);
|
||||
if (isset($this->children[$name])) {
|
||||
foreach ($this->children[$name] as $child) {
|
||||
/* @var $child Item */
|
||||
$items[$name]['children'][] = $child->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->saveToFile($items, $this->itemFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves assignments data into persistent storage.
|
||||
*/
|
||||
protected function saveAssignments()
|
||||
{
|
||||
$assignmentData = [];
|
||||
foreach ($this->assignments as $userId => $assignments) {
|
||||
foreach ($assignments as $name => $assignment) {
|
||||
/* @var $assignment Assignment */
|
||||
$assignmentData[$userId] = $assignment->roleName;
|
||||
}
|
||||
}
|
||||
$this->saveToFile($assignmentData, $this->assignmentFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves rules data into persistent storage.
|
||||
*/
|
||||
protected function saveRules()
|
||||
{
|
||||
$rules = [];
|
||||
foreach ($this->rules as $name => $rule) {
|
||||
$rules[$name] = serialize($rule);
|
||||
}
|
||||
$this->saveToFile($rules, $this->ruleFile);
|
||||
}
|
||||
}
|
||||
|
||||
37
tests/unit/framework/rbac/ExposedPhpManager.php
Normal file
37
tests/unit/framework/rbac/ExposedPhpManager.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
namespace yiiunit\framework\rbac;
|
||||
|
||||
use yii\rbac\PhpManager;
|
||||
|
||||
/**
|
||||
* Exposes protected properties and methods to inspect from outside
|
||||
*/
|
||||
class ExposedPhpManager extends PhpManager
|
||||
{
|
||||
/**
|
||||
* @var \yii\rbac\Item[]
|
||||
*/
|
||||
public $items = []; // itemName => item
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
public $children = []; // itemName, childName => child
|
||||
/**
|
||||
* @var \yii\rbac\Assignment[]
|
||||
*/
|
||||
public $assignments = []; // userId, itemName => assignment
|
||||
/**
|
||||
* @var \yii\rbac\Rule[]
|
||||
*/
|
||||
public $rules = []; // ruleName => rule
|
||||
|
||||
public function load()
|
||||
{
|
||||
parent::load();
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
parent::save();
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,9 @@ use yii\rbac\Permission;
|
||||
use yii\rbac\Role;
|
||||
use yiiunit\TestCase;
|
||||
|
||||
/**
|
||||
* ManagerTestCase
|
||||
*/
|
||||
abstract class ManagerTestCase extends TestCase
|
||||
{
|
||||
/**
|
||||
@@ -14,7 +17,7 @@ abstract class ManagerTestCase extends TestCase
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
public function testCreateRoleAndPermission()
|
||||
public function testCreateRole()
|
||||
{
|
||||
$role = $this->auth->createRole('admin');
|
||||
$this->assertTrue($role instanceof Role);
|
||||
@@ -57,174 +60,6 @@ abstract class ManagerTestCase extends TestCase
|
||||
$this->auth->addChild($user, $changeName);
|
||||
$this->assertCount(1, $this->auth->getChildren($user->name));
|
||||
}
|
||||
/*
|
||||
public function testRemove()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function testUpdate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function testCreateItem()
|
||||
{
|
||||
$type = Item::TYPE_TASK;
|
||||
$name = 'editUser';
|
||||
$description = 'edit a user';
|
||||
$ruleName = 'isAuthor';
|
||||
$data = [1, 2, 3];
|
||||
$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->ruleName, $ruleName);
|
||||
$this->assertEquals($item->data, $data);
|
||||
|
||||
// test shortcut
|
||||
$name2 = 'createUser';
|
||||
$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, $ruleName, $data);
|
||||
}
|
||||
|
||||
public function testGetItem()
|
||||
{
|
||||
$this->assertTrue($this->auth->getItem('readPost') instanceof Item);
|
||||
$this->assertTrue($this->auth->getItem('reader') instanceof Item);
|
||||
$this->assertNull($this->auth->getItem('unknown'));
|
||||
}
|
||||
|
||||
public function testRemoveItem()
|
||||
{
|
||||
$this->assertTrue($this->auth->getItem('updatePost') instanceof Item);
|
||||
$this->assertTrue($this->auth->removeItem('updatePost'));
|
||||
$this->assertNull($this->auth->getItem('updatePost'));
|
||||
$this->assertFalse($this->auth->removeItem('updatePost'));
|
||||
}
|
||||
|
||||
public function testChangeItemName()
|
||||
{
|
||||
$item = $this->auth->getItem('readPost');
|
||||
$this->assertTrue($item instanceof Item);
|
||||
$this->assertTrue($this->auth->hasItemChild('reader', 'readPost'));
|
||||
$item->name = 'readPost2';
|
||||
$item->save();
|
||||
$this->assertNull($this->auth->getItem('readPost'));
|
||||
$this->assertEquals($this->auth->getItem('readPost2'), $item);
|
||||
$this->assertFalse($this->auth->hasItemChild('reader', 'readPost'));
|
||||
$this->assertTrue($this->auth->hasItemChild('reader', 'readPost2'));
|
||||
}
|
||||
|
||||
public function testAddItemChild()
|
||||
{
|
||||
$this->auth->addItemChild('createPost', 'updatePost');
|
||||
|
||||
// test adding upper level item to lower one
|
||||
$this->setExpectedException('\yii\base\Exception');
|
||||
$this->auth->addItemChild('readPost', 'reader');
|
||||
}
|
||||
|
||||
public function testAddItemChild2()
|
||||
{
|
||||
// test adding inexistent items
|
||||
$this->setExpectedException('\yii\base\Exception');
|
||||
$this->assertFalse($this->auth->addItemChild('createPost2', 'updatePost'));
|
||||
}
|
||||
|
||||
public function testRemoveItemChild()
|
||||
{
|
||||
$this->assertTrue($this->auth->hasItemChild('reader', 'readPost'));
|
||||
$this->assertTrue($this->auth->removeItemChild('reader', 'readPost'));
|
||||
$this->assertFalse($this->auth->hasItemChild('reader', 'readPost'));
|
||||
$this->assertFalse($this->auth->removeItemChild('reader', 'readPost'));
|
||||
}
|
||||
|
||||
public function testGetItemChildren()
|
||||
{
|
||||
$this->assertEquals([], $this->auth->getItemChildren('readPost'));
|
||||
$children = $this->auth->getItemChildren('author');
|
||||
$this->assertEquals(3, count($children));
|
||||
$this->assertTrue(reset($children) instanceof Item);
|
||||
}
|
||||
|
||||
public function testAssign()
|
||||
{
|
||||
$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->ruleName, 'isAuthor');
|
||||
$this->assertEquals($auth->data, 'data');
|
||||
|
||||
$this->setExpectedException('\yii\base\Exception');
|
||||
$this->auth->assign('new user', 'createPost2', 'rule', 'data');
|
||||
}
|
||||
|
||||
public function testRevoke()
|
||||
{
|
||||
$this->assertTrue($this->auth->isAssigned('author B', 'author'));
|
||||
$auth = $this->auth->getAssignment('author B', 'author');
|
||||
$this->assertTrue($auth instanceof Assignment);
|
||||
$this->assertTrue($this->auth->revoke('author B', 'author'));
|
||||
$this->assertFalse($this->auth->isAssigned('author B', 'author'));
|
||||
$this->assertFalse($this->auth->revoke('author B', 'author'));
|
||||
}
|
||||
|
||||
public function testRevokeAll()
|
||||
{
|
||||
$this->assertTrue($this->auth->revokeAll('reader E'));
|
||||
$this->assertFalse($this->auth->isAssigned('reader E', 'reader'));
|
||||
}
|
||||
|
||||
public function testGetAssignments()
|
||||
{
|
||||
$this->auth->assign('author B', 'deletePost');
|
||||
$auths = $this->auth->getAssignments('author B');
|
||||
$this->assertEquals(2, count($auths));
|
||||
$this->assertTrue(reset($auths) instanceof Assignment);
|
||||
}
|
||||
|
||||
public function testGetItems()
|
||||
{
|
||||
$this->assertEquals(count($this->auth->getRoles()), 4);
|
||||
$this->assertEquals(count($this->auth->getOperations()), 4);
|
||||
$this->assertEquals(count($this->auth->getTasks()), 1);
|
||||
$this->assertEquals(count($this->auth->getItems()), 9);
|
||||
|
||||
$this->assertEquals(count($this->auth->getItems('author B', null)), 1);
|
||||
$this->assertEquals(count($this->auth->getItems('author C', null)), 0);
|
||||
$this->assertEquals(count($this->auth->getItems('author B', Item::TYPE_ROLE)), 1);
|
||||
$this->assertEquals(count($this->auth->getItems('author B', Item::TYPE_OPERATION)), 0);
|
||||
}
|
||||
|
||||
public function testClearAll()
|
||||
{
|
||||
$this->auth->clearAll();
|
||||
$this->assertEquals(count($this->auth->getRoles()), 0);
|
||||
$this->assertEquals(count($this->auth->getOperations()), 0);
|
||||
$this->assertEquals(count($this->auth->getTasks()), 0);
|
||||
$this->assertEquals(count($this->auth->getItems()), 0);
|
||||
$this->assertEquals(count($this->auth->getAssignments('author B')), 0);
|
||||
}
|
||||
|
||||
public function testClearAssignments()
|
||||
{
|
||||
$this->auth->clearAssignments();
|
||||
$this->assertEquals(count($this->auth->getAssignments('author B')), 0);
|
||||
}
|
||||
|
||||
public function testDetectLoop()
|
||||
{
|
||||
$this->setExpectedException('\yii\base\Exception');
|
||||
$this->auth->addItemChild('readPost', 'readPost');
|
||||
}
|
||||
*/
|
||||
|
||||
public function testGetRule()
|
||||
{
|
||||
|
||||
@@ -3,38 +3,74 @@
|
||||
namespace yiiunit\framework\rbac;
|
||||
|
||||
use Yii;
|
||||
use yii\rbac\PhpManager;
|
||||
|
||||
/**
|
||||
* @group rbac
|
||||
* @property \yii\rbac\PhpManager $auth
|
||||
* @property ExposedPhpManager $auth
|
||||
*/
|
||||
class PhpManagerTest extends ManagerTestCase
|
||||
{
|
||||
protected function getItemFile()
|
||||
{
|
||||
return Yii::$app->getRuntimePath() . '/rbac-items.php';
|
||||
}
|
||||
|
||||
protected function getAssignmentFile()
|
||||
{
|
||||
return Yii::$app->getRuntimePath() . '/rbac-assignments.php';
|
||||
}
|
||||
|
||||
protected function getRuleFile()
|
||||
{
|
||||
return Yii::$app->getRuntimePath() . '/rbac-rules.php';
|
||||
}
|
||||
|
||||
protected function removeDataFiles()
|
||||
{
|
||||
@unlink($this->getItemFile());
|
||||
@unlink($this->getAssignmentFile());
|
||||
@unlink($this->getRuleFile());
|
||||
}
|
||||
|
||||
protected function createManager()
|
||||
{
|
||||
return new ExposedPhpManager([
|
||||
'itemFile' => $this->getItemFile(),
|
||||
'assignmentFile' => $this->getAssignmentFile(),
|
||||
'ruleFile' => $this->getRuleFile(),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->mockApplication();
|
||||
$authFile = Yii::$app->getRuntimePath() . '/rbac.php';
|
||||
@unlink($authFile);
|
||||
$this->auth = new PhpManager();
|
||||
$this->auth->authFile = $authFile;
|
||||
$this->auth->init();
|
||||
$this->removeDataFiles();
|
||||
$this->auth = $this->createManager();
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
$this->removeDataFiles();
|
||||
parent::tearDown();
|
||||
@unlink($this->auth->authFile);
|
||||
}
|
||||
|
||||
public function testSaveLoad()
|
||||
{
|
||||
$this->prepareData();
|
||||
$this->auth->save();
|
||||
$this->auth->removeAll();
|
||||
$this->auth->load();
|
||||
// TODO : Check if loaded and saved data are the same.
|
||||
}
|
||||
|
||||
$items = $this->auth->items;
|
||||
$children = $this->auth->children;
|
||||
$assignments = $this->auth->assignments;
|
||||
$rules = $this->auth->rules;
|
||||
$this->auth->save();
|
||||
|
||||
$this->auth = $this->createManager();
|
||||
$this->auth->load();
|
||||
|
||||
$this->assertEquals($items, $this->auth->items);
|
||||
$this->assertEquals($children, $this->auth->children);
|
||||
$this->assertEquals($assignments, $this->auth->assignments);
|
||||
$this->assertEquals($rules, $this->auth->rules);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user