r98029 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r98028‎ | r98029 | r98030 >
Date:21:11, 24 September 2011
Author:happy-melon
Status:ok (Comments)
Tags:post1.18deploy 
Comment:
(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.
Modified paths:
  • /trunk/phase3/includes/DefaultSettings.php (modified) (history)
  • /trunk/phase3/includes/specials/SpecialPasswordReset.php (modified) (history)
  • /trunk/phase3/languages/messages/MessagesEn.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/DefaultSettings.php
@@ -4804,7 +4804,7 @@
48054805
48064806 /**
48074807 * Authentication plugin.
4808 - * @var AuthPlugin
 4808+ * @var $wgAuth AuthPlugin
48094809 */
48104810 $wgAuth = null;
48114811
Index: trunk/phase3/includes/specials/SpecialPasswordReset.php
@@ -28,6 +28,16 @@
2929 */
3030 class SpecialPasswordReset extends FormSpecialPage {
3131
 32+ /**
 33+ * @var Message
 34+ */
 35+ private $email;
 36+
 37+ /**
 38+ * @var Status
 39+ */
 40+ private $result;
 41+
3242 public function __construct() {
3343 parent::__construct( 'PasswordReset' );
3444 }
@@ -69,6 +79,14 @@
7080 );
7181 }
7282
 83+ if( $this->getUser()->isAllowed( 'passwordreset' ) ){
 84+ $a['Capture'] = array(
 85+ 'type' => 'check',
 86+ 'label-message' => 'passwordreset-capture',
 87+ 'help-message' => 'passwordreset-capture-help',
 88+ );
 89+ }
 90+
7391 return $a;
7492 }
7593
@@ -109,6 +127,16 @@
110128 }
111129 }
112130
 131+ if( isset( $data['Capture'] ) && !$this->getUser()->isAllowed( 'passwordreset' ) ){
 132+ // The user knows they don't have the passwordreset permission, but they tried to spoof the form. That's naughty
 133+ throw new PermissionsError( 'passwordreset' );
 134+ }
 135+
 136+ /**
 137+ * @var $firstUser User
 138+ * @var $users User[]
 139+ */
 140+
