jenkins-bot has submitted this change and it was merged.
Change subject: Added CAS logic to User::addAutopromoteOnceGroups
......................................................................
Added CAS logic to User::addAutopromoteOnceGroups
* This should avoid duplicate logging events on races or when
the cache fails to update.
* Also added getDBTouched() method to get user_touched itself.
Bug: T48834
Change-Id: Ib2cd0a2c72629fa4e13dcff4d2d6fbac8e690b32
---
M includes/User.php
M tests/phpunit/includes/UserTest.php
2 files changed, 102 insertions(+), 23 deletions(-)
Approvals:
Anomie: Looks good to me, approved
jenkins-bot: Verified
diff --git a/includes/User.php b/includes/User.php
index 4ada6b1..6218ce2 100644
--- a/includes/User.php
+++ b/includes/User.php
@@ -1422,35 +1422,83 @@
public function addAutopromoteOnceGroups( $event ) {
global $wgAutopromoteOnceLogInRC, $wgAuth;
- $toPromote = array();
- if ( !wfReadOnly() && $this->getId() ) {
- $toPromote = Autopromote::getAutopromoteOnceGroups(
$this, $event );
- if ( count( $toPromote ) ) {
- $oldGroups = $this->getGroups(); // previous
groups
+ if ( wfReadOnly() || !$this->getId() ) {
+ return array();
+ }
- foreach ( $toPromote as $group ) {
- $this->addGroup( $group );
- }
- // update groups in external authentication
database
- $wgAuth->updateExternalDBGroups( $this,
$toPromote );
+ $toPromote = Autopromote::getAutopromoteOnceGroups( $this,
$event );
+ if ( !count( $toPromote ) ) {
+ return array();
+ }
- $newGroups = array_merge( $oldGroups,
$toPromote ); // all groups
+ if ( !$this->checkAndSetTouched() ) {
+ return array(); // raced out (bug T48834)
+ }
- $logEntry = new ManualLogEntry( 'rights',
'autopromote' );
- $logEntry->setPerformer( $this );
- $logEntry->setTarget( $this->getUserPage() );
- $logEntry->setParameters( array(
- '4::oldgroups' => $oldGroups,
- '5::newgroups' => $newGroups,
- ) );
- $logid = $logEntry->insert();
- if ( $wgAutopromoteOnceLogInRC ) {
- $logEntry->publish( $logid );
- }
- }
+ $oldGroups = $this->getGroups(); // previous groups
+ foreach ( $toPromote as $group ) {
+ $this->addGroup( $group );
+ }
+
+ // update groups in external authentication database
+ $wgAuth->updateExternalDBGroups( $this, $toPromote );
+
+ $newGroups = array_merge( $oldGroups, $toPromote ); // all
groups
+
+ $logEntry = new ManualLogEntry( 'rights', 'autopromote' );
+ $logEntry->setPerformer( $this );
+ $logEntry->setTarget( $this->getUserPage() );
+ $logEntry->setParameters( array(
+ '4::oldgroups' => $oldGroups,
+ '5::newgroups' => $newGroups,
+ ) );
+ $logid = $logEntry->insert();
+ if ( $wgAutopromoteOnceLogInRC ) {
+ $logEntry->publish( $logid );
}
return $toPromote;
+ }
+
+ /**
+ * Bump user_touched if it didn't change since this object was loaded
+ *
+ * On success, the mTouched field is updated.
+ * The user serialization cache is always cleared.
+ *
+ * @return bool Whether user_touched was actually updated
+ * @since 1.26
+ */
+ protected function checkAndSetTouched() {
+ $this->load();
+
+ if ( !$this->mId ) {
+ return false; // anon
+ }
+
+ // Get a new user_touched that is higher than the old one
+ $oldTouched = $this->mTouched;
+ $newTouched = $this->newTouchedTimestamp();
+
+ $dbw = wfGetDB( DB_MASTER );
+ $dbw->update( 'user',
+ array( 'user_touched' => $dbw->timestamp( $newTouched )
),
+ array(
+ 'user_id' => $this->mId,
+ 'user_touched' => $dbw->timestamp( $oldTouched
) // CAS check
+ ),
+ __METHOD__
+ );
+ $success = ( $dbw->affectedRows() > 0 );
+
+ if ( $success ) {
+ $this->mTouched = $newTouched;
+ }
+
+ // Clears on failure too since that is desired if the cache is
stale
+ $this->clearSharedCache();
+
+ return $success;
}
/**
@@ -2356,6 +2404,17 @@
}
/**
+ * Get the user_touched timestamp field (time of last DB updates)
+ * @return string TS_MW Timestamp
+ * @since 1.26
+ */
+ protected function getDBTouched() {
+ $this->load();
+
+ return $this->mTouched;
+ }
+
+ /**
* @return Password
* @since 1.24
*/
diff --git a/tests/phpunit/includes/UserTest.php
b/tests/phpunit/includes/UserTest.php
index b74a7ea..370b5b2 100644
--- a/tests/phpunit/includes/UserTest.php
+++ b/tests/phpunit/includes/UserTest.php
@@ -425,4 +425,24 @@
$this->assertFalse( $user->isLoggedIn() );
$this->assertTrue( $user->isAnon() );
}
+
+ /**
+ * @covers User::checkAndSetTouched
+ */
+ public function testCheckAndSetTouched() {
+ $user = TestingAccessWrapper::newFromObject( User::newFromName(
'UTSysop' ) );
+ $this->assertTrue( $user->isLoggedIn() );
+
+ $touched = $user->getDBTouched();
+ $this->assertTrue(
+ $user->checkAndSetTouched(), "checkAndSetTouched()
succeded" );
+ $this->assertGreaterThan(
+ $touched, $user->getDBTouched(), "user_touched
increased with casOnTouched()" );
+
+ $touched = $user->getDBTouched();
+ $this->assertTrue(
+ $user->checkAndSetTouched(), "checkAndSetTouched()
succeded #2" );
+ $this->assertGreaterThan(
+ $touched, $user->getDBTouched(), "user_touched
increased with casOnTouched() #2" );
+ }
}
--
To view, visit https://gerrit.wikimedia.org/r/202589
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ib2cd0a2c72629fa4e13dcff4d2d6fbac8e690b32
Gerrit-PatchSet: 9
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Aaron Schulz <[email protected]>
Gerrit-Reviewer: Aaron Schulz <[email protected]>
Gerrit-Reviewer: Anomie <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits