diff --git a/framework/rbac/Assignment.php b/framework/rbac/Assignment.php index c2a9f56..576017e 100644 --- a/framework/rbac/Assignment.php +++ b/framework/rbac/Assignment.php @@ -19,24 +19,24 @@ use yii\base\Object; class Assignment extends Object { private $_auth; - private $_itemName; private $_userId; + private $_itemName; private $_bizRule; private $_data; /** * Constructor. * @param IManager $auth the authorization manager - * @param string $itemName authorization item name * @param mixed $userId user ID (see [[User::id]]) + * @param string $itemName authorization item name * @param string $bizRule the business rule associated with this assignment * @param mixed $data additional data for this assignment */ - public function __construct($auth, $itemName, $userId, $bizRule = null, $data = null) + public function __construct($auth, $userId, $itemName, $bizRule = null, $data = null) { $this->_auth = $auth; - $this->_itemName = $itemName; $this->_userId = $userId; + $this->_itemName = $itemName; $this->_bizRule = $bizRule; $this->_data = $data; } diff --git a/framework/rbac/DbManager.php b/framework/rbac/DbManager.php new file mode 100644 index 0000000..5f64694 --- /dev/null +++ b/framework/rbac/DbManager.php @@ -0,0 +1,574 @@ + + * @author Alexander Kochetov + * @since 2.0 + */ +class DbManager extends Manager +{ + /** + * @var Connection|string the DB connection object or the application component ID of the DB connection. + * After the DbManager object is created, if you want to change this property, you should only assign it + * with a DB connection object. + */ + public $db = 'db'; + /** + * @var string the name of the table storing authorization items. Defaults to 'tbl_auth_item'. + */ + public $itemTable = 'tbl_auth_item'; + /** + * @var string the name of the table storing authorization item hierarchy. Defaults to 'tbl_auth_item_child'. + */ + public $itemChildTable = 'tbl_auth_item_child'; + /** + * @var string the name of the table storing authorization item assignments. Defaults to 'tbl_auth_assignment'. + */ + public $assignmentTable = 'tbl_auth_assignment'; + + private $_usingSqlite; + + /** + * Initializes the application component. + * This method overrides the parent implementation by establishing the database connection. + */ + public function init() + { + if (is_string($this->db)) { + $this->db = Yii::$app->getComponent($this->db); + } + if (!$this->db instanceof Connection) { + throw new InvalidConfigException("DbManager::db must be either a DB connection instance or the application component ID of a DB connection."); + } + $this->_usingSqlite = !strncmp($this->db->getDriverName(), 'sqlite', 6); + parent::init(); + } + + /** + * Performs access check for the specified user. + * @param mixed $userId the user ID. This should can be either an integer and a string representing + * @param string $itemName the name of the operation that need access check + * the unique identifier of a user. See [[User::id]]. + * @param array $params name-value pairs that would be passed to biz 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. + */ + public function checkAccess($userId, $itemName, $params = array()) + { + $assignments = $this->getAssignments($userId); + return $this->checkAccessRecursive($userId, $itemName, $params, $assignments); + } + + /** + * Performs access check for the specified user. + * This method is internally called by [[checkAccess()]]. + * @param mixed $userId the user ID. This should can be either an integer and a string representing + * the unique identifier of a user. See [[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 + * 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 + * @return boolean whether the operations can be performed by the user. + */ + protected function checkAccessRecursive($userId, $itemName, $params, $assignments) + { + if (($item = $this->getItem($itemName)) === null) { + return false; + } + Yii::trace('Checking permission: ' . $item->getName(), __METHOD__); + if (!isset($params['userId'])) { + $params['userId'] = $userId; + } + if ($this->executeBizRule($item->getBizRule(), $params, $item->getData())) { + if (in_array($itemName, $this->defaultRoles)) { + return true; + } + if (isset($assignments[$itemName])) { + $assignment = $assignments[$itemName]; + if ($this->executeBizRule($assignment->getBizRule(), $params, $assignment->getData())) { + return true; + } + } + $query = new Query; + $parents = $query->select(array('parent')) + ->from($this->itemChildTable) + ->where('child=:name', array(':name' => $itemName)) + ->createCommand($this->db) + ->queryColumn(); + foreach ($parents as $parent) { + if ($this->checkAccessRecursive($userId, $parent, $params, $assignments)) { + return true; + } + } + } + return false; + } + + /** + * Adds an item as a child of another item. + * @param string $itemName the parent item name + * @param string $childName the child item name + * @return boolean whether the item is added successfully + * @throws Exception if either parent or child doesn't exist or if a loop has been detected. + */ + public function addItemChild($itemName, $childName) + { + if ($itemName === $childName) { + throw new Exception("Cannot add '$itemName' as a child of itself."); + } + $query = new Query; + $rows = $query->from($this->itemTable) + ->where('name=:name1 OR name=:name2', array( + ':name1' => $itemName, + ':name2' => $childName + )) + ->createCommand($this->db) + ->queryAll(); + if (count($rows) == 2) { + if ($rows[0]['name'] === $itemName) { + $parentType = $rows[0]['type']; + $childType = $rows[1]['type']; + } else { + $childType = $rows[0]['type']; + $parentType = $rows[1]['type']; + } + $this->checkItemChildType($parentType, $childType); + if ($this->detectLoop($itemName, $childName)) { + throw new Exception("Cannot add '$childName' as a child of '$itemName'. A loop has been detected."); + } + $this->db->createCommand() + ->insert($this->itemChildTable, array( + 'parent' => $itemName, + 'child' => $childName, + )); + return true; + } else { + throw new Exception("Either '$itemName' or '$childName' does not exist."); + } + } + + /** + * Removes a child from its parent. + * Note, the child item is not deleted. Only the parent-child relationship is removed. + * @param string $itemName the parent item name + * @param string $childName the child item name + * @return boolean whether the removal is successful + */ + public function removeItemChild($itemName, $childName) + { + return $this->db->createCommand() + ->delete($this->itemChildTable, 'parent=:parent AND child=:child', array( + ':parent' => $itemName, + ':child' => $childName + )) > 0; + } + + /** + * Returns a value indicating whether a child exists within a parent. + * @param string $itemName the parent item name + * @param string $childName the child item name + * @return boolean whether the child exists + */ + public function hasItemChild($itemName, $childName) + { + $query = new Query; + return $query->select(array('parent')) + ->from($this->itemChildTable) + ->where('parent=:parent AND child=:child', array( + ':parent' => $itemName, + ':child' => $childName)) + ->createCommand($this->db) + ->queryScalar() !== false; + } + + /** + * Returns the children of the specified item. + * @param mixed $names the parent item name. This can be either a string or an array. + * The latter represents a list of item names. + * @return Item[] all child items of the parent + */ + public function getItemChildren($names) + { + if (is_string($names)) { + $condition = 'parent=' . $this->db->quoteValue($names); + } elseif (is_array($names) && !empty($names)) { + foreach ($names as &$name) { + $name = $this->db->quoteValue($name); + } + $condition = 'parent IN (' . implode(', ', $names) . ')'; + } + $query = new Query; + $rows = $query->select(array('name', 'type', 'description', 'bizrule', 'data')) + ->from(array( + $this->itemTable, + $this->itemChildTable + )) + ->where($condition . ' AND name=child') + ->createCommand($this->db) + ->queryAll(); + $children = array(); + foreach ($rows as $row) { + if (($data = @unserialize($row['data'])) === false) { + $data = null; + } + $children[$row['name']] = new Item($this, $row['name'], $row['type'], $row['description'], $row['bizrule'], $data); + } + return $children; + } + + /** + * Assigns an authorization item to a user. + * @param mixed $userId the user ID (see [[User::id]]) + * @param string $itemName the item name + * @param string $bizRule 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 Exception 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) + { + if ($this->usingSqlite() && $this->getItem($itemName) === null) { + throw new Exception("The item '$itemName' does not exist."); + } + $this->db->createCommand() + ->insert($this->assignmentTable, array( + 'userid' => $userId, + 'itemname' => $itemName, + 'bizrule' => $bizRule, + 'data' => serialize($data) + )); + return new Assignment($this, $userId, $itemName, $bizRule, $data); + } + + /** + * Revokes an authorization assignment from a user. + * @param mixed $userId the user ID (see [[User::id]]) + * @param string $itemName the item name + * @return boolean whether removal is successful + */ + public function revoke($userId, $itemName) + { + return $this->db->createCommand() + ->delete($this->assignmentTable, 'itemname=:itemname AND userid=:userid', array( + ':userid' => $userId, + ':itemname' => $itemName + )) > 0; + } + + /** + * Returns a value indicating whether the item has been assigned to the user. + * @param mixed $userId the user ID (see [[User::id]]) + * @param string $itemName the item name + * @return boolean whether the item has been assigned to the user. + */ + public function isAssigned($itemName, $userId) + { + $query = new Query; + return $query->select(array('itemname')) + ->from($this->assignmentTable) + ->where('itemname=:itemname AND userid=:userid', array( + ':userid' => $userId, + ':itemname' => $itemName + )) + ->createCommand($this->db) + ->queryScalar() !== false; + } + + /** + * Returns the item assignment information. + * @param mixed $userId the user ID (see [[User::id]]) + * @param string $itemName the item name + * @return Assignment the item assignment information. Null is returned if + * the item is not assigned to the user. + */ + public function getAssignment($userId, $itemName) + { + $query = new Query; + $row = $query->from($this->assignmentTable) + ->where('itemname=:itemname AND userid=:userid', array( + ':userid' => $userId, + ':itemname' => $itemName + )) + ->createCommand($this->db) + ->queryRow(); + if ($row !== false) { + if (($data = @unserialize($row['data'])) === false) { + $data = null; + } + return new Assignment($this, $row['userid'], $row['itemname'], $row['bizrule'], $data); + } else { + return null; + } + } + + /** + * Returns the item assignments for the specified user. + * @param mixed $userId the user ID (see [[User::id]]) + * @return Assignment[] the item assignment information for the user. An empty array will be + * returned if there is no item assigned to the user. + */ + public function getAssignments($userId) + { + $query = new Query; + $rows = $query->from($this->assignmentTable) + ->where('userid=:userid', array(':userid' => $userId)) + ->createCommand($this->db) + ->queryAll(); + $assignments = array(); + foreach ($rows as $row) { + if (($data = @unserialize($row['data'])) === false) { + $data = null; + } + $assignments[$row['itemname']] = new Assignment($this, $row['userid'], $row['itemname'], $row['bizrule'], $data); + } + return $assignments; + } + + /** + * Saves the changes to an authorization assignment. + * @param Assignment $assignment the assignment that has been changed. + */ + public function saveAssignment($assignment) + { + $this->db->createCommand() + ->update($this->assignmentTable, array( + 'bizrule' => $assignment->getBizRule(), + 'data' => serialize($assignment->getData()), + ), 'itemname=:itemname AND userid=:userid', array( + 'userid' => $assignment->getUserId(), + 'itemname' => $assignment->getItemName() + )); + } + + /** + * 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 + * they are not assigned to a user. + * @param integer $type the item type (0: operation, 1: task, 2: role). Defaults to null, + * meaning returning all items regardless of their type. + * @return Item[] the authorization items of the specific type. + */ + public function getItems($userId = null, $type = null) + { + $query = new Query; + if ($userId === null && $type === null) { + $command = $query->from($this->itemTable) + ->createCommand($this->db); + } elseif ($userId === null) { + $command = $query->from($this->itemTable) + ->where('type=:type', array(':type' => $type)) + ->createCommand($this->db); + } elseif ($type === null) { + $command = $query->select(array('name', 'type', 'description', 't1.bizrule', 't1.data')) + ->from(array( + $this->itemTable . ' t1', + $this->assignmentTable . ' t2' + )) + ->where('name=itemname AND userid=:userid', array(':userid' => $userId)) + ->createCommand($this->db); + } else { + $command = $query->select('name', 'type', 'description', 't1.bizrule', 't1.data') + ->from(array( + $this->itemTable . ' t1', + $this->assignmentTable . ' t2' + )) + ->where('name=itemname AND type=:type AND userid=:userid', array( + ':userid' => $userId, + ':type' => $type + )) + ->createCommand($this->db); + } + $items = array(); + foreach ($command->queryAll() as $row) { + if (($data = @unserialize($row['data'])) === false) { + $data = null; + } + $items[$row['name']] = new Item($this, $row['name'], $row['type'], $row['description'], $row['bizrule'], $data); + } + return $items; + } + + /** + * Creates an authorization item. + * An authorization item represents an action permission (e.g. creating a post). + * 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 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) + { + $this->db->createCommand() + ->insert($this->itemTable, array( + 'name' => $name, + 'type' => $type, + 'description' => $description, + 'bizrule' => $bizRule, + 'data' => serialize($data) + )); + return new Item($this, $name, $type, $description, $bizRule, $data); + } + + /** + * 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 + */ + public function removeItem($name) + { + if ($this->usingSqlite()) { + $this->db->createCommand() + ->delete($this->itemChildTable, 'parent=:name1 OR child=:name2', array( + ':name1' => $name, + ':name2' => $name + )); + $this->db->createCommand() + ->delete($this->assignmentTable, 'itemname=:name', array( + ':name' => $name, + )); + } + + return $this->db->createCommand() + ->delete($this->itemTable, 'name=:name', array( + ':name' => $name + )) > 0; + } + + /** + * 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. + */ + public function getItem($name) + { + $query = new Query; + $row = $query->from($this->itemTable) + ->where('name=:name', array(':name' => $name)) + ->createCommand($this->db) + ->queryRow(); + + if ($row !== false) { + if (($data = @unserialize($row['data'])) === false) { + $data = null; + } + return new Item($this, $row['name'], $row['type'], $row['description'], $row['bizrule'], $data); + } else + return null; + } + + /** + * 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. + */ + public function saveItem($item, $oldName = null) + { + if ($this->usingSqlite() && $oldName !== null && $item->getName() !== $oldName) { + $this->db->createCommand() + ->update($this->itemChildTable, array( + 'parent' => $item->getName(), + ), 'parent=:whereName', array( + ':whereName' => $oldName, + )); + $this->db->createCommand() + ->update($this->itemChildTable, array( + 'child' => $item->getName(), + ), 'child=:whereName', array( + ':whereName' => $oldName, + )); + $this->db->createCommand() + ->update($this->assignmentTable, array( + 'itemname' => $item->getName(), + ), 'itemname=:whereName', array( + ':whereName' => $oldName, + )); + } + + $this->db->createCommand() + ->update($this->itemTable, array( + 'name' => $item->getName(), + 'type' => $item->getType(), + 'description' => $item->getDescription(), + 'bizrule' => $item->getBizRule(), + 'data' => serialize($item->getData()), + ), 'name=:whereName', array( + ':whereName' => $oldName === null ? $item->getName() : $oldName, + )); + } + + /** + * Saves the authorization data to persistent storage. + */ + public function save() + { + } + + /** + * Removes all authorization data. + */ + public function clearAll() + { + $this->clearAssignments(); + $this->db->createCommand()->delete($this->itemChildTable); + $this->db->createCommand()->delete($this->itemTable); + } + + /** + * Removes all authorization assignments. + */ + public function clearAssignments() + { + $this->db->createCommand()->delete($this->assignmentTable); + } + + /** + * Checks whether there is a loop in the authorization item hierarchy. + * @param string $itemName parent item name + * @param string $childName the name of the child item that is to be added to the hierarchy + * @return boolean whether a loop exists + */ + protected function detectLoop($itemName, $childName) + { + if ($childName === $itemName) { + return true; + } + foreach ($this->getItemChildren($childName) as $child) { + if ($this->detectLoop($itemName, $child->getName())) { + return true; + } + } + return false; + } + + /** + * @return boolean whether the database is a SQLite database + */ + protected function usingSqlite() + { + return $this->_usingSqlite; + } +} diff --git a/framework/rbac/IManager.php b/framework/rbac/IManager.php new file mode 100644 index 0000000..6eeb661 --- /dev/null +++ b/framework/rbac/IManager.php @@ -0,0 +1,173 @@ + + * @author Alexander Kochetov + * @since 2.0 + */ +interface IManager +{ + /** + * Performs access check for the specified user. + * @param mixed $userId the user ID. This should be either an integer or a string representing + * the unique identifier of a user. See [[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 + * with the tasks and roles assigned to the user. + * @return boolean whether the operations can be performed by the user. + */ + public function checkAccess($userId, $itemName, $params = array()); + + /** + * Creates an authorization item. + * An authorization item represents an action permission (e.g. creating a post). + * 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 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 + */ + public function createItem($name, $type, $description = '', $bizRule = 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 + */ + 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 + * they are not assigned to a user. + * @param integer $type the item type (0: operation, 1: task, 2: role). Defaults to null, + * meaning returning all items regardless of their type. + * @return Item[] the authorization items of the specific type. + */ + 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. + */ + 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. + */ + public function saveItem($item, $oldName = null); + + /** + * Adds an item as a child of another item. + * @param string $itemName the parent item name + * @param string $childName the child item name + * @throws \yii\base\Exception if either parent or child doesn't exist or if a loop has been detected. + */ + 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. + * @param string $itemName the parent item name + * @param string $childName the child item name + * @return boolean whether the removal is successful + */ + public function removeItemChild($itemName, $childName); + /** + * Returns a value indicating whether a child exists within a parent. + * @param string $itemName the parent item name + * @param string $childName the child item name + * @return boolean whether the child exists + */ + 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. + * The latter represents a list of item names. + * @return Item[] all child items of the parent + */ + public function getItemChildren($itemName); + + /** + * Assigns an authorization item to a user. + * @param mixed $userId the user ID (see [[User::id]]) + * @param string $itemName the item name + * @param string $bizRule 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 \yii\base\Exception 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); + /** + * Revokes an authorization assignment from a user. + * @param mixed $userId the user ID (see [[User::id]]) + * @param string $itemName the item name + * @return boolean whether removal is successful + */ + public function revoke($userId, $itemName); + /** + * Returns a value indicating whether the item has been assigned to the user. + * @param mixed $userId the user ID (see [[User::id]]) + * @param string $itemName the item name + * @return boolean whether the item has been assigned to the user. + */ + public function isAssigned($userId, $itemName); + /** + * Returns the item assignment information. + * @param mixed $userId the user ID (see [[User::id]]) + * @param string $itemName the item name + * @return Assignment the item assignment information. Null is returned if + * the item is not assigned to the user. + */ + public function getAssignment($userId, $itemName); + /** + * Returns the item assignments for the specified user. + * @param mixed $userId the user ID (see [[User::id]]) + * @return Item[] the item assignment information for the user. An empty array will be + * returned if there is no item assigned to the user. + */ + public function getAssignments($userId); + /** + * Saves the changes to an authorization assignment. + * @param Assignment $assignment the assignment that has been changed. + */ + public function saveAssignment($assignment); + /** + * Removes all authorization data. + */ + public function clearAll(); + /** + * Removes all authorization assignments. + */ + public function clearAssignments(); + /** + * Saves authorization data into persistent storage. + * If any change is made to the authorization data, please make + * sure you call this method to save the changed data into persistent storage. + */ + public function save(); + /** + * Executes a business rule. + * A business rule is a piece of PHP code that will be executed when [[checkAccess()]] is called. + * @param string $bizRule the business rule to be executed. + * @param array $params additional parameters to be passed to the business rule when being executed. + * @param mixed $data additional data that is associated with the corresponding authorization item or assignment + * @return boolean whether the execution returns a true value. + * If the business rule is empty, it will also return true. + */ + public function executeBizRule($bizRule, $params, $data); +} diff --git a/framework/rbac/Item.php b/framework/rbac/Item.php index ba78e60..d09196f 100644 --- a/framework/rbac/Item.php +++ b/framework/rbac/Item.php @@ -202,7 +202,7 @@ class Item extends Object /** * Returns the children of this item. - * @return array all child items of this item. + * @return Item[] all child items of this item. * @see IManager::getItemChildren */ public function getChildren() diff --git a/framework/rbac/Manager.php b/framework/rbac/Manager.php index 2f77e10..4846546 100644 --- a/framework/rbac/Manager.php +++ b/framework/rbac/Manager.php @@ -83,7 +83,7 @@ abstract class Manager extends Component implements IManager * This is a shortcut method to [[IManager::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 array roles (name=>AuthItem) + * @return Item[] roles (name=>AuthItem) */ public function getRoles($userId = null) { @@ -95,7 +95,7 @@ abstract class Manager extends Component implements IManager * This is a shortcut method to [[IManager::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 array tasks (name=>AuthItem) + * @return Item[] tasks (name=>AuthItem) */ public function getTasks($userId = null) { @@ -107,7 +107,7 @@ abstract class Manager extends Component implements IManager * This is a shortcut method to [[IManager::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 array operations (name=>AuthItem) + * @return Item[] operations (name=>AuthItem) */ public function getOperations($userId = null) { diff --git a/framework/rbac/PhpManager.php b/framework/rbac/PhpManager.php index 08f5c83..3f471c6 100644 --- a/framework/rbac/PhpManager.php +++ b/framework/rbac/PhpManager.php @@ -52,8 +52,8 @@ class PhpManager extends Manager * @param string $itemName the name of the operation that need access check * the unique identifier of a user. See [[User::id]]. * @param array $params name-value pairs that would be passed to biz rules associated - * with the tasks and roles assigned to the user. - * Since version 1.1.11 a param with name 'userId' is added to this array, which holds the value of $userId. + * 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. */ public function checkAccess($userId, $itemName, $params = array()) @@ -61,6 +61,7 @@ class PhpManager extends Manager if (!isset($this->_items[$itemName])) { return false; } + /** @var $item Item */ $item = $this->_items[$itemName]; Yii::trace('Checking permission: ' . $item->getName(), __METHOD__); if (!isset($params['userId'])) { @@ -71,6 +72,7 @@ class PhpManager extends Manager return true; } if (isset($this->_assignments[$userId][$itemName])) { + /** @var $assignment Assignment */ $assignment = $this->_assignments[$userId][$itemName]; if ($this->executeBizRule($assignment->getBizRule(), $params, $assignment->getData())) { return true; @@ -97,7 +99,9 @@ class PhpManager extends Manager if (!isset($this->_items[$childName], $this->_items[$itemName])) { throw new Exception("Either '$itemName' or '$childName' does not exist."); } + /** @var $child Item */ $child = $this->_items[$childName]; + /** @var $item Item */ $item = $this->_items[$itemName]; $this->checkItemChildType($item->getType(), $child->getType()); if ($this->detectLoop($itemName, $childName)) { @@ -142,7 +146,7 @@ class PhpManager extends Manager * Returns the children of the specified item. * @param mixed $names the parent item name. This can be either a string or an array. * The latter represents a list of item names. - * @return array all child items of the parent + * @return Item[] all child items of the parent */ public function getItemChildren($names) { @@ -176,7 +180,7 @@ class PhpManager extends Manager } elseif (isset($this->_assignments[$userId][$itemName])) { throw new Exception("Authorization item '$itemName' has already been assigned to user '$userId'."); } else { - return $this->_assignments[$userId][$itemName] = new Assignment($this, $itemName, $userId, $bizRule, $data); + return $this->_assignments[$userId][$itemName] = new Assignment($this, $userId, $itemName, $bizRule, $data); } } @@ -222,7 +226,7 @@ class PhpManager extends Manager /** * Returns the item assignments for the specified user. * @param mixed $userId the user ID (see [[User::id]]) - * @return array the item assignment information for the user. An empty array will be + * @return Assignment[] the item assignment information for the user. An empty array will be * returned if there is no item assigned to the user. */ public function getAssignments($userId) @@ -236,22 +240,24 @@ class PhpManager extends Manager * they are not assigned to a user. * @param integer $type the item type (0: operation, 1: task, 2: role). Defaults to null, * meaning returning all items regardless of their type. - * @return array the authorization items of the specific type. + * @return Item[] the authorization items of the specific type. */ public function getItems($userId = null, $type = null) { - if ($type === null && $userId === null) { + if ($userId === null && $type === null) { return $this->_items; } $items = array(); if ($userId === null) { foreach ($this->_items as $name => $item) { + /** @var $item Item */ if ($item->getType() == $type) { $items[$name] = $item; } } } elseif (isset($this->_assignments[$userId])) { foreach ($this->_assignments[$userId] as $assignment) { + /** @var $assignment Assignment */ $name = $assignment->getItemName(); if (isset($this->_items[$name]) && ($type === null || $this->_items[$name]->getType() == $type)) { $items[$name] = $this->_items[$name]; @@ -368,6 +374,7 @@ class PhpManager extends Manager { $items = array(); foreach ($this->_items as $name => $item) { + /** @var $item Item */ $items[$name] = array( 'type' => $item->getType(), 'description' => $item->getDescription(), @@ -376,6 +383,7 @@ class PhpManager extends Manager ); if (isset($this->_children[$name])) { foreach ($this->_children[$name] as $child) { + /** @var $child Item */ $items[$name]['children'][] = $child->getName(); } } @@ -383,6 +391,7 @@ class PhpManager extends Manager foreach ($this->_assignments as $userId => $assignments) { foreach ($assignments as $name => $assignment) { + /** @var $assignment Assignment */ if (isset($items[$name])) { $items[$name]['assignments'][$userId] = array( 'bizRule' => $assignment->getBizRule(), @@ -457,6 +466,7 @@ class PhpManager extends Manager return false; } foreach ($this->_children[$childName] as $child) { + /** @var $child Item */ if ($this->detectLoop($itemName, $child->getName())) { return true; }