ea8c9ca5098f125b4819edce40226813ef70f4af
[lhc/web/wiklou.git] / tests / phpunit / includes / api / ApiLoginTest.php
1 <?php
2
3 /**
4 * @group API
5 * @group Database
6 * @group medium
7 *
8 * @covers ApiLogin
9 */
10 class ApiLoginTest extends ApiTestCase {
11
12 /**
13 * Test result of attempted login with an empty username
14 */
15 public function testApiLoginNoName() {
16 $session = [
17 'wsTokenSecrets' => [ 'login' => 'foobar' ],
18 ];
19 $data = $this->doApiRequest( [ 'action' => 'login',
20 'lgname' => '', 'lgpassword' => self::$users['sysop']->getPassword(),
21 'lgtoken' => (string)( new MediaWiki\Session\Token( 'foobar', '' ) )
22 ], $session );
23 $this->assertEquals( 'Failed', $data[0]['login']['result'] );
24 }
25
26 public function testApiLoginBadPass() {
27 global $wgServer;
28
29 $user = self::$users['sysop'];
30 $userName = $user->getUser()->getName();
31 $user->getUser()->logout();
32
33 if ( !isset( $wgServer ) ) {
34 $this->markTestIncomplete( 'This test needs $wgServer to be set in LocalSettings.php' );
35 }
36 $ret = $this->doApiRequest( [
37 "action" => "login",
38 "lgname" => $userName,
39 "lgpassword" => "bad",
40 ] );
41
42 $result = $ret[0];
43
44 $this->assertNotInternalType( "bool", $result );
45 $a = $result["login"]["result"];
46 $this->assertEquals( "NeedToken", $a );
47
48 $token = $result["login"]["token"];
49
50 $ret = $this->doApiRequest(
51 [
52 "action" => "login",
53 "lgtoken" => $token,
54 "lgname" => $userName,
55 "lgpassword" => "badnowayinhell",
56 ],
57 $ret[2]
58 );
59
60 $result = $ret[0];
61
62 $this->assertNotInternalType( "bool", $result );
63 $a = $result["login"]["result"];
64
65 $this->assertEquals( 'Failed', $a );
66 }
67
68 public function testApiLoginGoodPass() {
69 global $wgServer;
70
71 if ( !isset( $wgServer ) ) {
72 $this->markTestIncomplete( 'This test needs $wgServer to be set in LocalSettings.php' );
73 }
74
75 $user = self::$users['sysop'];
76 $userName = $user->getUser()->getName();
77 $password = $user->getPassword();
78 $user->getUser()->logout();
79
80 $ret = $this->doApiRequest( [
81 "action" => "login",
82 "lgname" => $userName,
83 "lgpassword" => $password,
84 ]
85 );
86
87 $result = $ret[0];
88 $this->assertNotInternalType( "bool", $result );
89 $this->assertNotInternalType( "null", $result["login"] );
90
91 $a = $result["login"]["result"];
92 $this->assertEquals( "NeedToken", $a );
93 $token = $result["login"]["token"];
94
95 $ret = $this->doApiRequest(
96 [
97 "action" => "login",
98 "lgtoken" => $token,
99 "lgname" => $userName,
100 "lgpassword" => $password,
101 ],
102 $ret[2]
103 );
104
105 $result = $ret[0];
106
107 $this->assertNotInternalType( "bool", $result );
108 $a = $result["login"]["result"];
109
110 $this->assertEquals( "Success", $a );
111 }
112
113 /**
114 * @group Broken
115 */
116 public function testApiLoginGotCookie() {
117 $this->markTestIncomplete( "The server can't do external HTTP requests, "
118 . "and the internal one won't give cookies" );
119
120 global $wgServer, $wgScriptPath;
121
122 if ( !isset( $wgServer ) ) {
123 $this->markTestIncomplete( 'This test needs $wgServer to be set in LocalSettings.php' );
124 }
125 $user = self::$users['sysop'];
126 $userName = $user->getUser()->getName();
127 $password = $user->getPassword();
128
129 $req = MWHttpRequest::factory( self::$apiUrl . "?action=login&format=xml",
130 [ "method" => "POST",
131 "postData" => [
132 "lgname" => $userName,
133 "lgpassword" => $password
134 ]
135 ],
136 __METHOD__
137 );
138 $req->execute();
139
140 libxml_use_internal_errors( true );
141 $sxe = simplexml_load_string( $req->getContent() );
142 $this->assertNotInternalType( "bool", $sxe );
143 $this->assertThat( $sxe, $this->isInstanceOf( "SimpleXMLElement" ) );
144 $this->assertNotInternalType( "null", $sxe->login[0] );
145
146 $a = $sxe->login[0]->attributes()->result[0];
147 $this->assertEquals( ' result="NeedToken"', $a->asXML() );
148 $token = (string)$sxe->login[0]->attributes()->token;
149
150 $req->setData( [
151 "lgtoken" => $token,
152 "lgname" => $userName,
153 "lgpassword" => $password ] );
154 $req->execute();
155
156 $cj = $req->getCookieJar();
157 $serverName = parse_url( $wgServer, PHP_URL_HOST );
158 $this->assertNotEquals( false, $serverName );
159 $serializedCookie = $cj->serializeToHttpRequest( $wgScriptPath, $serverName );
160 $this->assertNotEquals( '', $serializedCookie );
161 $this->assertRegExp(
162 '/_session=[^;]*; .*UserID=[0-9]*; .*UserName=' . $user->userName . '; .*Token=/',
163 $serializedCookie
164 );
165 }
166
167 public function testRunLogin() {
168 $user = self::$users['sysop'];
169 $userName = $user->getUser()->getName();
170 $password = $user->getPassword();
171
172 $data = $this->doApiRequest( [
173 'action' => 'login',
174 'lgname' => $userName,
175 'lgpassword' => $password ] );
176
177 $this->assertArrayHasKey( "login", $data[0] );
178 $this->assertArrayHasKey( "result", $data[0]['login'] );
179 $this->assertEquals( "NeedToken", $data[0]['login']['result'] );
180 $token = $data[0]['login']['token'];
181
182 $data = $this->doApiRequest( [
183 'action' => 'login',
184 "lgtoken" => $token,
185 "lgname" => $userName,
186 "lgpassword" => $password ], $data[2] );
187
188 $this->assertArrayHasKey( "login", $data[0] );
189 $this->assertArrayHasKey( "result", $data[0]['login'] );
190 $this->assertEquals( "Success", $data[0]['login']['result'] );
191 }
192
193 public function testBotPassword() {
194 global $wgServer, $wgSessionProviders;
195
196 if ( !isset( $wgServer ) ) {
197 $this->markTestIncomplete( 'This test needs $wgServer to be set in LocalSettings.php' );
198 }
199
200 $this->setMwGlobals( [
201 'wgSessionProviders' => array_merge( $wgSessionProviders, [
202 [
203 'class' => MediaWiki\Session\BotPasswordSessionProvider::class,
204 'args' => [ [ 'priority' => 40 ] ],
205 ]
206 ] ),
207 'wgEnableBotPasswords' => true,
208 'wgBotPasswordsDatabase' => false,
209 'wgCentralIdLookupProvider' => 'local',
210 'wgGrantPermissions' => [
211 'test' => [ 'read' => true ],
212 ],
213 ] );
214
215 // Make sure our session provider is present
216 $manager = TestingAccessWrapper::newFromObject( MediaWiki\Session\SessionManager::singleton() );
217 if ( !isset( $manager->sessionProviders[MediaWiki\Session\BotPasswordSessionProvider::class] ) ) {
218 $tmp = $manager->sessionProviders;
219 $manager->sessionProviders = null;
220 $manager->sessionProviders = $tmp + $manager->getProviders();
221 }
222 $this->assertNotNull(
223 MediaWiki\Session\SessionManager::singleton()->getProvider(
224 MediaWiki\Session\BotPasswordSessionProvider::class
225 ),
226 'sanity check'
227 );
228
229 $user = self::$users['sysop'];
230 $centralId = CentralIdLookup::factory()->centralIdFromLocalUser( $user->getUser() );
231 $this->assertNotEquals( 0, $centralId, 'sanity check' );
232
233 $password = 'ngfhmjm64hv0854493hsj5nncjud2clk';
234 $passwordFactory = new PasswordFactory();
235 $passwordFactory->init( RequestContext::getMain()->getConfig() );
236 // A is unsalted MD5 (thus fast) ... we don't care about security here, this is test only
237 $passwordHash = $passwordFactory->newFromPlaintext( $password );
238
239 $dbw = wfGetDB( DB_MASTER );
240 $dbw->insert(
241 'bot_passwords',
242 [
243 'bp_user' => $centralId,
244 'bp_app_id' => 'foo',
245 'bp_password' => $passwordHash->toString(),
246 'bp_token' => '',
247 'bp_restrictions' => MWRestrictions::newDefault()->toJson(),
248 'bp_grants' => '["test"]',
249 ],
250 __METHOD__
251 );
252
253 $lgName = $user->getUser()->getName() . BotPassword::getSeparator() . 'foo';
254
255 $ret = $this->doApiRequest( [
256 'action' => 'login',
257 'lgname' => $lgName,
258 'lgpassword' => $password,
259 ] );
260
261 $result = $ret[0];
262 $this->assertNotInternalType( 'bool', $result );
263 $this->assertNotInternalType( 'null', $result['login'] );
264
265 $a = $result['login']['result'];
266 $this->assertEquals( 'NeedToken', $a );
267 $token = $result['login']['token'];
268
269 $ret = $this->doApiRequest( [
270 'action' => 'login',
271 'lgtoken' => $token,
272 'lgname' => $lgName,
273 'lgpassword' => $password,
274 ], $ret[2] );
275
276 $result = $ret[0];
277 $this->assertNotInternalType( 'bool', $result );
278 $a = $result['login']['result'];
279
280 $this->assertEquals( 'Success', $a );
281 }
282
283 }