From: Brad Jorsch Date: Fri, 4 May 2018 13:35:55 +0000 (-0400) Subject: BotPasswords: Indicate when a password needs reset X-Git-Tag: 1.31.1~18 X-Git-Url: https://git.heureux-cyclage.org/?p=lhc%2Fweb%2Fwiklou.git;a=commitdiff_plain;h=d4f32694a52a192b8b3a941d370c2a28f85d69a5 BotPasswords: Indicate when a password needs reset Certain things, such as changing the account's main login credentials, causes all bot passwords to be invalidated. This state should be indicated in Special:BotPasswords, and the API when login fails. Bug: T193829 Change-Id: Ib12929fed861742c9f2f76702c9ac3254e8a5d97 (cherry picked from commit ff6b4cb35c1944870fcd3cc525884790c20819b3) --- diff --git a/RELEASE-NOTES-1.31 b/RELEASE-NOTES-1.31 index 4331e4f457..f64c8fadcd 100644 --- a/RELEASE-NOTES-1.31 +++ b/RELEASE-NOTES-1.31 @@ -10,6 +10,7 @@ This is a security and maintenance release of the MediaWiki 1.31 branch. * (T198687) Fix various selectFields methods to use the string 'NULL', not null. * Special:BotPasswords now requires reauthentication. * (T191608, T187638) Add 'logid' parameter to Special:Log. +* (T193829) Indicate when a Bot Password needs reset. == MediaWiki 1.31 == diff --git a/includes/api/ApiLogin.php b/includes/api/ApiLogin.php index e4c4429eb3..0248f25ef6 100644 --- a/includes/api/ApiLogin.php +++ b/includes/api/ApiLogin.php @@ -130,7 +130,10 @@ class ApiLogin extends ApiBase { $session = $status->getValue(); $authRes = 'Success'; $loginType = 'BotPassword'; - } elseif ( !$botLoginData[2] || $status->hasMessage( 'login-throttled' ) ) { + } elseif ( !$botLoginData[2] || + $status->hasMessage( 'login-throttled' ) || + $status->hasMessage( 'botpasswords-needs-reset' ) + ) { $authRes = 'Failed'; $message = $status->getMessage(); LoggerFactory::getInstance( 'authentication' )->info( diff --git a/includes/specials/SpecialBotPasswords.php b/includes/specials/SpecialBotPasswords.php index c912e83b92..961ee1c558 100644 --- a/includes/specials/SpecialBotPasswords.php +++ b/includes/specials/SpecialBotPasswords.php @@ -111,6 +111,9 @@ class SpecialBotPasswords extends FormSpecialPage { 'type' => 'check', 'label-message' => 'botpasswords-label-resetpassword', ]; + if ( $this->botPassword->isInvalid() ) { + $fields['resetPassword']['default'] = true; + } } $lang = $this->getLanguage(); @@ -157,22 +160,39 @@ class SpecialBotPasswords extends FormSpecialPage { } else { $linkRenderer = $this->getLinkRenderer(); + $passwordFactory = new PasswordFactory(); + $passwordFactory->init( $this->getConfig() ); + $dbr = BotPassword::getDB( DB_REPLICA ); $res = $dbr->select( 'bot_passwords', - [ 'bp_app_id' ], + [ 'bp_app_id', 'bp_password' ], [ 'bp_user' => $this->userId ], __METHOD__ ); foreach ( $res as $row ) { + try { + $password = $passwordFactory->newFromCiphertext( $row->bp_password ); + $passwordInvalid = $password instanceof InvalidPassword; + unset( $password ); + } catch ( PasswordError $ex ) { + $passwordInvalid = true; + } + + $text = $linkRenderer->makeKnownLink( + $this->getPageTitle( $row->bp_app_id ), + $row->bp_app_id + ); + if ( $passwordInvalid ) { + $text .= $this->msg( 'word-separator' )->escaped() + . $this->msg( 'botpasswords-label-needsreset' )->parse(); + } + $fields[] = [ 'section' => 'existing', 'type' => 'info', 'raw' => true, - 'default' => $linkRenderer->makeKnownLink( - $this->getPageTitle( $row->bp_app_id ), - $row->bp_app_id - ), + 'default' => $text, ]; } diff --git a/includes/user/BotPassword.php b/includes/user/BotPassword.php index f102d49c3b..6b8153cde4 100644 --- a/includes/user/BotPassword.php +++ b/includes/user/BotPassword.php @@ -261,6 +261,15 @@ class BotPassword implements IDBAccessObject { } } + /** + * Whether the password is currently invalid + * @since 1.32 + * @return bool + */ + public function isInvalid() { + return $this->getPassword() instanceof InvalidPassword; + } + /** * Save the BotPassword to the database * @param string $operation 'update' or 'insert' @@ -491,7 +500,11 @@ class BotPassword implements IDBAccessObject { } // Check the password - if ( !$bp->getPassword()->equals( $password ) ) { + $passwordObj = $bp->getPassword(); + if ( $passwordObj instanceof InvalidPassword ) { + return Status::newFatal( 'botpasswords-needs-reset', $name, $appId ); + } + if ( !$passwordObj->equals( $password ) ) { return Status::newFatal( 'wrongpassword' ); } diff --git a/languages/i18n/en.json b/languages/i18n/en.json index 168ce075cc..331dabedf7 100644 --- a/languages/i18n/en.json +++ b/languages/i18n/en.json @@ -537,6 +537,7 @@ "botpasswords-existing": "Existing bot passwords", "botpasswords-createnew": "Create a new bot password", "botpasswords-editexisting": "Edit an existing bot password", + "botpasswords-label-needsreset": "(password needs reset)", "botpasswords-label-appid": "Bot name:", "botpasswords-label-create": "Create", "botpasswords-label-update": "Update", @@ -560,6 +561,7 @@ "botpasswords-restriction-failed": "Bot password restrictions prevent this login.", "botpasswords-invalid-name": "The username specified does not contain the bot password separator (\"$1\").", "botpasswords-not-exist": "User \"$1\" does not have a bot password named \"$2\".", + "botpasswords-needs-reset": "The bot password for bot name \"$2\" of {{GENDER:$1|user}} \"$1\" must be reset.", "resetpass_forbidden": "Passwords cannot be changed", "resetpass_forbidden-reason": "Passwords cannot be changed: $1", "resetpass-no-info": "You must be logged in to access this page directly.", diff --git a/languages/i18n/qqq.json b/languages/i18n/qqq.json index e7da4c68b8..a4927b64b1 100644 --- a/languages/i18n/qqq.json +++ b/languages/i18n/qqq.json @@ -734,6 +734,7 @@ "botpasswords-existing": "Form section label for the part of the form listing the user's existing bot passwords.", "botpasswords-createnew": "Form section label for the part of the form related to creating a new bot password.", "botpasswords-editexisting": "Form section label for the part of the form related to editing an existing bot password.", + "botpasswords-label-needsreset": "Indicator for when an existing bot password is invalid and needs to be reset.", "botpasswords-label-appid": "Form field label for the \"bot name\", internally known as the \"application ID\".", "botpasswords-label-create": "Button label for the button to create a new bot password.\n{{Identical|Create}}", "botpasswords-label-update": "Button label for the button to save changes to a bot password.\n{{Identical|Update}}", @@ -757,6 +758,7 @@ "botpasswords-restriction-failed": "Error message when login is rejected because the configured restrictions were not satisfied.", "botpasswords-invalid-name": "Error message when a username lacking the separator character is passed to BotPassword. Parameters:\n* $1 - The separator character.", "botpasswords-not-exist": "Error message when a username exists but does not a bot password for the given \"bot name\". Parameters:\n* $1 - username\n* $2 - bot name", + "botpasswords-needs-reset": "Error message when a bot password exists but needs to be reset. Parameters:\n* $1 - username\n* $2 - bot name", "resetpass_forbidden": "Used as error message in changing password. Maybe the external auth plugin won't allow local password changes.", "resetpass_forbidden-reason": "Like {{msg-mw|resetpass_forbidden}} but the auth provider gave a reason.\n\nParameters:\n* $1 - reason given by auth provider", "resetpass-no-info": "Error message for [[Special:ChangePassword]].\n\nParameters:\n* $1 (unused) - a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link description",