AccessRules - Expression

Here is what I am trying to do:

I have a table with groups in it:

id

group_name

and a user table

id

username

password (sha1)

email

group_id

what I would like to do is allow admins only to delete which Admins group_id is 1 but needless to say it doesn’t work.

If someone could help

This is the problem, its not working:


  array('allow',

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

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

                                'expression'=>'$users->group_id===1'

                                ),

my controller:


<?php


class UserController extends Controller

{

	/**

	 * @var string the default layout for the views. Defaults to '//layouts/column2', meaning

	 * using two-column layout. See 'protected/views/layouts/column2.php'.

	 */

	public $layout='//layouts/column2';


	/**

	 * @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','view'),

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

			),

			array('allow', // allow authenticated user to perform 'create' and 'update' actions

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

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

			),

//			array('allow', // allow admin user to perform 'admin' and 'delete' actions

//				'actions'=>array('admin','delete'),

//				'users'=>array('kmgoddard'),

//			),

                            array('allow',

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

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

                                'expression'=>'$users->group_id===1'

                                ),

                            

			array('deny',  // deny all users

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

			),

		);

	}


	/**

	 * Displays a particular model.

	 * @param integer $id the ID of the model to be displayed

	 */

	public function actionView($id)

	{

		$this->render('view',array(

			'model'=>$this->loadModel($id),

		));

	}


	/**

	 * Creates a new model.

	 * If creation is successful, the browser will be redirected to the 'view' page.

	 */

	/*public function actionCreate()

	{

		$model=new User;


		// Uncomment the following line if AJAX validation is needed

		// $this->performAjaxValidation($model);


		if(isset($_POST['User']))

		{

			$model->attributes=$_POST['User'];

			if($model->save())

				$this->redirect(array('view','id'=>$model->id));

		}


		$this->render('create',array(

			'model'=>$model,

		));

	} */

        

        /**

         * Creates a new model.

         * If creation is successful, the browser will be redirected to the 'view' page.

         */

        public function actionCreate()

        {

                $model=new User;

                // Uncomment the following line if AJAX validation is needed

                // $this->performAjaxValidation($model);

                if(isset($_POST['User']))

                {

                        $model->attributes=$_POST['User'];

                        $model->password = $model->hashPassword($_POST['User']['password'], $_POST['User']['email']);

                        if($model->save())

                                $this->redirect(array('view','id'=>$model->id));

                        else

                                $model->password = $_POST['User']['password'];

                }

                if(isset($_POST['User']))

		{

			$model->attributes=$_POST['User'];

			if($model->save())

				$this->redirect(array('view','id'=>$model->id));

		}


                $this->render('create',array(

                        'model'=>$model,

                ));

        }




	/**

	 * Updates a particular model.

	 * If update is successful, the browser will be redirected to the 'view' page.

	 * @param integer $id the ID of the model to be updated

	 */

	public function actionUpdate($id)

	{

		$model=$this->loadModel($id);


		// Uncomment the following line if AJAX validation is needed

		// $this->performAjaxValidation($model);


		if(isset($_POST['User']))

		{

			$model->attributes=$_POST['User'];

			if($model->save())

				$this->redirect(array('view','id'=>$model->id));

		}


		$this->render('update',array(

			'model'=>$model,

		));

	}


	/**

	 * 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();


			// 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.');

	}


	/**

	 * Lists all models.

	 */

	public function actionIndex()

	{

		$dataProvider=new CActiveDataProvider('User');

		$this->render('index',array(

			'dataProvider'=>$dataProvider,

		));

	}


	/**

	 * Manages all models.

	 */

	public function actionAdmin()

	{

		$model=new User('search');

		$model->unsetAttributes();  // clear any default values

		if(isset($_GET['User']))

			$model->attributes=$_GET['User'];


		$this->render('admin',array(

			'model'=>$model,

		));

	}


	/**

	 * 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)

	{

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

		if($model===null)

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

		return $model;

	}


	/**

	 * Performs the AJAX validation.

	 * @param CModel the model to be validated

	 */

