RBAC и accessRules и updateOwnPost

Друзья!

Пытаюсь разобраться с разделением прав и один момент никак не идёт.

Использую CDbAuthManager.

Добавил для пользователя следующие права



$auth = Yii::app()->authManager;


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


$auth->createOperation('createPost', 'create a post');


$role->addChild('createPost');


$auth->assign('manager', '2');


$auth->createOperation('updatePost','редактирование записи');


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


$task = $auth->createTask('updateOwnPost','редактирование своей записи',$bizRule);


$task->addChild('updatePost');


$role->addChild('updatePost');


сдесь кажется всё понятно, кроме пары моментов

... $params["post"]->authID; ...

сдесь в качестве authID должно быть название поля в таблице где хранится id автора ?

и второе это

$task->addChild('updatePost');

зачем ?

и теперь самое главное и непонятное, а именно:

поидее вышеприведённым кодом, я указал что пользователю группы "manager" делать (я рассчитываю что это редактирование своих постов)) )

и что мне надо указать в функции accessRules контроллера PostController ?!  ???

пробовал вот такой момент



array('allow',


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


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


),


но не работает, и что-то мне кажется что здесь получается некой дублирование.

Может быть здесь указывать что массив с правами из базы брать ?

мне кажется это логичным но я не нашёл как ?

вот последняя надежда на вас! спасайте!  ;)

да ладно вам ;) , признавайтесь, знаете же чем мне помочь !!!

Ну

$task->addChild(‘updatePost’);

Вам в коде не нужно будет проверять на

updateOwnPost, а только updatePost, но для пользователей которым разрешено редактировать только свои сообщения будет срабатывать еще и проверка на updateOwnPost, то есть свой ли это пост. То есть для выполнения операции updatePost для данного пользователя будет условием выполнение дополнительного условия проверки на авторство.

А вот как проверять на то что разрешено для меня пока тоже вопрос, по-ходу нужно писать фильтр, сейчас ищу как узнать в фильтре какое из действий выполняется, для составления запроса, названия скорее всего будет имя_операцииИмя_контролера ну и фильтр как-то должен выглядеть типа:



$params = "нужные для данного метода данные";


return Yii::app()->user->checkAccess('methodClass');

Вот что у меня вышло  ;D

[code=php]

      /**

 * @return array action filters


 */


public function filters()


{


	return array(


		// если нужно тут можно отключить или наоборот указать каким действиям применять фильтр


		'accessControlRBAC', // Проверка прав доступа на основе RBAC


	);


}





/**/


public function filterAccessControlRBAC($filterChain) {


	/** 


	 * id указывается для редактирования пользователя, у нас есть правило что 


	 * пользователь может редактировать только свой профиль, потому собираем параметры


	 * для бизнес-логики


	 */


	$params = isset($_GET['id']) ? array('userId'=>intval($_GET['id'])) : (isset($_POST['id']) ? array('userId'=>intval($_POST['id'])) : array()) ;


	


	/* Собираем название действия */


	$itemName = strtolower($this->getAction()->getId()).ucwords(strtolower($this->getId()));





	/* Проверяем права */


	if(!Yii::app()->user->checkAccess($itemName, $params)) {


		/* Эсли пользователь не авторизирован отправляем на страницу с формой входа */


		if(Yii::app()->user->isGuest) 


			$this->redirect(array('site/login'));			


		/**


		 * Эсли пользователь не гость значит ему не хватает прав доступа, думаю тут можно 


		 * сделать рендер какого-то шаблона если это можно делать в фильтрах не проверял.


		 */


		else


			throw new CHttpException(500,'Страница закрыта. У вас недостаточно прав для просмотра данной страницы.'); 





		return false;


	}


	


	/* Ну если все хорошо выполняем остальные фильтры */


	$filterChain->run();


	return true;


}

        

Спасибо за ответ.

но ваш вариант у меня не сработал. у меня всегда 'true' получается.

$task->addChild('updatePost');

да, это всё понятно … я запутался с тем, кто у кого child и думаю от этого частично и не получается. + надо в bizrule немного подкорректировать

странно получается, с тем списком правил котрый я привёл в первом посте, "updateOwnPost" даже не вызывается, соответственно и не срабатывает.

у меня получается так что пока не выполним

$role->addChild('updateOwnPost');

именно к роли работать не будет

тогда если так, то вот эта часть из мана всё равно не понятна

'updateOwnPost' просто не будет вызываться



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


$task=$auth->createTask('updateOwnPost','редактирование своей записи',$bizRule);


$task->addChild('updatePost');


растолкуйте если я где-то радикально ошибаюсь

ещё "момент" вот пример mc.aser



/* Собираем название действия */


$itemName = strtolower($this->getAction()->getId()).ucwords(strtolower($this->getId()));


мы в качестве $itemName updateOwnPost никогда не получим.

В accesRules нужно писать так:



