Refactor ApiTestCase to get token from ApiQueryTokens
authorAryeh Gregor <ayg@aryeh.name>
Wed, 28 Mar 2018 12:32:19 +0000 (15:32 +0300)
committerAryeh Gregor <ayg@aryeh.name>
Tue, 10 Apr 2018 17:45:32 +0000 (20:45 +0300)
Depends-On: I9375bc5f40268fd681a2d447c66a03f40b23390a
Change-Id: Ia21a974f2b463afc9324182137b95c80db86a6aa

tests/phpunit/includes/api/ApiEditPageTest.php
tests/phpunit/includes/api/ApiTestCase.php

index 9486f88..4790f6b 100644 (file)
@@ -290,7 +290,7 @@ class ApiEditPageTest extends ApiTestCase {
                        'basetimestamp' => $baseTime,
                        'section' => 'new',
                        'redirect' => true,
-               ], null, self::$users['sysop']->getUser() );
+               ] );
 
                $this->assertSame( 'Success', $re['edit']['result'],
                        "no problems expected when following redirect" );
@@ -336,7 +336,7 @@ class ApiEditPageTest extends ApiTestCase {
                                'text' => 'nix bar!',
                                'basetimestamp' => $baseTime,
                                'redirect' => true,
-                       ], null, self::$users['sysop']->getUser() );
+                       ] );
 
                        $this->fail( 'redirect-appendonly error expected' );
                } catch ( ApiUsageException $ex ) {
@@ -372,7 +372,7 @@ class ApiEditPageTest extends ApiTestCase {
                                'title' => $name,
                                'text' => 'nix bar!',
                                'basetimestamp' => $baseTime,
-                       ], null, self::$users['sysop']->getUser() );
+                       ] );
 
                        $this->fail( 'edit conflict expected' );
                } catch ( ApiUsageException $ex ) {
@@ -411,7 +411,7 @@ class ApiEditPageTest extends ApiTestCase {
                        'text' => 'nix bar!',
                        'basetimestamp' => $baseTime,
                        'section' => 'new',
-               ], null, self::$users['sysop']->getUser() );
+               ] );
 
                $this->assertSame( 'Success', $re['edit']['result'],
                        "no edit conflict expected here" );
@@ -458,7 +458,7 @@ class ApiEditPageTest extends ApiTestCase {
                        'text' => 'nix bar!',
                        'section' => 'new',
                        'redirect' => true,
-               ], null, self::$users['sysop']->getUser() );
+               ] );
 
                $this->assertSame( 'Success', $re['edit']['result'],
                        "no edit conflict expected here" );
