Implementing a User Level Access System

Introduction

I would like to provide you a quick tip on how to implement user level access to your Yii applications.

Please note that this article is a simple example and good security should be taken into account when we play with authentication systems.

Step 1. Setting up

a. Include a field on your user’s table named, yep you guessed, level
b. Create an object ‘LevelLookUp’ that will tell us who is who on this system (create LevelLookUp.php inside protected/component/)

class LevelLookUp{
      const MEMBER = 0;
      const ADMIN  = 2;
      // For CGridView, CListView Purposes
      public static function getLabel( $level ){
          if($level == self::MEMBER)
             return 'Member';
          if($level == self::ADMIN)
             return 'Administrator';
          return false;
      }
      // for dropdown lists purposes
      public static function getLevelList(){
          return array(
                 self::MEMBER=>'Member',
                 self::ADMIN=>'Administrator');
    }
}

c. Now, lets modify UserIdentity, located on your protected/components (normally by default), so we can store the user Model id on successful authentication, as CWebUser’s id property is set to the user Model’s username by default.

class UserIdentity extends CUserIdentity
{
    private $_id;
    /**
     * Authenticates a user.
     * @return boolean whether authentication succeeds.
     */
    public function authenticate()
    {
        $username = strtolower($this->username);
        // from database... change to suit your authentication criteria
        // -- Nope, I wont include mine --
        $user = User::model()->find('LOWER(username)=?', array($username));
        if($user===null)
            $this->errorCode=self::ERROR_USERNAME_INVALID;
        else if(!$user->validatePassword($this->password))
            $this->errorCode = self::ERROR_PASSWORD_INVALID;
        else{
            // successful login
            $this->_id = $user->id;
            $this->username = $user->username;
            $this->errorCode = self::ERROR_NONE;
        }
        return $this->errorCode == self::ERROR_NONE;
    }
    public function getId()
    {
        return $this->_id;
    }
}

d. Now we need to create our own extended CWebUser and we are going to call it EWebUser for the sake of this example, and save it on protected/components to be loaded automatically by our default’s configuration file.

class EWebUser extends CWebUser{

    protected $_model;

    function isAdmin(){
        $user = $this->loadUser();
        if ($user)
           return $user->level==LevelLookUp::ADMIN;
        return false;
    }
        
    // Load user model.
    protected function loadUser()
    {
        if ( $this->_model === null ) {
                $this->_model = User::model()->findByPk( $this->id );
        }
        return $this->_model;
    }
}

e. Finally, we modify main.php config file (this file is in protected/config folder) to tell Yii that we want to use our extended version of CWebUser.

// go to the 'user' section
// application components
    'components'=>array(
        'user'=>array(
            // There you go, use our 'extended' version
            'class'=>'application.components.EWebUser',
            // enable cookie-based authentication
            'allowAutoLogin'=>true,
        ),
Step 2: Putting everything together

Now that we know, who logged, we could easily find out if it is just a member or an administrator and render the elements by checking the level as simple as this:

// for normal content
if(Yii::app()->user->isAdmin())
     echo 'Is administrator';

// for CMenus
$this->widget('zii.widgets.CMenu',array(
    array('label'=>'Categories',
           'url'=>array('/category/index'),
           'visible'=>(Yii::app()->user->isAdmin()),
     //... More stuff
     //...

// for data chuncks
<?php if(Yii::app()->user->isAdmin():?>
<b>My HTML</b>
<?php endif;?>

// for access rules
return array(
      array('allow', 
	    'actions'=>array('create','delete','update'),
	    'expression'=>'$user->isAdmin()'
      ),
// ...

You can create more methods, like for example, isMember(), or whatever best suits you, in order to display the appropriate view or specific, data according to the user level.

27 0
37 followers
Viewed: 71 935 times
Version: 1.1
Category: Tutorials
Written by: Antonio Ramirez
Last updated by: Phil Loaiza
Created on: May 10, 2011
Last updated: 10 years ago
Update Article

Revisions

View all history

Related Articles