Hello,
I have the following setup:
A Permission named ‘manageBlocks’.
A Role named ‘AdminRole’ with Permission ‘manageBlocks’.
A User ‘user1’ with Role ‘AdminRole’.
A Controller ‘BlockController’ with:
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['post'],
]
],
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow'=>true,
'roles'=>['manageBlocks']
]
]
]
];
}
So I accidentily used a Permission in the ‘roles’ part of the ‘rules’. Which worked for ‘user1’ but maybe it shouldn’t?
I think this is why it works:
yii\filters\AccessRule.php has a function matchRole($user) which contains:
elseif ($user->can($role))
But this ‘can’ function is described as:
Checks if the user can perform the operation as specified by the given permission.
So according to the descriptions AccessRule->matchRole should check for a Role, but User->can should check for a Permission. But it seems that User->can checks for both Roles and Permissions?
I checked this and User->can calls $auth->checkAccess, in yii\rbac\DbManager.php:
public function checkAccess($userId, $permissionName, $params = [])
{
$assignments = $this->getAssignments($userId);
return $this->checkAccessRecursive($userId, $permissionName, $params, $assignments);
}
protected function checkAccessRecursive($user, $itemName, $params, $assignments)
{
So indeed eventually checkAccessRecursive treats the ‘permissionName’ as an ‘itemName’ which can be a Role or a Permission.
This means we’ve gone from a ‘role’ to a ‘permission’ to an ‘item’.
This doesn’t seem to be as clean as it should be. If in the future User->can does what is described (check for Permission) AccessRule->matchRole will not check for Roles anymore (but for Permissions).