@@ -529,6 +529,7 @@ class ApiEditPageTest extends ApiTestCase {
                $name = 'Help:' . __FUNCTION__;
                $uploader = self::$users['uploader']->getUser();
                $sysop = self::$users['sysop']->getUser();
+
                $apiResult = $this->doApiRequestWithToken( [
                        'action' => 'edit',
                        'title' => $name,
@@ -1528,21 +1529,14 @@ class ApiEditPageTest extends ApiTestCase {
        public function testCreateImageRedirectAnon() {
                $name = 'File:' . ucfirst( __FUNCTION__ );
 
-               // @todo When ApiTestCase supports anonymous users, this exception
-               // should no longer be thrown, and the test can then be updated to test
-               // for the actual expected behavior.
                $this->setExpectedException( ApiUsageException::class,
-                       'Invalid CSRF token.' );
-
-               $this->doApiRequestWithToken( [
-                       'action' => 'logout',
-               ] );
+                       "Anonymous users can't create image redirects." );
 
                $this->doApiRequestWithToken( [
                        'action' => 'edit',
                        'title' => $name,
                        'text' => '#REDIRECT [[File:Other file.png]]',
-               ] );
+               ], null, new User() );
        }
 
        public function testCreateImageRedirectLoggedIn() {
@@ -1581,21 +1575,16 @@ class ApiEditPageTest extends ApiTestCase {
        public function testProhibitedAnonymousEdit() {
                $name = 'Help:' . ucfirst( __FUNCTION__ );
 
-               // @todo See comment in testCreateImageRedirectAnon
                $this->setExpectedException( ApiUsageException::class,
-                       'Invalid CSRF token.' );
-               $this->setMwGlobals( 'wgRevokePermissions',
-                       [ '*' => [ 'edit' => true ] ] );
+                       'The action you have requested is limited to users in the group: ' );
 
-               $this->doApiRequestWithToken( [
-                       'action' => 'logout',
-               ] );
+               $this->setMwGlobals( 'wgRevokePermissions', [ '*' => [ 'edit' => true ] ] );
 
                $this->doApiRequestWithToken( [
                        'action' => 'edit',
                        'title' => $name,
                        'text' => 'Some text',
-               ] );
+               ], null, new User() );
        }
 
        public function testProhibitedChangeContentModel() {
index f1ff947..8e53b55 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use MediaWiki\Session\SessionManager;
+
 abstract class ApiTestCase extends MediaWikiLangTestCase {
        protected static $apiUrl;
 
@@ -67,11 +69,13 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
         * @param array|null $session
         * @param bool $appendModule
         * @param User|null $user
+        * @param string|null $tokenType Set to a string like 'csrf' to send an
+        *   appropriate token
         *
         * @return array
         */
        protected function doApiRequest( array $params, array $session = null,
-               $appendModule = false, User $user = null
+               $appendModule = false, User $user = null, $tokenType = null
        ) {
                global $wgRequest, $wgUser;
 
@@ -80,12 +84,26 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
                        $session = $wgRequest->getSessionArray();
                }
 
+               $sessionObj = SessionManager::singleton()->getEmptySession();
+
+               if ( $session !== null ) {
+                       foreach ( $session as $key => $value ) {
+                               $sessionObj->set( $key, $value );
+                       }
+               }
+
                // set up global environment
                if ( $user ) {
                        $wgUser = $user;
                }
 
-               $wgRequest = new FauxRequest( $params, true, $session );
+               if ( $tokenType !== null ) {
+                       $params['token'] = ApiQueryTokens::getToken(
+                               $wgUser, $sessionObj, ApiQueryTokens::getTokenTypeSalts()[$tokenType]
+                       )->toString();
+               }
+
+               $wgRequest = new FauxRequest( $params, true, $sessionObj );
                RequestContext::getMain()->setRequest( $wgRequest );
                RequestContext::getMain()->setUser( $wgUser );
                MediaWiki\Auth\AuthManager::resetCache();
@@ -113,40 +131,19 @@ abstract class ApiTestCase extends MediaWikiLangTestCase {
        }
 
        /**
-        * Add an edit token to the API request
-        * This is cheating a bit -- we grab a token in the correct format and then
-        * add it to the pseudo-session and to the request, without actually
-        * requesting a "real" edit token.
+        * Convenience function to access the token parameter of doApiRequest()
+        * more succinctly.
         *
         * @param array $params Key-value API params
         * @param array|null $session Session array
         * @param User|null $user A User object for the context
+        * @param string $tokenType Which token type to pass
         * @return array Result of the API call
-        * @throws Exception In case wsToken is not set in the session
         */
        protected function doApiRequestWithToken( array $params, array $session = null,
-               User $user = null
+               User $user = null, $tokenType = 'csrf'
        ) {
-               global $wgRequest;
-
-               if ( $session === null ) {
-                       $session = $wgRequest->getSessionArray();
-               }
-
-               if ( isset( $session['wsToken'] ) && $session['wsToken'] ) {
-                       // @todo Why does this directly mess with the session? Fix that.
-                       // add edit token to fake session
-                       $session['wsTokenSecrets']['default'] = $session['wsToken'];
-                       // add token to request parameters
-                       $timestamp = wfTimestamp();
-                       $params['token'] = hash_hmac( 'md5', $timestamp, $session['wsToken'] ) .
-                               dechex( $timestamp ) .
-                               MediaWiki\Session\Token::SUFFIX;
-
-                       return $this->doApiRequest( $params, $session, false, $user );
-               } else {
-                       throw new Exception( "Session token not available" );
-               }
+               return $this->doApiRequest( $params, $session, false, $user, $tokenType );
        }
 
        protected function doLogin( $testUser = 'sysop' ) {