From: Brad Jorsch Date: Fri, 14 Feb 2020 20:22:36 +0000 (-0500) Subject: API: Fix fetching login token from action=query&meta=tokens on private wikis X-Git-Tag: 1.34.1~6 X-Git-Url: http://git.cyclocoop.org/data/%7B%7B%20url_for%28%27static%27%2C%20filename=%27js/%40%20%27info_date_publication_anterieure%27%20=%3E%20%27Previously%20published%20on:%27%2C%20%27info_date_referencement%27%20=%3E%20%27THIS%20SITE%20REFERENCED%20ON:%27%2C%20%27info_derniere_etape%27%20=%3E%20%27Done%21%27%2C-%27info_derniers_articles_publies%27%20=%3E%20%27Your%20most%20recently%20published%20articles%27%2C-%27info_desactiver_messagerie_personnelle%27%20=%3E%20%27You%20can%20enable%20or%20disable%20your%20personal%20messaging%20on%20this%20site.%27%2C%20%27info_descriptif%27%20=%3E%20%27Description:%27%2C%20%27info_desinstaller_plugin%27%20=%3E%20%27%20deactivates%20the%20plugin%20and%20deletes%20the%20data%27%2C%20%27info_discussion_cours%27%20=%3E%20%27Current%20discussions%27%2C%40%40%20-332%2C7%20%20284%2C6%20%40%40%20Do%20not%20submit%20this%20import%20request.%3Cp%3EFor%20more%20information%2C%20please%20see%20%3Ca%20href=?a=commitdiff_plain;h=5e55aeed717707bdf095bdea7ec74b5aeeea3127;p=lhc%2Fweb%2Fwiklou.git API: Fix fetching login token from action=query&meta=tokens on private wikis Accidentally broken by I991809acf. Also added a test that should hopefully prevent this from accidentally being broken again. Bug: T245149 Change-Id: Ia7985397db50efe8af81f643f2a0a89d0ece179e (cherry picked from commit e0f3a29349ffd8a3be14cec164c1e0f719e0e74b) --- diff --git a/includes/api/ApiQuery.php b/includes/api/ApiQuery.php index a7ff729e84..9e937f5e04 100644 --- a/includes/api/ApiQuery.php +++ b/includes/api/ApiQuery.php @@ -509,15 +509,14 @@ class ApiQuery extends ApiBase { // parameters either. We do allow the 'rawcontinue' and 'indexpageids' // parameters since frameworks might add these unconditionally and they // can't expose anything here. + $allowedParams = [ 'rawcontinue' => 1, 'indexpageids' => 1 ]; $this->mParams = $this->extractRequestParams(); - $params = array_filter( - array_diff_key( - $this->mParams + $this->getPageSet()->extractRequestParams(), - [ 'rawcontinue' => 1, 'indexpageids' => 1 ] - ) - ); - if ( array_keys( $params ) !== [ 'meta' ] ) { - return true; + $request = $this->getRequest(); + foreach ( $this->mParams + $this->getPageSet()->extractRequestParams() as $param => $value ) { + $needed = $param === 'meta'; + if ( !isset( $allowedParams[$param] ) && $request->getCheck( $param ) !== $needed ) { + return true; + } } // Ask each module if it requires read mode. Any true => this returns diff --git a/tests/phpunit/includes/api/query/ApiQueryTest.php b/tests/phpunit/includes/api/query/ApiQueryTest.php index 20bd8557d0..bdbd64ce7e 100644 --- a/tests/phpunit/includes/api/query/ApiQueryTest.php +++ b/tests/phpunit/includes/api/query/ApiQueryTest.php @@ -172,4 +172,48 @@ class ApiQueryTest extends ApiTestCase { // This response field contains an XML document even if no pages were exported $this->assertNotContains( $title->getPrefixedText(), $data[0]['query']['export'] ); } + + public function testIsReadMode() { + $api = new ApiMain( + new FauxRequest( [ 'action' => 'query', 'meta' => 'tokens', 'type' => 'login' ] ) + ); + $queryApi = new ApiQuery( $api, 'query' ); + $this->assertFalse( $queryApi->isReadMode(), + 'isReadMode() => false when meta=tokens is the only module' ); + + $api = new ApiMain( new FauxRequest( [ + 'action' => 'query', 'meta' => 'tokens', 'type' => 'login', 'rawcontinue' => 1, + 'indexpageids' => 1 + ] ) + ); + $queryApi = new ApiQuery( $api, 'query' ); + $this->assertFalse( $queryApi->isReadMode(), + 'rawcontinue and indexpageids are also allowed' ); + + $api = new ApiMain( + new FauxRequest( [ 'action' => 'query', 'meta' => 'tokens|siteinfo', 'type' => 'login' ] ) + ); + $queryApi = new ApiQuery( $api, 'query' ); + $this->assertTrue( $queryApi->isReadMode(), + 'isReadMode() => true when other meta modules are present' ); + + $api = new ApiMain( new FauxRequest( [ + 'action' => 'query', 'meta' => 'tokens', 'type' => 'login', 'list' => 'allpages' + ] ) ); + $queryApi = new ApiQuery( $api, 'query' ); + $this->assertTrue( $queryApi->isReadMode(), + 'isReadMode() => true when other modules are present' ); + + $api = new ApiMain( new FauxRequest( [ + 'action' => 'query', 'meta' => 'tokens', 'type' => 'login', 'titles' => 'Foo' + ] ) ); + $queryApi = new ApiQuery( $api, 'query' ); + $this->assertTrue( $queryApi->isReadMode(), + 'isReadMode() => true when other ApiQuery parameters are present' ); + + $api = new ApiMain( new FauxRequest( [ 'action' => 'query' ] ) ); + $queryApi = new ApiQuery( $api, 'query' ); + $this->assertTrue( $queryApi->isReadMode(), + 'isReadMode() => true when no modules are requested' ); + } }