Difference between #2 and #5 of
Simple RBAC

Revision #5 has been created by François Gannaz on Apr 30, 2012, 3:49:16 PM with the memo:

Added a section on context
« previous (#2) next (#6) »

Changes

Title unchanged

Simple RBAC

Category unchanged

Tutorials

Yii version unchanged

Tags unchanged

Simple RBAC, Role based access control, roles, Authentication, Role based menu

Content changed

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 user table make a column named 'roles'
 
 
When you add users you can assign them different roles like 'Admin' / 'user' / 'staff' etc etc.
 
 
On your UserIdentity.php file 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);
 
 
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.
 
 
 
 
```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;
 
}
 

 
public function isUser(){
 
if(Yii::app()->user->isGuest)
 
return false;
 
else if(Yii::app()->user->roles == 'User')
 
return true;
 
else
 
return false;
 
}
 
}
 
 
?>
 
```
 
 
And now, from your controller accessRules() function try something like
 
 
 
 
```php 
public function accessRules()
 
{
 
return array(
 
array('allow',
 
'controllers'=>array('admin'),
 
'expression'=>'Utils::isAdmin()',
 
),
 
array('deny',  // deny all users
 
'users'=>array('*'),
 
),
 
);
 
}
 
```
 
 
Here I just protect my AdminController.php from other roles than Admin. Basically from AdminController.php file accessRules() function it checks the users Roles written in Utils.php file.
 
 
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', '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 Ideas', 'url'=>array('/userarea/ideaList'), 'visible'=>Utils::isUser()),
 
array('label'=>'Add new idea', 'url'=>array('/userarea/create'), 'visible'=>Utils::isUser()),
 
array('label'=>'Login', 'url'=>array('/site/login'), 'visible'=>Yii::app()->user->isGuest),
 
array('label'=>'Logout ('.Yii::app()->user->name.')', 'url'=>array('/site/logout'), 'visible'=>!Yii::app()->user->isGuest)
 
),
 
)); ?>
 
```
 
 
I hope this little code will help you
 
 
Thanks
need simple Role based access control without the long RBAC process then this article is just for you. Lets jump to the point.
 
 
## The user model
 
 
On your user table make a column named 'roles'. Create the model accordingly. It will be named "User" here.
 
 
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);`
 
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`.
 
 
## 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 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 checkAccess($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',
 
),
 
```
 
 
*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',
 
'action'=>array('admin'),
 
'roles'=>array('staff', 'devel'),
 
),
 
array('deny',  // deny all users
 
'users'=>array('*'),
 
),
 
);
 
}
 
```
 
 
Here the "admin" action of the controller has restricted access: only those with roles "staff" or "devel" can access it.
 
 
As described in the API doc of [http://www.yiiframework.com/doc/api/1.1/CAccessRule#roles-detail](CAccessRule), the "roles" attribute will in 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
 
$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'=>$user->checkAcces('staff')),
 
array('label'=>'Your Ideas', 'url'=>array('/userarea/ideaList'), 'visible'=>$user->checkAcces('normal')),
 
array('label'=>'Login', 'url'=>array('/site/login'), 'visible'=>$user->isGuest),
 
array('label'=>'Logout ('.Yii::app()->user->name.')', 'url'=>array('/site/logout'), 'visible'=>!$user->isGuest)
 
),
 
));
 
?>
 
```
 
 
## Going further: access context
 
 
A very usual need is to allow a user to update its own data but not other's.
 
In this case, the user's role is meaningless without the context: the data that will be 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)) {
 
```
 
 
Of 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`.
33 1
43 followers
Viewed: 95 236 times
Version: 1.1
Category: Tutorials
Written by: hasanavi
Last updated by: Stageline
Created on: Apr 29, 2012
Last updated: 5 years ago
Update Article

Revisions

View all history