3 namespace MediaWiki\Auth
;
7 * @covers MediaWiki\Auth\ResetPasswordSecondaryAuthenticationProvider
9 class ResetPasswordSecondaryAuthenticationProviderTest
extends \MediaWikiTestCase
{
11 * @dataProvider provideGetAuthenticationRequests
12 * @param string $action
13 * @param array $response
15 public function testGetAuthenticationRequests( $action, $response ) {
16 $provider = new ResetPasswordSecondaryAuthenticationProvider();
18 $this->assertEquals( $response, $provider->getAuthenticationRequests( $action, [] ) );
21 public static function provideGetAuthenticationRequests() {
23 [ AuthManager
::ACTION_LOGIN
, [] ],
24 [ AuthManager
::ACTION_CREATE
, [] ],
25 [ AuthManager
::ACTION_LINK
, [] ],
26 [ AuthManager
::ACTION_CHANGE
, [] ],
27 [ AuthManager
::ACTION_REMOVE
, [] ],
31 public function testBasics() {
32 $user = \User
::newFromName( 'UTSysop' );
35 $reqs = [ new \stdClass
];
37 $mb = $this->getMockBuilder( ResetPasswordSecondaryAuthenticationProvider
::class )
38 ->setMethods( [ 'tryReset' ] );
41 'beginSecondaryAuthentication' => [ $user, $reqs ],
42 'continueSecondaryAuthentication' => [ $user, $reqs ],
43 'beginSecondaryAccountCreation' => [ $user, $user2, $reqs ],
44 'continueSecondaryAccountCreation' => [ $user, $user2, $reqs ],
46 foreach ( $methods as $method => $args ) {
47 $mock = $mb->getMock();
48 $mock->expects( $this->once() )->method( 'tryReset' )
49 ->with( $this->identicalTo( $user ), $this->identicalTo( $reqs ) )
50 ->will( $this->returnValue( $obj ) );
51 $this->assertSame( $obj, call_user_func_array( [ $mock, $method ], $args ) );
55 public function testTryReset() {
56 $user = \User
::newFromName( 'UTSysop' );
58 $provider = $this->getMockBuilder(
59 ResetPasswordSecondaryAuthenticationProvider
::class
62 'providerAllowsAuthenticationDataChange', 'providerChangeAuthenticationData'
65 $provider->expects( $this->any() )->method( 'providerAllowsAuthenticationDataChange' )
66 ->will( $this->returnCallback( function ( $req ) {
67 $this->assertSame( 'UTSysop', $req->username
);
70 $provider->expects( $this->any() )->method( 'providerChangeAuthenticationData' )
71 ->will( $this->returnCallback( function ( $req ) {
72 $this->assertSame( 'UTSysop', $req->username
);
75 $config = new \
HashConfig( [
76 'AuthManagerConfig' => [
80 [ 'factory' => function () use ( $provider ) {
86 $manager = new AuthManager( new \FauxRequest
, $config );
87 $provider->setManager( $manager );
88 $provider = \TestingAccessWrapper
::newFromObject( $provider );
90 $msg = wfMessage( 'foo' );
91 $skipReq = new ButtonAuthenticationRequest(
93 wfMessage( 'authprovider-resetpass-skip-label' ),
94 wfMessage( 'authprovider-resetpass-skip-help' )
96 $passReq = new PasswordAuthenticationRequest();
97 $passReq->action
= AuthManager
::ACTION_CHANGE
;
98 $passReq->password
= 'Foo';
99 $passReq->retype
= 'Bar';
100 $passReq->allow
= \StatusValue
::newGood();
101 $passReq->done
= false;
103 $passReq2 = $this->getMockBuilder( PasswordAuthenticationRequest
::class )
104 ->enableProxyingToOriginalMethods()
106 $passReq2->action
= AuthManager
::ACTION_CHANGE
;
107 $passReq2->password
= 'Foo';
108 $passReq2->retype
= 'Foo';
109 $passReq2->allow
= \StatusValue
::newGood();
110 $passReq2->done
= false;
112 $passReq3 = new PasswordAuthenticationRequest();
113 $passReq3->action
= AuthManager
::ACTION_LOGIN
;
114 $passReq3->password
= 'Foo';
115 $passReq3->retype
= 'Foo';
116 $passReq3->allow
= \StatusValue
::newGood();
117 $passReq3->done
= false;
120 AuthenticationResponse
::newAbstain(),
121 $provider->tryReset( $user, [] )
124 $manager->setAuthenticationSessionData( 'reset-pass', 'foo' );
126 $provider->tryReset( $user, [] );
127 $this->fail( 'Expected exception not thrown' );
128 } catch ( \UnexpectedValueException
$ex ) {
129 $this->assertSame( 'reset-pass is not valid', $ex->getMessage() );
132 $manager->setAuthenticationSessionData( 'reset-pass', (object)[] );
134 $provider->tryReset( $user, [] );
135 $this->fail( 'Expected exception not thrown' );
136 } catch ( \UnexpectedValueException
$ex ) {
137 $this->assertSame( 'reset-pass msg is missing', $ex->getMessage() );
140 $manager->setAuthenticationSessionData( 'reset-pass', [
144 $provider->tryReset( $user, [] );
145 $this->fail( 'Expected exception not thrown' );
146 } catch ( \UnexpectedValueException
$ex ) {
147 $this->assertSame( 'reset-pass msg is not valid', $ex->getMessage() );
150 $manager->setAuthenticationSessionData( 'reset-pass', [
154 $provider->tryReset( $user, [] );
155 $this->fail( 'Expected exception not thrown' );
156 } catch ( \UnexpectedValueException
$ex ) {
157 $this->assertSame( 'reset-pass hard is missing', $ex->getMessage() );
160 $manager->setAuthenticationSessionData( 'reset-pass', [
166 $provider->tryReset( $user, [] );
167 $this->fail( 'Expected exception not thrown' );
168 } catch ( \UnexpectedValueException
$ex ) {
169 $this->assertSame( 'reset-pass req is not valid', $ex->getMessage() );
172 $manager->setAuthenticationSessionData( 'reset-pass', [
178 $provider->tryReset( $user, [ $passReq ] );
179 $this->fail( 'Expected exception not thrown' );
180 } catch ( \UnexpectedValueException
$ex ) {
181 $this->assertSame( 'reset-pass req is not valid', $ex->getMessage() );
184 $manager->setAuthenticationSessionData( 'reset-pass', [
188 $res = $provider->tryReset( $user, [] );
189 $this->assertInstanceOf( AuthenticationResponse
::class, $res );
190 $this->assertSame( AuthenticationResponse
::UI
, $res->status
);
191 $this->assertEquals( $msg, $res->message
);
192 $this->assertCount( 1, $res->neededRequests
);
193 $this->assertInstanceOf(
194 PasswordAuthenticationRequest
::class,
195 $res->neededRequests
[0]
197 $this->assertNotNull( $manager->getAuthenticationSessionData( 'reset-pass' ) );
198 $this->assertFalse( $passReq->done
);
200 $manager->setAuthenticationSessionData( 'reset-pass', [
205 $res = $provider->tryReset( $user, [] );
206 $this->assertInstanceOf( AuthenticationResponse
::class, $res );
207 $this->assertSame( AuthenticationResponse
::UI
, $res->status
);
208 $this->assertEquals( $msg, $res->message
);
209 $this->assertCount( 2, $res->neededRequests
);
210 $expectedPassReq = clone $passReq;
211 $expectedPassReq->required
= AuthenticationRequest
::OPTIONAL
;
212 $this->assertEquals( $expectedPassReq, $res->neededRequests
[0] );
213 $this->assertEquals( $skipReq, $res->neededRequests
[1] );
214 $this->assertNotNull( $manager->getAuthenticationSessionData( 'reset-pass' ) );
215 $this->assertFalse( $passReq->done
);
217 $passReq->retype
= 'Bad';
218 $manager->setAuthenticationSessionData( 'reset-pass', [
223 $res = $provider->tryReset( $user, [ $skipReq, $passReq ] );
224 $this->assertEquals( AuthenticationResponse
::newPass(), $res );
225 $this->assertNull( $manager->getAuthenticationSessionData( 'reset-pass' ) );
226 $this->assertFalse( $passReq->done
);
228 $passReq->retype
= 'Bad';
229 $manager->setAuthenticationSessionData( 'reset-pass', [
233 $res = $provider->tryReset( $user, [ $skipReq, $passReq ] );
234 $this->assertSame( AuthenticationResponse
::UI
, $res->status
);
235 $this->assertSame( 'badretype', $res->message
->getKey() );
236 $this->assertCount( 1, $res->neededRequests
);
237 $this->assertInstanceOf(
238 PasswordAuthenticationRequest
::class,
239 $res->neededRequests
[0]
241 $this->assertNotNull( $manager->getAuthenticationSessionData( 'reset-pass' ) );
242 $this->assertFalse( $passReq->done
);
244 $manager->setAuthenticationSessionData( 'reset-pass', [
248 $res = $provider->tryReset( $user, [ $skipReq, $passReq3 ] );
249 $this->assertSame( AuthenticationResponse
::UI
, $res->status
);
250 $this->assertEquals( $msg, $res->message
);
251 $this->assertCount( 1, $res->neededRequests
);
252 $this->assertInstanceOf(
253 PasswordAuthenticationRequest
::class,
254 $res->neededRequests
[0]
256 $this->assertNotNull( $manager->getAuthenticationSessionData( 'reset-pass' ) );
257 $this->assertFalse( $passReq->done
);
259 $passReq->retype
= $passReq->password
;
260 $passReq->allow
= \StatusValue
::newFatal( 'arbitrary-fail' );
261 $res = $provider->tryReset( $user, [ $skipReq, $passReq ] );
262 $this->assertSame( AuthenticationResponse
::UI
, $res->status
);
263 $this->assertSame( 'arbitrary-fail', $res->message
->getKey() );
264 $this->assertCount( 1, $res->neededRequests
);
265 $this->assertInstanceOf(
266 PasswordAuthenticationRequest
::class,
267 $res->neededRequests
[0]
269 $this->assertNotNull( $manager->getAuthenticationSessionData( 'reset-pass' ) );
270 $this->assertFalse( $passReq->done
);
272 $passReq->allow
= \StatusValue
::newGood();
273 $res = $provider->tryReset( $user, [ $skipReq, $passReq ] );
274 $this->assertEquals( AuthenticationResponse
::newPass(), $res );
275 $this->assertNull( $manager->getAuthenticationSessionData( 'reset-pass' ) );
276 $this->assertTrue( $passReq->done
);
278 $manager->setAuthenticationSessionData( 'reset-pass', [
283 $res = $provider->tryReset( $user, [ $passReq2 ] );
284 $this->assertEquals( AuthenticationResponse
::newPass(), $res );
285 $this->assertNull( $manager->getAuthenticationSessionData( 'reset-pass' ) );
286 $this->assertTrue( $passReq2->done
);
288 $passReq->done
= false;
289 $passReq2->done
= false;
290 $manager->setAuthenticationSessionData( 'reset-pass', [
295 $res = $provider->tryReset( $user, [ $passReq ] );
296 $this->assertInstanceOf( AuthenticationResponse
::class, $res );
297 $this->assertSame( AuthenticationResponse
::UI
, $res->status
);
298 $this->assertEquals( $msg, $res->message
);
299 $this->assertCount( 2, $res->neededRequests
);
300 $expectedPassReq = clone $passReq2;
301 $expectedPassReq->required
= AuthenticationRequest
::OPTIONAL
;
302 $this->assertEquals( $expectedPassReq, $res->neededRequests
[0] );
303 $this->assertEquals( $skipReq, $res->neededRequests
[1] );
304 $this->assertNotNull( $manager->getAuthenticationSessionData( 'reset-pass' ) );
305 $this->assertFalse( $passReq->done
);
306 $this->assertFalse( $passReq2->done
);