accessRules question for expression parameter

Hi,

In a book controller,

I’m trying to allow users to only view its own post and view other users who set view_mode to public.

As for edit, they could only edit their own file.

In the following code, I can’t get loadModel to work correctly, I’m not even sure if my logic is correct for the expression. I kinda felt my code is ugly:




public function accessRules()

	{

                $model = $this->loadModel($_GET['id']);

		return array(

			array('allow',  // allow regular users to perform 'index' and 'view' actions

				'actions'=>array('index','view','create','update','admin','delete'),

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

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

                                'expression' => '($user->id === '.$model->author_id.

                                    ' && ('.$model->view_mode.' === '.self::MODE_PUBLIC.

                                    ' || '.$model->view_mode.' === '.self::MODE_PRIVATE.'))'.

                                    ' || ($user->id !== '.$model->author_id.

                                    ' && '.$model->view_mode.' === '.self::MODE_PUBLIC.')',                                

			),

                        array('allow',  // allow regular users to perform 'index' and 'view' actions

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

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

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

                                'expression' => '$user->id === '.$model->author_id,                                

			),

			array('deny',  // deny all users

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

			),

		);

	}



below is my loadModel




        public function loadModel($id)

	{

                $model=Flowbook::model()->findByPk($id);


		if($model===null)

			throw new CHttpException(404,'The requested page does not exist.');

		return $model;

	}



If I refer to the blog tutorial I assumed that $id is just a $_GET[‘id’]

but I kept receiving


Undefined index: id 

What seems to be the problem?

nevermind, I found the solution, for those encountering the same problem loadModel should be assigned the user id, in this case:


$model = $this->loadModel(Yii::app()->user->id);

It seems to me that you are still confused about $id(or $_GET[‘id’]) in your FlowbookController.

(I’m in the assumption that you are working with a gii-generated crud codes for a model named Flowbook, or modifying the sample codes of blog tutorial.)

  1. $id or $_GET[‘id’] is only defined in your “view”, “update” and “delete” actions. It is not defined in “index”, “admin” and “create” actions.

  2. $id or $_GET[‘id’] is for a primary key of Flowbook, not for the current user id. It won’t make sense to call loadModel() by user id.

Thanks, but if that’s the case, how do I call the loadModel on accessRules

I’m not very familiar with the accessRule’s expression, but I think your accessRules should be something like this …




public function accessRules()

{

	return array(

		array('allow',  // allow regular users to perform 'index', 'view', 'admin' and 'create'

			'actions'=>array('index','view','admin','create'),

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

		),

		array('allow',  // allow regular users to perform 'update' and 'delete' his own book

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

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

			'expression' => array($this, 'isOwner'),

		),

		array('deny',  // deny all users

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

		),

	);

}


public function isOwner($user, $rule)

{

	$model = $this->loadModel($_GET['id']);

	return $user->id === $model->author_id;

}




Please refer to the reference and the comment #1976.

http://www.yiiframework.com/doc/api/1.1/CAccessRule#expression-detail

Thanks

Hi,

I did something like this, it’s working, but I’m not sure if it is working correctly. Will produce the intended result of filtering all results from index, view, add, update, delete, create and admin operations?

I’m particularly talking about the normalAccess method’s use of


$model = Flowbook::model()->find(); 

for filtering




public function accessRules()

	{

		return array(

			array('allow', 

				'actions'=>array('index','view','create','update','admin','delete'),

				'roles'=>array('2'), //Regular User     

                                'expression' => array($this,'normalAccess')

			),

			array('deny',  // deny all users

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

			),

		);

	}

        

        protected function normalAccess($user,$rule)

        {

            //only allow if (authorID = userID) or (authorID <> userID and view_mode == public)

            $model = Flowbook::model()->find();

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

            

            return ($userID === $model->author_id) || 

                ($user !== $model->author_id && $model->view_mode === self::MODE_PUBLIC);            

        }



Hi,

Because you don’t give any parameters, “Flowbook::model()->find()” will return a Flowbook model instance of the first row in “flowbook” table. Usually it is not the one that a user is going to view, update or delete.

So you have to get the target flowbook model instance by "Flowbook::model()->findByPk([$_GET[‘id’]) when the action is “view”, “update” or “delete”.

And as for “admin”, “create” and “index”, there’s no specific target model instance to check, and there’s no $_GET[‘id’] specified. You should handle these actions with other means, maybe by the user’s role.

If that’s the case actionIndex will be dependent on roles instead of expression. I didn’t know that. Thanks

Strange normalAccess method is still allowing userB to view private post userA.