Disallow User::setPassword() on users not in database
authorBrad Jorsch <bjorsch@wikimedia.org>
Fri, 30 Oct 2015 15:19:12 +0000 (11:19 -0400)
committerBrad Jorsch <bjorsch@wikimedia.org>
Fri, 30 Oct 2015 15:33:58 +0000 (11:33 -0400)
Change I2c736ad mostly removed the password handling from the User
object, but left in a little password handling to preserve the existing
ability to call $user->setPassword() before the user was actually added
to the database. That ability is now removed.

Bug: T47716
Change-Id: Id3d40742f2e2b197ad6facd149cc6350006bf289

includes/User.php
maintenance/createAndPromote.php

index a6b897d..eb3ab9d 100644 (file)
@@ -185,8 +185,6 @@ class User implements IDBAccessObject {
        public $mName;
        /** @var string */
        public $mRealName;
-       /** @var Password|null */
-       private $mPassword = null;
 
        /** @var string */
        public $mEmail;
@@ -2400,32 +2398,32 @@ class User implements IDBAccessObject {
 
        /**
         * Actually set the password and such
+        * @since 1.27 cannot set a password for a user not in the database
         * @param string|null $str New password to set or null to set an invalid
         *  password hash meaning that the user will not be able to log in
         *  through the web interface.
         */
        private function setPasswordInternal( $str ) {
                $id = self::idFromName( $this->getName() );
-               if ( $id ) {
-                       $passwordFactory = new PasswordFactory();
-                       $passwordFactory->init( RequestContext::getMain()->getConfig() );
-                       $dbw = wfGetDB( DB_MASTER );
-                       $dbw->update(
-                               'user',
-                               array(
-                                       'user_password' => $passwordFactory->newFromPlaintext( $str )->toString(),
-                                       'user_newpassword' => PasswordFactory::newInvalidPassword()->toString(),
-                                       'user_newpass_time' => $dbw->timestampOrNull( null ),
-                               ),
-                               array(
-                                       'user_id' => $id,
-                               ),
-                               __METHOD__
-                       );
-                       $this->mPassword = null;
-               } else {
-                       $this->mPassword = $str;
+               if ( $id == 0 ) {
+                       throw new LogicException( 'Cannot set a password for a user that is not in the database.' );
                }
+
+               $passwordFactory = new PasswordFactory();
+               $passwordFactory->init( RequestContext::getMain()->getConfig() );
+               $dbw = wfGetDB( DB_MASTER );
+               $dbw->update(
+                       'user',
+                       array(
+                               'user_password' => $passwordFactory->newFromPlaintext( $str )->toString(),
+                               'user_newpassword' => PasswordFactory::newInvalidPassword()->toString(),
+                               'user_newpass_time' => $dbw->timestampOrNull( null ),
+                       ),
+                       array(
+                               'user_id' => $id,
+                       ),
+                       __METHOD__
+               );
        }
 
        /**
@@ -3882,11 +3880,6 @@ class User implements IDBAccessObject {
                }
                $this->mId = $dbw->insertId();
 
-               // Set the password now that it's in the DB, if applicable
-               if ( $this->mPassword !== null ) {
-                       $this->setPasswordInternal( $this->mPassword );
-               }
-
                // Clear instance cache other than user table data, which is already accurate
                $this->clearInstanceCache();
 
index 861b364..c1a2022 100644 (file)
@@ -106,6 +106,12 @@ class CreateAndPromote extends Maintenance {
                        }
                }
 
+               if ( !$exists ) {
+                       # Insert the account into the database
+                       $user->addToDatabase();
+                       $user->saveSettings();
+               }
+
                if ( $password ) {
                        # Try to set the password
                        try {
@@ -119,12 +125,6 @@ class CreateAndPromote extends Maintenance {
                        }
                }
 
-               if ( !$exists ) {
-                       # Insert the account into the database
-                       $user->addToDatabase();
-                       $user->saveSettings();
-               }
-
                # Promote user
                array_map( array( $user, 'addGroup' ), $promotions );