Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
59.26% |
32 / 54 |
|
42.86% |
3 / 7 |
CRAP | |
0.00% |
0 / 1 |
ApiQueryTokens | |
59.26% |
32 / 54 |
|
42.86% |
3 / 7 |
21.74 | |
0.00% |
0 / 1 |
execute | |
88.89% |
16 / 18 |
|
0.00% |
0 / 1 |
4.02 | |||
getTokenTypeSalts | |
18.75% |
3 / 16 |
|
0.00% |
0 / 1 |
4.15 | |||
getToken | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
getAllowedParams | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
1 | |||
getExamplesMessages | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
isReadMode | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getHelpUrls | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * Module to fetch tokens via action=query&meta=tokens |
4 | * |
5 | * Copyright © 2014 Wikimedia Foundation and contributors |
6 | * |
7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by |
9 | * the Free Software Foundation; either version 2 of the License, or |
10 | * (at your option) any later version. |
11 | * |
12 | * This program is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU General Public License along |
18 | * with this program; if not, write to the Free Software Foundation, Inc., |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
20 | * http://www.gnu.org/copyleft/gpl.html |
21 | * |
22 | * @file |
23 | * @since 1.24 |
24 | */ |
25 | |
26 | use MediaWiki\Api\ApiHookRunner; |
27 | use MediaWiki\MediaWikiServices; |
28 | use MediaWiki\User\User; |
29 | use Wikimedia\ParamValidator\ParamValidator; |
30 | |
31 | /** |
32 | * Module to fetch tokens via action=query&meta=tokens |
33 | * |
34 | * @ingroup API |
35 | * @since 1.24 |
36 | */ |
37 | class ApiQueryTokens extends ApiQueryBase { |
38 | |
39 | public function execute() { |
40 | $params = $this->extractRequestParams(); |
41 | |
42 | if ( $this->lacksSameOriginSecurity() ) { |
43 | $this->addWarning( [ 'apiwarn-tokens-origin' ] ); |
44 | return; |
45 | } |
46 | |
47 | $user = $this->getUser(); |
48 | $session = $this->getRequest()->getSession(); |
49 | $salts = self::getTokenTypeSalts(); |
50 | |
51 | $done = []; |
52 | $path = [ 'query', $this->getModuleName() ]; |
53 | $this->getResult()->addArrayType( $path, 'assoc' ); |
54 | |
55 | foreach ( $params['type'] as $type ) { |
56 | $token = self::getToken( $user, $session, $salts[$type] )->toString(); |
57 | $fit = $this->getResult()->addValue( $path, $type . 'token', $token ); |
58 | |
59 | if ( !$fit ) { |
60 | // Abuse type as a query-continue parameter and set it to all unprocessed types |
61 | $this->setContinueEnumParameter( 'type', |
62 | array_diff( $params['type'], $done ) ); |
63 | break; |
64 | } |
65 | $done[] = $type; |
66 | } |
67 | } |
68 | |
69 | /** |
70 | * Get the salts for known token types |
71 | * @return (string|array)[] Returning a string will use that as the salt |
72 | * for User::getEditTokenObject() to fetch the token, which will give a |
73 | * LoggedOutEditToken (always "+\\") for anonymous users. Returning an |
74 | * array will use it as parameters to MediaWiki\Session\Session::getToken(), |
75 | * which will always return a full token even for anonymous users. |
76 | */ |
77 | public static function getTokenTypeSalts() { |
78 | static $salts = null; |
79 | if ( !$salts ) { |
80 | $salts = [ |
81 | 'csrf' => '', |
82 | 'watch' => 'watch', |
83 | 'patrol' => 'patrol', |
84 | 'rollback' => 'rollback', |
85 | 'userrights' => 'userrights', |
86 | 'login' => [ '', 'login' ], |
87 | 'createaccount' => [ '', 'createaccount' ], |
88 | ]; |
89 | $hookContainer = MediaWikiServices::getInstance()->getHookContainer(); |
90 | $hookRunner = new ApiHookRunner( $hookContainer ); |
91 | $hookRunner->onApiQueryTokensRegisterTypes( $salts ); |
92 | ksort( $salts ); |
93 | } |
94 | |
95 | return $salts; |
96 | } |
97 | |
98 | /** |
99 | * Get a token from a salt |
100 | * @param User $user |
101 | * @param MediaWiki\Session\Session $session |
102 | * @param string|array $salt A string will be used as the salt for |
103 | * User::getEditTokenObject() to fetch the token, which will give a |
104 | * LoggedOutEditToken (always "+\\") for anonymous users. An array will |
105 | * be used as parameters to MediaWiki\Session\Session::getToken(), which |
106 | * will always return a full token even for anonymous users. An array will |
107 | * also persist the session. |
108 | * @return MediaWiki\Session\Token |
109 | */ |
110 | public static function getToken( User $user, MediaWiki\Session\Session $session, $salt ) { |
111 | if ( is_array( $salt ) ) { |
112 | $session->persist(); |
113 | return $session->getToken( ...$salt ); |
114 | } else { |
115 | return $user->getEditTokenObject( $salt, $session->getRequest() ); |
116 | } |
117 | } |
118 | |
119 | public function getAllowedParams() { |
120 | return [ |
121 | 'type' => [ |
122 | ParamValidator::PARAM_DEFAULT => 'csrf', |
123 | ParamValidator::PARAM_ISMULTI => true, |
124 | ParamValidator::PARAM_TYPE => array_keys( self::getTokenTypeSalts() ), |
125 | ParamValidator::PARAM_ALL => true, |
126 | ], |
127 | ]; |
128 | } |
129 | |
130 | protected function getExamplesMessages() { |
131 | return [ |
132 | 'action=query&meta=tokens' |
133 | => 'apihelp-query+tokens-example-simple', |
134 | 'action=query&meta=tokens&type=watch|patrol' |
135 | => 'apihelp-query+tokens-example-types', |
136 | ]; |
137 | } |
138 | |
139 | public function isReadMode() { |
140 | // So login tokens can be fetched on private wikis |
141 | return false; |
142 | } |
143 | |
144 | public function getHelpUrls() { |
145 | return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Tokens'; |
146 | } |
147 | } |