Source for file reset.php

Documentation is available at reset.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Site
  4.  * @subpackage  com_users
  5.  *
  6.  * @copyright   Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7.  * @license     GNU General Public License version 2 or later; see LICENSE.txt
  8.  */
  9.  
  10. defined('_JEXEC'or die;
  11.  
  12. /**
  13.  * Rest model class for Users.
  14.  *
  15.  * @package     Joomla.Site
  16.  * @subpackage  com_users
  17.  * @since       1.5
  18.  */
  19. class UsersModelReset extends JModelForm
  20. {
  21.     /**
  22.      * Method to get the password reset request form.
  23.      *
  24.      * @param   array      $data        Data for the form.
  25.      * @param   boolean    $loadData    True if the form is to load its own data (default case), false if not.
  26.      * @return  JForm    A JForm object on success, false on failure
  27.      * @since   1.6
  28.      */
  29.     public function getForm($data array()$loadData true)
  30.     {
  31.         // Get the form.
  32.         $form $this->loadForm('com_users.reset_request''reset_request'array('control' => 'jform''load_data' => $loadData));
  33.         if (empty($form))
  34.         {
  35.             return false;
  36.         }
  37.  
  38.         return $form;
  39.     }
  40.  
  41.     /**
  42.      * Method to get the password reset complete form.
  43.      *
  44.      * @param   array      $data        Data for the form.
  45.      * @param   boolean    $loadData    True if the form is to load its own data (default case), false if not.
  46.      * @return  JForm    A JForm object on success, false on failure
  47.      * @since   1.6
  48.      */
  49.     public function getResetCompleteForm($data array()$loadData true)
  50.     {
  51.         // Get the form.
  52.         $form $this->loadForm('com_users.reset_complete''reset_complete'$options array('control' => 'jform'));
  53.         if (empty($form))
  54.         {
  55.             return false;
  56.         }
  57.  
  58.         return $form;
  59.     }
  60.  
  61.     /**
  62.      * Method to get the password reset confirm form.
  63.      *
  64.      * @param   array      $data        Data for the form.
  65.      * @param   boolean    $loadData    True if the form is to load its own data (default case), false if not.
  66.      * @return  JForm    A JForm object on success, false on failure
  67.      * @since   1.6
  68.      */
  69.     public function getResetConfirmForm($data array()$loadData true)
  70.     {
  71.         // Get the form.
  72.         $form $this->loadForm('com_users.reset_confirm''reset_confirm'$options array('control' => 'jform'));
  73.         if (empty($form))
  74.         {
  75.             return false;
  76.         }
  77.  
  78.         return $form;
  79.     }
  80.  
  81.     /**
  82.      * Override preprocessForm to load the user plugin group instead of content.
  83.      *
  84.      * @param   object    form object.
  85.      * @param   mixed     The data expected for the form.
  86.      * @throws    Exception if there is an error in the form event.
  87.      * @since   1.6
  88.      */
  89.     protected function preprocessForm(JForm $form$data$group 'user')
  90.     {
  91.         parent::preprocessForm($form$data$group);
  92.     }
  93.  
  94.     /**
  95.      * Method to auto-populate the model state.
  96.      *
  97.      * Note. Calling getState in this method will result in recursion.
  98.      *
  99.      * @since   1.6
  100.      */
  101.     protected function populateState()
  102.     {
  103.         // Get the application object.
  104.         $params JFactory::getApplication()->getParams('com_users');
  105.  
  106.         // Load the parameters.
  107.         $this->setState('params'$params);
  108.     }
  109.  
  110.     /**
  111.      * @since   1.6
  112.      */
  113.     function processResetComplete($data)
  114.     {
  115.         // Get the form.
  116.         $form $this->getResetCompleteForm();
  117.         $data['email'JStringPunycode::emailToPunycode($data['email']);
  118.  
  119.         // Check for an error.
  120.         if ($form instanceof Exception)
  121.         {
  122.             return $form;
  123.         }
  124.  
  125.         // Filter and validate the form data.
  126.         $data $form->filter($data);
  127.         $return $form->validate($data);
  128.  
  129.         // Check for an error.
  130.         if ($return instanceof Exception)
  131.         {
  132.             return $return;
  133.         }
  134.  
  135.         // Check the validation results.
  136.         if ($return === false)
  137.         {
  138.             // Get the validation messages from the form.
  139.             foreach ($form->getErrors(as $formError)
  140.             {
  141.                 $this->setError($formError->getMessage());
  142.             }
  143.             return false;
  144.         }
  145.  
  146.         // Get the token and user id from the confirmation process.
  147.         $app JFactory::getApplication();
  148.         $token $app->getUserState('com_users.reset.token'null);
  149.         $userId $app->getUserState('com_users.reset.user'null);
  150.  
  151.         // Check the token and user id.
  152.         if (empty($token|| empty($userId))
  153.         {
  154.             return new JException(JText::_('COM_USERS_RESET_COMPLETE_TOKENS_MISSING')403);
  155.         }
  156.  
  157.         // Get the user object.
  158.         $user JUser::getInstance($userId);
  159.  
  160.         // Check for a user and that the tokens match.
  161.         if (empty($user|| $user->activation !== $token)
  162.         {
  163.             $this->setError(JText::_('COM_USERS_USER_NOT_FOUND'));
  164.             return false;
  165.         }
  166.  
  167.         // Make sure the user isn't blocked.
  168.         if ($user->block)
  169.         {
  170.             $this->setError(JText::_('COM_USERS_USER_BLOCKED'));
  171.             return false;
  172.         }
  173.  
  174.         // Generate the new password hash.
  175.         $salt JUserHelper::genRandomPassword(32);
  176.         $crypted JUserHelper::getCryptedPassword($data['password1']$salt);
  177.         $password $crypted ':' $salt;
  178.  
  179.         // Update the user object.
  180.         $user->password $password;
  181.         $user->activation '';
  182.         $user->password_clear $data['password1'];
  183.  
  184.         // Save the user to the database.
  185.         if (!$user->save(true))
  186.         {
  187.             return new JException(JText::sprintf('COM_USERS_USER_SAVE_FAILED'$user->getError())500);
  188.         }
  189.  
  190.         // Flush the user data from the session.
  191.         $app->setUserState('com_users.reset.token'null);
  192.         $app->setUserState('com_users.reset.user'null);
  193.  
  194.         return true;
  195.     }
  196.  
  197.     /**
  198.      * @since   1.6
  199.      */
  200.     function processResetConfirm($data)
  201.     {
  202.         // Get the form.
  203.         $form $this->getResetConfirmForm();
  204.         $data['email'JStringPunycode::emailToPunycode($data['email']);
  205.  
  206.         // Check for an error.
  207.         if ($form instanceof Exception)
  208.         {
  209.             return $form;
  210.         }
  211.  
  212.         // Filter and validate the form data.
  213.         $data $form->filter($data);
  214.         $return $form->validate($data);
  215.  
  216.         // Check for an error.
  217.         if ($return instanceof Exception)
  218.         {
  219.             return $return;
  220.         }
  221.  
  222.         // Check the validation results.
  223.         if ($return === false)
  224.         {
  225.             // Get the validation messages from the form.
  226.             foreach ($form->getErrors(as $formError)
  227.             {
  228.                 $this->setError($formError->getMessage());
  229.             }
  230.             return false;
  231.         }
  232.  
  233.         // Find the user id for the given token.
  234.         $db $this->getDbo();
  235.         $query $db->getQuery(true)
  236.             ->select('activation')
  237.             ->select('id')
  238.             ->select('block')
  239.             ->from($db->quoteName('#__users'))
  240.             ->where($db->quoteName('username'' = ' $db->quote($data['username']));
  241.  
  242.         // Get the user id.
  243.         $db->setQuery($query);
  244.  
  245.         try
  246.         {
  247.             $user $db->loadObject();
  248.         }
  249.         catch (RuntimeException $e)
  250.         {
  251.             return new JException(JText::sprintf('COM_USERS_DATABASE_ERROR'$e->getMessage())500);
  252.         }
  253.  
  254.         // Check for a user.
  255.         if (empty($user))
  256.         {
  257.             $this->setError(JText::_('COM_USERS_USER_NOT_FOUND'));
  258.             return false;
  259.         }
  260.  
  261.         $parts explode(':'$user->activation);
  262.         $crypt $parts[0];
  263.         if (!isset($parts[1]))
  264.         {
  265.             $this->setError(JText::_('COM_USERS_USER_NOT_FOUND'));
  266.             return false;
  267.         }
  268.         $salt $parts[1];
  269.         $testcrypt JUserHelper::getCryptedPassword($data['token']$salt);
  270.  
  271.         // Verify the token
  272.         if (!($crypt == $testcrypt))
  273.         {
  274.             $this->setError(JText::_('COM_USERS_USER_NOT_FOUND'));
  275.             return false;
  276.         }
  277.  
  278.         // Make sure the user isn't blocked.
  279.         if ($user->block)
  280.         {
  281.             $this->setError(JText::_('COM_USERS_USER_BLOCKED'));
  282.             return false;
  283.         }
  284.  
  285.         // Push the user data into the session.
  286.         $app JFactory::getApplication();
  287.         $app->setUserState('com_users.reset.token'$crypt ':' $salt);
  288.         $app->setUserState('com_users.reset.user'$user->id);
  289.  
  290.         return true;
  291.     }
  292.  
  293.     /**
  294.      * Method to start the password reset process.
  295.      *
  296.      * @since   1.6
  297.      */
  298.     public function processResetRequest($data)
  299.     {
  300.         $config JFactory::getConfig();
  301.  
  302.         // Get the form.
  303.         $form $this->getForm();
  304.  
  305.         $data['email'JStringPunycode::emailToPunycode($data['email']);
  306.  
  307.         // Check for an error.
  308.         if ($form instanceof Exception)
  309.         {
  310.             return $form;
  311.         }
  312.  
  313.         // Filter and validate the form data.
  314.         $data $form->filter($data);
  315.         $return $form->validate($data);
  316.  
  317.         // Check for an error.
  318.         if ($return instanceof Exception)
  319.         {
  320.             return $return;
  321.         }
  322.  
  323.         // Check the validation results.
  324.         if ($return === false)
  325.         {
  326.             // Get the validation messages from the form.
  327.             foreach ($form->getErrors(as $formError)
  328.             {
  329.                 $this->setError($formError->getMessage());
  330.             }
  331.             return false;
  332.         }
  333.  
  334.         // Find the user id for the given email address.
  335.         $db $this->getDbo();
  336.         $query $db->getQuery(true)
  337.             ->select('id')
  338.             ->from($db->quoteName('#__users'))
  339.             ->where($db->quoteName('email'' = ' $db->quote($data['email']));
  340.  
  341.         // Get the user object.
  342.         $db->setQuery($query);
  343.  
  344.         try
  345.         {
  346.             $userId $db->loadResult();
  347.         }
  348.         catch (RuntimeException $e)
  349.         {
  350.             $this->setError(JText::sprintf('COM_USERS_DATABASE_ERROR'$e->getMessage())500);
  351.             return false;
  352.         }
  353.  
  354.         // Check for a user.
  355.         if (empty($userId))
  356.         {
  357.             $this->setError(JText::_('COM_USERS_INVALID_EMAIL'));
  358.             return false;
  359.         }
  360.  
  361.         // Get the user object.
  362.         $user JUser::getInstance($userId);
  363.  
  364.         // Make sure the user isn't blocked.
  365.         if ($user->block)
  366.         {
  367.             $this->setError(JText::_('COM_USERS_USER_BLOCKED'));
  368.             return false;
  369.         }
  370.  
  371.         // Make sure the user isn't a Super Admin.
  372.         if ($user->authorise('core.admin'))
  373.         {
  374.             $this->setError(JText::_('COM_USERS_REMIND_SUPERADMIN_ERROR'));
  375.             return false;
  376.         }
  377.  
  378.         // Make sure the user has not exceeded the reset limit
  379.         if (!$this->checkResetLimit($user))
  380.         {
  381.             $resetLimit = (int) JFactory::getApplication()->getParams()->get('reset_time');
  382.             $this->setError(JText::plural('COM_USERS_REMIND_LIMIT_ERROR_N_HOURS'$resetLimit));
  383.             return false;
  384.         }
  385.         // Set the confirmation token.
  386.         $token JApplication::getHash(JUserHelper::genRandomPassword());
  387.         $salt JUserHelper::getSalt('crypt-md5');
  388.         $hashedToken md5($token $salt':' $salt;
  389.  
  390.         $user->activation $hashedToken;
  391.  
  392.         // Save the user to the database.
  393.         if (!$user->save(true))
  394.         {
  395.             return new JException(JText::sprintf('COM_USERS_USER_SAVE_FAILED'$user->getError())500);
  396.         }
  397.  
  398.         // Assemble the password reset confirmation link.
  399.         $mode $config->get('force_ssl'0== : -1;
  400.         $itemid UsersHelperRoute::getLoginRoute();
  401.         $itemid $itemid !== null '&Itemid=' $itemid '';
  402.         $link 'index.php?option=com_users&view=reset&layout=confirm' $itemid;
  403.  
  404.         // Put together the email template data.
  405.         $data $user->getProperties();
  406.         $data['fromname'$config->get('fromname');
  407.         $data['mailfrom'$config->get('mailfrom');
  408.         $data['sitename'$config->get('sitename');
  409.         $data['link_text'JRoute::_($linkfalse$mode);
  410.         $data['link_html'JRoute::_($linktrue$mode);
  411.         $data['token'$token;
  412.  
  413.         $subject JText::sprintf(
  414.             'COM_USERS_EMAIL_PASSWORD_RESET_SUBJECT',
  415.             $data['sitename']
  416.         );
  417.  
  418.         $body JText::sprintf(
  419.             'COM_USERS_EMAIL_PASSWORD_RESET_BODY',
  420.             $data['sitename'],
  421.             $data['token'],
  422.             $data['link_text']
  423.         );
  424.  
  425.         // Send the password reset request email.
  426.         $return JFactory::getMailer()->sendMail($data['mailfrom']$data['fromname']$user->email$subject$body);
  427.         // Check for an error.
  428.         if ($return !== true)
  429.         {
  430.             return new JException(JText::_('COM_USERS_MAIL_FAILED')500);
  431.         }
  432.  
  433.         return true;
  434.     }
  435.  
  436.     /**
  437.      * Method to check if user reset limit has been exceeded within the allowed time period.
  438.      *
  439.      * @param   JUser  the user doing the password reset
  440.      *
  441.      * @return  boolean true if user can do the reset, false if limit exceeded
  442.      *
  443.      * @since    2.5
  444.      */
  445.     public function checkResetLimit($user)
  446.     {
  447.         $params JFactory::getApplication()->getParams();
  448.         $maxCount = (int) $params->get('reset_count');
  449.         $resetHours = (int) $params->get('reset_time');
  450.         $result true;
  451.  
  452.         $lastResetTime strtotime($user->lastResetTimestrtotime($user->lastResetTime0;
  453.         $hoursSinceLastReset (strtotime(JFactory::getDate()->toSql()) $lastResetTime3600;
  454.  
  455.         // If it's been long enough, start a new reset count
  456.         if ($hoursSinceLastReset $resetHours)
  457.         {
  458.             $user->lastResetTime JFactory::getDate()->toSql();
  459.             $user->resetCount 1;
  460.         }
  461.  
  462.         // If we are under the max count, just increment the counter
  463.         elseif ($user->resetCount $maxCount)
  464.         {
  465.             $user->resetCount;
  466.         }
  467.  
  468.         // At this point, we know we have exceeded the maximum resets for the time period
  469.         else
  470.         {
  471.             $result false;
  472.         }
  473.         return $result;
  474.     }
  475. }

Documentation generated on Tue, 19 Nov 2013 15:11:51 +0100 by phpDocumentor 1.4.3