From: Brad Jorsch Date: Tue, 10 May 2016 20:40:46 +0000 (-0400) Subject: Add SessionManager::invalidateSessionsForUser X-Git-Tag: 1.31.0-rc.0~7024^2 X-Git-Url: https://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/banques/?a=commitdiff_plain;h=3e618de36377403ab0f853101c0d88c33e27ae21;p=lhc%2Fweb%2Fwiklou.git Add SessionManager::invalidateSessionsForUser Most of the time calling User::setToken() is enough, but CentralAuth needs to be able to call CentralAuthUser::resetAuthToken() on command. Change-Id: Iad2ae914a81481f040e047b550f3fd3437277626 --- diff --git a/includes/AuthPlugin.php b/includes/AuthPlugin.php index 6449d371cc..add587674f 100644 --- a/includes/AuthPlugin.php +++ b/includes/AuthPlugin.php @@ -352,6 +352,9 @@ class AuthPluginUser { return false; } + /** + * @deprecated since 1.28, use SessionManager::invalidateSessionForUser() instead. + */ public function resetAuthToken() { # Override this! return true; diff --git a/includes/session/SessionManager.php b/includes/session/SessionManager.php index 6c17de5ef2..4320e205d2 100644 --- a/includes/session/SessionManager.php +++ b/includes/session/SessionManager.php @@ -301,6 +301,19 @@ final class SessionManager implements SessionManagerInterface { return $this->getSessionFromInfo( $infos[0], $request ); } + public function invalidateSessionsForUser( User $user ) { + global $wgAuth; + + $user->setToken(); + $user->saveSettings(); + + $wgAuth->getUserInstance( $user )->resetAuthToken(); + + foreach ( $this->getProviders() as $provider ) { + $provider->invalidateSessionsForUser( $user ); + } + } + public function getVaryHeaders() { // @codeCoverageIgnoreStart if ( defined( 'MW_NO_SESSION' ) && MW_NO_SESSION !== 'warn' ) { diff --git a/includes/session/SessionManagerInterface.php b/includes/session/SessionManagerInterface.php index b3e28fe127..d4e52c7a16 100644 --- a/includes/session/SessionManagerInterface.php +++ b/includes/session/SessionManagerInterface.php @@ -24,6 +24,7 @@ namespace MediaWiki\Session; use Psr\Log\LoggerAwareInterface; +use User; use WebRequest; /** @@ -72,6 +73,17 @@ interface SessionManagerInterface extends LoggerAwareInterface { */ public function getEmptySession( WebRequest $request = null ); + /** + * Invalidate sessions for a user + * + * After calling this, existing sessions should be invalid. For mutable + * session providers, this generally means the user has to log in again; + * for immutable providers, it generally means the loss of session data. + * + * @param User $user + */ + public function invalidateSessionsForUser( User $user ); + /** * Return the HTTP headers that need varying on. * diff --git a/includes/session/SessionProvider.php b/includes/session/SessionProvider.php index 3cd065d837..995af24c52 100644 --- a/includes/session/SessionProvider.php +++ b/includes/session/SessionProvider.php @@ -27,6 +27,7 @@ use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerInterface; use Config; use Language; +use User; use WebRequest; /** @@ -358,6 +359,19 @@ abstract class SessionProvider implements SessionProviderInterface, LoggerAwareI } } + /** + * Invalidate existing sessions for a user + * + * If the provider has its own equivalent of CookieSessionProvider's Token + * cookie (and doesn't use User::getToken() to implement it), it should + * reset whatever token it does use here. + * + * @protected For use by \MediaWiki\Session\SessionManager only + * @param User $user; + */ + public function invalidateSessionsForUser( User $user ) { + } + /** * Return the HTTP headers that need varying on. * diff --git a/includes/specials/SpecialUserlogin.php b/includes/specials/SpecialUserlogin.php index a77c79eb09..45315a79af 100644 --- a/includes/specials/SpecialUserlogin.php +++ b/includes/specials/SpecialUserlogin.php @@ -699,7 +699,7 @@ class LoginForm extends SpecialPage { $u->setEmail( $this->mEmail ); $u->setRealName( $this->mRealName ); - $u->setToken(); + SessionManager::singleton()->invalidateSessionsForUser( $u ); Hooks::run( 'LocalUserCreated', [ $u, $autocreate ] ); $oldUser = $u; diff --git a/includes/user/User.php b/includes/user/User.php index ee617a2caf..c78829bc99 100644 --- a/includes/user/User.php +++ b/includes/user/User.php @@ -2489,9 +2489,9 @@ class User implements IDBAccessObject { throw new PasswordError( wfMessage( 'externaldberror' )->text() ); } - $this->setToken(); $this->setOption( 'watchlisttoken', false ); $this->setPasswordInternal( $str ); + SessionManager::singleton()->invalidateSessionsForUser( $this ); return true; } @@ -2508,9 +2508,9 @@ class User implements IDBAccessObject { global $wgAuth; if ( $wgAuth->allowSetLocalPassword() ) { - $this->setToken(); $this->setOption( 'watchlisttoken', false ); $this->setPasswordInternal( $str ); + SessionManager::singleton()->invalidateSessionsForUser( $this ); } } diff --git a/tests/phpunit/includes/session/SessionManagerTest.php b/tests/phpunit/includes/session/SessionManagerTest.php index d04d7ec46d..2dee8bc7f5 100644 --- a/tests/phpunit/includes/session/SessionManagerTest.php +++ b/tests/phpunit/includes/session/SessionManagerTest.php @@ -642,6 +642,35 @@ class SessionManagerTest extends MediaWikiTestCase { } } + public function testInvalidateSessionsForUser() { + $user = User::newFromName( 'UTSysop' ); + $manager = $this->getManager(); + + $providerBuilder = $this->getMockBuilder( 'DummySessionProvider' ) + ->setMethods( [ 'invalidateSessionsForUser', '__toString' ] ); + + $provider1 = $providerBuilder->getMock(); + $provider1->expects( $this->once() )->method( 'invalidateSessionsForUser' ) + ->with( $this->identicalTo( $user ) ); + $provider1->expects( $this->any() )->method( '__toString' ) + ->will( $this->returnValue( 'MockProvider1' ) ); + + $provider2 = $providerBuilder->getMock(); + $provider2->expects( $this->once() )->method( 'invalidateSessionsForUser' ) + ->with( $this->identicalTo( $user ) ); + $provider2->expects( $this->any() )->method( '__toString' ) + ->will( $this->returnValue( 'MockProvider2' ) ); + + $this->config->set( 'SessionProviders', [ + $this->objectCacheDef( $provider1 ), + $this->objectCacheDef( $provider2 ), + ] ); + + $oldToken = $user->getToken( true ); + $manager->invalidateSessionsForUser( $user ); + $this->assertNotEquals( $oldToken, $user->getToken() ); + } + public function testGetVaryHeaders() { $manager = $this->getManager(); diff --git a/tests/phpunit/includes/session/SessionProviderTest.php b/tests/phpunit/includes/session/SessionProviderTest.php index 18b1efd460..f80baf2fa6 100644 --- a/tests/phpunit/includes/session/SessionProviderTest.php +++ b/tests/phpunit/includes/session/SessionProviderTest.php @@ -27,6 +27,8 @@ class SessionProviderTest extends MediaWikiTestCase { $this->assertSame( $manager, $priv->manager ); $this->assertSame( $manager, $provider->getManager() ); + $provider->invalidateSessionsForUser( new \User ); + $this->assertSame( [], $provider->getVaryHeaders() ); $this->assertSame( [], $provider->getVaryCookies() ); $this->assertSame( null, $provider->suggestLoginUsername( new \FauxRequest ) );