ChangePassword fixes:
authorChad Horohoe <demon@users.mediawiki.org>
Fri, 20 Feb 2009 18:35:49 +0000 (18:35 +0000)
committerChad Horohoe <demon@users.mediawiki.org>
Fri, 20 Feb 2009 18:35:49 +0000 (18:35 +0000)
* (bug 15876) Allow on-wiki password resets. Needs 'reset-passwords' right, given by default to nobody (commented in DefaultSettings)
* Stronger username checking. If we're not allowed to change other people's passwords, don't even attempt it

RELEASE-NOTES
includes/DefaultSettings.php
includes/User.php
includes/specials/SpecialResetpass.php
languages/messages/MessagesEn.php
maintenance/language/messages.inc

index a6d1e2c..c22e4fc 100644 (file)
@@ -113,6 +113,8 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
 * Special:ListUsers: Sort list of usergroups by alphabet
 * (bug 16762) Special:Movepage now shows a list of subpages when possible
 * (bug 17585) Hide legend on Special:Specialpages from non-privileged users
+* (bug 15876) Users with 'reset-passwords' right can change the passwords of
+  other users.
 
 === Bug fixes in 1.15 ===
 * (bug 16968) Special:Upload no longer throws useless warnings.
index 6b7addc..c54427b 100644 (file)
@@ -1255,6 +1255,8 @@ $wgGroupPermissions['sysop']['movefile']         = true;
 // Permission to change users' group assignments
 $wgGroupPermissions['bureaucrat']['userrights']  = true;
 $wgGroupPermissions['bureaucrat']['noratelimit'] = true;
+// Permission to change users' passwords
+# $wgGroupPermissions['bureaucrat']['reset-passwords'] = true;
 // Permission to change users' groups assignments across wikis
 #$wgGroupPermissions['bureaucrat']['userrights-interwiki'] = true;
 
index 81246a1..cc57c2b 100644 (file)
@@ -162,6 +162,7 @@ class User {
                'proxyunbannable',
                'purge',
                'read',
+               'reset-passwords',
                'reupload',
                'reupload-shared',
                'rollback',
index 059f8db..60453bb 100644 (file)
@@ -9,6 +9,9 @@
  * @ingroup SpecialPage
  */
 class SpecialResetpass extends SpecialPage {
+
+       private $mSelfChange = true; // Usually, but sometimes not :)
+
        public function __construct() {
                parent::__construct( 'Resetpass' );
        }
@@ -19,7 +22,7 @@ class SpecialResetpass extends SpecialPage {
        function execute( $par ) {
                global $wgUser, $wgAuth, $wgOut, $wgRequest;
 
-               $this->mUserName = $wgRequest->getVal( 'wpName' );
+               $this->mUserName = $wgRequest->getVal( 'wpName', $par );
                $this->mOldpass = $wgRequest->getVal( 'wpPassword' );
                $this->mNewpass = $wgRequest->getVal( 'wpNewPassword' );
                $this->mRetype = $wgRequest->getVal( 'wpRetype' );
@@ -31,17 +34,33 @@ class SpecialResetpass extends SpecialPage {
                        $this->error( wfMsg( 'resetpass_forbidden' ) );
                        return;
                }
+               
+               // Default to our own username when not given one
+               if ( !$this->mUserName ) {
+                       $this->mUserName = $wgUser->getName();
+               }
+               
+               // Are we changing our own?
+               if ( $wgUser->getName() != $this->mUserName  ) {
+                       $this->mSelfChange = false; // We're changing someone else
+               }
 
                if( !$wgRequest->wasPosted() && !$wgUser->isLoggedIn() ) {
                        $this->error( wfMsg( 'resetpass-no-info' ) );
                        return;
                }
 
+               if ( !$this->mSelfChange && !$wgUser->isAllowed( 'reset-passwords' ) ) {
+                       $this->error( wfMsg( 'resetpass-no-others' ) );
+                       return;
+               }
+
                if( $wgRequest->wasPosted() && $wgUser->matchEditToken( $wgRequest->getVal('token') ) ) {
                        try {
                                $this->attemptReset( $this->mNewpass, $this->mRetype );
                                $wgOut->addWikiMsg( 'resetpass_success' );
-                               if( !$wgUser->isLoggedIn() ) {
+                               // Only attempt this login session if we're changing our own password
+                               if( $this->mSelfChange && !$wgUser->isLoggedIn() ) {
                                        $data = array(
                                                'action'     => 'submitlogin',
                                                'wpName'     => $this->mUserName,
@@ -77,9 +96,7 @@ class SpecialResetpass extends SpecialPage {
                $wgOut->disallowUserJs();
 
                $self = SpecialPage::getTitleFor( 'Resetpass' );
-               if ( !$this->mUserName ) {
-                       $this->mUserName = $wgUser->getName();
-               }
+
                $rememberMe = '';
                if ( !$wgUser->isLoggedIn() ) {
                        $rememberMe = '<tr>' .
@@ -104,15 +121,14 @@ class SpecialResetpass extends SpecialPage {
                                        'action' => $self->getLocalUrl(),
                                        'id' => 'mw-resetpass-form' ) ) .       
                        Xml::hidden( 'token', $wgUser->editToken() ) .
-                       Xml::hidden( 'wpName', $this->mUserName ) .
                        Xml::hidden( 'returnto', $wgRequest->getVal( 'returnto' ) ) .
                        wfMsgExt( 'resetpass_text', array( 'parse' ) ) .
                        Xml::openElement( 'table', array( 'id' => 'mw-resetpass-table' ) ) .
                        $this->pretty( array(
-                               array( 'wpName', 'username', 'text', $this->mUserName ),
-                               array( 'wpPassword', $oldpassMsg, 'password', $this->mOldpass ),
-                               array( 'wpNewPassword', 'newpassword', 'password', '' ),
-                               array( 'wpRetype', 'retypenew', 'password', '' ),
+                               array( 'wpName', 'username', 'text', $this->mUserName, !$this->mSelfChange ),
+                               array( 'wpPassword', $oldpassMsg, 'password', $this->mOldpass, $this->mSelfChange ),
+                               array( 'wpNewPassword', 'newpassword', 'password', '', true ),
+                               array( 'wpRetype', 'retypenew', 'password', '', true ),
                        ) ) .
                        $rememberMe .
                        '<tr>' .
@@ -130,21 +146,16 @@ class SpecialResetpass extends SpecialPage {
        function pretty( $fields ) {
                $out = '';
                foreach( $fields as $list ) {
-                       list( $name, $label, $type, $value ) = $list;
-                       if( $type == 'text' ) {
-                               $field = htmlspecialchars( $value );
-                       } else {
-                               $field = Xml::input( $name, 20, $value,
-                                       array( 'id' => $name, 'type' => $type ) );
-                       }
+                       list( $name, $label, $type, $value, $enabled ) = $list;
+                       $params = array( 'id' => $name, 'type' => $type );
+                       if ( !$enabled )
+                               $params['disabled'] = 'disabled';
+                       $field = Xml::input( $name, 20, $value, $params );
                        $out .= '<tr>';
-                       $out .= "<td class='mw-label'>";
-                       if ( $type != 'text' )
-                               $out .= Xml::label( wfMsg( $label ), $name );
-                       else 
-                               $out .=  wfMsg( $label );
+                       $out .= '<td class="mw-label">';
+                       $out .= Xml::label( wfMsg( $label ), $name );
                        $out .= '</td>';
-                       $out .= "<td class='mw-input'>";
+                       $out .= '<td class="mw-input">';
                        $out .= $field;
                        $out .= '</td>';
                        $out .= '</tr>';
@@ -166,9 +177,11 @@ class SpecialResetpass extends SpecialPage {
                        throw new PasswordError( wfMsg( 'badretype' ) );
                }
 
-               if( !$user->checkTemporaryPassword($this->mOldpass) && !$user->checkPassword($this->mOldpass) ) {
-                       wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'wrongpassword' ) );
-                       throw new PasswordError( wfMsg( 'resetpass-wrong-oldpass' ) );
+               if ( $this->mSelfChange ) {
+                       if( !$user->checkTemporaryPassword($this->mOldpass) && !$user->checkPassword($this->mOldpass) ) {
+                               wfRunHooks( 'PrefsPasswordAudit', array( $user, $newpass, 'wrongpassword' ) );
+                               throw new PasswordError( wfMsg( 'resetpass-wrong-oldpass' ) );
+                       }
                }
                
                try {
index 582532e..2e6a0f3 100644 (file)
@@ -1016,6 +1016,7 @@ You may have already successfully changed your password or requested a new tempo
 'resetpass-wrong-oldpass'   => 'Invalid temporary or current password.
 You may have already successfully changed your password or requested a new temporary password.',
 'resetpass-temp-password'   => 'Temporary password:',
+'resetpass-no-others'       => 'You cannot reset the password for other users.',
 
 # Edit page toolbar
 'bold_sample'     => 'Bold text',
index 69360b0..97fc834 100644 (file)
@@ -461,6 +461,7 @@ $wgMessageStructure = array(
                'resetpass-submit-loggedin',
                'resetpass-wrong-oldpass',
                'resetpass-temp-password',
+               'resetpass-no-others',
        ),
        'toolbar' => array(
                'bold_sample',