Simple authorization system

You are viewing revision #11 of this wiki article.
This is the latest version of this article.
You may want to see the changes made in this revision.

« previous (#10)

How to create a simple (non-RBAC) authorization system

As I notice reading the forum, this is a frequent doubt, so I decided to write this article.

This article covers only the authorization system. I assume you already know how to create an authentication system ( login ).

Database

Firstly, in the 'user' table, create a new integer field called 'accessLevel', that defines the user's access level

Extending CWebUser

in your config file (usually protected/config/main.php)

'components'=>array(
  'user'=>array(
    //tell the application to use your WebUser class instead of the default CWebUser
    'class'=>'WebUser',
    //...
  ),
),

In your components folder ( protected/components ) create a 'WebUser.php' file and a class like this:

/**
 * @property boolean $isAdmin
 * @property boolean $isSuperAdmin
 * @property User $user
 */
class WebUser extends CWebUser{
 /**
  * cache for the logged in User active record
  * @return User
  */
 private $_user;
 /**
  * is the user a superadmin ?
  * @return boolean
  */
 function getIsSuperAdmin(){
  return ( $this->user && $this->user->accessLevel == User::LEVEL_SUPERADMIN );
 }
 /**
  * is the user an administrator ?
  * @return boolean
  */
 function getIsAdmin(){
  return ( $this->user && $this->user->accessLevel >= User::LEVEL_ADMIN );
 }
 /**
  * get the logged user
  * @return User|null the user active record or null if user is guest
  */
 function getUser(){
  if( $this->isGuest )
   return null;
  if( $this->_user === null ){
   $this->_user = User::model()->findByPk( $this->id );
  }
  return $this->_user;
 }
}

Usage

now to validate the user using the filter accessControl

//in your controller
function accessRules(){
  return array(
    //only accessable by admins
    array('allow',
      'expression'=>'$user->isAdmin',
       //the 'user' var in an accessRule expression is a reference to Yii::app()->user
    ),
    //deny all other users
    array('deny',
      'users'=>array('*').
    ),
  );
}

using it in your views

if(Yii::app()->user->isAdmin){
   echo 'Welcome, administrator!';
}
if(Yii::app()->user->isSuperAdmin){
   echo 'You are the man!';
}

Data representation

Now in your User model, to facilitate the data representation of an integer field do the following

class User extends CActiveRecord{
 //define the number of levels that you need
 const LEVEL_REGISTERED=0, LEVEL_AUTHOR=1, LEVEL_ADMIN=6, LEVEL_SUPERADMIN=99;

 /**
  * define the label for each level
  * @param int $level the level to get the label or null to return a list of labels
  * @return array|string
  */
 static function getAccessLevelList( $level = null ){
  $levelList=array(
   self::LEVEL_REGISTERED => 'Registered',
   self::LEVEL_AUTHOR => 'Author',
   self::LEVEL_ADMIN => 'Administrator'
  );
  if( $level === null)
   return $levelList;
  return $levelList[ $level ];
 }
}

//using it in forms
$form->dropDownList($model,'accessLevel',$model->accessLevelList);

//using it in DetailView
$this->widget('zii.widgets.CDetailView',array(
  'data'=>$model,
  'attributes'=>array(
   //...,
   array(
    'name'=>'accessLevel',
    'value'=>$model->accessLevelList[$model->accessLevel],
   ),
  ),
));

//using it in GridView
$this->widget('zii.widgets.CGridView',array(
  'dataProvider'=>$model->search(),
  'columns'=>array(
   //...,
   array(
    'name'=>'accessLevel',
    'value'=>'$data->accessLevelList[$data->accessLevel]',
   ),
  ),
));

//display the administrator label 
echo User::getAccessLevelList( User::LEVEL_ADMIN );


And that is it. I hope that helps you.

Cheers, Gustavo

Read more
Links

Chinese Version

14 0
17 followers
Viewed: 45 734 times
Version: Unknown (update)
Category: How-tos
Written by: Gustavo
Last updated by: Gustavo
Created on: Nov 24, 2011
Last updated: 11 years ago
Update Article

Revisions

View all history

Related Articles