113141 if ( isset( $data['Username'] ) && $data['Username'] !== '' ) {
114142 $method = 'username';
115143 $users = array( User::newFromName( $data['Username'] ) );
@@ -199,15 +227,15 @@
200228 $password = $user->randomPassword();
201229 $user->setNewpassword( $password );
202230 $user->saveSettings();
203 - $passwords[] = wfMessage( 'passwordreset-emailelement', $user->getName(), $password );
 231+ $passwords[] = wfMessage( 'passwordreset-emailelement', $user->getName(), $password )->plain(); // We'll escape the whole thing later
204232 }
205233 $passwordBlock = implode( "\n\n", $passwords );
206234
207235 // Send in the user's language; which should hopefully be the same
208236 $userLanguage = $firstUser->getOption( 'language' );
209237
210 - $body = wfMessage( $msg )->inLanguage( $userLanguage );
211 - $body->params(
 238+ $this->email = wfMessage( $msg )->inLanguage( $userLanguage );
 239+ $this->email->params(
212240 $username,
213241 $passwordBlock,
214242 count( $passwords ),
@@ -217,18 +245,38 @@
218246
219247 $title = wfMessage( 'passwordreset-emailtitle' );
220248
221 - $result = $firstUser->sendMail( $title->text(), $body->text() );
 249+ $this->result = $firstUser->sendMail( $title->escaped(), $this->email->escaped() );
222250
223 - if ( $result->isGood() ) {
 251+ // Blank the email if the user is not supposed to see it
 252+ if( !isset( $data['Capture'] ) || !$data['Capture'] ) {
 253+ $this->email = null;
 254+ }
 255+
 256+ if ( $this->result->isGood() ) {
224257 return true;
 258+ } elseif( isset( $data['Capture'] ) && $data['Capture'] ){
 259+ // The email didn't send, but maybe they knew that and that's why they captured it
 260+ return true;
225261 } else {
226262 // @todo FIXME: The email didn't send, but we have already set the password throttle
227263 // timestamp, so they won't be able to try again until it expires... :(
228 - return array( array( 'mailerror', $result->getMessage() ) );
 264+ return array( array( 'mailerror', $this->result->getMessage() ) );
229265 }
230266 }
231267
232268 public function onSuccess() {
 269+ if( $this->getUser()->isAllowed( 'passwordreset' ) && $this->email != null ){
 270+ // @todo: Logging
 271+
 272+ if( $this->result->isGood() ){
 273+ $this->getOutput()->addWikiMsg( 'passwordreset-emailsent-capture' );
 274+ } else {
 275+ $this->getOutput()->addWikiMsg( 'passwordreset-emailerror-capture', $this->result->getMessage() );
 276+ }
 277+
 278+ $this->getOutput()->addHTML( Html::rawElement( 'pre', array(), $this->email->escaped() ) );
 279+ }
 280+
233281 $this->getOutput()->addWikiMsg( 'passwordreset-emailsent' );
234282 $this->getOutput()->returnToMain();
235283 }
Index: trunk/phase3/languages/messages/MessagesEn.php
@@ -1183,6 +1183,8 @@
11841184 'passwordreset-pretext' => '{{PLURAL:$1||Enter one of the pieces of data below}}',
11851185 'passwordreset-username' => 'Username:',
11861186 'passwordreset-domain' => 'Domain:',
 1187+'passwordreset-capture' => 'View the resulting email?',
 1188+'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.',
11871189 'passwordreset-email' => 'E-mail address:',
11881190 'passwordreset-emailtitle' => 'Account details on {{SITENAME}}',
11891191 'passwordreset-emailtext-ip' => 'Someone (probably you, from IP address $1) requested a reminder of your
@@ -1209,6 +1211,8 @@
12101212 'passwordreset-emailelement' => 'Username: $1
12111213 Temporary password: $2',
12121214 'passwordreset-emailsent' => 'A reminder e-mail has been sent.',
 1215+'passwordreset-emailsent-capture' => 'A reminder e-mail has been sent, which is shown below.',
 1216+'passwordreset-emailerror-capture' => 'A reminder e-mail was generated, which is shown below, but sending it to the user failed: $1',
12131217
12141218 # Special:ChangeEmail
12151219 'changeemail' => 'Change E-mail address',
@@ -1980,6 +1984,7 @@
19811985 'right-siteadmin' => 'Lock and unlock the database',
19821986 'right-override-export-depth' => 'Export pages including linked pages up to a depth of 5',
19831987 'right-sendemail' => 'Send e-mail to other users',
 1988+'right-passwordreset' => 'View password reset emails',
19841989
19851990 # User rights log
19861991 'rightslog' => 'User rights log',

Follow-up revisions

RevisionCommit summaryAuthorDate
r98035FU r98029 - message documentation.happy-melon21:37, 24 September 2011
r98076email -> e-mail for consistencyraymond18:43, 25 September 2011

Comments

#Comment by Happy-melon (talk | contribs)   21:16, 24 September 2011

Although I know we'd rather not backport new features into 1.18, this is actually a bugfix for a regression in PasswordReset between 1.17 and 1.18 ("regression" as in it no longer works because core stole its special page name :D). With this commit too, the extension is completely deprecated and admins can simply remove it, rather than having to fix it for a release and then replace it next time.

#Comment by Siebrand (talk | contribs)   21:25, 24 September 2011

Messages.Inc was not updated. Please add message documentation for the newly added messages. Thanks.

#Comment by Happy-melon (talk | contribs)   21:38, 24 September 2011

Damn, I actually had this in, then I started copying the right-passwordreset message from the PasswordReset extension, realised halfway through that the right actually does something kinda different now, so reverted all those changes and thereby threw out these ones... :(

Status & tagging log