RBAC and Access Filter Question

Hi all! I am trying to figure out RBAC, and I was hoping someone could help me a little. I used the script posted here to set up my tables and relationships:

http://www.yiiframew…83.html#msg3583

And I tried to follow the rules here to set up restrictions:

http://www.yiiframew…ide/topics.auth

My example I am working on to learn is just to add permissions to add more users, delete users, etc. I only have on table so far (aside from the RBAC tables the script set up), so there is nothing too crazy going on.

My understanding is that I setup up access rules in the UserController file like so:



	public function accessRules()


	{


		return array(


		


			array('allow',


				'actions'=>array('delete','show'),


				'roles'=>array('deleteUser'),


			),


			array('allow',


				'actions'=>array('show','list'),


				'roles'=>array('viewUser', 'updateOwnUser'),


			),


			array('allow',


				'actions'=>array('update'),


				'roles'=>array('updateUser', 'updateOwnUser'),


			),


			array('allow',


				'actions'=>array('create'),


				'roles'=>array('createUser'),


			),


			array('deny',  // deny all users


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


			),


		);


	}


However, when I do these things, I get the following from the script:

PHP Error


Description





Undefined variable: condition


Source File





/Users/corey/Sites/framework/web/auth/CDbAuthManager.php(123)





00111:      * @since 1.0.3


00112:      */


00113:     protected function checkDefaultRoles($itemName,$userId,$params)


00114:     {


00115:         $names=array();


00116:         foreach($this->defaultRoles as $role)


00117:         {


00118:             if(is_string($role))


00119:                 $names[]=$this->db->quoteValue($role);


00120:             else


00121:                 $names[]=$role;


00122:         }


00123: if(count($condition)<4)


00124:             $condition='name='.implode(' OR name=',$names);


00125:         else


00126:             $condition='name IN ('.implode(', ',$names).')';


00127:         $sql="SELECT name, type, description, bizrule, data FROM {$this->itemTable} WHERE $condition";


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


00129:         $rows=$command->queryAll();


00130: 


00131:         foreach($rows as $row)


00132:         {


00133:             $item=new CAuthItem($this,$row['name'],$row['type'],$row['description'],$row['bizrule'],unserialize($row['data']));


00134:             if($item->checkAccess($itemName,$params))


00135:                 return true;





Stack Trace





#0 /Users/corey/Sites/framework/web/auth/CDbAuthManager.php(84): CDbAuthManager->checkDefaultRoles()


#1 /Users/corey/Sites/framework/web/auth/CWebUser.php(542): CDbAuthManager->checkAccess()


#2 /Users/corey/Sites/framework/web/auth/CAccessControlFilter.php(221): CWebUser->checkAccess()


#3 /Users/corey/Sites/framework/web/auth/CAccessControlFilter.php(171): CAccessRule->isRoleMatched()


#4 /Users/corey/Sites/framework/web/auth/CAccessControlFilter.php(93): CAccessRule->isUserAllowed()


#5 /Users/corey/Sites/framework/web/filters/CFilter.php(39): CAccessControlFilter->preFilter()


#6 /Users/corey/Sites/framework/web/CController.php(885): CAccessControlFilter->filter()


#7 /Users/corey/Sites/framework/web/filters/CInlineFilter.php(59): UserController->filterAccessControl()


#8 /Users/corey/Sites/framework/web/filters/CFilterChain.php(125): CInlineFilter->filter()


#9 /Users/corey/Sites/framework/web/CController.php(248): CFilterChain->run()


#10 /Users/corey/Sites/framework/web/CController.php(225): UserController->runActionWithFilters()


#11 /Users/corey/Sites/framework/web/CWebApplication.php(335): UserController->run()


#12 /Users/corey/Sites/framework/web/CWebApplication.php(123): CWebApplication->runController()


#13 /Users/corey/Sites/framework/base/CApplication.php(170): CWebApplication->processRequest()


#14 /Users/corey/Sites/RTS/index.php(11): CWebApplication->run()





2009-03-08 16:15:49 Apache/2.0.59 (Unix) PHP/5.2.6 DAV/2 Yii Framework/1.0.3


Does anyone know what I am doing wrong? Also, let me know if I need to include more stuff to determine the solution. Sorry I am so new at RBAC! Thanks for any help I get!

(For the record, this is all off my laptop so I am not really concerned if absolute paths are shown here :) )

This is a bug that has been fixed in SVN. Thanks.

Man your response was so quick! Thanks!

OK, so I was looking further into this. I think we may need an SQL change in CDbAuthManager on Line 86.

Right Now it is

SELECT name, type, description, t1.bizrule, t1.data, t2.bizrule AS bizrule2, t2.data AS data2 FROM {$this->itemTable} t1, {$this->assignmentTable} t2 WHERE name=itemname AND userid=:userid

And we are only assigning $userId to :userid. I think there is a typo and a logical error, so please correct me if I am wrong. I think the SQL should be

SELECT


	name,


	type,


	description,


	t1.bizrule,


	t1.data,


	t2.bizrule AS bizrule2,


	t2.data AS data2


FROM


	{$this->itemTable} t1


	INNER JOIN {$this->itemChildTable} m1 ON t1.name = m1.child


	INNER JOIN {$this->assignmentTable} t2 ON (t1.name IN (m1.parent, m1.child))


WHERE


	LOWER(m1.child)=:itemname


	AND


	t2.userid=:userid


	; 

And we need to assign $itemName = :itemname as weill as $userId = :userid

Right now, the SQL in place only checks for a direct assignment and leaves children permissions out of the picture. I think the one I am suggesting takes multiple levels into account. Or is the idea that when I assign a user to a role I should recursively assign all children of that role in the assignment table then (in which case the first SQL works fine?

Also, PostgreSQL is case sensitive, so because the name of the permission is lowercased somewhere along the line, I had to add a LOWER() on the field before we compare it.

checkAccess() is a recursive call. Each call will execute the SQL and check the direct children.

Cool. The final code update recomendation I have is this then:

		


		$sql="SELECT LOWER(name) AS name, type, description, t1.bizrule, t1.data, t2.bizrule AS bizrule2, t2.data AS data2 FROM {$this->itemTable} t1, {$this->assignmentTable} t2 WHERE LOWER(name)=:itemname AND userid=:userid";


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


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


		$command->bindValue(':itemname',$itemName);


Added LOWER() calls to match the fact that Yii makes the item name lower case and then compares against the values in the database (PostgrSQL is case sensitive) and : before itemname in where cause, and bound :itemname because that looks like what you meant to do originally

Again, this is from the SVN version, not the release version of CDbAuthManager.