Merge "Give TestCase::checkHasDiff3 a better name"
[lhc/web/wiklou.git] / includes / session / SessionManager.php
index 0e45468..6b221fd 100644 (file)
@@ -55,7 +55,10 @@ final class SessionManager implements SessionManagerInterface {
        private $config;
 
        /** @var BagOStuff|null */
-       private $store;
+       private $tempStore;
+
+       /** @var BagOStuff|null */
+       private $permStore;
 
        /** @var SessionProvider[] */
        private $sessionProviders = null;
@@ -159,16 +162,17 @@ final class SessionManager implements SessionManagerInterface {
                        $this->setLogger( \MediaWiki\Logger\LoggerFactory::getInstance( 'session' ) );
                }
 
+               $this->tempStore = new \HashBagOStuff;
                if ( isset( $options['store'] ) ) {
                        if ( !$options['store'] instanceof BagOStuff ) {
                                throw new \InvalidArgumentException(
                                        '$options[\'store\'] must be an instance of BagOStuff'
                                );
                        }
-                       $this->store = $options['store'];
+                       $this->permStore = $options['store'];
                } else {
-                       $this->store = \ObjectCache::getInstance( $this->config->get( 'SessionCacheType' ) );
-                       $this->store->setLogger( $this->logger );
+                       $this->permStore = \ObjectCache::getInstance( $this->config->get( 'SessionCacheType' ) );
+                       $this->permStore->setLogger( $this->logger );
                }
 
                register_shutdown_function( array( $this, 'shutdown' ) );
@@ -178,15 +182,6 @@ final class SessionManager implements SessionManagerInterface {
                $this->logger = $logger;
        }
 
-       public function getPersistedSessionId( WebRequest $request ) {
-               $info = $this->getSessionInfoForRequest( $request );
-               if ( $info && $info->wasPersisted() ) {
-                       return $info->getId();
-               } else {
-                       return null;
-               }
-       }
-
        public function getSessionForRequest( WebRequest $request ) {
                $info = $this->getSessionInfoForRequest( $request );
 
@@ -211,7 +206,14 @@ final class SessionManager implements SessionManagerInterface {
                // Test this here to provide a better log message for the common case
                // of "no such ID"
                $key = wfMemcKey( 'MWSession', $id );
-               if ( is_array( $this->store->get( $key ) ) ) {
+               $existing = $this->tempStore->get( $key );
+               if ( $existing === false ) {
+                       $existing = $this->permStore->get( $key );
+                       if ( $existing !== false ) {
+                               $this->tempStore->set( $key, $existing );
+                       }
+               }
+               if ( is_array( $existing ) ) {
                        $info = new SessionInfo( SessionInfo::MIN_PRIORITY, array( 'id' => $id, 'idIsSafe' => true ) );
                        if ( $this->loadSessionInfoFromStore( $info, $request ) ) {
                                $session = $this->getSessionFromInfo( $info, $request );
@@ -249,7 +251,14 @@ final class SessionManager implements SessionManagerInterface {
                        }
 
                        $key = wfMemcKey( 'MWSession', $id );
-                       if ( is_array( $this->store->get( $key ) ) ) {
+                       $existing = $this->tempStore->get( $key );
+                       if ( $existing === false ) {
+                               $existing = $this->permStore->get( $key );
+                               if ( $existing !== false ) {
+                                       $this->tempStore->set( $key, $existing );
+                               }
+                       }
+                       if ( is_array( $existing ) ) {
                                throw new \InvalidArgumentException( 'Session ID already exists' );
                        }
                }
@@ -496,6 +505,16 @@ final class SessionManager implements SessionManagerInterface {
                \Hooks::run( 'AuthPluginAutoCreate', array( $user ) );
                \Hooks::run( 'LocalUserCreated', array( $user, true ) );
 
+               # Notify AuthPlugin too
+               $tmpUser = $user;
+               $wgAuth->initUser( $tmpUser, true );
+               if ( $tmpUser !== $user ) {
+                       $logger->warning( __METHOD__ . ': ' .
+                               get_class( $wgAuth ) . '::initUser() replaced the user object' );
+               }
+
+               $user->saveSettings();
+
                # Update user count
                \DeferredUpdates::addUpdate( new \SiteStatsUpdate( 0, 0, 0, 0, 1 ) );
 
@@ -519,8 +538,8 @@ final class SessionManager implements SessionManagerInterface {
 
                // Reset the user's token to kill existing sessions
                $user = User::newFromName( $username );
-               if ( $user && $user->getToken() ) {
-                       $user->setToken( true );
+               if ( $user && $user->getToken( false ) ) {
+                       $user->setToken();
                        $user->saveSettings();
                }
 
@@ -659,7 +678,13 @@ final class SessionManager implements SessionManagerInterface {
         */
        private function loadSessionInfoFromStore( SessionInfo &$info, WebRequest $request ) {
                $key = wfMemcKey( 'MWSession', $info->getId() );
-               $blob = $this->store->get( $key );
+               $blob = $this->tempStore->get( $key );
+               if ( $blob === false ) {
+                       $blob = $this->permStore->get( $key );
+                       if ( $blob !== false ) {
+                               $this->tempStore->set( $key, $blob );
+                       }
+               }
 
                $newParams = array();
 
@@ -667,7 +692,8 @@ final class SessionManager implements SessionManagerInterface {
                        // Sanity check: blob must be an array, if it's saved at all
                        if ( !is_array( $blob ) ) {
                                $this->logger->warning( "Session $info: Bad data" );
-                               $this->store->delete( $key );
+                               $this->tempStore->delete( $key );
+                               $this->permStore->delete( $key );
                                return false;
                        }
 
@@ -676,7 +702,8 @@ final class SessionManager implements SessionManagerInterface {
                                !isset( $blob['metadata'] ) || !is_array( $blob['metadata'] )
                        ) {
                                $this->logger->warning( "Session $info: Bad data structure" );
-                               $this->store->delete( $key );
+                               $this->tempStore->delete( $key );
+                               $this->permStore->delete( $key );
                                return false;
                        }
 
@@ -691,7 +718,8 @@ final class SessionManager implements SessionManagerInterface {
                                !array_key_exists( 'provider', $metadata )
                        ) {
                                $this->logger->warning( "Session $info: Bad metadata" );
-                               $this->store->delete( $key );
+                               $this->tempStore->delete( $key );
+                               $this->permStore->delete( $key );
                                return false;
                        }
 
@@ -701,7 +729,8 @@ final class SessionManager implements SessionManagerInterface {
                                $newParams['provider'] = $provider = $this->getProvider( $metadata['provider'] );
                                if ( !$provider ) {
                                        $this->logger->warning( "Session $info: Unknown provider, " . $metadata['provider'] );
-                                       $this->store->delete( $key );
+                                       $this->tempStore->delete( $key );
+                                       $this->permStore->delete( $key );
                                        return false;
                                }
                        } elseif ( $metadata['provider'] !== (string)$provider ) {
@@ -800,6 +829,9 @@ final class SessionManager implements SessionManagerInterface {
                        if ( !empty( $metadata['forceHTTPS'] ) && !$info->forceHTTPS() ) {
                                $newParams['forceHTTPS'] = true;
                        }
+                       if ( !empty( $metadata['persisted'] ) && !$info->wasPersisted() ) {
+                               $newParams['persisted'] = true;
+                       }
 
                        if ( !$info->isIdSafe() ) {
                                $newParams['idIsSafe'] = true;
@@ -889,7 +921,8 @@ final class SessionManager implements SessionManagerInterface {
                        $backend = new SessionBackend(
                                $this->allSessionIds[$id],
                                $info,
-                               $this->store,
+                               $this->tempStore,
+                               $this->permStore,
                                $this->logger,
                                $this->config->get( 'ObjectCacheSessionExpiry' )
                        );
@@ -966,7 +999,9 @@ final class SessionManager implements SessionManagerInterface {
                do {
                        $id = wfBaseConvert( \MWCryptRand::generateHex( 40 ), 16, 32, 32 );
                        $key = wfMemcKey( 'MWSession', $id );
-               } while ( isset( $this->allSessionIds[$id] ) || is_array( $this->store->get( $key ) ) );
+               } while ( isset( $this->allSessionIds[$id] ) ||
+                       is_array( $this->tempStore->get( $key ) ) || is_array( $this->permStore->get( $key ) )
+               );
                return $id;
        }
 
@@ -976,7 +1011,7 @@ final class SessionManager implements SessionManagerInterface {
         * @param PHPSessionHandler $handler
         */
        public function setupPHPSessionHandler( PHPSessionHandler $handler ) {
-               $handler->setManager( $this, $this->store, $this->logger );
+               $handler->setManager( $this, $this->permStore, $this->logger );
        }
 
        /**