Difference between #5 and #2 of Simple RBAC

unchanged
Title
Simple RBAC
unchanged
Category
Tutorials
unchanged
Tags
Simple RBAC, Role based access control, roles, Authentication, Role based menu
changed
Content
If you are the one who need simple Role based access control without
the long RBAC process then this article is just for you. Lets jump to the point.

On your## The user table make a column named
'roles'model

When you add users you can assign them different roles like 'Admin' /
'user' / 'staff' etc etc.On your user table make a column named
'roles'. Create the model accordingly. It will be named "User"
here.

On your UserIdentity.php file write something like..When you add
users you can assign them a role among 'admin', 'user', 'staff' etc etc.

## The authentication

In the file "protected/components/UserIdentity.php" write
something like:

~~~
[php]
class UserIdentity extends CUserIdentity
{
    private $id;

    public function authenticate()
    {
       
$record=User::model()->findByAttributes(array('email'=>$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
        {
            $this->id=$record->id;
            $this->setState('roles', $record->roles);            
            $this->errorCode=self::ERROR_NONE;
        }
        return !$this->errorCode;
    }
 
    public function getId(){
        return $this->id;
    }
}
~~~

The important line is 
$this->setState('roles',
$record->roles);`$this->setState('roles', $record->roles);`
It adds user roles to their session.
You can fetch the role of the current user with
`Yii::app()->user->getState('roles')` or simply
`Yii::app()->user->roles`.

You are just adding user roles to their session. 

Now, make a Utils.php file under protected/components directory and implement a
simple Role check function based on how many roles you have.##
Checking permissions: structure

Modify or create the "WebUser.php" file under the
"protected/components" directory so that it overloads the
`checkAccess()` method.

~~~
[php]
<?php 

class Utils{
	public function isAdmin(){
		if(Yii::app()->user->isGuest)
			return false;
		else if(Yii::app()->user->roles == 'Admin')
			return true;
		else
			return false;
	}class WebUser extends CWebUser
{
	/**
	 * Overrides a Yii method that is used for roles in controllers (accessRules).
	 *
	 * @param string $operation Name of the operation required (here, a role).
	 * @param mixed $params (opt) Parameters for this operation, usually the object
to access.
	 * @return bool Permission granted?
	 */
	public function isUser(){
		if(Yii::app()->user->isGuest)
			return false;
		else if(Yii::app()->user->roles == 'User')
			return true;
		elsecheckAccess($operation, $params=array())
	{
		if (empty($this->id)) {
			// Not identified => no rights
			return false;
		}
		$role = $this->getState("roles");
		if ($role === 'admin') {
			return true; // admin role has access to everything
		}
		// allow access if the operation request is the current user's role
		return ($operation === $role);
	}
}
~~~

You can define your own logic in this `checkAccess()` methods.

**Make sure this class is used by Yii.** The config file
"protected/config/main.php" must contain:

?>~~~
[php]
'components' => array(
	// ...
	'user' => array(
		'class' => 'WebUser',
	),
~~~

And now, from your controller accessRules() function try something
like*Sidenote:*  
[CWebUser::checkAccess()] usually connects to the authorization system loaded in
Yii.
Here we are replacing it with a simple system that just deals with roles instead
of the hierarchical system defined by the derivatives of [CAuthManager]. See the
official tutorial,
[http://www.yiiframework.com/doc/guide/1.1/en/topics.auth#role-based-access-control](Role-Based
Access Control) for details.

## Checking permissions: usage

* In your PHP code, use `Yii::app()->user->checkAccess('admin')` to check
if the current user has the 'admin' role.
  The call `Yii::app()->user->checkAccess('staff')` will return true if
the user has the role "staff" or "admin".
* In your controller, you can filter with `accessRules()` using the
"roles" attribute of the rule.

See examples below.

### How to filter access to actions

The controller must contain:

~~~
[php]
public function filters()
{
	return array(
		'accessControl', // perform access control for CRUD operations
	);
}

public function accessRules()
{	
	return array(
		array('allow',
			'controllers'=>array('admin'),
			'expression'=>'Utils::isAdmin()',			'action'=>array('admin'),
			'roles'=>array('staff', 'devel'),
		),
		array('deny',  // deny all users
			'users'=>array('*'),
		),
	);
}
~~~

Here I just protect my AdminController.php from otherthe
"admin" action of the controller has restricted access: only those
with roles than Admin. Basically from AdminController.php file
accessRules() function it checks"staff" or
"devel" can access it.

As described in the users Roles writtenAPI doc of
[http://www.yiiframework.com/doc/api/1.1/CAccessRule#roles-detail](CAccessRule),
the "roles" attribute will in Utils.php
file.fact call `Yii::app()->user->checkAccess()`.

### How to display a different menu according to roles

You can also use just one menu for all users based upon different roles. for
example

~~~
[php]
<?php $this->widget('zii.widgets.CMenu',array(
			'items'=>array(				
				array('label'=>'Users',
$user = Yii::app()->user; // just a convenience to shorten expressions
$this->widget('zii.widgets.CMenu',array(
	'items'=>array(				
		array('label'=>'Users', 'url'=>array('/manageUser/admin'),
'visible'=>Utils::isAdmin()),
				array('label'=>'Ideas', 'url'=>array('/manageIdea/admin'),
'visible'=>Utils::isAdmin()),
				array('label'=>'Page Editor', 'url'=>array('/admin/pageeditor'),
'visible'=>Utils::isAdmin()),
				array('label'=>'Your'visible'=>$user->checkAcces('staff')),
		array('label'=>'Your Ideas', 'url'=>array('/userarea/ideaList'),
'visible'=>Utils::isUser()),
				array('label'=>'Add new idea', 'url'=>array('/userarea/create'),
'visible'=>Utils::isUser()),
				array('label'=>'Login','visible'=>$user->checkAcces('normal')),
		array('label'=>'Login', 'url'=>array('/site/login'),
'visible'=>Yii::app()->user->isGuest),
				array('label'=>'Logout'visible'=>$user->isGuest),
		array('label'=>'Logout ('.Yii::app()->user->name.')',
'url'=>array('/site/logout'),
'visible'=>!Yii::app()->user->isGuest)
			),
		)); ?>'visible'=>!$user->isGuest)
	),
));
?>
~~~

I hope## Going further: access context

A very usual need is to allow a user to update its own data but not other's.
In this little codecase, the user's role is meaningless
without the context: the data that will help yoube
modified.

This is why [CWebUser::checkAccess()] has an optional "$param"
parameter. Now suppose we want to check is a user has the right to update a Post
record. We can write:
~~~
[php]
if (Yii::app()->user->checkAccess('normal', $post)) {
~~~

ThanksOf course `WebUser::checkAccess()` must be extended to use
this "$params" parameter.
This will depend on your application's logic.
For instance, it could be as simple as granting access iff `$post->userId ==
$this->id`.