You are viewing revision #3 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version or see the changes made in this revision.
Hi Everyone
You can use 'expression' option in default accessControl in any controller to allow only the owner to do some action in the controller.
You do not need to set up complex RBAC for simple use.
Here is how to do it.
class ExampleController extends Controller {
/**
* @return array action filters
*/
public function filters() {
return array(
'accessControl', // perform access control for CRUD operations
);
}
/**
* Specifies the access control rules.
* This method is used by the 'accessControl' filter.
* @return array access control rules
*/
public function accessRules() {
return array(
array('allow', // allow all users to perform 'index' and 'view' actions
'actions' => array('index'),
'users' => array('*'),
),
array('allow', // allow authenticated user to perform 'create' action
'actions' => array('create'),
'users' => array('@'),
),
array('allow', // allow only the owner to perform 'view' 'update' 'delete' actions
'actions' => array('view', 'update', 'delete'),
'expression' => array('ExampleController','allowOnlyOwner')
),
array('allow', // allow admin user to perform 'admin' and 'delete' actions
'actions' => array('admin', 'delete'),
'users' => array('admin', 'foo', 'bar'),
),
array('deny', // deny all users
'users' => array('*'),
),
);
}
/**
* Allow only the owner to do the action
* @return boolean whether or not the user is the owner
*/
public function allowOnlyOwner(){
if(Yii::app()->user->isAdmin){
return true;
}
else{
$example = Example::model()->findByPk($_GET["id"]);
return $example->uid === Yii::app()->user->id;
}
}
}
In this ExampleController, it uses the default accessControl and accessRule.
In this default accessRule, add actions to allow ( 'view', 'update', 'delete' ) and expression for it ( array('ExampleController','allowOnlyOwner') ).
"ExampleController" is the class where the method 'allowOnlyOwner' is. These can be any other class and method. You can use $this instead of "ExampleController" if 'allowOnlyOwner" is in the same controller as accessRules.
In function allowOnlyOwner, I assumed that the user class has 'isAdmin' property ( Yii::app()->user->isAdmin ). This can be any other condition if you can check if the user is 'admin'.
For example,
//Check if the user name is in array of administrators
if(in_array(Yii::app()->user->name, array('admin', 'foo', 'bar'))){
return true;
}
I also assumed that the primary key 'id' of Example::model() is given through $_GET['id'] and $example->uid is the user's id in Example::model().
If the result ($example->uid === Yii::app()->user->id ) is true, then the action is allowed.
The $example can be reused to avoid duplicate loading by storing it as property in the controller. For example, $this->example = $example;
The whole code is below:
class ExampleController extends Controller {
/**
* Store the found result row of Example model
*/
private $example = NULL;
/**
* @return array action filters
*/
public function filters() {
return array(
'accessControl', // perform access control for CRUD operations
);
}
/**
* Specifies the access control rules.
* This method is used by the 'accessControl' filter.
* @return array access control rules
*/
public function accessRules() {
return array(
array('allow', // allow all users to perform 'index' and 'view' actions
'actions' => array('index'),
'users' => array('*'),
),
array('allow', // allow authenticated user to perform 'create' action
'actions' => array('create'),
'users' => array('@'),
),
array('allow', // allow only the owner to perform 'view' 'update' 'delete' actions
'actions' => array('view', 'update', 'delete'),
'expression' => array('ExampleController','allowOnlyOwner')
),
array('allow', // allow admin user to perform 'admin' and 'delete' actions
'actions' => array('admin', 'delete'),
'users' => array('admin', 'foo', 'bar'),
),
array('deny', // deny all users
'users' => array('*'),
),
);
}
/**
* Allow only the owner to do the action
* @return boolean whether or not the user is the owner
*/
public function allowOnlyOwner(){
if(Yii::app()->user->isAdmin){
return true;
}
else{
$example = Example::model()->findByPk($_GET["id"]);
$this->example = $example;
return $example->uid === Yii::app()->user->id;
}
}
/**
* Deletes a particular model.
* If deletion is successful, the browser will be redirected to the 'admin' page.
* @param integer $id the ID of the model to be deleted
*/
public function actionDelete($id) {
if (Yii::app()->request->isPostRequest) {
// we only allow deletion via POST request
$this->loadModel($id)->delete();
//initialize '$this->example' for next action
$this->example = NULL;
// if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
if (!isset($_GET['ajax']))
$this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('admin'));
}
else
throw new CHttpException(400, 'Invalid request. Please do not repeat this request again.');
}
/**
* Returns the data model based on the primary key given in the GET variable.
* If the data model is not found, an HTTP exception will be raised.
* @param integer the ID of the model to be loaded
*/
public function loadModel($id) {
if(!$this->example) $this->example = Example::model()->findByPk($id);
if ($this->example === NULL)
throw new CHttpException(404, 'The requested page does not exist.');
return $this->example;
}
}
Have fun.
error while calling the method allowOnlyOwner()
array('allow', // allow only the owner to perform 'view' 'update' 'delete' actions
'actions' => array('view', 'update', 'delete'), 'expression' => array('ExampleController','allowOnlyOwner') ),
'expression' => array('ExampleController','allowOnlyOwner') this makes the function call static so either you have to make the function allowOnlyOwner static or you have to write $this in place of the controller name as you have mentioned.
Great one
Thanks for sharing this.
I think most of simple rules can be achieved by this "expression".
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.