yii2: matchCallback does not work with other rules
I have been playing with this for a bit, and it doesn’t make sense. Maybe it is “coded” this way on purpose, but if it is, then it isn’t documented. So if matchCallback
is not supposed to contain other rules, then the docs should make that clear! However, scouring the code, it looks like it is supposed to match ALL of the rules.
Here is what I found in the code:
public function allows($action, $user, $request)
{
if ($this->matchAction($action)
&& $this->matchRole($user)
&& $this->matchIP($request->getUserIP())
&& $this->matchVerb($request->getMethod())
&& $this->matchController($action->controller)
&& $this->matchCustom($action)
) {
return $this->allow ? true : false;
} else {
return null;
}
}
This seems to indicate all the rules are required, including matchCustom
.
So if you have a rule like so:
[
'actions' => ['create'],
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
return AdminRole::canCreateUserAccounts(); // return boolean
}
],
They should be logged in (@
) AND matchCallback
should return true. I also tried by removing the allow
line, still lets them pass right on through.
It seems if matchCallback
is false, it lets me in. If it is true, it blocks me… This seems backwards…
So since it seemed backwards, I experimented with the allow
rule… setting it allow
to true, then toggled the user->id check between 1 (me) and 2 for another user… It had no effect at all, like allow
=>true overrides it no matter what. Setting allow
to false, does the same action as if it was commented out.
public function behaviors()
{
return [
'access' => [
'rules' => [
[
'actions' => ['index'],
//'allow' => true,
//'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
if ( Yii::$app->user->id === 1 ) {
return true;
}
return false;
},
],
],
],
];
}
It just seems like I can’t make it happy. What I am trying to do is actually run a function inside the match callback. For example: AdminRole::canCreateAccounts() which does a check if the admin is ROOT level (only root admins can create accounts). It grabs the current users role from db column, and returns true if they can, false if not. When using that function, it throws an error if the user is not logged in. Well, I had roles
set to @
during my testing, so that should have failed and sent them to the login page, before my action tried to access user data…
Am I missing something? or is the matchCallback clunky?
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Comments: 16 (10 by maintainers)
@mikehaertl It would be a handy feature.
I don’t really like having to declare every single action throughout the entire system. So using:
is great for that. However, it overrides the other rules.
The only way to get around it (without going down a rabbit hole of RBAC or extending things), is to explicitly declare each and every action.
A way to overcome this would be awesome. A way to tell it if
matchCallback
returns true, to allow it no matter what. And false, deny it no matter what. I understand, if it returns null, to keep checking. It is just annoying that the 1st global “authorized users” rule overrides it completely.