RBAC <-> User relations

Hello there,

I have been researching on RBAC systems for days. I only got the gist of it.

After checking Srbac and Rights, I can say, Rights are quite decent.

However, I have a question which is not directly related to the extension.

Given that I am using RBAC systems, say, Rights, is it really necessary to assign roles to each individual users? (which I found too tiresome)

Can (and HOW?) I assign role_id to user table so I can associate it (user->role_id) with role->id2?

And why Yii RBAC database scheme are so confusing? Roles lie together with permissions and etc. (which what makes it so confusing?)

Why are we making a distinction between task and permission? I guess, tasks inherit permission or is it really so?

Thanks in advance.

[Post moved by the author to General Discussion)

I my understanding of it, a task is a special instance of a permission.

For example, a task called updateOwnPosts carries the business rule that only allow the current user to update a post if she’s the owner.

‘updateOwnPosts’ has the permission post.update as a child.

See this:

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

Scroll down a bit, and you’ll see this:


$auth->createOperation('updatePost','update a post');

$auth->createOperation('deletePost','delete a post');

 

$bizRule='return Yii::app()->user->id==$params["post"]->authID;';

$task=$auth->createTask('updateOwnPost','update a post by author himself',$bizRule);

$task->addChild('updatePost');

 

$role=$auth->createRole('reader');

$role->addChild('readPost');

 

$role=$auth->createRole('author');

$role->addChild('reader');

$role->addChild('createPost');

$role->addChild('updateOwnPost');

Don’t get confuse about role, permission and task are absolutely the same stuff.

You have just to assing and check access with them, nothing more. If you want to create a complex herarchy of permission, there are this 3 categories for your own confort, but there are no real difference among them.

As I am always working with a small set of permission (2 or 3 roles), I am always using just roles.

Is really only a question of convenience.

Thank you @jacmoe, it is less confusing for me, that is, we can also assign bizrule to permissions as well, so, what is the point?

In Rights extension, the author created a task called PostAdministrator which has access to all Post actions, and has no bizrule at all…

But, for me, most important point is how can associate users (maybe via $user->role_id) to role itself (which initially has no id field)

For associate a role with a rule use assign:


<?php Yii::app()->authManager->assign('roleId', 'userId')?>

For chech if a user has a permission, use checkAccess:


<?php if (Yii::app()->authManager->checkAccess( 'roleId', 'userId')) ...?>

That’s just a convenient way of grouping permissions.

Just assign the PostAdministrator task to a role and it gives access to all it’s children.

At least that’s how I view it.

That’s the whole point, zaccaria, I don’t think it is efficient to repeat and store all assignments, rather, I wish to set a role_id in user table which points to role->id (or, say, item->id (where type = 2)…

Is it going to break the system (CDbAuthManager)?

One of the nice things about Yii’s built-in RBAC is that your permissions tree can grow to any size, with users having any number of roles. If your site gets complex enough you should consider just building a UI for yourself around the Yii RBAC without doing funky things like circumventing the Yii Auth assignments. However for very small sites just using single role assignments could be adequate.

For me it was convenient to organize it like:

  • Roles: The only type of YiiAuthItem that should be assigned to a user; contains any number of tasks.

  • Tasks: Usually not assigned to a user; contain operations.

  • Operations: Never assigned to a user; represents the finest granularity of action you can think of, or at least corresponds to actions in Controllers (index, create, delete, admin, etc).

Bizrules are for special cases for example where you want a user to be able to edit posts but only their own posts. In that case your bizrule would be something like


return Yii::app()->user->id == $post->creator_id;

I appreciate your clear explanation, awesomejuice.

However let me restate my problem/wish;

I would like to skip Yii’s built-in checking on AuthAssignment table, rather, I wish to associate a user to a item id (role id) (that’s I need to add a new field in AuthItem table).

I checked CDbAutManager class. It constantly looks for AuthAssignment table to get many operation. Plus I don’t have depth knowledge to override current methods of it, and I am afraid I will break the system, that is, checkAccess method will not work as desired.

Hope I made it clearer,

You don’t need to change the system, it can suite any needs.

What exactly you want to do?

If you want to assing only once, you can create a role that inheirts many permission, and assign this specific role.

If you want to give some permission to a specific user, you don’t need rbac at all, just allow only this user in filters.

Sir, I don’t want to assign roles to individuals as it is designed in the Auth class. Rather, I want to retrieve roles from either role table or AuthItem table (where type=2) and set its id to user’s role_id field.

Is that clear enough?

So, I found a workaround, which I don’t say it is handsome.




class AppAuthManager extends CDbAuthManager

{

        public function checkAccess($itemName,$userId,$params=array())

	{

		//$assignments=$this->getAuthAssignments($userId);

		$assignments=$this->getUserRole($userId);

		return $this->checkAccessRecursive($itemName,$userId,$params,$assignments);

	}


public function getUserRole($userId)

	{

		$itemName=$this->getItemName($this->getRoleId($userId));

		$assignments[$itemName]=new CAuthAssignment($this,$itemName,$userId);

		return $assignments;

	}

	

	public function getItemName($roleId)

	{

		$sql="SELECT name FROM {$this->itemTable} WHERE id=:roleid";

		$command=$this->db->createCommand($sql);

		$command->bindValue(':roleid',$roleId);

		return $command->queryScalar();

	}


        public function getRoleId($userId)

	{

		$sql="SELECT role_id FROM {$this->userTable} WHERE id=:userid";

		$command=$this->db->createCommand($sql);

		$command->bindValue(':userid',$userId);

		return $command->queryScalar();

	}

}




As you may guess, assign() method does not work at all. However this works for me, at the moment.

I also made a change in AuthItem table, added ‘id’ field in it, which I can associate it with role’s name, and it is what I set in user->role_id.

Do you have any better idea?

The Rights extension does that.

Use it.

Or learn from it. ;)

Well, I guess I will quit looking for the perfection, and start using Rights right away. :)

Thank you all for your reactions.