Assuming your user is associated with some AR model:
<?php
// access rules
return array(
// Admin has full access. Applies to every controller action.
array(
'allow',
'expression' =>'Yii::app()->user->model->isAdmin',
),
// delegate to user model methods to determine ownership
array(
'allow',
'expression' =>'Yii::app()->user->model->isPostOwner(Yii::app()->request->getQuery("postId"))',
'actions' =>array('editPost', 'uploadPostImage'),
),
array(
'allow',
'expression' =>'Yii::app()->user->model->isImageOwner(Yii::app()->request->getQuery("imageId"))',
'actions' =>array('editImage'),
),
array('deny'),
);
...
// In your user model
public function isPostOwner($postId)
{
$post = Post::model()->findByPk($postId);
return !$post || ($post->owner_id === $this->id);
}
public function isImageOwner($imageId)
{
$image = Image::model()->findByPk($imageId);
return $image && ($image->owner_id === $this->id) && $this->isPostOwner($image->post_id);
}
If you abstract your action params away from the HTTP request, a la my yii-rest extension or the Symfony2 FOSRESTBundle, you can do this more systematically.
In general, I think action parameters should be treated as a model, not as a raw array like Yii does out of this box. This is a good reason why. Suppose the action param $postId was actually just an instance of Post; your access rules would be extremely clear. (See below.) You could also validate them!
// Access rules if action params was an object/model
return [
[
'allow',
'expression' =>'Yii::app()->user->isAdmin',
],
[
'allow',
'expression' =>[$this->actionParams->post, 'isOwnedByUser'],
'actions' =>...
],
[
'allow',
'expression' =>[$this->actionParams->image, 'isOwnedByUser'],
'actions' =>...
],
];