views:

619

answers:

1

Background information:

I'm in my admin module, and I created a view helper in modules/admin/views/helpers/AdminPanel.php. I have a layout plugin that forces my view to use the layout in admin/views/layouts/default.phtml.

I'm trying to access my ACL object to determine whether or not the user has resources in the context of a view helper, and then determine whether to return the admin panel html by parsing a configs/admin-nav.xml or not return anything at all.

I'm calling it in my admin layout like so:

<?php echo $this->AdminPanel(); ?>

And the class code which is blank, which I need to access the acl object in:

class My_View_Helper_AdminPanel extends Zend_View_Helper_Abstract {

public function AdminPanel() {}

}

I tried this:

$acl = Zend_Controller_Action_HelperBroker::getStaticHelper('acl');

But this probably isn't what I'm looking for as it forces the default module's views/layouts/default.phtml to load and errors occur.

Here's my global bootstrap file:

<?php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{

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

    protected function _initDoctype() {
    $this->bootstrap('view');
    $view = $this->getResource('view');
    $view->setEncoding('UTF-8');
    $view->doctype('HTML4_STRICT');
    }

    protected function _initAutoload() {
    $autoloader = Zend_Loader_Autoloader::getInstance();
    $autoloader->registerNamespace('KG_');
    $resourceLoader = new Zend_Loader_Autoloader_Resource(
        array(
        'basePath' => APPLICATION_PATH,
        'namespace' => '',
        'resourceTypes' => array(
            'form' => array(
            'path' => 'forms/',
            'namespace' => 'Form_'
            ),
            'model' => array(
            'path' => 'models/',
            'namespace' => 'Model_'
            )
        )
        ));
    return $autoloader;
    }

    protected function _initAclAuth() {
    $this->_acl = new Model_Acl;
    $this->_auth = Zend_Auth::getInstance();
    }

    protected function _initNav() {
    $this->bootstrap('layout');
    $layout = $this->getResource('layout');
    $view = $layout->getView();
    $config = new Zend_Config_Xml( APPLICATION_PATH . '/configs/nav.xml', 'mainNav');
    $navigation = new Zend_Navigation( $config );

    $fc = Zend_Controller_Front::getInstance();
    $fc->registerPlugin( new KG_Controller_Plugin_Acl( $this->_acl, $this->_auth ) );

    $role = $this->_auth->getStorage()->read()->role;

    if ( !$role ) {
        $role = 'guest';
    }

    $view->navigation( $navigation )->setAcl( $this->_acl)->setRole( $role );
    }


    protected function _initEncoding() {
    $fc = Zend_Controller_Front::getInstance();
    $response = new Zend_Controller_Response_Http;
    $response->setHeader('Content-Type','text/html;charset=utf-8', true);
    $fc->setResponse($response);
    }

}
+1  A: 

Your KG_Controller_Plugin_Acl plugin should be taking care of the access logic, not your view. If the user doesn't have access to the resource, you should error out or redirect the user to somewhere else.

The layout should be set within the controller. Preferably in the init() method with:

$this->_helper->layout->setLayout();

It looks like you followed the same or a similar tutorial as I did for Zend_Acl. I'm posting my plugin for reference, which includes the logic to handle access control from within the plugin:

class App_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
{

    protected $_auth = null;
    protected $_acl = null;

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

    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
        if ($this->_auth->hasIdentity()) {
            $identity = $this->_auth->getIdentity();
            $role = $identity->acl_role;
        } else {
            $role = 'guest';
        }

        // Mapping to determine which Resource the current
        // request refers to (really simple for this example!)
        $resource = $request->controller;
        $privilege = $request->action;


        if (!$this->_acl->has($resource)) {
            $resource = null;
        }

        // ACL Access Check
        if (!$this->_acl->isAllowed($role, $resource, $privilege)) {
            if ($this->_auth->hasIdentity()) {
                // authenticated, denied access, forward to /error/permissions
                $request->setModuleName('default');
                $request->setControllerName('error');
                $request->setActionName('permissions');
            } else {
                // not authenticated, forward to login form
                $request->setModuleName('default');
                $request->setControllerName('auth');
                $request->setActionName('login');
            }
        }
    }
}
Mark
I'm already doing this, because if a user accesses `/admin/index` and he doesn't have access, is not allowed, then it redirects to `/admin/login` which uses the admin module's `default.phtml` layout file. I would like to have just one layout file for the admin... which contains the echo for adminPanel.. I got the impression that that was the right way of doing things.. leaving the echo for the view helper there and do the acl logic within it.. what if for instance there are multiple regions / view helpers that need different access levels? would there be a separate layout for each?
meder