How to pass $params to CWebUser::checkAccess() via controller's accessRules()

Hi,

When you use the standard CAccessControlFilter filter and define a controller’s accessRules() method to return rules, and specify a ‘roles’ parameter in one of the rules, CAccessControlFilter ultimately calls CWebUser::checkAccess() for each of the roles listed, to determine if the user have one of the roles.

However, CWebUser::checkAccess() also accepts as a default argument a $params array, which according to documentation is supposed to contain "name-value pairs that would be passed to business rules associated with the tasks and roles assigned to the user"

But I can’t find a place in the rules array to place such parameters, so that they get passed to checkAccess().

Is it possible? If not, how is the $params array intended to be used?

thanks

m.

No, it’s impossible (at least out of the box).

You can still call checkAccess() with parameters directly(manually) in your controller actions.

You may also want to look at this topic.

http://www.yiiframework.com/forum/index.php/topic/32890-user-access/

I see, thanks.

So that means the accessControl filter doesn’t allow you to use Yii’s basic Access Control features (like business rules)…

I guess I will have the same problem even if I use the RBAM extension, won’t I? The documentation explains everything about managing and assigning authorization items (and they do have bizrules and data) but doesn’t say a word about how to check permissions from the application. I guess I’ll still have to call checkAccess manually from the actions, right? (or extend AccessControlFilter)

thanks

m.

Yes, I think you are right.

However, I think the RBAC extension like yii-rights(this has been my choice) has a big advantage.

By using it as a filter, the access controlling can be significantly simplified, and is also made easier to be maintained.

And, while I agree that the biz-rule extended access control filter might be a great help, but I don’t think that it will satisfy all the needs.

For example, I often dynamically show and hide links and/or buttons according to the user’s right.

In such a case the filter doesn’t give us any help and we have to call checkAccess() manually in the view.

Of course, I didn’t mean that calling checkAccess() manually should never be necessary. That’s a one of a thousand cases where you need it, regardless of filters.

But when you are filtering the access to the action, you don’t want to do it by writing at the beginning of your actionWhatever() method:


if (!checkAccess(...)) throw new CHttpException(403)

Definitely. :)

You may want to check this.

http://www.yiiframework.com/forum/index.php/topic/32890-user-access/page__view__findpost__p__160404

Sounds good! thanks

By the way,

when you need to create authorization items that have a parameter, are business rules the way to go, or is there a better strategy?

For example, soppose you have a blog application with multiple "sections" and that every post belongs to a section. Then you may want to create authorization items (operations, tasks and roles) relative to a given section: e.g. operation "write post in <section>", or role "author in <section>", etc etc.

Well, if the section is a static one so that it can have a dedicated controller or an action, then I would create an authorization item for that controller or action.

Otherwise, I would have to use a business rule for it.

No, the sections need to be dynamic. :D

Thinking about it, I’m afraid a business rule could never solve the problem, because the id of the section needs to be part of the unique identifier (name?) of the authorization item.

Let’s say we want to be able to assign users roles such as:

Athor in section 1

Author in section 2

Editor in section 1

Editor in section 2

where Author means he has permission to create posts in that section, Editor means he has permission to edit/delete posts in that section.

At first thought, one says: ok I’ll create a role called “Author in section”, and role called “Editor in section” (let’s ignore the child tasks and operations for the moment). These items need a business rule to determine whether the section the user wants to post/edit in is the section he is an author/editor for.

RBAM apparently allows you to store "data" together with an athrorisation assignment; and to store bizrule for a given role. So if I want to assign a given user the Author role for a given section, I would assign him the role "Author in Section" and put the id of the section in the "data". That data supposedly is passed to the bizrule when performing the check.

BUT…

Than will only work if you can assign the same role to the same user multiple times with different values of “data” in each assignment, which I don’t think is the case. Or is it?

So, I couldn’t give have a user the role of author or editor for more than one specific areas.

When we have multiple dynamic sections, I think we have to have a look-up table that defines the auth relations between the users and the sections, so that we can pass the section ID to the business rule as a parameter.

Of course we need that table, but I don’t think the standard authManager mechanism provides a way to perform the check, without extending it.

What business rule would you pass the section ID to? Business rules belong to authorization items, or to assignments, but authorization items have a unique id, and assignments are uniquely identified by the auth item id and the user id. So you can’t assign the same auth item to the same user more than once with different section IDs…

I’m thinking something like the following.

In the controller action:




$post = Post::model()->findByPk($id);

if (Yii::app()->user->checkAccess('SectionEditor', array('section_id' => $post->section->id))

{

    ....

}

else if (Yii::app()->user->checkAccess('SectionAuthor', array('section_id' => $post->section->id))

{

    ....

}

else

{

    .... auth error

}



Business rule:




$user_id = Yii::app()->user->id;

$section_id = $params['section_id'];

$record = SectionUser::model()->findByAttributes(array(

    'user_id' => $user_id,

    'section_id' => $section_id,

));

return ($record != null);