array('allow',


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


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


),


Т.е в список 'roles' нужно писать не имя роли, а имя допустимых для данного action'a операций (или задач, tasks).

Сама задача, должна быть присвоена как дочерняя для роли:



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


...


$role->addChild('updateOwnPost');


AuthManager когда будет проверять права для пользователя с ролью 'manager', определит что дочерняя операция 'updateOwnPost' разрешена.

С точки зрения раздачи прав доступа разницы между операциями, задачами и ролями вообще нет.

Тут весь смысл в создании операций, задач и ролей и создании правильных связей между ними:



$auth = Yii::app()->authManager;


$auth->createOperation('createPost', 'create a post');





$op = $auth->createOperation('updatePost','редактирование записи');


// Всем, кому можно создавать посты, можно и редактировать


$op->addChild('createPost');





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


// Manager может создавать / редактировать записи 


$role->addChild('updatePost');





// Пользователь с id=2 получает все права manager


$auth->assign('manager', '2');





// Сохраняем настройки RBAC - это делается только один раз


$auth->save();


Дальше в контроллере:



public function filters()


{


    return array(


	    'accessControl', // perform access control for CRUD operations


	);


}








public function accessRules()


{


    return array(


	array('allow',  


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


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


	),


	array('deny',  // deny all users


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


	),


   );


}


Для aсtion'ов 'create' и 'update' разрешен доступ с ролью 'createPost', соответсвенно разрешен доступ и с ролями 'updatePost' и 'manager'.

Что же касается бизнес-правил, то я и сам еще до конца с ними не разобрался, но похоже, что они автоматически проверятся не могут, т.к. нужны дополнительные параметры, т.е. их можно использовать для дополнительного ограничения доступа уже внутри action'ов.

Кстати еще я не понял в чем отличие "операции" (operation) от "задачи" (task) - и тем и другим можно назначать дочерние операции и бизнес-правила.

Вообще, на мой взгляд, описание RBAC в "The Definitive Guide to Yii" 

непонятное и несколько вводящее в заблуждение - как раз куска на счет применения в accessRules() там не хватает.

Quote

Вообще, на мой взгляд, описание RBAC в "The Definitive Guide to Yii" 

непонятное и несколько вводящее в заблуждение - как раз куска на счет применения в accessRules() там не хватает.

Абсолютно согласен, фильтр свой я и придумал что бы автоматом можно было передавать доп параметры для бизнес правил.

Кто общается с разработчиками попросите описать эту часть в документации…

Друзья, я кажется разобрался, спасибо большое за участие.

только я вот что думаю: если мы используем authManager, то есть создаём роли таски и операции, то корректнее в фильтре вызывать checkAccess, а не как в демке статично происать массив.

Или я не прав ?!

Хотя второй вариант поидее быстрее работать будет.

Quote

Абсолютно согласен, фильтр свой я и придумал что бы автоматом можно было передавать доп параметры для бизнес правил.

Кто общается с разработчиками попросите описать эту часть в документации…

Уже попросил, обещают описать - http://www.yiiframew…2.html#msg16312.

Quote

Друзья, я кажется разобрался, спасибо большое за участие.

только я вот что думаю: если мы используем authManager, то есть создаём роли таски и операции, то корректнее в фильтре вызывать checkAccess, а не как в демке статично происать массив.

Или я не прав ?!

Хотя второй вариант поидее быстрее работать будет.

Роли, таски и операции создаются один раз и сохраняются в базу или в файл.

Потом мы их можем использовать в методе accessRules(), тогда доступ проверяется автоматически. Или в фильтре вызывать checkAccess - но это имеет смысл только для операций с бизнес правилами, которым нужно передавать дополнительные параметры.

Хотя с другой стороны, можно вообще не писать бизнес-правила, а доступ проверять уже внутри action'a:



public function actionUpdate()


{


    if (Yii::app()->user->checkAccess('updateOwnPost') &&


        !Yii::app()->user->checkAccess('updatePost')) {


        // проверить, что пользователь пытается редактировать свой пост


     }


}	  


Quote

Хотя с другой стороны, можно вообще не писать бизнес-правила, а доступ проверять уже внутри action'a:


public function actionUpdate()


{


    if (Yii::app()->user->checkAccess('updateOwnPost') &&


        !Yii::app()->user->checkAccess('updatePost')) {


        // проверить, что пользователь пытается редактировать свой пост


     }


}	  


Но это как-то не по спортивному  ;D

тогда можно уже использовать



  // optional, a PHP exp​ression whose value indicates whether this rule applies


  // This option is available since version 1.0.3.


  'exp​ression'=>'!$user->isGuest && $user->level==2',

в accessRules()



array(


  'allow',  // or 'deny'


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


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


  'exp​ression'=>'$post->authId = Yii::app()->user->getId()',


)


*это не рабочий код, это набросок…