Diy Rbac

I’m in the middle of making an RBAC module for myself I though I share some of the hacky uncommented spaghetti code I came up with, this is not a cut and paste operation, I’m guiding you to make your own.

I will be posting more later. Like whats up with the crc32

In Yii we have multiple ways to dynamically check access, some of the ways I investigated were:

  1. We could edit the /protected/components/Controller.php and add a method there, as all the generated Controllers inherit from that class rather than /framework/web/CController.php.

This wouldn’t work to well with a module.

  1. We could generate a single controller that redirects all requests to a class that inherits from CAction.

Again this wouldn’t work to well with a module.

  1. Do about same as above, but in the configuration add a controller to ‘catchAllRequest’.

This could work, but it seemed like this was more for putting up an ‘Under Construction Message’

  1. Make a new Controller class and change all the Controllers so they inherit from them.

This could work but all the end users controllers would have to be modified to inherit from it.

  1. Use the preload? I didn’t want to mess with this, as I didn’t know how to make it function and whether or not we could use all components built within Yii.

  2. Attach a behavior to the entire project, that dynamically inserts itself into the processing chain, checks to make sure you have access, if you don’t you get redirected or an error, if you do the normal processing continues.

Under my config I added this along with the autoloading config of my module(not shown).


'modules'=>array(

		.....

		

	),

        'behaviors'=>array('RBACBehavior'),

	// application components

	'components'=>array(...



The first thing is we want to extend the CBehaviour class, and (5.4 Only) Copy and paste the CController into a new file replace "class CController extends CBaseController" with trait MyTrait, (Below PHP 5.4 you will have to copy and paste the methods) this is so we can use the redirect.




class RBACBehavior extends CBehavior

{

    use RBACTraits;

 


         

        private $_httpRequest;


        private $_requestUri;


        private $_controllerObj;

        

    public function events()

    {

        return array_merge(parent::events(), array(

            'onBeginRequest'=>'beginRequest',

        ));

    }

    

    public function beginRequest()

    {

        $this->InitUrlParams();

        $accessCode = $this->findAccess();

        if($accessCode==0)

        {

                //$this->redirect('index.php');

        }

         

    }

    

    public function InitUrlParams()

    {

        $this->_httpRequest = new CHttpRequest;

        $this->_requestUri = Yii::app()->getUrlManager()->parseUrl($this->_httpRequest->getRequestUri());

        $this->_controllerObj = Yii::app()->createController($this->_requestUri);

                

    }

    

        public function urlParms()

        {

            if(empty($this->_controllerObj[0]->module))

            {

                if(empty($this->_controllerObj[1]))

                {

                    return array('controller'=>$this->_controllerObj[0]->id, 'action'=>$this->_controllerObj[0]->defaultAction, 'index'=>dechex(crc32($this->_controllerObj[0]->id . $this->_controllerObj[0]->defaultAction)));

                }

                else

                {

                    return array('controller'=>$this->_controllerObj[0]->id, 'action'=>$this->_controllerObj[1],  'index'=>dechex(crc32($this->_controllerObj[0]->id . $this->_controllerObj[1])));

                }

            }

            else

            {

                if(empty($this->_controllerObj[1]))

                {

                    return array('module'=>$this->_controllerObj[0]->module->id, 'controller'=>$this->_controllerObj[0]->id, 'action'=>$this->_controllerObj[0]->defaultAction,  'index'=>dechex(dechex(crc32($this->_controllerObj[0]->module->id . $this->_controllerObj[0]->id . $this->_controllerObj[0]->defaultAction))));

                }

                else

                {

                    return array('module'=>$this->_controllerObj[0]->module->id, 'controller'=>$this->_controllerObj[0]->id, 'action'=>$this->_controllerObj[1], 'index'=>dechex(crc32($this->_controllerObj[0]->module->id . $this->_controllerObj[0]->id . $this->_controllerObj[1])));

                }

            }

        }

        

        

        public function findAction()

        {

            $actionid = $this->urlParms();

            $sql = 'SELECT action_id FROM tbl_actions WHERE action_md5 = :actionid';

            $connection=Yii::app()->db;  

            $command=$connection->createCommand($sql);

            $command->bindParam(":actionid",$actionid['index'],PDO::PARAM_STR);


            $result= $command->queryRow(true);

            if(!empty($result))

            {

                return $result;

            }

            else

            {

                return 0;

            }

                  

            

        }

            public function findAccess()

            {

                    $actionid = $this->findAction();

                    

                    if($actionid['action_id'] != 0)

                    {

                        $roleid = $this->findRole();

                        

                        $sql = 'SELECT access FROM tbl_rules WHERE :actionid = action_id AND :roleid = role_id';

                        

                        $connection=Yii::app()->db;  

                       

                        $command=$connection->createCommand($sql);

                        $command->bindParam(":actionid",$actionid['action_id'],PDO::PARAM_STR);

                        $command->bindParam(":roleid",$roleid,PDO::PARAM_STR);

                        

                        $result = $command->queryRow(true);

                        

                        if(empty($result['access']))

                        {

                            return 0;

                        }

                        else

                        {

                            return $result['access'];

                        }

                    }

                    else

                    {

                        return 0;

                    }

            }

            

            public function findRole()

            {

                    if(!Yii::app()->user->isGuest)

                    {

                        $userid = Yii::app()->user->getId;

                        $sql = 'SELECT role_id FROM tbl_users WHERE tbl_users.user_id = :userid';

                        $connection=Yii::app()->db;  

                        $command=$connection->createCommand($sql);

                        $command->bindParam(":userid",$userid,PDO::PARAM_STR);

                        return $command->query();

                    }

                    else

                    {

                        return 1;

                    }

                     

            }

}



For some reason Reflection wasn’t working right on my windows server, I don’t know why it says a file dosn’t exist but its pointing directly to it. Well anyways here it is.


    public function actionViewActions()

    {

                $RBACaction = '_viewActions';

                $model['find'] = $this->getControllerActions();

                $this->render('index', array('RBACaction'=>$RBACaction, 'model'=>$model));    

    }

    

  

    

    public function scanDirs($directory, $itemsArray=array())

    {

        $glob=glob($directory . '/*');

        

        foreach($glob as $key01=>$val01)

        {

            if(is_dir($val01))

            {

                $itemsArray = array_merge($itemsArray, $this->scanDirs($val01));

            }

            else

            {

                    if(preg_match('#.+Controller\.php#', $val01) && !preg_match('#.+/components/Controller.php#', $val01))

                    {

                        $itemsArray[]=$val01; 

                    }

            }

        }

        return $itemsArray;

    }

    

 

    

    

    public function getControllers()

    {

        return $filesArray = $this->scanDirs(Yii::app()->basePath);

    }

    

    public function getControllerActions()

    {

        $contArray=array();

        

        $controllers=$this->getControllers();

        

        foreach($controllers as $key01=>$val01)

        {

            

            $contArray[$key01]['file_path'] = $val01;

            $contArray[$key01]['file_name'] = $this->getFileName($val01);

            $contArray[$key01]['module'] = $this->getModules($val01);

            $contArray[$key01]['class_name'] = $this->getClassName($contArray[$key01]['file_name']);

            $contArray[$key01]['class_as_url'] = $this->getCUrlName($contArray[$key01]['class_name']);

            $contArray[$key01]['methods'] = $this->getActionMethods($val01);

            //$contArray[$key01]['method_as_url'] = $this->getMUrlName($contArray[$key01]['methods']);

   

        }

        return $contArray;

    }

    

    

    public function getClassName($val)

    {

        preg_match('#\w+(?=\.php)#', $val, $return);

        return $return[0];

        

    }

    

    public function getFileName($val)

    {

        preg_match('#\w+\.php#', $val, $return);

        return $return[0];

    }

    

    public function getModules($val)

    {

        preg_match_all('#(?<=modules/)\w+#', $val, $array);

        if(!empty($array[0][1]))

        {

            foreach($array[0] as $key01=>$val01)

            {

                $array[0][$key01]=lcfirst($array[0][$key01]);

            }

            return $implode = implode($array[0], '/');

        }

        elseif(isset($array[0][0]))

        {

        return $array[0][0];

        }

        else

        {

            return null;

        }

    }

    

    public function getCUrlName($val)

    {

        return lcfirst(preg_replace('#Controller#', '',$val));

    }

     

    

    public function getActionMethods($val)

    {

        $file = file_get_contents($val);

        preg_match_all('#(?<=action)(?!s)[a-z A-Z]+(?=\()#', $file, $find);

        foreach($find[0] as $key01=>$val01)

        {

            $find[0][$key01] = lcfirst($find[0][$key01]);

        }

        return $find[0];

    }