CodeIgniter framework, roles management

Coding Critique is the place to post source code for peer review by other members of DevNetwork. Any kind of code can be posted. Code posted does not have to be limited to PHP. All members are invited to contribute constructive criticism with the goal of improving the code. Posted code should include some background information about it and what areas you specifically would like help with.

Popular code excerpts may be moved to "Code Snippets" by the moderators.

Moderator: General Moderators

Post Reply
User avatar
VladSun
DevNet Master
Posts: 4313
Joined: Wed Jun 27, 2007 9:44 am
Location: Sofia, Bulgaria

CodeIgniter framework, roles management

Post by VladSun »

Hello, CodeIgniters :)
I am working on a relatively big project with a lot of controllers and actions and unknown number of user roles. I've decided to use CodeIgniter framework.
The first problem that I faced was the implementation of user authorization and his role permissions logic.
I wrote a solution that works pretty good for me, but I need your criticism, so I can make it better and continue to use it in future projects cleanly.

So ... in /system/codeigniter/CodeIgniter.php I change this code:

Code: Select all

 
        // Call the requested method.
        // Any URI segments present (besides the class/function) will be passed to the method for convenience       
        call_user_func_array(array(&$CI, $method), array_slice($RTR->rsegments, (($RTR->fetch_directory() == '') ? 2 : 3)))
to

Code: Select all

 
        if (method_exists($CI, '_check_privileges'))
        {
            if ($CI->_check_privileges($class, $method))
            {
                // Call the requested method.
                // Any URI segments present (besides the class/function) will be passed to the method for convenience       
                call_user_func_array(array(&$CI, $method), array_slice($RTR->rsegments, (($RTR->fetch_directory() == '') ? 2 : 3)));        
            }
        }
        else
        {
            // Call the requested method.
            // Any URI segments present (besides the class/function) will be passed to the method for convenience       
            call_user_func_array(array(&$CI, $method), array_slice($RTR->rsegments, (($RTR->fetch_directory() == '') ? 2 : 3)));        
        }
I create a new base class for Controller (simplified version, no error reporting, etc.):

Code: Select all

 
class CC_Controller extends Controller 
{
    var $is_login = false;
    
    function CC_Controller($is_login = false)
    {
        parent::Controller();
        
        $this->is_login = $is_login;
        $this->user_logged = empty($_SESSION) ? false : (!empty($_SESSION['user_id']) ? true : false);
    }
    
    function _check_privileges($object = null, $method = null)
    {
        // Populate object/method values
        $this->object = $object;
        $this->method = $method;
        
        // Only login controller should set $is_login to true
        if ($this->is_login)
            return true;
            
        // Obviously user could not be granted any permissions when not logged in 
        if (!$this->user_logged)
            return false;
 
        if (empty($object) || empty($method))
            return false;
 
        // Role model should return 2D Array of object/methods
        $this->load->model('role_model', '_role');
        $this->role_permissions = $this->_role->get_permissions($_SESSION['user_role']);
 
        // Role not found
        if (empty($this->role_permissions))
            return false;
 
        // Permission to access this controller not granted 
        if (empty($this->role_permissions[strtolower($object)]))
            return false;
 
        // Permission to access this action of the controller not granted 
        if (empty($this->role_permissions[strtolower($object)][strtolower($method)]))
            return false;
 
        // OK
        return true;
    }
}
 
Every controller in my application folder must extend the CC_Controller class.

Any comments are welcome :)

PS: Maybe implementing a group role permissions is a good idea, but I think it should be placed in the Model, transparently to the CC_Controller ($_SESSION['user_id'] should be passed to get_permissions()?).
There are 10 types of people in this world, those who understand binary and those who don't
Gruessle
Forum Newbie
Posts: 2
Joined: Wed Apr 23, 2008 3:25 pm
Location: Florida

Re: CodeIgniter framework, roles management

Post by Gruessle »

CodeIgnitor is great. I had the same problem when I created my CI side.
Lately I been checking in to Zend framework and I have a suggestion for you.

If you have already coded a lot in CI and don't wont to switch. You can always use Zend components within CI.
Zend has a great authentication class and ACL class. You don't have to use all of ZF you can just use those classes within CI.

Here is an example for ZF ACL, which will work standalone.

Code: Select all

 
require_once 'Acl.php';
$acl = new Tamer_ACL();
$acl->aclCreate();
 
echo 'Guest view: ';
echo $acl->isAllowed('guest', null, 'view') ? "allowed" : "denied";
 
echo 'Guest edit: ';
echo  $acl->isAllowed('guest', null, 'edit') ? "allowed" : "denied";
 
 
File Acl.php

Code: Select all

<?php
require_once 'Zend/Acl.php';
require_once 'Zend/Acl/Role.php';
require_once 'Zend/Acl/Resource.php';
 
class Tamer_ACL extends Zend_ACL 
{
    function aclCreate()
    {
        $this->addRole(new Zend_Acl_Role('guest'));
        //$this->deny('guest', null, 'view');
        
        $this->addRole(new Zend_Acl_Role('member'));
        $this->allow('member', null, array('view'));
        
        // Administrator does not inherit access controls
        $this->addRole(new Zend_Acl_Role('admin'), 'member');
        $this->allow('admin', null, array('add', 'edit', 'delete'));
        
        $this->add(new Zend_Acl_Resource('adminArea'));
        $this->add(new Zend_Acl_Resource('jobsearch'));
    }
}
?>
User avatar
VladSun
DevNet Master
Posts: 4313
Joined: Wed Jun 27, 2007 9:44 am
Location: Sofia, Bulgaria

Re: CodeIgniter framework, roles management

Post by VladSun »

Thanks for answering :)

As far as I can understand it, the Acl.php is equal to my Role_Model file :) I didn't want to show its code because one may use a different storage. In my case I used DB storage and wrote a controller to manage roles, role rules and role rule permissions :)

The main problem was where to put the role control implementation - as you see I modified the CI core files, because I wasn't able to find a better insert point.

I think it works pretty good, because the descendant controller don't care about it - it's fully transparent for them.
There are 10 types of people in this world, those who understand binary and those who don't
Post Reply