Empty array in accessRules

Hello,

I would like to propose this as a bug, although it’s not clear it is one:

If you have an access rule like this

array(‘allow’,

    'actions'=>array(),


    'users'=>array('@'),

),

then instead of disallowing everything, it allows everything for authenticated users. (See also http://www.yiiframework.com/forum/index.php?/topic/11054-access-rules-for-the-module/)

I feel the default behavior needs to be changed, took me some time to figure out what was going on because I totally did not expect this behavior.

Best wishes,

Lupin

This is expected behavior. See the second tip in this section of the guide:

http://www.yiiframework.com/doc/guide/1.1/en/topics.auth#access-control-filter

Sorry, I should have written that this empty array allows everything even when a general deny rule finishes the accessRules.

So to add a full example, a ruleset like this

    public function accessRules()


    {


            return array(


                    array('allow',


                    'actions'=>array(),


                            'users'=>array('*'),


                    ),


                    array('deny',  // deny all users


                            'users'=>array('*'),


                    ),


            );


    }

allows everything. Specifying the empty array as the value of ‘actions’ should be different from leaving it undefined since it logically is.

I don’t understand. The first matching rule in a set of rules “wins”. So in your case the first rule is a match all rule, that allows everything. No request will ever make it to the deny rule in the end.

Oh, and could you please try to higlight your code examples with the “< >” Button in the editor? It’s very hard to read this way.

Yes, and that’s what I mean, why (not code wise, but logically) does the first case match all? After all, the array of actions it should match is empty, so it shouldn’t match any action.

Sorry about the highlighting, didn’t know.

It’s by design, as per current implementation…

Check the source of CAccessRule->isActionMatched() - http://www.yiiframework.com/doc/api/1.1/CAccessRule#isActionMatched-detail


return empty($this->actions) || in_array(strtolower($action->getId()),$this->actions);

So if the actions array is empty it maches all requested actions…

The default is to use “any” for every parameter you don’t specify/leave empty. That makes much sense, because otherwhise you’d always have to specify all available parameters (like roles, ips, verbs, …). So if you’re not satisfied with your first rule, why not leave it away?

I know it’s by implementation, that’s why I’m not saying it’s a bug, but I think the behavior isn’t correct either.

The point is, I’m saying that if you specify any array and don’t leave it undefined, that’s different, then it should be checked if the action is in the array, it should not be substituted by “any.” If it happens to be the empty array, then obviously this check has to fail. This is the only logical behavior, and while I’m not experienced with either PHP or Yii, I do feel competent to judge this by my scientific background ;)

Also “just leaving out” is of course a solution, but that’s like solving a bug by “just doing something else.” The array might be automatically generated, for example, and so on.

I think i understand what you mean, but still i wouldn’t agree. You want your first rule to translate to:

Allow no actions.

But that’s not how it works. Instead you have to say

Deny all actions.

You can not create a deny rule with an allow rule. So if you want to deny something, you have to explicitely specify a deny rule. From the combination of allow + deny you then can create your complex authorization chain (similar to a firewall, look at iptables for example). So if you consider that, it’s only convenient to translate an empty list of allowed actions to “any” because nothing else would make sense: An allow rule with empty actions would be completely ignored.

Even if you still don’t agree, i guess you’ll have to get used to this. A change here would break backward compatibility and Yii tries to avoid such breaks whenever possible.

Yes, completely ignoring the rule would be the syntactically correct behavior as it does vacuously not apply to any action.

This sounds reasonable, in fact so reasonable that while I still think the behavior is confusing it’s better to stick to it. Maybe not for Yii 2.0 though.