From 9de2bfd1fea524737bfbfbc40bcf1efc1b9a40eb Mon Sep 17 00:00:00 2001 From: Happy-melon Date: Sat, 24 Sep 2011 21:11:41 +0000 Subject: [PATCH] (bug 30636) integrate the remaining functionality of the PasswordReset extension into core, to make the fact that its Special:PasswordReset conflicts (as of 1.18) with the new core special page of the same name no longer relevant. The extension just allows admins with the 'passwordreset' permission to arbitrarily change other users' passwords, which is really scary. This core change uses the same permission, but instead gives them the ability to view the password reset email that would be sent to another user. So they can record the temporary password, and give it to the user via a medium other than email; but when the user logs in with it they will be forced to change it and the admin will no longer know what it is. It would be nice to log these viewing actions, but I'm not sure which log it should go into, or whether it's worth creating a new one just for this (rare and disabled-by-default) action. --- includes/DefaultSettings.php | 2 +- includes/specials/SpecialPasswordReset.php | 60 +++++++++++++++++++--- languages/messages/MessagesEn.php | 5 ++ 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 4a89ea8b0d..b9dacbf44d 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -4804,7 +4804,7 @@ $wgExtensionCredits = array(); /** * Authentication plugin. - * @var AuthPlugin + * @var $wgAuth AuthPlugin */ $wgAuth = null; diff --git a/includes/specials/SpecialPasswordReset.php b/includes/specials/SpecialPasswordReset.php index f8df8314fe..b07ef80f70 100644 --- a/includes/specials/SpecialPasswordReset.php +++ b/includes/specials/SpecialPasswordReset.php @@ -28,6 +28,16 @@ */ class SpecialPasswordReset extends FormSpecialPage { + /** + * @var Message + */ + private $email; + + /** + * @var Status + */ + private $result; + public function __construct() { parent::__construct( 'PasswordReset' ); } @@ -69,6 +79,14 @@ class SpecialPasswordReset extends FormSpecialPage { ); } + if( $this->getUser()->isAllowed( 'passwordreset' ) ){ + $a['Capture'] = array( + 'type' => 'check', + 'label-message' => 'passwordreset-capture', + 'help-message' => 'passwordreset-capture-help', + ); + } + return $a; } @@ -109,6 +127,16 @@ class SpecialPasswordReset extends FormSpecialPage { } } + if( isset( $data['Capture'] ) && !$this->getUser()->isAllowed( 'passwordreset' ) ){ + // The user knows they don't have the passwordreset permission, but they tried to spoof the form. That's naughty + throw new PermissionsError( 'passwordreset' ); + } + + /** + * @var $firstUser User + * @var $users User[] + */ + if ( isset( $data['Username'] ) && $data['Username'] !== '' ) { $method = 'username'; $users = array( User::newFromName( $data['Username'] ) ); @@ -199,15 +227,15 @@ class SpecialPasswordReset extends FormSpecialPage { $password = $user->randomPassword(); $user->setNewpassword( $password ); $user->saveSettings(); - $passwords[] = wfMessage( 'passwordreset-emailelement', $user->getName(), $password ); + $passwords[] = wfMessage( 'passwordreset-emailelement', $user->getName(), $password )->plain(); // We'll escape the whole thing later } $passwordBlock = implode( "\n\n", $passwords ); // Send in the user's language; which should hopefully be the same $userLanguage = $firstUser->getOption( 'language' ); - $body = wfMessage( $msg )->inLanguage( $userLanguage ); - $body->params( + $this->email = wfMessage( $msg )->inLanguage( $userLanguage ); + $this->email->params( $username, $passwordBlock, count( $passwords ), @@ -217,18 +245,38 @@ class SpecialPasswordReset extends FormSpecialPage { $title = wfMessage( 'passwordreset-emailtitle' ); - $result = $firstUser->sendMail( $title->text(), $body->text() ); + $this->result = $firstUser->sendMail( $title->escaped(), $this->email->escaped() ); - if ( $result->isGood() ) { + // Blank the email if the user is not supposed to see it + if( !isset( $data['Capture'] ) || !$data['Capture'] ) { + $this->email = null; + } + + if ( $this->result->isGood() ) { + return true; + } elseif( isset( $data['Capture'] ) && $data['Capture'] ){ + // The email didn't send, but maybe they knew that and that's why they captured it return true; } else { // @todo FIXME: The email didn't send, but we have already set the password throttle // timestamp, so they won't be able to try again until it expires... :( - return array( array( 'mailerror', $result->getMessage() ) ); + return array( array( 'mailerror', $this->result->getMessage() ) ); } } public function onSuccess() { + if( $this->getUser()->isAllowed( 'passwordreset' ) && $this->email != null ){ + // @todo: Logging + + if( $this->result->isGood() ){ + $this->getOutput()->addWikiMsg( 'passwordreset-emailsent-capture' ); + } else { + $this->getOutput()->addWikiMsg( 'passwordreset-emailerror-capture', $this->result->getMessage() ); + } + + $this->getOutput()->addHTML( Html::rawElement( 'pre', array(), $this->email->escaped() ) ); + } + $this->getOutput()->addWikiMsg( 'passwordreset-emailsent' ); $this->getOutput()->returnToMain(); } diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index 7f6a5f0630..8d53be93be 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -1183,6 +1183,8 @@ You may have already successfully changed your password or requested a new tempo 'passwordreset-pretext' => '{{PLURAL:$1||Enter one of the pieces of data below}}', 'passwordreset-username' => 'Username:', 'passwordreset-domain' => 'Domain:', +'passwordreset-capture' => 'View the resulting email?', +'passwordreset-capture-help' => 'If you check this box, the email (with the temporary password) will be shown to you as well as being sent to the user.', 'passwordreset-email' => 'E-mail address:', 'passwordreset-emailtitle' => 'Account details on {{SITENAME}}', 'passwordreset-emailtext-ip' => 'Someone (probably you, from IP address $1) requested a reminder of your @@ -1209,6 +1211,8 @@ password.', 'passwordreset-emailelement' => 'Username: $1 Temporary password: $2', 'passwordreset-emailsent' => 'A reminder e-mail has been sent.', +'passwordreset-emailsent-capture' => 'A reminder e-mail has been sent, which is shown below.', +'passwordreset-emailerror-capture' => 'A reminder e-mail was generated, which is shown below, but sending it to the user failed: $1', # Special:ChangeEmail 'changeemail' => 'Change E-mail address', @@ -1980,6 +1984,7 @@ Your e-mail address is not revealed when other users contact you.', 'right-siteadmin' => 'Lock and unlock the database', 'right-override-export-depth' => 'Export pages including linked pages up to a depth of 5', 'right-sendemail' => 'Send e-mail to other users', +'right-passwordreset' => 'View password reset emails', # User rights log 'rightslog' => 'User rights log', -- 2.20.1