Error 403 You Are Not Authorized To Perform This Action.

Hi,

I followed the tutorial in Chapter 7 carefully. When I click on project/view&id=1, I get taken to the Login Page. The only way to login is through the User One and User Two userids created in chapter 5 (which I understand because of the Rbac implementation,which utilizes DB to authentication). After successfully logging in When I click on "Add User To Project", I get Error 403 You are not authorized to perform this action.

Below is my ProjectController class:


<?php


class ProjectController 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

			'postOnly + delete', // we only allow deletion via POST request

		);

	}


	/**

	 * 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('admin'),

			),

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

		));

	} */




	/**

	* Displays a particular model.

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

	*/

	public function actionView($id)

	{

		$issueDataProvider=new CActiveDataProvider('Issue',

		array(

		      'criteria'=>array(

		      'condition'=>'project_id=:projectId',

		      'params'=>array(':projectId'=>$this->loadModel($id)->id),

		),

		'pagination'=>array(

		'pageSize'=>1,

		),

		));

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

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

		'issueDataProvider'=>$issueDataProvider,

		));

	}


	/**

	 * Creates a new model.

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

	 */

	public function actionCreate()

	{

		$model=new Project;


		// Uncomment the following line if AJAX validation is needed

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


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

		{

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

			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['Project']))

		{

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

			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)

	{

		$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'));

	}


	/**

	 * Lists all models.

	 */

	public function actionIndex()

	{

		$dataProvider=new CActiveDataProvider('Project');

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

			'dataProvider'=>$dataProvider,

		));

	}


	/**

	 * Manages all models.

	 */

	public function actionAdmin()

	{

		$model=new Project('search');

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

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

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


		$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=Project::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']==='project-form')

		{

			echo CActiveForm::validate($model);

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

		}

	}


	/**

	* Provides a form so that project administrators can

	* associate other users to the project

	*/

	public function actionAdduser($id)

	{

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

		if(!Yii::app()->user->checkAccess('createUser', array('project'=>$project)))

		{

			throw new CHttpException(403,'You are not authorized to perform this action.');

		}


		$form=new ProjectUserForm;


		// collect user input data

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

		{

			$form->attributes=$_POST['ProjectUserForm'];

			$form->project = $project;


			// validate user input

			if($form->validate())

			{

				if($form->assign())

				{

					Yii::app()->user->setFlash('success',$form->username . "has been added to the project." );


					//reset the form for another user to be associated if desired

					$form->unsetAttributes();

					$form->clearErrors();

				}

			}

		}


		$form->project = $project;

		$this->render('adduser',array('model'=>$form));

	}

}



Below is my accessRules()method within the Controller class:


   public function accessRules()

        {

                return array(

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

                                'controllers'=>array('issue','project','user'),

                                'actions'=>array('index', 'view', 'addUser'),

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

                        ),

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

                                'controllers'=>array('issue','project','user'),

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

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

                        ),

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

                                'controllers'=>array('issue','project','user'),

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

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

                        ),

                        array('deny', // deny all users

                                'controllers'=>array('issue','project','user'),

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

                        ),

                );

        }



I manually inserted the values ‘owner’ to itemname and 1 to the userid fields in tbl_auth_assignment. Basically what it did was it associated “User One” (from chapter 5) to authorization item “owner” in tbl_auth_item. After which, I got the expected results. The actual command was insert into tbl_auth_assignment (itemname,userid) values(‘owner’,1).

What I still don’t understand is that the Rbac command that I executed earlier via ./yiic rbac did not add any values to the tbl_auth_assignment. The tbl_auth_assignment.bizrules field is not populated. How does it get populated. Can some one explain this to me?

I have the same problem, only I can’t access it with any of users. Both, User One, and User Two get 403 error :mellow: The only way for me to through is to remove


        if(!Yii::app()->user->checkAccess('createUser', array('project' => $project)))

        {

            throw new CHttpException(403, 'You are not authorized to perform this action');

        }

can anyone help?

Check the tbl_auth_assignment table. If it is empty, thats the problem. Run the following 2 insert statements on mysql:

insert into tbl_auth_assignment (itemname,userid) values(‘owner’,1)

insert into tbl_auth_assignment (itemname,userid) values(‘member’,2)

1-st sql will associate "User One" to authorization item "owner" in tbl_auth_item.

2-nd sql will associate "User Two" to authorization item "member" in tbl_auth_item.

Now you should get the expected results. That is if you log in as User One, you will see the link “Add User To Project” and if you log in as User Two you won’t see the link.

I don’t know why Rbac does not add these records. If you find out let me know.

I found what is causing the 403 error, but cannot think of a good way to solve it. The before_filter find_optional_project makes the following call that returns false:

allowed = User.current.allowed_to?({:controller => params[:controller], :action => params[:action]}, @project, :global => true)

The simple simpe fix is to replace params[:controller] with ‘issues’ , but I’m looking for a better way to write that out.

SOLVED!

First, you need to assign ‘owner’ role to the creator user of the project. Modify actionCreate() in ProjectController.php with this:

if($model->save()){

//assign the user creating the new project as an owner of the project, 


//so they have access to all project features


&#036;form=new ProjectUserForm;


&#036;form-&gt;username = Yii::app()-&gt;user-&gt;name;


&#036;form-&gt;project = &#036;model;


&#036;form-&gt;role = 'owner';


if(&#036;form-&gt;validate())


{


	&#036;form-&gt;assign();


}





&#036;this-&gt;redirect(array('view','id'=&gt;&#036;model-&gt;id));

}

Moreover, from PACKTpub official page of this book, into SUPPORT tab, you can fine this errata:

Errata type: Others | Page number: 178-179

This is not exactly a book error, but in order for the application to allow a user to create multiple projects as well as assign the same users to multiple projects within the same role, we need to make a small change to the code when associating a user to a role upon project creation. We need wrap the role assignment in an if statement to determine whether or not the user has already been added to the RBAC hierarchy for that role.

if(!$auth->isAssigned($this->role, $this->_user->id))

{

$bizRule=‘return isset($params[“project”]) && $params[“project”]->allowCurrentUser("’.$this->role.’");’;

$auth->assign($this->role,$this->_user->id, $bizRule);

}

Change this in assign() method in ProjectUserForm.php :wink: