CSteipp has uploaded a new change for review. https://gerrit.wikimedia.org/r/50034
Change subject: (bug 18057) Add conflict detection for status ...................................................................... (bug 18057) Add conflict detection for status Adds a hash of the current locked and hidden values for a user in the form submission. If another admin has updated the user's status, then the conflict will be detected and the operation aborted. The hash can be optionally passed with an api request, to optionally perform the conflict detection. The MD5 should be easy to calculate in any code using the api. Change-Id: Ia985e152ccabb77454f0eb87bbb78f0e220d5674 --- M CentralAuth.i18n.php M CentralAuthUser.php M api/ApiSetGlobalAccountStatus.php M specials/SpecialCentralAuth.php 4 files changed, 30 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/CentralAuth refs/changes/34/50034/1 diff --git a/CentralAuth.i18n.php b/CentralAuth.i18n.php index 571e20a..7c066fa 100644 --- a/CentralAuth.i18n.php +++ b/CentralAuth.i18n.php @@ -186,6 +186,7 @@ 'centralauth-admin-nonexistent' => 'There is no global account for "<nowiki>$1</nowiki>"', 'centralauth-admin-delete-nonexistent' => 'Error: the global account "<nowiki>$1</nowiki>" does not exist.', 'centralauth-token-mismatch' => 'Sorry, we could not process your form submission due to a loss of session data.', + 'centralauth-state-mismatch' => 'Error: An edit conflict for this user was detected. Please verify your change and try again.', 'centralauth-admin-reason' => 'Reason:', 'centralauth-admin-reason-other' => 'Other/additional reason:', 'centralauth-admin-unhide-nonexistent' => 'Error: the global account "<nowiki>$1</nowiki>" does not exist.', diff --git a/CentralAuthUser.php b/CentralAuthUser.php index 3a50267..5840d74 100644 --- a/CentralAuthUser.php +++ b/CentralAuthUser.php @@ -2237,4 +2237,16 @@ public function attachedOn( $wiki ) { return $this->exists() && in_array( $wiki, $this->mAttachedArray ); } + + /** + * Get a hash representing the user/locked/hidden state of this user, + * used to check for edit conflicts + * + * @para $recache - force a reload of the user from the database + * @return String + */ + public function getStateHash( $recache = false ) { + $this->loadState( $recache ); + return md5( $this->mGlobalId . ':' . $this->mName . ':' . $this->mHidden . ':' . (int) $this->mLocked ); + } } diff --git a/api/ApiSetGlobalAccountStatus.php b/api/ApiSetGlobalAccountStatus.php index 38ce990..ddab9f1 100644 --- a/api/ApiSetGlobalAccountStatus.php +++ b/api/ApiSetGlobalAccountStatus.php @@ -45,8 +45,13 @@ $setLocked = $this->getParameter( 'locked' ) == 'lock'; $setHidden = $this->getParameter( 'hidden' ); $reason = $this->getParameter( 'reason' ); + $stateCheck = $this->getParameter( 'statecheck' ); $isLocked = $globalUser->isLocked(); $oldHiddenLevel = $globalUser->getHiddenLevel(); + + if ( $stateCheck && $stateCheck !== $globalUser->getStateHash( true ) ) { + $this->dieUsage( "Edit conflict detected, Aborting." ); + } if ( $setHidden !== null && // hidden is set @@ -170,6 +175,10 @@ ApiBase::PARAM_TYPE => 'string', ApiBase::PARAM_REQUIRED => true ), + 'statecheck' => array( + ApiBase::PARAM_TYPE => 'string', + ApiBase::PARAM_REQUIRED => false + ), ); } @@ -179,7 +188,8 @@ 'locked' => 'Change whether this user is locked or not.', 'hidden' => 'Change whether this user is not hidden, hidden from lists, or suppressed.', 'reason' => "Reason for changing the user's status.", - 'token' => 'Your edit token.' + 'token' => 'Your edit token.', + 'statecheck' => 'Optional MD5 of the expected current <username>:<hidden>:<locked>, to detect edit conflicts.' ); } @@ -221,6 +231,9 @@ 'reason' => array( ApiBase::PROP_TYPE => 'string', ApiBase::PROP_NULLABLE => true + ), + 'statecheck' => array( + ApiBase::PROP_TYPE => 'string' ) ) ); diff --git a/specials/SpecialCentralAuth.php b/specials/SpecialCentralAuth.php index 6ced080..d656123 100644 --- a/specials/SpecialCentralAuth.php +++ b/specials/SpecialCentralAuth.php @@ -118,6 +118,8 @@ $deleted = true; $this->logAction( 'delete', $this->mUserName, $this->getRequest()->getVal( 'reason' ) ); } + } elseif ( $this->mMethod == 'set-status' && $this->getRequest()->getVal( 'wpUserState' ) !== $globalUser->getStateHash( true ) ) { + $this->showError( 'centralauth-state-mismatch' ); } elseif ( $this->mMethod == 'set-status' && $this->mCanLock ) { $setLocked = $this->getRequest()->getBool( 'wpStatusLocked' ); $setHidden = $this->getRequest()->getVal( 'wpStatusHidden' ); @@ -605,6 +607,7 @@ $form .= Xml::fieldset( $this->msg( 'centralauth-admin-status' )->text() ); $form .= Html::hidden( 'wpMethod', 'set-status' ); $form .= Html::hidden( 'wpEditToken', $this->getUser()->getEditToken() ); + $form .= Html::hidden( 'wpUserState', $this->mGlobalUser->getStateHash(false) ); $form .= $this->msg( 'centralauth-admin-status-intro' )->parseAsBlock(); // Radio buttons -- To view, visit https://gerrit.wikimedia.org/r/50034 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ia985e152ccabb77454f0eb87bbb78f0e220d5674 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/CentralAuth Gerrit-Branch: master Gerrit-Owner: CSteipp <cste...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits