SpecialPasswordReset.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. <?php
  2. /**
  3. * Implements Special:PasswordReset
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. * http://www.gnu.org/copyleft/gpl.html
  19. *
  20. * @file
  21. * @ingroup SpecialPage
  22. */
  23. use MediaWiki\MediaWikiServices;
  24. /**
  25. * Special page for requesting a password reset email.
  26. *
  27. * Requires the TemporaryPasswordPrimaryAuthenticationProvider and the
  28. * EmailNotificationSecondaryAuthenticationProvider (or something providing equivalent
  29. * functionality) to be enabled.
  30. *
  31. * @ingroup SpecialPage
  32. */
  33. class SpecialPasswordReset extends FormSpecialPage {
  34. /** @var PasswordReset */
  35. private $passwordReset = null;
  36. /**
  37. * @var Status
  38. */
  39. private $result;
  40. /**
  41. * @var string $method Identifies which password reset field was specified by the user.
  42. */
  43. private $method;
  44. public function __construct() {
  45. parent::__construct( 'PasswordReset', 'editmyprivateinfo' );
  46. }
  47. private function getPasswordReset() {
  48. if ( $this->passwordReset === null ) {
  49. $this->passwordReset = MediaWikiServices::getInstance()->getPasswordReset();
  50. }
  51. return $this->passwordReset;
  52. }
  53. public function doesWrites() {
  54. return true;
  55. }
  56. public function userCanExecute( User $user ) {
  57. return $this->getPasswordReset()->isAllowed( $user )->isGood();
  58. }
  59. public function checkExecutePermissions( User $user ) {
  60. $status = Status::wrap( $this->getPasswordReset()->isAllowed( $user ) );
  61. if ( !$status->isGood() ) {
  62. throw new ErrorPageError( 'internalerror', $status->getMessage() );
  63. }
  64. parent::checkExecutePermissions( $user );
  65. }
  66. /**
  67. * @param string $par
  68. */
  69. public function execute( $par ) {
  70. $out = $this->getOutput();
  71. $out->disallowUserJs();
  72. parent::execute( $par );
  73. }
  74. protected function getFormFields() {
  75. $resetRoutes = $this->getConfig()->get( 'PasswordResetRoutes' );
  76. $a = [];
  77. if ( isset( $resetRoutes['username'] ) && $resetRoutes['username'] ) {
  78. $a['Username'] = [
  79. 'type' => 'text',
  80. 'default' => $this->getRequest()->getSession()->suggestLoginUsername(),
  81. 'label-message' => 'passwordreset-username',
  82. ];
  83. if ( $this->getUser()->isLoggedIn() ) {
  84. $a['Username']['default'] = $this->getUser()->getName();
  85. }
  86. }
  87. if ( isset( $resetRoutes['email'] ) && $resetRoutes['email'] ) {
  88. $a['Email'] = [
  89. 'type' => 'email',
  90. 'label-message' => 'passwordreset-email',
  91. ];
  92. }
  93. return $a;
  94. }
  95. protected function getDisplayFormat() {
  96. return 'ooui';
  97. }
  98. public function alterForm( HTMLForm $form ) {
  99. $resetRoutes = $this->getConfig()->get( 'PasswordResetRoutes' );
  100. $form->setSubmitDestructive();
  101. $form->addHiddenFields( $this->getRequest()->getValues( 'returnto', 'returntoquery' ) );
  102. $i = 0;
  103. if ( isset( $resetRoutes['username'] ) && $resetRoutes['username'] ) {
  104. $i++;
  105. }
  106. if ( isset( $resetRoutes['email'] ) && $resetRoutes['email'] ) {
  107. $i++;
  108. }
  109. $message = ( $i > 1 ) ? 'passwordreset-text-many' : 'passwordreset-text-one';
  110. $form->setHeaderText( $this->msg( $message, $i )->parseAsBlock() );
  111. $form->setSubmitTextMsg( 'mailmypassword' );
  112. }
  113. /**
  114. * Process the form. At this point we know that the user passes all the criteria in
  115. * userCanExecute(), and if the data array contains 'Username', etc, then Username
  116. * resets are allowed.
  117. * @param array $data
  118. * @throws MWException
  119. * @throws ThrottledError|PermissionsError
  120. * @return Status
  121. */
  122. public function onSubmit( array $data ) {
  123. $username = $data['Username'] ?? null;
  124. $email = $data['Email'] ?? null;
  125. $this->method = $username ? 'username' : 'email';
  126. $this->result = Status::wrap(
  127. $this->getPasswordReset()->execute( $this->getUser(), $username, $email ) );
  128. if ( $this->result->hasMessage( 'actionthrottledtext' ) ) {
  129. throw new ThrottledError;
  130. }
  131. return $this->result;
  132. }
  133. public function onSuccess() {
  134. if ( $this->method === 'email' ) {
  135. $this->getOutput()->addWikiMsg( 'passwordreset-emailsentemail' );
  136. } else {
  137. $this->getOutput()->addWikiMsg( 'passwordreset-emailsentusername' );
  138. }
  139. $this->getOutput()->returnToMain();
  140. }
  141. /**
  142. * Hide the password reset page if resets are disabled.
  143. * @return bool
  144. */
  145. public function isListed() {
  146. if ( $this->getPasswordReset()->isAllowed( $this->getUser() )->isGood() ) {
  147. return parent::isListed();
  148. }
  149. return false;
  150. }
  151. protected function getGroupName() {
  152. return 'users';
  153. }
  154. }