Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zend Framework: need typical example of ACL

Can some one guide me for typical implementation example of ACL. Like 'admin' can access 'admin' module, 'user' can access 'user module', and guest can access 'open' pages.

like image 423
Simpanoz Avatar asked Mar 06 '11 09:03

Simpanoz


2 Answers

I can paste you my ACL. It consists of three elements: acl.ini, ACL controller plugin (My_Controller_Plugin_Acl) and My_Acl class, and USER table. However it does not deal with modules, but with controllers and actions. Nevertheless it may give you some general idea about ACL. My use of ACL is based on the one in a book called "Zend Framework in Action".

USER table (privilege field is used for ACL):

CREATE  TABLE IF NOT EXISTS `USER` (
  `user_id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  `email` VARCHAR(85) NOT NULL ,
  `password` CHAR(32) NOT NULL,
  `phone` VARCHAR(45) NULL ,
  `phone_public` TINYINT(1) NULL DEFAULT 0 ,     
  `first_name` VARCHAR(45) NULL ,
  `last_name` VARCHAR(45) NULL ,
  `last_name_public` TINYINT(1) NULL DEFAULT 1 ,
  `is_enabled` TINYINT(1) NOT NULL DEFAULT 1 ,
  `created` TIMESTAMP NOT NULL,
  `privilage` ENUM('BASIC','PREMIUM','ADMIN') NOT NULL DEFAULT 'BASIC' ,
  PRIMARY KEY (`user_id`) ,
  UNIQUE INDEX `email_UNIQUE` (`email` ASC) )
ENGINE = InnoDB;

acl.ini (I have four privileges, such that basic inherits from guest, premium inherits form basic and administrator for premium):

; roles
acl.roles.guest = null
acl.roles.basic = guest
acl.roles.premium = basic
acl.roles.administrator = premium

; resources
acl.resources.deny.all.all = guest


acl.resources.allow.index.all = guest
acl.resources.allow.error.all = guest
acl.resources.allow.user.login = guest
acl.resources.allow.user.logout = guest
acl.resources.allow.user.create = guest

acl.resources.allow.user.index = basic
acl.resources.allow.user.success = basic

My_Acl class (creates ACL roles and resources based on the ini file):

class My_Acl extends Zend_Acl {

    public function __construct() {
        $aclConfig = Zend_Registry::get('acl');
        $roles = $aclConfig->acl->roles;
        $resources = $aclConfig->acl->resources;
        $this->_addRoles($roles);
        $this->_addResources($resources);
    }

    protected function _addRoles($roles) {

        foreach ($roles as $name => $parents) {
            if (!$this->hasRole($name)) {
                if (empty($parents)) {
                    $parents = null;
                } else {
                    $parents = explode(',', $parents);
                }                    
                $this->addRole(new Zend_Acl_Role($name), $parents);             
            }
        }       
    }

    protected function _addResources($resources) {          

        foreach ($resources as $permissions => $controllers) {         

            foreach ($controllers as $controller => $actions) {
                if ($controller == 'all') {
                    $controller = null;
                } else {
                    if (!$this->has($controller)) {
                        $this->add(new Zend_Acl_Resource($controller));
                    }
                }

                foreach ($actions as $action => $role) {
                    if ($action == 'all') {
                        $action = null;
                    }
                    if ($permissions == 'allow') {
                        $this->allow($role, $controller, $action);
                    }
                    if ($permissions == 'deny') {                           
                        $this->deny($role, $controller, $action);
                    }
                }
            }
        }
    }

}

My_Controller_Plugin_Acl:

class My_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract {

    /**
     *
     * @var Zend_Auth
     */
    protected $_auth;

    protected $_acl;
    protected $_action;
    protected $_controller;
    protected $_currentRole;

    public function __construct(Zend_Acl $acl, array $options = array()) {
        $this->_auth = Zend_Auth::getInstance();
        $this->_acl = $acl;

    }

   public function preDispatch(Zend_Controller_Request_Abstract $request) {

        $this->_init($request);        

        // if the current user role is not allowed to do something
        if (!$this->_acl->isAllowed($this->_currentRole, $this->_controller, $this->_action)) {

            if ('guest' == $this->_currentRole) {
                $request->setControllerName('user');
                $request->setActionName('login');
            } else {
                $request->setControllerName('error');
                $request->setActionName('noauth');
            }
        }
    }

    protected function _init($request) {
        $this->_action = $request->getActionName();
        $this->_controller = $request->getControllerName();
        $this->_currentRole = $this->_getCurrentUserRole();
    }

    protected function _getCurrentUserRole() {      

        if ($this->_auth->hasIdentity()) {
            $authData = $this->_auth->getIdentity();
            $role = isset($authData->property->privilage)?strtolower($authData->property->privilage): 'guest';
        } else {
            $role = 'guest';
        }

        return $role;
    }

}

Finally a part of Bootstrap.php where everything is initialized:

protected function _initLoadAclIni() {
    $config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/acl.ini');
    Zend_Registry::set('acl', $config);
}

protected function _initAclControllerPlugin() {
    $this->bootstrap('frontcontroller');
    $this->bootstrap('loadAclIni');

    $front = Zend_Controller_Front::getInstance();

    $aclPlugin = new My_Controller_Plugin_Acl(new My_Acl());

    $front->registerPlugin($aclPlugin);
}
like image 164
Marcin Avatar answered Nov 05 '22 02:11

Marcin


I have a simple example that might fits your needs

class Dagho_Acl_Main extends Zend_Acl {
    public function   __construct() {
        $anonymous = new Zend_Acl_Role("anonymous");
        $customer = new Zend_Acl_Role("customer");
        $admin = new Zend_Acl_Role("admin");
        $anonymousResource  = new Zend_Acl_Resource("acl");
        $defaultResource = new Zend_Acl_Resource("default");
        $customerResource  = new Zend_Acl_Resource("user");
        $adminResource  = new Zend_Acl_Resource("manage");


        $this->addRole($anonymous)
             ->addRole($customer)
             ->addRole($admin);
        $this->addResource($anonymousResource)
             ->addResource($defaultResource)
             ->addResource($customerResource)
             ->addResource($adminResource);


        $this->allow($anonymous, $anonymousResource);
        $this->allow($anonymous, $defaultResource);
        $this->deny($anonymous, $customerResource);
        $this->deny($anonymous, $adminResource);

        $this->allow($customer, $anonymousResource);
        $this->allow($customer, $defaultResource);
        $this->allow($customer, $customerResource);
        $this->deny($customer, $adminResource);

        $this->allow($admin, $defaultResource);
        $this->allow($admin, $anonymousResource);
        $this->allow($admin, $adminResource);
        $this->deny($admin, $customerResource);
       return $this ;
    }
}

and here is my plugin :

<?php

class Dagho_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract {

    public function preDispatch(Zend_Controller_Request_Abstract $request) {
        $module = $request->getModuleName();
        $controller = $request->getControllerName();
        $action = $request->getActionName();
        $doctrineAuth = new Dagho_Auth_Doctrine();
        $logged = $doctrineAuth->checklogin();
        $identity = $doctrineAuth->getIdentity();
        Zend_Registry::set("identity", $identity);
        if ($logged && $identity["role"] !== "anonymous") {
            /// user had an identity  let's check the ACL
            $acl = new Dagho_Acl_Main();
            $isAllowed = $acl->isAllowed($identity["role"], $module);
            if (!$isAllowed) {
                return $request->setModuleName("acl")->setControllerName("index")
                        ->setActionName("denied")->setDispatched(true);
            } else {
                /// user has identity and he is allowed to access it
                return;
            }
        } elseif ($logged === false || ($logged && $identity["role"] === "anonymous" )) {
            //// user not logged on > login.php or its his first visit
            $identity = $doctrineAuth->getStorage()->write(array('name' => 'anonymous', 'role' => "anonymous",));
            Zend_Registry::set("identity", $identity);
            return $request->setModuleName("acl")->setControllerName("index")
                    ->setActionName("login")->setDispatched(true);
        } else {
            return $request->setModuleName("acl")->setControllerName("index")
                    ->setActionName("denied")->setDispatched(true);
        }
        parent::preDispatch($request);
    }

}
like image 4
tawfekov Avatar answered Nov 05 '22 01:11

tawfekov