views:

98

answers:

2

We are trying to add a couple of actions to the AccountController to add another action after the forgotpasswordpost action. The problem is if we add the action to the preDispatch logict to make sure you don't have to be logged in it still redirects back to the login page.

public function preDispatch()
    {
        // a brute-force protection here would be nice

        parent::preDispatch();

        if (!$this->getRequest()->isDispatched()) {
            return;
        }

        $action = $this->getRequest()->getActionName();
        if (!preg_match('/^(create|login|logoutSuccess|forgotpassword|forgotpasswordpost|confirm|confirmation|newactionhere)/i', $action)) {
            if (!$this->_getSession()->authenticate($this)) {
                $this->setFlag('', 'no-dispatch', true);
            }
        } else {
            $this->_getSession()->setNoReferer(true);
        }
    }

This doesn't work because we are calling the parent first which runs this as well but of course the preg_match doesn't match and it runs the authenticate method which runs the method $action->getResponse()->setRedirect($url) which of course sets the header and when it gets back to our code it doesn't matter and then redirects.

We could just remove the call to the parent but I am not sure that is the best approach since the parent calls its parent as well which runs some stuff to set the layout area and then also calls the parent method. I was thinking to just call the parent wtih Mage_Core_Controller_Front_Action but wasn't sure that was the right approach either.

+1  A: 

I suggest that you add an Observer on postDispatch, filter for accountController and then set the _redirect. Let me know if you need more info.

Jonathan Day
+1  A: 

So this is what we did, we got the flag and checked if the action had the flag of no-dispatch. then we unset it, cleared the header and reset the response code.

public function preDispatch()
{
    // a brute-force protection here would be nice

    parent::preDispatch();

    $action = $this->getRequest()->getActionName();

    // The parent preDispatch call will set:
    // 1. the 'no-dispatch' flag and set a
    // 2. a 'Location' header for a 302 redirect to the login page
    //    for any actions which are not on the list.
    // 3. a HTTP Response Code of 302 (temporary redirect).
    // We add additional actions securityquestion and securityquestionpost in our override below, but
    // we need to undo the settings which get set by the call to the parent above.
    if (preg_match('/^(securityquestion|securityquestionpost)/i', $action))
    {
        $flag = 'no-dispatch';

        if ($this->getFlag($action, $flag))
        {
              unset($this->_flags[$action][$flag]); // Remove the flag to unset it
              $this->getResponse()->clearHeader('Location'); // Remove Location header for redirect
              $this->getResponse()->setHttpResponseCode(200); // Set HTTP Response Code to OK

        }
    }

    if (!$this->getRequest()->isDispatched()) {
        return;
    }


    if (!preg_match('/^(create|login|logoutSuccess|forgotpassword|forgotpasswordpost|confirm|confirmation|securityquestion|securityquestionpost)/i', $action)) {
        if (!$this->_getSession()->authenticate($this)) {
            $this->setFlag('', 'no-dispatch', true);
        }
    } else {
        $this->_getSession()->setNoReferer(true);
    }
}
dan.codes