Question

$this->add ( new Zend_Acl_Resource ( 'index' ) );
$this->addRole ( new Zend_Acl_Role ( 'guest' ) );
$this->allow('guest', 'index','view');

and i have problem in this condition

if (! $this->_acl->isAllowed ( $role, $resource, $action )){ 
    ... redirect to access denied
}
  • Guest is allowed to access to Contoller index and action view.
  • But when he types in url /index/view2 it should redirect him to error page because action view2 doesnt exist
  • But this condition sais that he is allowed olny for action view. So it isnot redirect him to error page but to acces denied

How can solve this problem?

Was it helpful?

Solution

You could check for the resource(action) to exist in the acl:

if(!$this->_acl->has($resource) || $this->_acl->isAllowed($role, $resource, $action))

Else could simply deny by default. If you then check for a non-existing action the acl will return false by default.
If you simply want to detect if a not-existing action is called from your controller, you can use the __call method of the controller.

For a more specific solution you should provide more information like where you perform the acl-check, how you setup your acl, ....

Example to catch not-existing actions in your controller:

My_Controller extends Zend_Controller_Action
{
    __call($method, $args)
    {
        throw new Exception("Action does not exist"); // This is done by default
        // Just do whatever you want to do in this function (like redirecting)
    }
}

Anyway this could be done with the ErrorhandlerPlugin even without the magic function. As you only want to redirect to the error page you actually just have to take care, that the acl check doesn't throw any exceptions because a resource (or Action) isn't found. Depending on where you do your check you have several posibilities do do this but assuming every controller is one Resource and you do all add them this shouldn't be a problem.

OTHER TIPS

I call ACL in predispatch of frontcontroller plugin

public function preDispatch(Zend_Controller_Request_Abstract $request) {
    if ($this->_auth->hasIdentity ()) {
        $rights = $this->_auth->getIdentity ()->rights;
        if ($rights == 2) {
            $role = 'admin';
        } elseif ($rights == 1) {
            $role = 'user';
        } else {
            $role = 'guest';
        }
    } else {
        $role = 'guest';
    }
    $controller = $request->controller;
    $action = $request->action;
    $module = $request->module;
    $resource = $controller;
    if ($this->_acl->has ( $resource )) {
        if (! $this->_acl->isAllowed ( $role, $resource, $action )) {
            if (! $this->_auth->hasIdentity ()) {
                //redirect to login
                $module = $this->_noauth ['module'];
                $controller = $this->_noauth ['controller'];
                $action = $this->_noauth ['action'];            
            } else {
                //redirect to access denied
                $module = $this->_noacl ['module'];
                $controller = $this->_noacl ['controller'];
                $action = $this->_noacl ['action'];
            }
            $request->setModuleName ( $module );
            $request->setControllerName ( $controller );
            $request->setActionName ( $action );
        }
    } else {
        //controller not found
        $module = ('default');
        $controller = ('error');
        $action = ('not-found');
        $request->setModuleName ( $module );
        $request->setControllerName ( $controller );
        $request->setActionName ( $action );
    }           
}

I would do it by throwing NotAllowed exception.

if (! $this->_acl->isAllowed ( $role, $resource, $action )){ 
    throw new YourNotAllowedException('some error message');
}

Then in error controller I'd handle this exception:

if ($error->exception instanceof NotAllowed) {
   // manual forward setting request params 
   // (url remains the same, but user sees the login page)
}

The standard exceptions would be handled as usual.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top