MediaWiki  master
AuthPluginPrimaryAuthenticationProviderTest.php
Go to the documentation of this file.
1 <?php
2 
3 namespace MediaWiki\Auth;
4 
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::class );
24  $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
25 
26  $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
27  $this->assertEquals(
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::class );
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::class );
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' ], false, false, [], [] ] );
77  }
78 
79  public function testOnUserLoggedIn() {
80  $user = \User::newFromName( 'UTSysop' );
81 
82  $plugin = $this->createMock( \AuthPlugin::class );
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::class );
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::class );
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::class );
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::class );
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 
151  public function testGetAuthenticationRequests( $action, $response, $allowPasswordChange ) {
152  $plugin = $this->createMock( \AuthPlugin::class );
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 ],
169  [ AuthManager::ACTION_CHANGE, $arr, true ],
171  [ AuthManager::ACTION_REMOVE, $arr, true ],
173  ];
174  }
175 
176  public function testAuthentication() {
180 
181  $plugin = $this->getMockBuilder( \AuthPlugin::class )
182  ->setMethods( [ 'authenticate' ] )
183  ->getMock();
184  $plugin->expects( $this->never() )->method( 'authenticate' );
185  $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
186 
187  $this->assertEquals(
189  $provider->beginPrimaryAuthentication( [] )
190  );
191 
192  $req->username = 'foo';
193  $req->password = null;
194  $this->assertEquals(
196  $provider->beginPrimaryAuthentication( $reqs )
197  );
198 
199  $req->username = null;
200  $req->password = 'bar';
201  $this->assertEquals(
203  $provider->beginPrimaryAuthentication( $reqs )
204  );
205 
206  $req->username = 'foo';
207  $req->password = 'bar';
208 
209  $plugin = $this->getMockBuilder( \AuthPlugin::class )
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(
220  $provider->beginPrimaryAuthentication( $reqs )
221  );
222 
223  $plugin = $this->getMockBuilder( \AuthPlugin::class )
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(
232  $provider->beginPrimaryAuthentication( $reqs )
233  );
234 
235  $pluginUser = $this->getMockBuilder( \AuthPluginUser::class )
236  ->setMethods( [ 'isLocked' ] )
237  ->disableOriginalConstructor()
238  ->getMock();
239  $pluginUser->expects( $this->once() )->method( 'isLocked' )
240  ->will( $this->returnValue( true ) );
241  $plugin = $this->getMockBuilder( \AuthPlugin::class )
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(
252  $provider->beginPrimaryAuthentication( $reqs )
253  );
254 
255  $plugin = $this->getMockBuilder( \AuthPlugin::class )
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(
266  $provider->beginPrimaryAuthentication( $reqs )
267  );
268 
269  $plugin = $this->getMockBuilder( \AuthPlugin::class )
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::class )
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::class )
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::class );
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::class );
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::class );
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::class )
354  ->disableOriginalConstructor()
355  ->getMock();
356  $pluginUser->expects( $this->once() )->method( 'isLocked' )
357  ->will( $this->returnValue( true ) );
358  $plugin = $this->createMock( \AuthPlugin::class );
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::class, $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::class )
374  ->disableOriginalConstructor()
375  ->getMock();
376  $pluginUser->expects( $this->once() )->method( 'isLocked' )
377  ->will( $this->returnValue( false ) );
378  $plugin = $this->createMock( \AuthPlugin::class );
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::class, $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 
395  $plugin = $this->getMockBuilder( \AuthPlugin::class )
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::class )
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 
436  $plugin = $this->createMock( \AuthPlugin::class );
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 
454  public function testProviderAllowsAuthenticationDataChange( $type, $allow, $expect ) {
455  $domains = $type instanceof PasswordDomainAuthenticationRequest ? [ 'foo', 'bar' ] : [];
456  $plugin = $this->createMock( \AuthPlugin::class );
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  }
472  $req->username = 'UTSysop';
473  $req->password = 'Pa$$w0Rd!!!';
474  $req->retype = 'Pa$$w0Rd!!!';
475  $this->assertEquals( $expect, $provider->providerAllowsAuthenticationDataChange( $req ) );
476  }
477 
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' ) ],
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 
505  $plugin = $this->createMock( \AuthPlugin::class );
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 
515  $req->username = 'foo';
516  $req->password = 'bar';
517 
518  $plugin = $this->createMock( \AuthPlugin::class );
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::class );
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::class );
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 
571  public function testAccountCreationType( $can, $expect ) {
572  $plugin = $this->createMock( \AuthPlugin::class );
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 [
585  ];
586  }
587 
588  public function testTestForAccountCreation() {
589  $user = \User::newFromName( 'foo' );
590 
591  $plugin = $this->createMock( \AuthPlugin::class );
592  $plugin->expects( $this->any() )->method( 'domainList' )->willReturn( [] );
593  $provider = new AuthPluginPrimaryAuthenticationProvider( $plugin );
594  $this->assertEquals(
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 
608 
609  $plugin = $this->createMock( \AuthPlugin::class );
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::class );
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(
633  $provider->beginPrimaryAccountCreation( $user, $user, [] )
634  );
635 
636  $req->username = 'foo';
637  $req->password = null;
638  $this->assertEquals(
640  $provider->beginPrimaryAccountCreation( $user, $user, $reqs )
641  );
642 
643  $req->username = null;
644  $req->password = 'bar';
645  $this->assertEquals(
647  $provider->beginPrimaryAccountCreation( $user, $user, $reqs )
648  );
649 
650  $req->username = 'foo';
651  $req->password = 'bar';
652 
653  $plugin = $this->createMock( \AuthPlugin::class );
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(
670  $provider->beginPrimaryAccountCreation( $user, $user, $reqs )
671  );
672 
673  $plugin = $this->createMock( \AuthPlugin::class );
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::class );
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 }
This is a value object for authentication requests with a username, password, and domain...
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition: deferred.txt:11
processing should stop and the error should be shown to the user * false
Definition: hooks.txt:187
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses & $ret
Definition: hooks.txt:1996
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:2173
string $action
Cache what action this request is.
Definition: MediaWiki.php:48
AuthManager \MediaWiki\Auth\AuthPluginPrimaryAuthenticationProvider.
this hook is for auditing only $response
Definition: hooks.txt:785
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return true
Definition: hooks.txt:1996
static newFatal( $message)
Factory function for fatal errors.
Definition: StatusValue.php:68
testGetAuthenticationRequests( $action, $response, $allowPasswordChange)
provideGetAuthenticationRequests
Backwards-compatibility wrapper for AuthManager via $wgAuth.
const FAIL
Indicates that the authentication failed.
Primary authentication provider wrapper for AuthPlugin.
An error page which can definitely be safely rendered using the OutputPage.
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:81
const ACTION_CHANGE
Change a user&#39;s credentials.
testProviderAllowsAuthenticationDataChange( $type, $allow, $expect)
provideProviderAllowsAuthenticationDataChange
const TYPE_NONE
Provider cannot create or link to accounts.
const ACTION_LINK
Link an existing user to a third-party account.
Definition: AuthManager.php:95
This is a value object for authentication requests with a username and password.
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
this hook is for auditing only $req
Definition: hooks.txt:990
you have access to all of the normal MediaWiki so you can get a DB use the etc For full docs on the Maintenance class
Definition: maintenance.txt:52
const ACTION_REMOVE
Remove a user&#39;s credentials.
msg( $key, $fallback)
Get a message from i18n.
Definition: MWException.php:75
const ACTION_CREATE
Create a new user.
Definition: AuthManager.php:90
</td >< td > &</td >< td > t want your writing to be edited mercilessly and redistributed at will
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition: User.php:585
const ACTION_LOGIN
Log in with an existing (not necessarily local) user.
Definition: AuthManager.php:85
return true to allow those checks to and false if checking is done & $user
Definition: hooks.txt:1487
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200