PageRenderTime 48ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/components/com_users/models/reset.php

https://bitbucket.org/ian_maclennan/joomla-cms
PHP | 398 lines | 219 code | 63 blank | 116 comment | 31 complexity | 1be9234ab96e055b0942e59af9dda610 MD5 | raw file
Possible License(s): JSON, GPL-2.0, LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /**
  3. * @version $Id$
  4. * @package Joomla.Site
  5. * @subpackage com_users
  6. * @copyright Copyright (C) 2005 - 2011 Open Source Matters, Inc. All rights reserved.
  7. * @license GNU General Public License version 2 or later; see LICENSE.txt
  8. */
  9. defined('_JEXEC') or die;
  10. jimport('joomla.application.component.modelform');
  11. jimport('joomla.event.dispatcher');
  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. return false;
  35. }
  36. return $form;
  37. }
  38. /**
  39. * Method to get the password reset complete form.
  40. *
  41. * @param array $data Data for the form.
  42. * @param boolean $loadData True if the form is to load its own data (default case), false if not.
  43. * @return JForm A JForm object on success, false on failure
  44. * @since 1.6
  45. */
  46. public function getResetCompleteForm($data = array(), $loadData = true)
  47. {
  48. // Get the form.
  49. $form = $this->loadForm('com_users.reset_complete', 'reset_complete', $options = array('control' => 'jform'));
  50. if (empty($form)) {
  51. return false;
  52. }
  53. return $form;
  54. }
  55. /**
  56. * Method to get the password reset confirm form.
  57. *
  58. * @param array $data Data for the form.
  59. * @param boolean $loadData True if the form is to load its own data (default case), false if not.
  60. * @return JForm A JForm object on success, false on failure
  61. * @since 1.6
  62. */
  63. public function getResetConfirmForm($data = array(), $loadData = true)
  64. {
  65. // Get the form.
  66. $form = $this->loadForm('com_users.reset_confirm', 'reset_confirm', $options = array('control' => 'jform'));
  67. if (empty($form)) {
  68. return false;
  69. }
  70. return $form;
  71. }
  72. /**
  73. * Override preprocessForm to load the user plugin group instead of content.
  74. *
  75. * @param object A form object.
  76. * @param mixed The data expected for the form.
  77. * @throws Exception if there is an error in the form event.
  78. * @since 1.6
  79. */
  80. protected function preprocessForm(JForm $form, $data, $group = 'user')
  81. {
  82. parent::preprocessForm($form, $data, $group);
  83. }
  84. /**
  85. * Method to auto-populate the model state.
  86. *
  87. * Note. Calling getState in this method will result in recursion.
  88. *
  89. * @since 1.6
  90. */
  91. protected function populateState()
  92. {
  93. // Get the application object.
  94. $params = JFactory::getApplication()->getParams('com_users');
  95. // Load the parameters.
  96. $this->setState('params', $params);
  97. }
  98. /**
  99. * @since 1.6
  100. */
  101. function processResetComplete($data)
  102. {
  103. // Get the form.
  104. $form = $this->getResetCompleteForm();
  105. // Check for an error.
  106. if (JError::isError($form)) {
  107. return $form;
  108. }
  109. // Filter and validate the form data.
  110. $data = $form->filter($data);
  111. $return = $form->validate($data);
  112. // Check for an error.
  113. if (JError::isError($return)) {
  114. return $return;
  115. }
  116. // Check the validation results.
  117. if ($return === false) {
  118. // Get the validation messages from the form.
  119. foreach ($form->getErrors() as $message) {
  120. $this->setError($message);
  121. }
  122. return false;
  123. }
  124. // Get the token and user id from the confirmation process.
  125. $app = JFactory::getApplication();
  126. $token = $app->getUserState('com_users.reset.token', null);
  127. $userId = $app->getUserState('com_users.reset.user', null);
  128. // Check the token and user id.
  129. if (empty($token) || empty($userId)) {
  130. return new JException(JText::_('COM_USERS_RESET_COMPLETE_TOKENS_MISSING'), 403);
  131. }
  132. // Get the user object.
  133. $user = JUser::getInstance($userId);
  134. // Check for a user and that the tokens match.
  135. if (empty($user) || $user->activation !== $token) {
  136. $this->setError(JText::_('COM_USERS_USER_NOT_FOUND'));
  137. return false;
  138. }
  139. // Make sure the user isn't blocked.
  140. if ($user->block) {
  141. $this->setError(JText::_('COM_USERS_USER_BLOCKED'));
  142. return false;
  143. }
  144. // Generate the new password hash.
  145. jimport('joomla.user.helper');
  146. $salt = JUserHelper::genRandomPassword(32);
  147. $crypted = JUserHelper::getCryptedPassword($data['password1'], $salt);
  148. $password = $crypted.':'.$salt;
  149. // Update the user object.
  150. $user->password = $password;
  151. $user->activation = '';
  152. $user->password_clear = $data['password1'];
  153. // Save the user to the database.
  154. if (!$user->save(true)) {
  155. return new JException(JText::sprintf('COM_USERS_USER_SAVE_FAILED', $user->getError()), 500);
  156. }
  157. // Flush the user data from the session.
  158. $app->setUserState('com_users.reset.token', null);
  159. $app->setUserState('com_users.reset.user', null);
  160. return true;
  161. }
  162. /**
  163. * @since 1.6
  164. */
  165. function processResetConfirm($data)
  166. {
  167. jimport('joomla.user.helper');
  168. // Get the form.
  169. $form = $this->getResetConfirmForm();
  170. // Check for an error.
  171. if (JError::isError($form)) {
  172. return $form;
  173. }
  174. // Filter and validate the form data.
  175. $data = $form->filter($data);
  176. $return = $form->validate($data);
  177. // Check for an error.
  178. if (JError::isError($return)) {
  179. return $return;
  180. }
  181. // Check the validation results.
  182. if ($return === false) {
  183. // Get the validation messages from the form.
  184. foreach ($form->getErrors() as $message) {
  185. $this->setError($message);
  186. }
  187. return false;
  188. }
  189. // Find the user id for the given token.
  190. $db = $this->getDbo();
  191. $query = $db->getQuery(true);
  192. $query->select('activation');
  193. $query->select('id');
  194. $query->select('block');
  195. $query->from('`#__users`');
  196. $query->where('`username` = '.$db->Quote($data['username']));
  197. // Get the user id.
  198. $db->setQuery((string) $query);
  199. $user = $db->loadObject();
  200. // Check for an error.
  201. if ($db->getErrorNum()) {
  202. return new JException(JText::sprintf('COM_USERS_DATABASE_ERROR', $db->getErrorMsg()), 500);
  203. }
  204. // Check for a user.
  205. if (empty($user)) {
  206. $this->setError(JText::_('COM_USERS_USER_NOT_FOUND'));
  207. return false;
  208. }
  209. $parts = explode( ':', $user->activation );
  210. $crypt = $parts[0];
  211. if (!isset($parts[1])) {
  212. $this->setError(JText::_('COM_USERS_USER_NOT_FOUND'));
  213. return false;
  214. }
  215. $salt = $parts[1];
  216. $testcrypt = JUserHelper::getCryptedPassword($data['token'], $salt);
  217. // Verify the token
  218. if (!($crypt == $testcrypt))
  219. {
  220. $this->setError(JText::_('COM_USERS_USER_NOT_FOUND'));
  221. return false;
  222. }
  223. // Make sure the user isn't blocked.
  224. if ($user->block) {
  225. $this->setError(JText::_('COM_USERS_USER_BLOCKED'));
  226. return false;
  227. }
  228. // Push the user data into the session.
  229. $app = JFactory::getApplication();
  230. $app->setUserState('com_users.reset.token', $crypt.':'.$salt);
  231. $app->setUserState('com_users.reset.user', $user->id);
  232. return true;
  233. }
  234. /**
  235. * Method to start the password reset process.
  236. *
  237. * @since 1.6
  238. */
  239. public function processResetRequest($data)
  240. {
  241. $config = JFactory::getConfig();
  242. // Get the form.
  243. $form = $this->getForm();
  244. // Check for an error.
  245. if (JError::isError($form)) {
  246. return $form;
  247. }
  248. // Filter and validate the form data.
  249. $data = $form->filter($data);
  250. $return = $form->validate($data);
  251. // Check for an error.
  252. if (JError::isError($return)) {
  253. return $return;
  254. }
  255. // Check the validation results.
  256. if ($return === false) {
  257. // Get the validation messages from the form.
  258. foreach ($form->getErrors() as $message) {
  259. $this->setError($message);
  260. }
  261. return false;
  262. }
  263. jimport('joomla.user.helper');
  264. // Find the user id for the given email address.
  265. $db = $this->getDbo();
  266. $query = $db->getQuery(true);
  267. $query->select('id');
  268. $query->from('`#__users`');
  269. $query->where('`email` = '.$db->Quote($data['email']));
  270. // Get the user object.
  271. $db->setQuery((string) $query);
  272. $userId = $db->loadResult();
  273. // Check for an error.
  274. if ($db->getErrorNum()) {
  275. $this->setError(JText::sprintf('COM_USERS_DATABASE_ERROR', $db->getErrorMsg()), 500);
  276. return false;
  277. }
  278. // Check for a user.
  279. if (empty($userId)) {
  280. $this->setError(JText::_('COM_USERS_INVALID_EMAIL'));
  281. return false;
  282. }
  283. // Get the user object.
  284. $user = JUser::getInstance($userId);
  285. // Make sure the user isn't blocked.
  286. if ($user->block) {
  287. $this->setError(JText::_('COM_USERS_USER_BLOCKED'));
  288. return false;
  289. }
  290. // Make sure the user isn't a Super Admin.
  291. if ($user->authorise('core.admin')) {
  292. $this->setError(JText::_('COM_USERS_REMIND_SUPERADMIN_ERROR'));
  293. return false;
  294. }
  295. // Set the confirmation token.
  296. $token = JUtility::getHash(JUserHelper::genRandomPassword());
  297. $salt = JUserHelper::getSalt('crypt-md5');
  298. $hashedToken = md5($token.$salt).':'.$salt;
  299. $user->activation = $hashedToken;
  300. // Save the user to the database.
  301. if (!$user->save(true)) {
  302. return new JException(JText::sprintf('COM_USERS_USER_SAVE_FAILED', $user->getError()), 500);
  303. }
  304. // Assemble the password reset confirmation link.
  305. $mode = $config->get('force_ssl', 0) == 2 ? 1 : -1;
  306. $itemid = UsersHelperRoute::getLoginRoute();
  307. $itemid = $itemid !== null ? '&Itemid='.$itemid : '';
  308. $link = 'index.php?option=com_users&view=reset&layout=confirm'.$itemid;
  309. // Put together the email template data.
  310. $data = $user->getProperties();
  311. $data['fromname'] = $config->get('fromname');
  312. $data['mailfrom'] = $config->get('mailfrom');
  313. $data['sitename'] = $config->get('sitename');
  314. $data['link_text'] = JRoute::_($link, false, $mode);
  315. $data['link_html'] = JRoute::_($link, true, $mode);
  316. $data['token'] = $token;
  317. $subject = JText::sprintf(
  318. 'COM_USERS_EMAIL_PASSWORD_RESET_SUBJECT',
  319. $data['sitename']
  320. );
  321. $body = JText::sprintf(
  322. 'COM_USERS_EMAIL_PASSWORD_RESET_BODY',
  323. $data['sitename'],
  324. $data['token'],
  325. $data['link_text']
  326. );
  327. // Send the password reset request email.
  328. $return = JUtility::sendMail($data['mailfrom'], $data['fromname'], $user->email, $subject, $body);
  329. // Check for an error.
  330. if ($return !== true) {
  331. return new JException(JText::_('COM_USERS_MAIL_FAILED'), 500);
  332. }
  333. return true;
  334. }
  335. }