97681eb76f224f0d229c05bbe787ebefb7f13797
[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 $this->assertArrayHasKey( 'lgtoken', $data[0]['login'] );
192 }
193
194 public function testBotPassword() {
195 global $wgServer, $wgSessionProviders;
196
197 if ( !isset( $wgServer ) ) {
198 $this->markTestIncomplete( 'This test needs $wgServer to be set in LocalSettings.php' );
199 }
200
201 $this->setMwGlobals( [
202 'wgSessionProviders' => array_merge( $wgSessionProviders, [
203 [
204 'class' => MediaWiki\Session\BotPasswordSessionProvider::class,
205 'args' => [ [ 'priority' => 40 ] ],
206 ]
207 ] ),
208 'wgEnableBotPasswords' => true,
209 'wgBotPasswordsDatabase' => false,
210 'wgCentralIdLookupProvider' => 'local',
211 'wgGrantPermissions' => [
212 'test' => [ 'read' => true ],
213 ],
214 ] );
215
216 // Make sure our session provider is present
217 $manager = TestingAccessWrapper::newFromObject( MediaWiki\Session\SessionManager::singleton() );
218 if ( !isset( $manager->sessionProviders[MediaWiki\Session\BotPasswordSessionProvider::class] ) ) {
219 $tmp = $manager->sessionProviders;
220 $manager->sessionProviders = null;
221 $manager->sessionProviders = $tmp + $manager->getProviders();
222 }
223 $this->assertNotNull(
224 MediaWiki\Session\SessionManager::singleton()->getProvider(
225 MediaWiki\Session\BotPasswordSessionProvider::class
226 ),
227 'sanity check'
228 );
229
230 $user = self::$users['sysop'];
231 $centralId = CentralIdLookup::factory()->centralIdFromLocalUser( $user->getUser() );
232 $this->assertNotEquals( 0, $centralId, 'sanity check' );
233
234 $password = 'ngfhmjm64hv0854493hsj5nncjud2clk';
235 $passwordFactory = new PasswordFactory();
236 $passwordFactory->init( RequestContext::getMain()->getConfig() );
237 // A is unsalted MD5 (thus fast) ... we don't care about security here, this is test only
238 $passwordHash = $passwordFactory->newFromPlaintext( $password );
239
240 $dbw = wfGetDB( DB_MASTER );
241 $dbw->insert(
242 'bot_passwords',
243 [
244 'bp_user' => $centralId,
245 'bp_app_id' => 'foo',
246 'bp_password' => $passwordHash->toString(),
247 'bp_token' => '',
248 'bp_restrictions' => MWRestrictions::newDefault()->toJson(),
249 'bp_grants' => '["test"]',
250 ],
251 __METHOD__
252 );
253
254 $lgName = $user->getUser()->getName() . BotPassword::getSeparator() . 'foo';
255
256 $ret = $this->doApiRequest( [
257 'action' => 'login',
258 'lgname' => $lgName,
259 'lgpassword' => $password,
260 ] );
261
262 $result = $ret[0];
263 $this->assertNotInternalType( 'bool', $result );
264 $this->assertNotInternalType( 'null', $result['login'] );
265
266 $a = $result['login']['result'];
267 $this->assertEquals( 'NeedToken', $a );
268 $token = $result['login']['token'];
269
270 $ret = $this->doApiRequest( [
271 'action' => 'login',
272 'lgtoken' => $token,
273 'lgname' => $lgName,
274 'lgpassword' => $password,
275 ], $ret[2] );
276
277 $result = $ret[0];
278 $this->assertNotInternalType( 'bool', $result );
279 $a = $result['login']['result'];
280
281 $this->assertEquals( 'Success', $a );
282 }
283
284 }