	protected function performAjaxValidation($model)

	{

		if(isset($_POST['ajax']) && $_POST['ajax']==='user-form')

		{

			echo CActiveForm::validate($model);

			Yii::app()->end();

		}

	}

}



My Model


<?php


/**

 * This is the model class for table "user".

 *

 * The followings are the available columns in table 'user':

 * @property integer $id

 * @property string $username

 * @property string $password

 * @property string $email

 * @property integer $group_id

 */




class User extends CActiveRecord

{

	/**

	 * Returns the static model of the specified AR class.

	 * @return User the static model class

	 */

	public static function model($className=__CLASS__)

	{

		return parent::model($className);

	}


	/**

	 * @return string the associated database table name

	 */

	public function tableName()

	{

		return 'user';

	}

        /**

	 * @return string the associated database table name

	 */

        /**

         * @return boolean validate user

         */

        public function validatePassword($password, $username){

                return $this->hashPassword($password, $username) === $this->password;

                

        }

        /**

         * @return hashed value

         */

        

        public function hashPassword($phrase, $salt = null){

                return sha1($phrase);

        }

	


	/**

	 * @return array validation rules for model attributes.

	 */

	/**

	 * @return array validation rules for model attributes.

	 */

	public function rules()

	{

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		return array(

			array('username, password,email, group_id','required'),

			array('username, password, email', 'length', 'max'=>128),

			// The following rule is used by search().

			// Please remove those attributes that should not be searched.

			array('id, username, password, email, group_id', 'safe', 'on'=>'search'),

		);

	}


	/**

	 * @return array relational rules.

	 */

	public function relations()

	{

		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		return array(

			'group' => array(self::BELONGS_TO, 'Groups', 'group_id'),

		);

	}


	/**

	 * @return array customized attribute labels (name=>label)

	 */

	public function attributeLabels()

	{

		return array(

			'id' => 'ID',

			'username' => 'Username',

			'password' => 'Password',

			'email' => 'Email',

                        'group_id' => 'Group',

		);

	}


	/**

	 * Retrieves a list of models based on the current search/filter conditions.

	 * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.

	 */

	public function search()

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;


		$criteria->compare('id',$this->id);

		$criteria->compare('username',$this->username,true);

		$criteria->compare('password',$this->password,true);

		$criteria->compare('email',$this->email,true);

                $criteria->compare('group_id',$this->group_id);


		return new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

		));

	}

}

You have to use ‘$user’, this is the same as ‘Yii::app()->user’ in the expression. This is the current user with the ‘states’ saved on authenticate in his session.




array('allow',

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

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

      'expression'=>'$user->group_id===1'

     ),



And on authenticate the useridentity you have to assign the group_id to the Yii::app()->user.

You have to distinguish your user model from the db and the CWebUser (Yii::app()->user).





class UserIdentity extends CUserIdentity

{

    private $_id;

    public function authenticate()

    {

        

        $record=User::model()->findByAttributes(array('username'=>$this->username));




        if($record===null)

            $this->errorCode=self::ERROR_USERNAME_INVALID;

        else if($record->password!==md5($this->password))

            $this->errorCode=self::ERROR_PASSWORD_INVALID;

        else

        {

            //assign the username as unique id

             $this->_id=$record->username;


            //assign the group_id from your "User model" to "Yii::app()->user->group_id" 

            $this->setState('group_id', $record->group_id);

            

            //more attributes you want to access through "Yii::app()->user->..."   

            $this->setState('email', $record->email);

            ....    


            $this->errorCode=self::ERROR_NONE;

        }

        return !$this->errorCode;

    }

 

    public function getId()

    {

        return $this->_id;

    }

}




In the code above, we store the user group_id via

$this->setState(‘group_id’, $record->group_id);. After the login you can obtain the group_id of the current user by simply using Yii::app()->user->group_id.

See

  • rules expression

  • Authentication