Search code examples
zend-frameworkdefaultaclrolesmodular

zend acl Modular implementation?


I am trying to implement zend ACL in my project, i am facing three problems. To explain the problems this is the code:

My library plugin class

class Mylib_Controller_Plugin_AccessCheck extends Zend_Controller_Plugin_Abstract {

    private $_acl = null;
    private $_auth = null;

    public function __construct(Zend_Acl $acl, Zend_Auth $auth) {
        $this->_acl = $acl;
        $this->auth = $auth;
    }

    public function preDispatch(Zend_Controller_Request_Abstract $request) {
        $module = $request->getModuleName();
        $recourse = $request->getControllerName();
        $action = $request->getActionName();
            $identity = $this->auth->getStorage()->read();
    if (!isset($identity->Role)) {

            $role = 'default';
        } else {
        $role = $identity->Role;
        }

        if (!$this->_acl->isAllowed($role, $module, $recourse)) {
            $request->setModuleName('Admin')
                    ->setControllerName('User')
                    ->setActionName('index');
        }


    }

}

This is my ACL class in the models folder

class Application_Model_DbTable_LibraryAcl extends Zend_Acl {

    public function __construct() {
        $this->addRole(new Zend_acl_Role('default'));
        $this->addRole(new Zend_acl_Role('User'));
        $this->addRole(new Zend_acl_Role('Admin'), 'User');



        $this->add(new Zend_Acl_Resource('Admin'))
                ->add(new Zend_Acl_Resource('default'))

        ;



        $this->allow('Admin')
                ->deny(array('User', 'default'));

    }

}

This is the _initAppAutoload in the bootstarp

 $acl = new Application_Model_DbTable_LibraryAcl();

        $auth = Zend_Auth::getInstance();


        $fc = Zend_Controller_Front::getInstance();

        $fc->setControllerDirectory(array('default' => '/../application/modules/default/controllers',
            'Admin' => '/../application/modules/Admin/controllers'));
        $fc->registerPlugin(new Hyderlib_Controller_Plugin_AccessCheck($acl, $auth));

1) the first problem is how can i specify in the Application_Model_DbTable_LibraryAcl that i have a modular implementation with admin and default folders or how can i create a tree of resources for each module?

2)i don't have a default role in my database but i want to make this default user to have some previligaes without creating an account(That's why i check the identity of the role and if it is none i set it to default). is that the best practice to do so or even logical ?

3) how can i check in my Mylib_Controller_Plugin_AccessCheck class in the _isAllowed method for the action too not just the module and the controller.?

Also this way of redirecting is also giving me an error of isn't redirecting properly


Solution

  • Here goes,

    1) the first problem is how can i specify in the Application_Model_DbTable_LibraryAcl that i have a modular implementation with admin and default folders or how can i create a tree of resources for each module?

    You are pretty close already, for a basic implementation:

    class Application_Model_DbTable_LibraryAcl extends Zend_Acl {
    
    public function __construct() {
        //add Roles
        //default role has very limited access
        $this->addRole(new Zend_acl_Role('default'));
        //User inherits all default access
        $this->addRole(new Zend_acl_Role('User'), 'default');
        //Admin inherits all User and Default acces
        $this->addRole(new Zend_acl_Role('Admin'), 'User');
    
        //add resources, caps don't seem to be a problem.
        //add Admin module resource
        $this->add(new Zend_Acl_Resource('admin'));
        //add Admin module Index controller resource, specify admin as parent 
        $this->add(new Zend_Acl_Resource('index'), 'admin');
        //add default module access
        $this->add(new Zend_Acl_Resource('default'));
    
        //add access rules
        //default in Zend_Acl is to deny all
    
        //everyone has access to the front page and the error page
        $this->allow(NULL, 'default', array('index', 'error'));
        $this->allow(NULL, 'default', array('index', 'index'));
    
        //add default user rules
        //allow default access to login logout
        $this->allow('default', 'default', array('login', 'logout'));
    
        //add crud access for User
        $this->allow('User', 'default', array('add', 'update'));
    
        //admin can do all
        $this->allow('Admin', NULL);
      }
    
    }
    

    This is probably not perfect, but should give you the idea of what to do. you can test the results as you need.

    2)i don't have a default role in my database but i want to make this default user to have some previligaes without creating an account(That's why i check the identity of the role and if it is none i set it to default). is that the best practice to do so or even logical ?

    Works for me, it's really hard to check a users role 'til you know who they are. Check away.

    3) how can i check in my Mylib_Controller_Plugin_AccessCheck class in the _isAllowed method for the action too not just the module and the controller.?

    public function preDispatch(Zend_Controller_Request_Abstract $request) {
            $module   = $request->getModuleName();
            $recourse = $request->getControllerName();
            $action   = $request->getActionName();
                $identity = $this->auth->getStorage()->read();
        if (!isset($identity->Role)) {
                $role = 'default';
            } else {
                $role = $identity->Role;
            }
            //default role is default, if role is not allowed and not set to default send to error controller.
            if (!$this->_acl->isAllowed($role, $module, $recourse, $action)) {
                if ($role == 'default'){
                    $request->setModuleName('default')
                            ->setControllerName('index')
                            ->setActionName('login');
                } else {
                    $request->setModuleName('default')
                            ->setControllerName('error')
                            ->setActionName('noauth');
            }
    

    Adding the action name to the isAllowed() seems to work for my app, but the testing has not benn very extensive. So use with caution. I'm like you still trying to get my head all the way around these concepts.