views:

143

answers:

2

Hey guys,

I just created a plugin to go with my site to make sure a user is authenticated before performing an action. This is the plugin:

class Booze_Plugin_AclPlugin extends Zend_Controller_Plugin_Abstract{

public function preDispatch(Zend_Controller_Request_Abstract $request)
{
    $auth = Booze_Permissions_Auth::getInstance();
    $acl = Zend_Registry::get('acl');

    if(!$auth->hasIdentity())
    {
        $role = Booze_Permissions_Roles::GUEST;
    }
    else
    {
        $role = $auth->getUser()->role;
    }

    $resource = $request->getControllerName();
    $privilege = $request->getActionName();

    if(!$acl->isAllowed($role, $resource, $privilege))
    {
        Booze_Log::log("ACLPlugin: Sent to login");

        $request->setControllerName('login');
        $request->setActionName('index');
        $request->setDispatched(false);
    }
}

}

It seems to work for pages that aren't async. However, I have a controller who's job is to perform async functions. This is that controller (relevant parts):

class AsyncController extends Zend_Controller_Action{

public function init()
{

    if(!$this->getRequest()->isXMLHttpRequest())
    {
        $this->_forward('index', 'index');
    }

    $this->_helper->viewRenderer->setNoRender();
    $this->_helper->getHelper('layout')->disableLayout();
 }

 public function addcommentAction()
 {
    $params = $this->getDecoded('comment', true);
    $params_array = (array)$params;

    $auth = Booze_Permissions_Auth::getInstance();
    if(!$auth->hasIdentity())
    {
        $this->getResponse()->setBody("Guest");
    }

    $params_array['user_id'] = $auth->getUser('user_id');
    $params_array['store_id'] = Booze_Storage::get('store_id');

    if($this->comments->insertComment($params_array))
    {
        $this->getResponse()->setBody("success");
    }
    else
    {
        $this->getResponse()->setBody("CommentFail");
    }
 }

When I call the async function addcommentAction, even when signed in as a guest, it does not take me to the login controller. I have, however, found out from firebug, that it IS sending the html for the login controller, but just isn't showing up in my browser. In my mind this must have something to do with the fact that the async controller has, in the init, turned off view rendering and the layout. I've tried messing with it, and can't figure out a reliable way to make sure the redirect in the plugin always renders, and shows itself. Any help would be outstanding.

A: 

have you tried to do a header() redirect? like:

$this->_helper->getHelper('Redirector')->setCode(303)
                                       ->setExit(false)
                                       ->setGotoSimple('index', 'login');

Edit: As you sayd in your comment, you do get the correct html (login) - couldn't you check in the login action, if the request is async and return some error code that you then handle in your javascript request code?

smoove666
Hey, I don't know how to get helpers in plug-ins. When I've tried it hasn't worked because $this seems to refer to the plugin and not the controller it's enacted on.
Ethan
@Ethan: `$redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('Redirector');`
jason
It's still doing the same thing. I'm pretty sure it's because it's performing a "Get" on the data, and is just getting the html, and not directing to it.
Ethan
A: 

I would add in the !isAllowed() part of plugin this:

if(!$acl->isAllowed($role, $resource, $privilege))
{
    if(!$this->getRequest()->isXMLHttpRequest())
    {
        //@todo getResponse
        $response->setBody(Zend_Json::encode(array('result'=>'fail', 'reason'=>'Need login');
        $response->sendResponse();
        exit;
    }

    Booze_Log::log("ACLPlugin: Sent to login");

    $request->setControllerName('login');
    $request->setActionName('index');
    $request->setDispatched(false);
}

Than on your async page handle incloming JSON when result is 'fail'.

Tomáš Fejfar
Of course it should not be the '!' in the isxmlhttprequest ;)
Tomáš Fejfar
Hey, I like your idea. Since the plugin is enacted at preDispatch, where could I put the test for "fail" in the Async controller? If I put it directly in the preDispatch in the controller would the test work there? Is there another function i could use?
Ethan
No, the test should be in page's body :) I assume your using AJAX for the async request don't you?
Tomáš Fejfar
Sounds good. It's not automatic, which i'd still like, but is a bit more flexible, so thanks!
Ethan