*/ class Mage_Customer_AccountController extends Mage_Core_Controller_Front_Action { const CUSTOMER_ID_SESSION_NAME = "customerId"; const TOKEN_SESSION_NAME = "token"; /** * Action list where need check enabled cookie * * @var array */ protected $_cookieCheckActions = array('loginPost', 'createpost'); /** * Retrieve customer session model object * * @return Mage_Customer_Model_Session */ protected function _getSession() { return Mage::getSingleton('customer/session'); } /** * Action predispatch * * Check customer authentication for some actions */ public function preDispatch() { // a brute-force protection here would be nice parent::preDispatch(); if (!$this->getRequest()->isDispatched()) { return; } $action = strtolower($this->getRequest()->getActionName()); $openActions = array( 'create', 'login', 'logoutsuccess', 'forgotpassword', 'forgotpasswordpost', 'changeforgotten', 'resetpassword', 'resetpasswordpost', 'confirm', 'confirmation' ); $pattern = '/^(' . implode('|', $openActions) . ')/i'; if (!preg_match($pattern, $action)) { if (!$this->_getSession()->authenticate($this)) { $this->setFlag('', 'no-dispatch', true); } } else { $this->_getSession()->setNoReferer(true); } } /** * Action postdispatch * * Remove No-referer flag from customer session after each action */ public function postDispatch() { parent::postDispatch(); $this->_getSession()->unsNoReferer(false); } /** * Default customer account page */ public function indexAction() { $this->loadLayout(); $this->_initLayoutMessages('customer/session'); $this->_initLayoutMessages('catalog/session'); $this->getLayout()->getBlock('content')->append( $this->getLayout()->createBlock('customer/account_dashboard') ); $this->getLayout()->getBlock('head')->setTitle($this->__('My Account')); $this->renderLayout(); } /** * Customer login form page */ public function loginAction() { if ($this->_getSession()->isLoggedIn()) { $this->_redirect('*/*/'); return; } $this->getResponse()->setHeader('Login-Required', 'true'); $this->loadLayout(); $this->_initLayoutMessages('customer/session'); $this->_initLayoutMessages('catalog/session'); $this->renderLayout(); } /** * Login post action */ public function loginPostAction() { if ($this->_getSession()->isLoggedIn()) { $this->_redirect('*/*/'); return; } $session = $this->_getSession(); if ($this->getRequest()->isPost()) { $login = $this->getRequest()->getPost('login'); if (!empty($login['username']) && !empty($login['password'])) { try { $session->login($login['username'], $login['password']); if ($session->getCustomer()->getIsJustConfirmed()) { $this->_welcomeCustomer($session->getCustomer(), true); } } catch (Mage_Core_Exception $e) { switch ($e->getCode()) { case Mage_Customer_Model_Customer::EXCEPTION_EMAIL_NOT_CONFIRMED: $value = Mage::helper('customer')->getEmailConfirmationUrl($login['username']); $message = Mage::helper('customer')->__('This account is not confirmed. Click here to resend confirmation email.', $value); break; case Mage_Customer_Model_Customer::EXCEPTION_INVALID_EMAIL_OR_PASSWORD: $message = $e->getMessage(); break; default: $message = $e->getMessage(); } $session->addError($message); $session->setUsername($login['username']); } catch (Exception $e) { // Mage::logException($e); // PA DSS violation: this exception log can disclose customer password } } else { $session->addError($this->__('Login and password are required.')); } } $this->_loginPostRedirect(); } /** * Define target URL and redirect customer after logging in */ protected function _loginPostRedirect() { $session = $this->_getSession(); if (!$session->getBeforeAuthUrl() || $session->getBeforeAuthUrl() == Mage::getBaseUrl()) { // Set default URL to redirect customer to $session->setBeforeAuthUrl(Mage::helper('customer')->getAccountUrl()); // Redirect customer to the last page visited after logging in if ($session->isLoggedIn()) { if (!Mage::getStoreConfigFlag( Mage_Customer_Helper_Data::XML_PATH_CUSTOMER_STARTUP_REDIRECT_TO_DASHBOARD )) { $referer = $this->getRequest()->getParam(Mage_Customer_Helper_Data::REFERER_QUERY_PARAM_NAME); if ($referer) { // Rebuild referer URL to handle the case when SID was changed $referer = Mage::getModel('core/url') ->getRebuiltUrl(Mage::helper('core')->urlDecode($referer)); if ($this->_isUrlInternal($referer)) { $session->setBeforeAuthUrl($referer); } } } else if ($session->getAfterAuthUrl()) { $session->setBeforeAuthUrl($session->getAfterAuthUrl(true)); } } else { $session->setBeforeAuthUrl(Mage::helper('customer')->getLoginUrl()); } } else if ($session->getBeforeAuthUrl() == Mage::helper('customer')->getLogoutUrl()) { $session->setBeforeAuthUrl(Mage::helper('customer')->getDashboardUrl()); } else { if (!$session->getAfterAuthUrl()) { $session->setAfterAuthUrl($session->getBeforeAuthUrl()); } if ($session->isLoggedIn()) { $session->setBeforeAuthUrl($session->getAfterAuthUrl(true)); } } $this->_redirectUrl($session->getBeforeAuthUrl(true)); } /** * Customer logout action */ public function logoutAction() { $this->_getSession()->logout() ->setBeforeAuthUrl(Mage::getUrl()); $this->_redirect('*/*/logoutSuccess'); } /** * Logout success page */ public function logoutSuccessAction() { $this->loadLayout(); $this->renderLayout(); } /** * Customer register form page */ public function createAction() { if ($this->_getSession()->isLoggedIn()) { $this->_redirect('*/*'); return; } $this->loadLayout(); $this->_initLayoutMessages('customer/session'); $this->renderLayout(); } /** * Create customer account action */ public function createPostAction() { if (!$this->_validateFormKey()) { $this->_redirectError(Mage::getUrl('*/*/create', array('_secure' => true))); return; } $session = $this->_getSession(); if ($session->isLoggedIn()) { $this->_redirect('*/*/'); return; } if ($this->getRequest()->isPost()) { $errors = array(); if (!$customer = Mage::registry('current_customer')) { $customer = Mage::getModel('customer/customer')->setId(null); } /* @var $customerForm Mage_Customer_Model_Form */ $customerForm = Mage::getModel('customer/form'); $customerForm->setFormCode('customer_account_create') ->setEntity($customer); $customerData = $customerForm->extractData($this->getRequest()); if ($this->getRequest()->getParam('is_subscribed', false)) { $customer->setIsSubscribed(1); } /** * Initialize customer group id */ $customer->getGroupId(); if ($this->getRequest()->getPost('create_address')) { /* @var $address Mage_Customer_Model_Address */ $address = Mage::getModel('customer/address'); /* @var $addressForm Mage_Customer_Model_Form */ $addressForm = Mage::getModel('customer/form'); $addressForm->setFormCode('customer_register_address') ->setEntity($address); $addressData = $addressForm->extractData($this->getRequest(), 'address', false); $addressErrors = $addressForm->validateData($addressData); if ($addressErrors === true) { $address->setId(null) ->setIsDefaultBilling($this->getRequest()->getParam('default_billing', false)) ->setIsDefaultShipping($this->getRequest()->getParam('default_shipping', false)); $addressForm->compactData($addressData); $customer->addAddress($address); $addressErrors = $address->validate(); if (is_array($addressErrors)) { $errors = array_merge($errors, $addressErrors); } } else { $errors = array_merge($errors, $addressErrors); } } try { $customerErrors = $customerForm->validateData($customerData); if ($customerErrors !== true) { $errors = array_merge($customerErrors, $errors); } else { $customerForm->compactData($customerData); $customer->setPassword($this->getRequest()->getPost('password')); $customer->setConfirmation($this->getRequest()->getPost('confirmation')); $customerErrors = $customer->validate(); if (is_array($customerErrors)) { $errors = array_merge($customerErrors, $errors); } } $validationResult = count($errors) == 0; if (true === $validationResult) { $customer->save(); Mage::dispatchEvent('customer_register_success', array('account_controller' => $this, 'customer' => $customer) ); if ($customer->isConfirmationRequired()) { $customer->sendNewAccountEmail( 'confirmation', $session->getBeforeAuthUrl(), Mage::app()->getStore()->getId() ); $session->addSuccess($this->__('Account confirmation is required. Please, check your email for the confirmation link. To resend the confirmation email please click here.', Mage::helper('customer')->getEmailConfirmationUrl($customer->getEmail()))); $this->_redirectSuccess(Mage::getUrl('*/*/index', array('_secure'=>true))); return; } else { $session->setCustomerAsLoggedIn($customer); $url = $this->_welcomeCustomer($customer); $this->_redirectSuccess($url); return; } } else { $session->setCustomerFormData($this->getRequest()->getPost()); if (is_array($errors)) { foreach ($errors as $errorMessage) { $session->addError(Mage::helper('core')->escapeHtml($errorMessage)); } } else { $session->addError($this->__('Invalid customer data')); } } } catch (Mage_Core_Exception $e) { $session->setCustomerFormData($this->getRequest()->getPost()); if ($e->getCode() === Mage_Customer_Model_Customer::EXCEPTION_EMAIL_EXISTS) { $url = Mage::getUrl('customer/account/forgotpassword'); $message = $this->__('There is already an account with this email address. If you are sure that it is your email address, click here to get your password and access your account.', $url); } else { $message = Mage::helper('core')->escapeHtml($e->getMessage()); } $session->addError($message); } catch (Exception $e) { $session->setCustomerFormData($this->getRequest()->getPost()) ->addException($e, $this->__('Cannot save the customer.')); } } $this->_redirectError(Mage::getUrl('*/*/create', array('_secure' => true))); } /** * Add welcome message and send new account email. * Returns success URL * * @param Mage_Customer_Model_Customer $customer * @param bool $isJustConfirmed * @return string */ protected function _welcomeCustomer(Mage_Customer_Model_Customer $customer, $isJustConfirmed = false) { $this->_getSession()->addSuccess( $this->__('Thank you for registering with %s.', Mage::app()->getStore()->getFrontendName()) ); if ($this->_isVatValidationEnabled()) { // Show corresponding VAT message to customer $configAddressType = Mage::helper('customer/address')->getTaxCalculationAddressType(); $userPrompt = ''; switch ($configAddressType) { case Mage_Customer_Model_Address_Abstract::TYPE_SHIPPING: $userPrompt = $this->__('If you are a registered VAT customer, please click here to enter you shipping address for proper VAT calculation', Mage::getUrl('customer/address/edit')); break; default: $userPrompt = $this->__('If you are a registered VAT customer, please click here to enter you billing address for proper VAT calculation', Mage::getUrl('customer/address/edit')); } $this->_getSession()->addSuccess($userPrompt); } $customer->sendNewAccountEmail( $isJustConfirmed ? 'confirmed' : 'registered', '', Mage::app()->getStore()->getId() ); $successUrl = Mage::getUrl('*/*/index', array('_secure'=>true)); if ($this->_getSession()->getBeforeAuthUrl()) { $successUrl = $this->_getSession()->getBeforeAuthUrl(true); } return $successUrl; } /** * Confirm customer account by id and confirmation key */ public function confirmAction() { if ($this->_getSession()->isLoggedIn()) { $this->_redirect('*/*/'); return; } try { $id = $this->getRequest()->getParam('id', false); $key = $this->getRequest()->getParam('key', false); $backUrl = $this->getRequest()->getParam('back_url', false); if (empty($id) || empty($key)) { throw new Exception($this->__('Bad request.')); } // load customer by id (try/catch in case if it throws exceptions) try { $customer = Mage::getModel('customer/customer')->load($id); if ((!$customer) || (!$customer->getId())) { throw new Exception('Failed to load customer by id.'); } } catch (Exception $e) { throw new Exception($this->__('Wrong customer account specified.')); } // check if it is inactive if ($customer->getConfirmation()) { if ($customer->getConfirmation() !== $key) { throw new Exception($this->__('Wrong confirmation key.')); } // activate customer try { $customer->setConfirmation(null); $customer->save(); } catch (Exception $e) { throw new Exception($this->__('Failed to confirm customer account.')); } // log in and send greeting email, then die happy $this->_getSession()->setCustomerAsLoggedIn($customer); $successUrl = $this->_welcomeCustomer($customer, true); $this->_redirectSuccess($backUrl ? $backUrl : $successUrl); return; } // die happy $this->_redirectSuccess(Mage::getUrl('*/*/index', array('_secure'=>true))); return; } catch (Exception $e) { // die unhappy $this->_getSession()->addError($e->getMessage()); $this->_redirectError(Mage::getUrl('*/*/index', array('_secure'=>true))); return; } } /** * Send confirmation link to specified email */ public function confirmationAction() { $customer = Mage::getModel('customer/customer'); if ($this->_getSession()->isLoggedIn()) { $this->_redirect('*/*/'); return; } // try to confirm by email $email = $this->getRequest()->getPost('email'); if ($email) { try { $customer->setWebsiteId(Mage::app()->getStore()->getWebsiteId())->loadByEmail($email); if (!$customer->getId()) { throw new Exception(''); } if ($customer->getConfirmation()) { $customer->sendNewAccountEmail('confirmation', '', Mage::app()->getStore()->getId()); $this->_getSession()->addSuccess($this->__('Please, check your email for confirmation key.')); } else { $this->_getSession()->addSuccess($this->__('This email does not require confirmation.')); } $this->_getSession()->setUsername($email); $this->_redirectSuccess(Mage::getUrl('*/*/index', array('_secure' => true))); } catch (Exception $e) { $this->_getSession()->addException($e, $this->__('Wrong email.')); $this->_redirectError(Mage::getUrl('*/*/*', array('email' => $email, '_secure' => true))); } return; } // output form $this->loadLayout(); $this->getLayout()->getBlock('accountConfirmation') ->setEmail($this->getRequest()->getParam('email', $email)); $this->_initLayoutMessages('customer/session'); $this->renderLayout(); } /** * Forgot customer password page */ public function forgotPasswordAction() { $this->loadLayout(); $this->getLayout()->getBlock('forgotPassword')->setEmailValue( $this->_getSession()->getForgottenEmail() ); $this->_getSession()->unsForgottenEmail(); $this->_initLayoutMessages('customer/session'); $this->renderLayout(); } /** * Forgot customer password action */ public function forgotPasswordPostAction() { $email = (string) $this->getRequest()->getPost('email'); if ($email) { if (!Zend_Validate::is($email, 'EmailAddress')) { $this->_getSession()->setForgottenEmail($email); $this->_getSession()->addError($this->__('Invalid email address.')); $this->_redirect('*/*/forgotpassword'); return; } /** @var $customer Mage_Customer_Model_Customer */ $customer = Mage::getModel('customer/customer') ->setWebsiteId(Mage::app()->getStore()->getWebsiteId()) ->loadByEmail($email); if ($customer->getId()) { try { $newResetPasswordLinkToken = Mage::helper('customer')->generateResetPasswordLinkToken(); $customer->changeResetPasswordLinkToken($newResetPasswordLinkToken); $customer->sendPasswordResetConfirmationEmail(); } catch (Exception $exception) { $this->_getSession()->addError($exception->getMessage()); $this->_redirect('*/*/forgotpassword'); return; } } $this->_getSession() ->addSuccess(Mage::helper('customer')->__('If there is an account associated with %s you will receive an email with a link to reset your password.', Mage::helper('customer')->htmlEscape($email))); $this->_redirect('*/*/'); return; } else { $this->_getSession()->addError($this->__('Please enter your email.')); $this->_redirect('*/*/forgotpassword'); return; } } /** * Display reset forgotten password form * */ public function changeForgottenAction() { try { list($customerId, $resetPasswordLinkToken) = $this->_getRestorePasswordParameters($this->_getSession()); $this->_validateResetPasswordLinkToken($customerId, $resetPasswordLinkToken); $this->loadLayout(); $this->renderLayout(); } catch (Exception $exception) { $this->_getSession()->addError(Mage::helper('customer')->__('Your password reset link has expired.')); $this->_redirect('*/*/forgotpassword'); } } /** * Checks reset forgotten password token * * User is redirected on this action when he clicks on the corresponding link in password reset confirmation email. * */ public function resetPasswordAction() { try { $customerId = (int)$this->getRequest()->getQuery("id"); $resetPasswordLinkToken = (string)$this->getRequest()->getQuery('token'); $this->_validateResetPasswordLinkToken($customerId, $resetPasswordLinkToken); $this->_saveRestorePasswordParameters($customerId, $resetPasswordLinkToken) ->_redirect('*/*/changeforgotten'); } catch (Exception $exception) { $this->_getSession()->addError(Mage::helper('customer')->__('Your password reset link has expired.')); $this->_redirect('*/*/forgotpassword'); } } /** * Reset forgotten password * * Used to handle data recieved from reset forgotten password form * */ public function resetPasswordPostAction() { list($customerId, $resetPasswordLinkToken) = $this->_getRestorePasswordParameters($this->_getSession()); $password = (string)$this->getRequest()->getPost('password'); $passwordConfirmation = (string)$this->getRequest()->getPost('confirmation'); try { $this->_validateResetPasswordLinkToken($customerId, $resetPasswordLinkToken); } catch (Exception $exception) { $this->_getSession()->addError(Mage::helper('customer')->__('Your password reset link has expired.')); $this->_redirect('*/*/'); return; } $errorMessages = array(); if (iconv_strlen($password) <= 0) { array_push($errorMessages, Mage::helper('customer')->__('New password field cannot be empty.')); } /** @var $customer Mage_Customer_Model_Customer */ $customer = Mage::getModel('customer/customer')->load($customerId); $customer->setPassword($password); $customer->setConfirmation($passwordConfirmation); $validationErrorMessages = $customer->validate(); if (is_array($validationErrorMessages)) { $errorMessages = array_merge($errorMessages, $validationErrorMessages); } if (!empty($errorMessages)) { $this->_getSession()->setCustomerFormData($this->getRequest()->getPost()); foreach ($errorMessages as $errorMessage) { $this->_getSession()->addError($errorMessage); } $this->_redirect('*/*/changeforgotten'); return; } try { // Empty current reset password token i.e. invalidate it $customer->setRpToken(null); $customer->setRpTokenCreatedAt(null); $customer->setConfirmation(null); $customer->save(); $this->_getSession()->unsetData(self::TOKEN_SESSION_NAME); $this->_getSession()->unsetData(self::CUSTOMER_ID_SESSION_NAME); $this->_getSession()->addSuccess(Mage::helper('customer')->__('Your password has been updated.')); $this->_redirect('*/*/login'); } catch (Exception $exception) { $this->_getSession()->addException($exception, $this->__('Cannot save a new password.')); $this->_redirect('*/*/changeforgotten'); return; } } /** * Check if password reset token is valid * * @param int $customerId * @param string $resetPasswordLinkToken * @throws Mage_Core_Exception */ protected function _validateResetPasswordLinkToken($customerId, $resetPasswordLinkToken) { if (!is_int($customerId) || !is_string($resetPasswordLinkToken) || empty($resetPasswordLinkToken) || empty($customerId) || $customerId < 0 ) { throw Mage::exception('Mage_Core', Mage::helper('customer')->__('Invalid password reset token.')); } /** @var $customer Mage_Customer_Model_Customer */ $customer = Mage::getModel('customer/customer')->load($customerId); if (!$customer || !$customer->getId()) { throw Mage::exception('Mage_Core', Mage::helper('customer')->__('Wrong customer account specified.')); } $customerToken = $customer->getRpToken(); if (strcmp($customerToken, $resetPasswordLinkToken) != 0 || $customer->isResetPasswordLinkTokenExpired()) { throw Mage::exception('Mage_Core', Mage::helper('customer')->__('Your password reset link has expired.')); } } /** * Forgot customer account information page */ public function editAction() { $this->loadLayout(); $this->_initLayoutMessages('customer/session'); $this->_initLayoutMessages('catalog/session'); $block = $this->getLayout()->getBlock('customer_edit'); if ($block) { $block->setRefererUrl($this->_getRefererUrl()); } $data = $this->_getSession()->getCustomerFormData(true); $customer = $this->_getSession()->getCustomer(); if (!empty($data)) { $customer->addData($data); } if ($this->getRequest()->getParam('changepass')==1){ $customer->setChangePassword(1); } $this->getLayout()->getBlock('head')->setTitle($this->__('Account Information')); $this->getLayout()->getBlock('messages')->setEscapeMessageFlag(true); $this->renderLayout(); } /** * Change customer password action */ public function editPostAction() { if (!$this->_validateFormKey()) { return $this->_redirect('*/*/edit'); } if ($this->getRequest()->isPost()) { /** @var $customer Mage_Customer_Model_Customer */ $customer = $this->_getSession()->getCustomer(); /** @var $customerForm Mage_Customer_Model_Form */ $customerForm = Mage::getModel('customer/form'); $customerForm->setFormCode('customer_account_edit') ->setEntity($customer); $customerData = $customerForm->extractData($this->getRequest()); $errors = array(); $customerErrors = $customerForm->validateData($customerData); if ($customerErrors !== true) { $errors = array_merge($customerErrors, $errors); } else { $customerForm->compactData($customerData); $errors = array(); // If password change was requested then add it to common validation scheme if ($this->getRequest()->getParam('change_password')) { $currPass = $this->getRequest()->getPost('current_password'); $newPass = $this->getRequest()->getPost('password'); $confPass = $this->getRequest()->getPost('confirmation'); $oldPass = $this->_getSession()->getCustomer()->getPasswordHash(); if (Mage::helper('core/string')->strpos($oldPass, ':')) { list($_salt, $salt) = explode(':', $oldPass); } else { $salt = false; } if ($customer->hashPassword($currPass, $salt) == $oldPass) { if (strlen($newPass)) { /** * Set entered password and its confirmation - they * will be validated later to match each other and be of right length */ $customer->setPassword($newPass); $customer->setConfirmation($confPass); } else { $errors[] = $this->__('New password field cannot be empty.'); } } else { $errors[] = $this->__('Invalid current password'); } } // Validate account and compose list of errors if any $customerErrors = $customer->validate(); if (is_array($customerErrors)) { $errors = array_merge($errors, $customerErrors); } } if (!empty($errors)) { $this->_getSession()->setCustomerFormData($this->getRequest()->getPost()); foreach ($errors as $message) { $this->_getSession()->addError($message); } $this->_redirect('*/*/edit'); return $this; } try { $customer->setConfirmation(null); $customer->save(); $this->_getSession()->setCustomer($customer) ->addSuccess($this->__('The account information has been saved.')); $this->_redirect('customer/account'); return; } catch (Mage_Core_Exception $e) { $this->_getSession()->setCustomerFormData($this->getRequest()->getPost()) ->addError($e->getMessage()); } catch (Exception $e) { $this->_getSession()->setCustomerFormData($this->getRequest()->getPost()) ->addException($e, $this->__('Cannot save the customer.')); } } $this->_redirect('*/*/edit'); } /** * Filtering posted data. Converting localized data if needed * * @param array * @return array */ protected function _filterPostData($data) { $data = $this->_filterDates($data, array('dob')); return $data; } /** * Check whether VAT ID validation is enabled * * @param Mage_Core_Model_Store|string|int $store * @return bool */ protected function _isVatValidationEnabled($store = null) { return Mage::helper('customer/address')->isVatValidationEnabled($store); } /** * Get restore password params. * * @param Mage_Customer_Model_Session $session * @return array array ($customerId, $resetPasswordToken) */ protected function _getRestorePasswordParameters(Mage_Customer_Model_Session $session) { return array( (int) $session->getData(self::CUSTOMER_ID_SESSION_NAME), (string) $session->getData(self::TOKEN_SESSION_NAME) ); } /** * Save restore password params to session. * * @param int $customerId * @param string $resetPasswordLinkToken * @return $this */ protected function _saveRestorePasswordParameters($customerId, $resetPasswordLinkToken) { $this->_getSession() ->setData(self::CUSTOMER_ID_SESSION_NAME, $customerId) ->setData(self::TOKEN_SESSION_NAME, $resetPasswordLinkToken); return $this; } }