]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - tests/phpunit/includes/auth/AuthPluginPrimaryAuthenticationProviderTest.php
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.git] / tests / phpunit / includes / auth / AuthPluginPrimaryAuthenticationProviderTest.php
1 <?php
2
3 namespace MediaWiki\Auth;
4
5 /**
6  * @group AuthManager
7  * @covers MediaWiki\Auth\AuthPluginPrimaryAuthenticationProvider
8  */
9 class AuthPluginPrimaryAuthenticationProviderTest extends \MediaWikiTestCase {
10         public function testConstruction() {
11                 $plugin = new AuthManagerAuthPlugin();
12                 try {
13                         $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
14                         $this->fail( 'Expected exception not thrown' );
15                 } catch ( \InvalidArgumentException $ex ) {
16                         $this->assertSame(
17                                 'Trying to wrap AuthManagerAuthPlugin in AuthPluginPrimaryAuthenticationProvider ' .
18                                         'makes no sense.',
19                                 $ex->getMessage()
20                         );
21                 }
22
23                 $plugin = $this->createMock( 'AuthPlugin' );
24                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
25
26                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
27                 $this->assertEquals(
28                         [ new PasswordAuthenticationRequest ],
29                         $provider->getAuthenticationRequests( AuthManager::ACTION_LOGIN, [] )
30                 );
31
32                 $req = $this->createMock( PasswordAuthenticationRequest::class );
33                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin, get_class( $req ) );
34                 $this->assertEquals(
35                         [ $req ],
36                         $provider->getAuthenticationRequests( AuthManager::ACTION_LOGIN, [] )
37                 );
38
39                 $reqType = get_class( $this->createMock( AuthenticationRequest::class ) );
40                 try {
41                         $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin, $reqType );
42                         $this->fail( 'Expected exception not thrown' );
43                 } catch ( \InvalidArgumentException $ex ) {
44                         $this->assertSame(
45                                 "$reqType is not a MediaWiki\\Auth\\PasswordAuthenticationRequest",
46                                 $ex->getMessage()
47                         );
48                 }
49         }
50
51         public function testOnUserSaveSettings() {
52                 $user = \User::newFromName( 'UTSysop' );
53
54                 $plugin = $this->createMock( 'AuthPlugin' );
55                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
56                 $plugin->expects( $this->once() )->method( 'updateExternalDB' )
57                         ->with( $this->identicalTo( $user ) );
58                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
59
60                 \Hooks::run( 'UserSaveSettings', [ $user ] );
61         }
62
63         public function testOnUserGroupsChanged() {
64                 $user = \User::newFromName( 'UTSysop' );
65
66                 $plugin = $this->createMock( 'AuthPlugin' );
67                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
68                 $plugin->expects( $this->once() )->method( 'updateExternalDBGroups' )
69                         ->with(
70                                 $this->identicalTo( $user ),
71                                 $this->identicalTo( [ 'added' ] ),
72                                 $this->identicalTo( [ 'removed' ] )
73                         );
74                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
75
76                 \Hooks::run( 'UserGroupsChanged', [ $user, [ 'added' ], [ 'removed' ] ] );
77         }
78
79         public function testOnUserLoggedIn() {
80                 $user = \User::newFromName( 'UTSysop' );
81
82                 $plugin = $this->createMock( 'AuthPlugin' );
83                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
84                 $plugin->expects( $this->exactly( 2 ) )->method( 'updateUser' )
85                         ->with( $this->identicalTo( $user ) );
86                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
87                 \Hooks::run( 'UserLoggedIn', [ $user ] );
88
89                 $plugin = $this->createMock( 'AuthPlugin' );
90                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
91                 $plugin->expects( $this->once() )->method( 'updateUser' )
92                         ->will( $this->returnCallback( function ( &$user ) {
93                                 $user = \User::newFromName( 'UTSysop' );
94                         } ) );
95                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
96                 try {
97                         \Hooks::run( 'UserLoggedIn', [ $user ] );
98                         $this->fail( 'Expected exception not thrown' );
99                 } catch ( \UnexpectedValueException $ex ) {
100                         $this->assertSame(
101                                 get_class( $plugin ) . '::updateUser() tried to replace $user!',
102                                 $ex->getMessage()
103                         );
104                 }
105         }
106
107         public function testOnLocalUserCreated() {
108                 $user = \User::newFromName( 'UTSysop' );
109
110                 $plugin = $this->createMock( 'AuthPlugin' );
111                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
112                 $plugin->expects( $this->exactly( 2 ) )->method( 'initUser' )
113                         ->with( $this->identicalTo( $user ), $this->identicalTo( false ) );
114                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
115                 \Hooks::run( 'LocalUserCreated', [ $user, false ] );
116
117                 $plugin = $this->createMock( 'AuthPlugin' );
118                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
119                 $plugin->expects( $this->once() )->method( 'initUser' )
120                         ->will( $this->returnCallback( function ( &$user ) {
121                                 $user = \User::newFromName( 'UTSysop' );
122                         } ) );
123                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
124                 try {
125                         \Hooks::run( 'LocalUserCreated', [ $user, false ] );
126                         $this->fail( 'Expected exception not thrown' );
127                 } catch ( \UnexpectedValueException $ex ) {
128                         $this->assertSame(
129                                 get_class( $plugin ) . '::initUser() tried to replace $user!',
130                                 $ex->getMessage()
131                         );
132                 }
133         }
134
135         public function testGetUniqueId() {
136                 $plugin = $this->createMock( 'AuthPlugin' );
137                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
138                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
139                 $this->assertSame(
140                         'MediaWiki\\Auth\\AuthPluginPrimaryAuthenticationProvider:' . get_class( $plugin ),
141                         $provider->getUniqueId()
142                 );
143         }
144
145         /**
146          * @dataProvider provideGetAuthenticationRequests
147          * @param string $action
148          * @param array $response
149          * @param bool $allowPasswordChange
150          */
151         public function testGetAuthenticationRequests( $action, $response, $allowPasswordChange ) {
152                 $plugin = $this->createMock( 'AuthPlugin' );
153                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
154                 $plugin->expects( $this->any() )->method( 'allowPasswordChange' )
155                         ->will( $this->returnValue( $allowPasswordChange ) );
156                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
157                 $this->assertEquals( $response, $provider->getAuthenticationRequests( $action, [] ) );
158         }
159
160         public static function provideGetAuthenticationRequests() {
161                 $arr = [ new PasswordAuthenticationRequest() ];
162                 return [
163                         [ AuthManager::ACTION_LOGIN, $arr, true ],
164                         [ AuthManager::ACTION_LOGIN, $arr, false ],
165                         [ AuthManager::ACTION_CREATE, $arr, true ],
166                         [ AuthManager::ACTION_CREATE, $arr, false ],
167                         [ AuthManager::ACTION_LINK, [], true ],
168                         [ AuthManager::ACTION_LINK, [], false ],
169                         [ AuthManager::ACTION_CHANGE, $arr, true ],
170                         [ AuthManager::ACTION_CHANGE, [], false ],
171                         [ AuthManager::ACTION_REMOVE, $arr, true ],
172                         [ AuthManager::ACTION_REMOVE, [], false ],
173                 ];
174         }
175
176         public function testAuthentication() {
177                 $req = new PasswordAuthenticationRequest();
178                 $req->action = AuthManager::ACTION_LOGIN;
179                 $reqs = [ PasswordAuthenticationRequest::class => $req ];
180
181                 $plugin = $this->getMockBuilder( 'AuthPlugin' )
182                         ->setMethods( [ 'authenticate' ] )
183                         ->getMock();
184                 $plugin->expects( $this->never() )->method( 'authenticate' );
185                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
186
187                 $this->assertEquals(
188                         AuthenticationResponse::newAbstain(),
189                         $provider->beginPrimaryAuthentication( [] )
190                 );
191
192                 $req->username = 'foo';
193                 $req->password = null;
194                 $this->assertEquals(
195                         AuthenticationResponse::newAbstain(),
196                         $provider->beginPrimaryAuthentication( $reqs )
197                 );
198
199                 $req->username = null;
200                 $req->password = 'bar';
201                 $this->assertEquals(
202                         AuthenticationResponse::newAbstain(),
203                         $provider->beginPrimaryAuthentication( $reqs )
204                 );
205
206                 $req->username = 'foo';
207                 $req->password = 'bar';
208
209                 $plugin = $this->getMockBuilder( 'AuthPlugin' )
210                         ->setMethods( [ 'userExists', 'authenticate' ] )
211                         ->getMock();
212                 $plugin->expects( $this->once() )->method( 'userExists' )
213                         ->will( $this->returnValue( true ) );
214                 $plugin->expects( $this->once() )->method( 'authenticate' )
215                         ->with( $this->equalTo( 'Foo' ), $this->equalTo( 'bar' ) )
216                         ->will( $this->returnValue( true ) );
217                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
218                 $this->assertEquals(
219                         AuthenticationResponse::newPass( 'Foo', $req ),
220                         $provider->beginPrimaryAuthentication( $reqs )
221                 );
222
223                 $plugin = $this->getMockBuilder( 'AuthPlugin' )
224                         ->setMethods( [ 'userExists', 'authenticate' ] )
225                         ->getMock();
226                 $plugin->expects( $this->once() )->method( 'userExists' )
227                         ->will( $this->returnValue( false ) );
228                 $plugin->expects( $this->never() )->method( 'authenticate' );
229                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
230                 $this->assertEquals(
231                         AuthenticationResponse::newAbstain(),
232                         $provider->beginPrimaryAuthentication( $reqs )
233                 );
234
235                 $pluginUser = $this->getMockBuilder( 'AuthPluginUser' )
236                         ->setMethods( [ 'isLocked' ] )
237                         ->disableOriginalConstructor()
238                         ->getMock();
239                 $pluginUser->expects( $this->once() )->method( 'isLocked' )
240                         ->will( $this->returnValue( true ) );
241                 $plugin = $this->getMockBuilder( 'AuthPlugin' )
242                         ->setMethods( [ 'userExists', 'getUserInstance', 'authenticate' ] )
243                         ->getMock();
244                 $plugin->expects( $this->once() )->method( 'userExists' )
245                         ->will( $this->returnValue( true ) );
246                 $plugin->expects( $this->once() )->method( 'getUserInstance' )
247                         ->will( $this->returnValue( $pluginUser ) );
248                 $plugin->expects( $this->never() )->method( 'authenticate' );
249                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
250                 $this->assertEquals(
251                         AuthenticationResponse::newAbstain(),
252                         $provider->beginPrimaryAuthentication( $reqs )
253                 );
254
255                 $plugin = $this->getMockBuilder( 'AuthPlugin' )
256                         ->setMethods( [ 'userExists', 'authenticate' ] )
257                         ->getMock();
258                 $plugin->expects( $this->once() )->method( 'userExists' )
259                         ->will( $this->returnValue( true ) );
260                 $plugin->expects( $this->once() )->method( 'authenticate' )
261                         ->with( $this->equalTo( 'Foo' ), $this->equalTo( 'bar' ) )
262                         ->will( $this->returnValue( false ) );
263                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
264                 $this->assertEquals(
265                         AuthenticationResponse::newAbstain(),
266                         $provider->beginPrimaryAuthentication( $reqs )
267                 );
268
269                 $plugin = $this->getMockBuilder( 'AuthPlugin' )
270                         ->setMethods( [ 'userExists', 'authenticate', 'strict' ] )
271                         ->getMock();
272                 $plugin->expects( $this->once() )->method( 'userExists' )
273                         ->will( $this->returnValue( true ) );
274                 $plugin->expects( $this->once() )->method( 'authenticate' )
275                         ->with( $this->equalTo( 'Foo' ), $this->equalTo( 'bar' ) )
276                         ->will( $this->returnValue( false ) );
277                 $plugin->expects( $this->any() )->method( 'strict' )->will( $this->returnValue( true ) );
278                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
279                 $ret = $provider->beginPrimaryAuthentication( $reqs );
280                 $this->assertSame( AuthenticationResponse::FAIL, $ret->status );
281                 $this->assertSame( 'wrongpassword', $ret->message->getKey() );
282
283                 $plugin = $this->getMockBuilder( 'AuthPlugin' )
284                         ->setMethods( [ 'userExists', 'authenticate', 'strictUserAuth' ] )
285                         ->getMock();
286                 $plugin->expects( $this->once() )->method( 'userExists' )
287                         ->will( $this->returnValue( true ) );
288                 $plugin->expects( $this->once() )->method( 'authenticate' )
289                         ->with( $this->equalTo( 'Foo' ), $this->equalTo( 'bar' ) )
290                         ->will( $this->returnValue( false ) );
291                 $plugin->expects( $this->any() )->method( 'strictUserAuth' )
292                         ->with( $this->equalTo( 'Foo' ) )
293                         ->will( $this->returnValue( true ) );
294                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
295                 $ret = $provider->beginPrimaryAuthentication( $reqs );
296                 $this->assertSame( AuthenticationResponse::FAIL, $ret->status );
297                 $this->assertSame( 'wrongpassword', $ret->message->getKey() );
298
299                 $plugin = $this->getMockBuilder( 'AuthPlugin' )
300                         ->setMethods( [ 'domainList', 'validDomain', 'setDomain', 'userExists', 'authenticate' ] )
301                         ->getMock();
302                 $plugin->expects( $this->any() )->method( 'domainList' )
303                         ->will( $this->returnValue( [ 'Domain1', 'Domain2' ] ) );
304                 $plugin->expects( $this->any() )->method( 'validDomain' )
305                         ->will( $this->returnCallback( function ( $domain ) {
306                                 return in_array( $domain, [ 'Domain1', 'Domain2' ] );
307                         } ) );
308                 $plugin->expects( $this->once() )->method( 'setDomain' )
309                         ->with( $this->equalTo( 'Domain2' ) );
310                 $plugin->expects( $this->once() )->method( 'userExists' )
311                         ->will( $this->returnValue( true ) );
312                 $plugin->expects( $this->once() )->method( 'authenticate' )
313                         ->with( $this->equalTo( 'Foo' ), $this->equalTo( 'bar' ) )
314                         ->will( $this->returnValue( true ) );
315                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
316                 list( $req ) = $provider->getAuthenticationRequests( AuthManager::ACTION_LOGIN, [] );
317                 $req->username = 'foo';
318                 $req->password = 'bar';
319                 $req->domain = 'Domain2';
320                 $provider->beginPrimaryAuthentication( [ $req ] );
321         }
322
323         public function testTestUserExists() {
324                 $plugin = $this->createMock( 'AuthPlugin' );
325                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
326                 $plugin->expects( $this->once() )->method( 'userExists' )
327                         ->with( $this->equalTo( 'Foo' ) )
328                         ->will( $this->returnValue( true ) );
329                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
330
331                 $this->assertTrue( $provider->testUserExists( 'foo' ) );
332
333                 $plugin = $this->createMock( 'AuthPlugin' );
334                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
335                 $plugin->expects( $this->once() )->method( 'userExists' )
336                         ->with( $this->equalTo( 'Foo' ) )
337                         ->will( $this->returnValue( false ) );
338                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
339
340                 $this->assertFalse( $provider->testUserExists( 'foo' ) );
341         }
342
343         public function testTestUserCanAuthenticate() {
344                 $plugin = $this->createMock( 'AuthPlugin' );
345                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
346                 $plugin->expects( $this->once() )->method( 'userExists' )
347                         ->with( $this->equalTo( 'Foo' ) )
348                         ->will( $this->returnValue( false ) );
349                 $plugin->expects( $this->never() )->method( 'getUserInstance' );
350                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
351                 $this->assertFalse( $provider->testUserCanAuthenticate( 'foo' ) );
352
353                 $pluginUser = $this->getMockBuilder( 'AuthPluginUser' )
354                         ->disableOriginalConstructor()
355                         ->getMock();
356                 $pluginUser->expects( $this->once() )->method( 'isLocked' )
357                         ->will( $this->returnValue( true ) );
358                 $plugin = $this->createMock( 'AuthPlugin' );
359                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
360                 $plugin->expects( $this->once() )->method( 'userExists' )
361                         ->with( $this->equalTo( 'Foo' ) )
362                         ->will( $this->returnValue( true ) );
363                 $plugin->expects( $this->once() )->method( 'getUserInstance' )
364                         ->with( $this->callback( function ( $user ) {
365                                 $this->assertInstanceOf( 'User', $user );
366                                 $this->assertEquals( 'Foo', $user->getName() );
367                                 return true;
368                         } ) )
369                         ->will( $this->returnValue( $pluginUser ) );
370                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
371                 $this->assertFalse( $provider->testUserCanAuthenticate( 'foo' ) );
372
373                 $pluginUser = $this->getMockBuilder( 'AuthPluginUser' )
374                         ->disableOriginalConstructor()
375                         ->getMock();
376                 $pluginUser->expects( $this->once() )->method( 'isLocked' )
377                         ->will( $this->returnValue( false ) );
378                 $plugin = $this->createMock( 'AuthPlugin' );
379                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
380                 $plugin->expects( $this->once() )->method( 'userExists' )
381                         ->with( $this->equalTo( 'Foo' ) )
382                         ->will( $this->returnValue( true ) );
383                 $plugin->expects( $this->once() )->method( 'getUserInstance' )
384                         ->with( $this->callback( function ( $user ) {
385                                 $this->assertInstanceOf( 'User', $user );
386                                 $this->assertEquals( 'Foo', $user->getName() );
387                                 return true;
388                         } ) )
389                         ->will( $this->returnValue( $pluginUser ) );
390                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
391                 $this->assertTrue( $provider->testUserCanAuthenticate( 'foo' ) );
392         }
393
394         public function testProviderRevokeAccessForUser() {
395                 $plugin = $this->getMockBuilder( 'AuthPlugin' )
396                         ->setMethods( [ 'userExists', 'setPassword' ] )
397                         ->getMock();
398                 $plugin->expects( $this->once() )->method( 'userExists' )->willReturn( true );
399                 $plugin->expects( $this->once() )->method( 'setPassword' )
400                         ->with( $this->callback( function ( $u ) {
401                                 return $u instanceof \User && $u->getName() === 'Foo';
402                         } ), $this->identicalTo( null ) )
403                         ->willReturn( true );
404                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
405                 $provider->providerRevokeAccessForUser( 'foo' );
406
407                 $plugin = $this->getMockBuilder( 'AuthPlugin' )
408                         ->setMethods( [ 'domainList', 'userExists', 'setPassword' ] )
409                         ->getMock();
410                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [ 'D1', 'D2', 'D3' ] );
411                 $plugin->expects( $this->exactly( 3 ) )->method( 'userExists' )
412                         ->willReturnCallback( function () use ( $plugin ) {
413                                 return $plugin->getDomain() !== 'D2';
414                         } );
415                 $plugin->expects( $this->exactly( 2 ) )->method( 'setPassword' )
416                         ->with( $this->callback( function ( $u ) {
417                                 return $u instanceof \User && $u->getName() === 'Foo';
418                         } ), $this->identicalTo( null ) )
419                         ->willReturnCallback( function () use ( $plugin ) {
420                                 $this->assertNotEquals( 'D2', $plugin->getDomain() );
421                                 return $plugin->getDomain() !== 'D1';
422                         } );
423                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
424                 try {
425                         $provider->providerRevokeAccessForUser( 'foo' );
426                         $this->fail( 'Expected exception not thrown' );
427                 } catch ( \UnexpectedValueException $ex ) {
428                         $this->assertSame(
429                                 'AuthPlugin failed to reset password for Foo in the following domains: D1',
430                                 $ex->getMessage()
431                         );
432                 }
433         }
434
435         public function testProviderAllowsPropertyChange() {
436                 $plugin = $this->createMock( 'AuthPlugin' );
437                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
438                 $plugin->expects( $this->any() )->method( 'allowPropChange' )
439                         ->will( $this->returnCallback( function ( $prop ) {
440                                 return $prop === 'allow';
441                         } ) );
442                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
443
444                 $this->assertTrue( $provider->providerAllowsPropertyChange( 'allow' ) );
445                 $this->assertFalse( $provider->providerAllowsPropertyChange( 'deny' ) );
446         }
447
448         /**
449          * @dataProvider provideProviderAllowsAuthenticationDataChange
450          * @param string $type
451          * @param bool|null $allow
452          * @param StatusValue $expect
453          */
454         public function testProviderAllowsAuthenticationDataChange( $type, $allow, $expect ) {
455                 $domains = $type instanceof PasswordDomainAuthenticationRequest ? [ 'foo', 'bar' ] : [];
456                 $plugin = $this->createMock( 'AuthPlugin' );
457                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( $domains );
458                 $plugin->expects( $allow === null ? $this->never() : $this->once() )
459                         ->method( 'allowPasswordChange' )->will( $this->returnValue( $allow ) );
460                 $plugin->expects( $this->any() )->method( 'validDomain' )
461                         ->willReturnCallback( function ( $d ) use ( $domains ) {
462                                 return in_array( $d, $domains, true );
463                         } );
464                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
465
466                 if ( is_object( $type ) ) {
467                         $req = $type;
468                 } else {
469                         $req = $this->createMock( $type );
470                 }
471                 $req->action = AuthManager::ACTION_CHANGE;
472                 $req->username = 'UTSysop';
473                 $req->password = 'Pa$$w0Rd!!!';
474                 $req->retype = 'Pa$$w0Rd!!!';
475                 $this->assertEquals( $expect, $provider->providerAllowsAuthenticationDataChange( $req ) );
476         }
477
478         public static function provideProviderAllowsAuthenticationDataChange() {
479                 $domains = [ 'foo', 'bar' ];
480                 $reqNoDomain = new PasswordDomainAuthenticationRequest( $domains );
481                 $reqValidDomain = new PasswordDomainAuthenticationRequest( $domains );
482                 $reqValidDomain->domain = 'foo';
483                 $reqInvalidDomain = new PasswordDomainAuthenticationRequest( $domains );
484                 $reqInvalidDomain->domain = 'invalid';
485
486                 return [
487                         [ AuthenticationRequest::class, null, \StatusValue::newGood( 'ignored' ) ],
488                         [ new PasswordAuthenticationRequest, true, \StatusValue::newGood() ],
489                         [
490                                 new PasswordAuthenticationRequest,
491                                 false,
492                                 \StatusValue::newFatal( 'authmanager-authplugin-setpass-denied' )
493                         ],
494                         [ $reqNoDomain, true, \StatusValue::newGood( 'ignored' ) ],
495                         [ $reqValidDomain, true, \StatusValue::newGood() ],
496                         [
497                                 $reqInvalidDomain,
498                                 true,
499                                 \StatusValue::newFatal( 'authmanager-authplugin-setpass-bad-domain' )
500                         ],
501                 ];
502         }
503
504         public function testProviderChangeAuthenticationData() {
505                 $plugin = $this->createMock( 'AuthPlugin' );
506                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
507                 $plugin->expects( $this->never() )->method( 'setPassword' );
508                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
509                 $provider->providerChangeAuthenticationData(
510                         $this->createMock( AuthenticationRequest::class )
511                 );
512
513                 $req = new PasswordAuthenticationRequest();
514                 $req->action = AuthManager::ACTION_CHANGE;
515                 $req->username = 'foo';
516                 $req->password = 'bar';
517
518                 $plugin = $this->createMock( 'AuthPlugin' );
519                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
520                 $plugin->expects( $this->once() )->method( 'setPassword' )
521                         ->with( $this->callback( function ( $u ) {
522                                 return $u instanceof \User && $u->getName() === 'Foo';
523                         } ), $this->equalTo( 'bar' ) )
524                         ->will( $this->returnValue( true ) );
525                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
526                 $provider->providerChangeAuthenticationData( $req );
527
528                 $plugin = $this->createMock( 'AuthPlugin' );
529                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
530                 $plugin->expects( $this->once() )->method( 'setPassword' )
531                         ->with( $this->callback( function ( $u ) {
532                                 return $u instanceof \User && $u->getName() === 'Foo';
533                         } ), $this->equalTo( 'bar' ) )
534                         ->will( $this->returnValue( false ) );
535                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
536                 try {
537                         $provider->providerChangeAuthenticationData( $req );
538                         $this->fail( 'Expected exception not thrown' );
539                 } catch ( \ErrorPageError $e ) {
540                         $this->assertSame( 'authmanager-authplugin-setpass-failed-title', $e->title );
541                         $this->assertSame( 'authmanager-authplugin-setpass-failed-message', $e->msg );
542                 }
543
544                 $plugin = $this->createMock( 'AuthPlugin' );
545                 $plugin->expects( $this->any() )->method( 'domainList' )
546                         ->will( $this->returnValue( [ 'Domain1', 'Domain2' ] ) );
547                 $plugin->expects( $this->any() )->method( 'validDomain' )
548                         ->will( $this->returnCallback( function ( $domain ) {
549                                 return in_array( $domain, [ 'Domain1', 'Domain2' ] );
550                         } ) );
551                 $plugin->expects( $this->once() )->method( 'setDomain' )
552                         ->with( $this->equalTo( 'Domain2' ) );
553                 $plugin->expects( $this->once() )->method( 'setPassword' )
554                         ->with( $this->callback( function ( $u ) {
555                                 return $u instanceof \User && $u->getName() === 'Foo';
556                         } ), $this->equalTo( 'bar' ) )
557                         ->will( $this->returnValue( true ) );
558                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
559                 list( $req ) = $provider->getAuthenticationRequests( AuthManager::ACTION_CREATE, [] );
560                 $req->username = 'foo';
561                 $req->password = 'bar';
562                 $req->domain = 'Domain2';
563                 $provider->providerChangeAuthenticationData( $req );
564         }
565
566         /**
567          * @dataProvider provideAccountCreationType
568          * @param bool $can
569          * @param string $expect
570          */
571         public function testAccountCreationType( $can, $expect ) {
572                 $plugin = $this->createMock( 'AuthPlugin' );
573                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
574                 $plugin->expects( $this->once() )
575                         ->method( 'canCreateAccounts' )->will( $this->returnValue( $can ) );
576                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
577
578                 $this->assertSame( $expect, $provider->accountCreationType() );
579         }
580
581         public static function provideAccountCreationType() {
582                 return [
583                         [ true, PrimaryAuthenticationProvider::TYPE_CREATE ],
584                         [ false, PrimaryAuthenticationProvider::TYPE_NONE ],
585                 ];
586         }
587
588         public function testTestForAccountCreation() {
589                 $user = \User::newFromName( 'foo' );
590
591                 $plugin = $this->createMock( 'AuthPlugin' );
592                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
593                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
594                 $this->assertEquals(
595                         \StatusValue::newGood(),
596                         $provider->testForAccountCreation( $user, $user, [] )
597                 );
598         }
599
600         public function testAccountCreation() {
601                 $user = \User::newFromName( 'foo' );
602                 $user->setEmail( 'email' );
603                 $user->setRealName( 'realname' );
604
605                 $req = new PasswordAuthenticationRequest();
606                 $req->action = AuthManager::ACTION_CREATE;
607                 $reqs = [ PasswordAuthenticationRequest::class => $req ];
608
609                 $plugin = $this->createMock( 'AuthPlugin' );
610                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
611                 $plugin->expects( $this->any() )->method( 'canCreateAccounts' )
612                         ->will( $this->returnValue( false ) );
613                 $plugin->expects( $this->never() )->method( 'addUser' );
614                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
615                 try {
616                         $provider->beginPrimaryAccountCreation( $user, $user, [] );
617                         $this->fail( 'Expected exception was not thrown' );
618                 } catch ( \BadMethodCallException $ex ) {
619                         $this->assertSame(
620                                 'Shouldn\'t call this when accountCreationType() is NONE', $ex->getMessage()
621                         );
622                 }
623
624                 $plugin = $this->createMock( 'AuthPlugin' );
625                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
626                 $plugin->expects( $this->any() )->method( 'canCreateAccounts' )
627                         ->will( $this->returnValue( true ) );
628                 $plugin->expects( $this->never() )->method( 'addUser' );
629                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
630
631                 $this->assertEquals(
632                         AuthenticationResponse::newAbstain(),
633                         $provider->beginPrimaryAccountCreation( $user, $user, [] )
634                 );
635
636                 $req->username = 'foo';
637                 $req->password = null;
638                 $this->assertEquals(
639                         AuthenticationResponse::newAbstain(),
640                         $provider->beginPrimaryAccountCreation( $user, $user, $reqs )
641                 );
642
643                 $req->username = null;
644                 $req->password = 'bar';
645                 $this->assertEquals(
646                         AuthenticationResponse::newAbstain(),
647                         $provider->beginPrimaryAccountCreation( $user, $user, $reqs )
648                 );
649
650                 $req->username = 'foo';
651                 $req->password = 'bar';
652
653                 $plugin = $this->createMock( 'AuthPlugin' );
654                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
655                 $plugin->expects( $this->any() )->method( 'canCreateAccounts' )
656                         ->will( $this->returnValue( true ) );
657                 $plugin->expects( $this->once() )->method( 'addUser' )
658                         ->with(
659                                 $this->callback( function ( $u ) {
660                                         return $u instanceof \User && $u->getName() === 'Foo';
661                                 } ),
662                                 $this->equalTo( 'bar' ),
663                                 $this->equalTo( 'email' ),
664                                 $this->equalTo( 'realname' )
665                         )
666                         ->will( $this->returnValue( true ) );
667                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
668                 $this->assertEquals(
669                         AuthenticationResponse::newPass(),
670                         $provider->beginPrimaryAccountCreation( $user, $user, $reqs )
671                 );
672
673                 $plugin = $this->createMock( 'AuthPlugin' );
674                 $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
675                 $plugin->expects( $this->any() )->method( 'canCreateAccounts' )
676                         ->will( $this->returnValue( true ) );
677                 $plugin->expects( $this->once() )->method( 'addUser' )
678                         ->with(
679                                 $this->callback( function ( $u ) {
680                                         return $u instanceof \User && $u->getName() === 'Foo';
681                                 } ),
682                                 $this->equalTo( 'bar' ),
683                                 $this->equalTo( 'email' ),
684                                 $this->equalTo( 'realname' )
685                         )
686                         ->will( $this->returnValue( false ) );
687                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
688                 $ret = $provider->beginPrimaryAccountCreation( $user, $user, $reqs );
689                 $this->assertSame( AuthenticationResponse::FAIL, $ret->status );
690                 $this->assertSame( 'authmanager-authplugin-create-fail', $ret->message->getKey() );
691
692                 $plugin = $this->createMock( 'AuthPlugin' );
693                 $plugin->expects( $this->any() )->method( 'canCreateAccounts' )
694                         ->will( $this->returnValue( true ) );
695                 $plugin->expects( $this->any() )->method( 'domainList' )
696                         ->will( $this->returnValue( [ 'Domain1', 'Domain2' ] ) );
697                 $plugin->expects( $this->any() )->method( 'validDomain' )
698                         ->will( $this->returnCallback( function ( $domain ) {
699                                 return in_array( $domain, [ 'Domain1', 'Domain2' ] );
700                         } ) );
701                 $plugin->expects( $this->once() )->method( 'setDomain' )
702                         ->with( $this->equalTo( 'Domain2' ) );
703                 $plugin->expects( $this->once() )->method( 'addUser' )
704                         ->with( $this->callback( function ( $u ) {
705                                 return $u instanceof \User && $u->getName() === 'Foo';
706                         } ), $this->equalTo( 'bar' ) )
707                         ->will( $this->returnValue( true ) );
708                 $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
709                 list( $req ) = $provider->getAuthenticationRequests( AuthManager::ACTION_CREATE, [] );
710                 $req->username = 'foo';
711                 $req->password = 'bar';
712                 $req->domain = 'Domain2';
713                 $provider->beginPrimaryAccountCreation( $user, $user, [ $req ] );
714         }
715
716 }