6 use Wikimedia\TestingAccessWrapper;
29 if ( !$this->config ) {
30 $this->config = new \HashConfig();
37 if ( !$this->manager ) {
42 ->setMethods( [
'checkPasswordValidity' ] )
43 ->setConstructorArgs( [ [
'loginOnly' => $loginOnly ] ] )
46 $provider->expects( $this->
any() )->method(
'checkPasswordValidity' )
47 ->will( $this->returnCallback(
function () {
50 $provider->setConfig(
$config );
51 $provider->setLogger(
new \Psr\Log\NullLogger() );
52 $provider->setManager( $this->manager );
59 $userName =
$user->getName();
60 $lowerInitialUserName = mb_strtolower( $userName[0] ) . substr( $userName, 1 );
66 $provider->accountCreationType()
69 $this->assertTrue( $provider->testUserExists( $userName ) );
70 $this->assertTrue( $provider->testUserExists( $lowerInitialUserName ) );
71 $this->assertFalse( $provider->testUserExists(
'DoesNotExist' ) );
72 $this->assertFalse( $provider->testUserExists(
'<invalid>' ) );
78 $provider->accountCreationType()
81 $this->assertTrue( $provider->testUserExists( $userName ) );
82 $this->assertFalse( $provider->testUserExists(
'DoesNotExist' ) );
86 $req->username =
'<invalid>';
87 $provider->providerChangeAuthenticationData(
$req );
92 $userName =
$user->getName();
97 $this->assertFalse( $provider->testUserCanAuthenticate(
'<invalid>' ) );
99 $this->assertFalse( $provider->testUserCanAuthenticate(
'DoesNotExist' ) );
101 $this->assertTrue( $provider->testUserCanAuthenticate( $userName ) );
102 $lowerInitialUserName = mb_strtolower( $userName[0] ) . substr( $userName, 1 );
103 $this->assertTrue( $provider->testUserCanAuthenticate( $lowerInitialUserName ) );
108 [
'user_name' => $userName ]
110 $this->assertFalse( $provider->testUserCanAuthenticate( $userName ) );
115 [
'user_password' =>
'0123456789abcdef0123456789abcdef' ],
116 [
'user_name' => $userName ]
118 $this->assertTrue( $provider->testUserCanAuthenticate( $userName ) );
126 $this->
setMwGlobals( [
'wgPasswordExpireGrace' => 100 ] );
128 $this->config->set(
'PasswordExpireGrace', 100 );
129 $this->config->set(
'InvalidPasswordReset',
true );
132 $provider->setConfig( $this->config );
133 $provider->setLogger(
new \Psr\Log\NullLogger() );
134 $provider->setManager( $this->manager );
135 $providerPriv = TestingAccessWrapper::newFromObject( $provider );
138 $userName =
$user->getName();
140 $row = $dbw->selectRow(
143 [
'user_name' => $userName ],
147 $this->manager->removeAuthenticationSessionData(
null );
148 $row->user_password_expires =
wfTimestamp( TS_MW, time() + 200 );
149 $providerPriv->setPasswordResetFlag( $userName, \
Status::newGood(), $row );
150 $this->assertNull( $this->manager->getAuthenticationSessionData(
'reset-pass' ) );
152 $this->manager->removeAuthenticationSessionData(
null );
153 $row->user_password_expires =
wfTimestamp( TS_MW, time() - 200 );
154 $providerPriv->setPasswordResetFlag( $userName, \
Status::newGood(), $row );
155 $ret = $this->manager->getAuthenticationSessionData(
'reset-pass' );
156 $this->assertNotNull(
$ret );
157 $this->assertSame(
'resetpass-expired',
$ret->msg->getKey() );
158 $this->assertTrue(
$ret->hard );
160 $this->manager->removeAuthenticationSessionData(
null );
161 $row->user_password_expires =
wfTimestamp( TS_MW, time() - 1 );
162 $providerPriv->setPasswordResetFlag( $userName, \
Status::newGood(), $row );
163 $ret = $this->manager->getAuthenticationSessionData(
'reset-pass' );
164 $this->assertNotNull(
$ret );
165 $this->assertSame(
'resetpass-expired-soft',
$ret->msg->getKey() );
166 $this->assertFalse(
$ret->hard );
168 $this->manager->removeAuthenticationSessionData(
null );
169 $row->user_password_expires =
null;
172 $providerPriv->setPasswordResetFlag( $userName,
$status, $row );
173 $ret = $this->manager->getAuthenticationSessionData(
'reset-pass' );
174 $this->assertNotNull(
$ret );
175 $this->assertSame(
'resetpass-validity-soft',
$ret->msg->getKey() );
176 $this->assertFalse(
$ret->hard );
178 $this->manager->removeAuthenticationSessionData(
null );
179 $row->user_password_expires =
null;
182 $providerPriv->setPasswordResetFlag( $userName,
$status, $row );
183 $ret = $this->manager->getAuthenticationSessionData(
'reset-pass' );
184 $this->assertNotNull(
$ret );
185 $this->assertSame(
'resetpass-validity',
$ret->msg->getKey() );
186 $this->assertTrue(
$ret->hard );
188 $this->manager->removeAuthenticationSessionData(
null );
189 $row->user_password_expires =
null;
192 $providerPriv->setPasswordResetFlag( $userName,
$status, $row );
193 $ret = $this->manager->getAuthenticationSessionData(
'reset-pass' );
194 $this->assertNull(
$ret );
199 $userName = $testUser->getUser()->getName();
213 $provider->beginPrimaryAuthentication( [] )
216 $req->username =
'foo';
217 $req->password =
null;
220 $provider->beginPrimaryAuthentication( $reqs )
223 $req->username =
null;
224 $req->password =
'bar';
227 $provider->beginPrimaryAuthentication( $reqs )
230 $req->username =
'<invalid>';
231 $req->password =
'WhoCares';
232 $ret = $provider->beginPrimaryAuthentication( $reqs );
235 $provider->beginPrimaryAuthentication( $reqs )
238 $req->username =
'DoesNotExist';
239 $req->password =
'DoesNotExist';
240 $ret = $provider->beginPrimaryAuthentication( $reqs );
247 $ret->message->getKey()
251 $req->username = $userName;
252 $req->password = $testUser->getPassword();
254 $ret = $provider->beginPrimaryAuthentication( $reqs );
261 $ret->message->getKey()
265 $this->manager->removeAuthenticationSessionData(
null );
269 $provider->beginPrimaryAuthentication( $reqs )
271 $this->assertNull( $this->manager->getAuthenticationSessionData(
'reset-pass' ) );
274 $this->manager->removeAuthenticationSessionData(
null );
276 $req->username = mb_strtolower( $userName[0] ) . substr( $userName, 1 );
279 $provider->beginPrimaryAuthentication( $reqs )
281 $this->assertNull( $this->manager->getAuthenticationSessionData(
'reset-pass' ) );
282 $req->username = $userName;
285 $this->manager->removeAuthenticationSessionData(
null );
287 $this->validity->error(
'arbitrary-warning' );
290 $provider->beginPrimaryAuthentication( $reqs )
292 $this->assertNotNull( $this->manager->getAuthenticationSessionData(
'reset-pass' ) );
296 $req->password =
'Wrong';
297 $ret = $provider->beginPrimaryAuthentication( $reqs );
304 $ret->message->getKey()
308 $password =
':B:salt:' . md5(
'salt-' . md5(
"\xe1\xe9\xed\xf3\xfa" ) );
309 $dbw->update(
'user', [
'user_password' => $password ], [
'user_name' => $userName ] );
310 $req->password =
'áéíóú';
311 $ret = $provider->beginPrimaryAuthentication( $reqs );
318 $ret->message->getKey()
321 $this->config->set(
'LegacyEncoding',
true );
324 $provider->beginPrimaryAuthentication( $reqs )
327 $req->password =
'áéíóú Wrong';
328 $ret = $provider->beginPrimaryAuthentication( $reqs );
335 $ret->message->getKey()
339 $this->config->set(
'PasswordSalt',
false );
340 $password = md5(
'FooBar' );
341 $dbw->update(
'user', [
'user_password' => $password ], [
'user_name' => $userName ] );
342 $req->password =
'FooBar';
345 $provider->beginPrimaryAuthentication( $reqs )
348 $this->config->set(
'PasswordSalt',
true );
349 $password = md5(
"$id-" . md5(
'FooBar' ) );
350 $dbw->update(
'user', [
'user_password' => $password ], [
'user_name' => $userName ] );
351 $req->password =
'FooBar';
354 $provider->beginPrimaryAuthentication( $reqs )
378 $req->password =
'NewPassword';
379 $req->retype =
'NewPassword';
383 $this->assertEquals( $expect1, $provider->providerAllowsAuthenticationDataChange(
$req,
false ) );
384 $this->assertEquals( $expect2, $provider->providerAllowsAuthenticationDataChange(
$req,
true ) );
386 $req->retype =
'BadRetype';
389 $provider->providerAllowsAuthenticationDataChange(
$req,
false )
393 $provider->providerAllowsAuthenticationDataChange(
$req,
true )
399 $provider->providerAllowsAuthenticationDataChange(
$req,
true ),
400 'loginOnly mode should claim to ignore all changes'
406 $err->error(
'arbitrary-warning' );
434 $usernameTransform,
$type, $loginOnly, $changed ) {
436 $user = $testUser->getUser()->getName();
437 if ( is_callable( $usernameTransform ) ) {
438 $user = call_user_func( $usernameTransform,
$user );
440 $cuser = ucfirst(
$user );
441 $oldpass = $testUser->getPassword();
442 $newpass =
'NewPassword';
445 $oldExpiry = $dbw->selectField(
'user',
'user_password_expires', [
'user_name' => $cuser ] );
448 'ResetPasswordExpiration' => [
function (
$user, &$expires ) {
449 $expires =
'30001231235959';
458 $loginReq->username =
$user;
459 $loginReq->password = $oldpass;
463 $provider->beginPrimaryAuthentication( $loginReqs ),
468 $changeReq =
new $type();
470 $changeReq = $this->createMock(
$type );
473 $changeReq->username =
$user;
474 $changeReq->password = $newpass;
475 $provider->providerChangeAuthenticationData( $changeReq );
477 if ( $loginOnly && $changed ) {
480 $expectExpiry =
null;
481 } elseif ( $changed ) {
484 $expectExpiry =
'30001231235959';
488 $expectExpiry = $oldExpiry;
491 $loginReq->password = $oldpass;
492 $ret = $provider->beginPrimaryAuthentication( $loginReqs );
493 if ( $old ===
'pass' ) {
497 'old password should pass'
503 'old password should fail'
507 $ret->message->getKey(),
508 'old password should fail'
512 $loginReq->password = $newpass;
513 $ret = $provider->beginPrimaryAuthentication( $loginReqs );
514 if ( $new ===
'pass' ) {
518 'new password should pass'
524 'new password should fail'
528 $ret->message->getKey(),
529 'new password should fail'
537 $dbw->selectField(
'user',
'user_password_expires', [
'user_name' => $cuser ] )
557 $req->username =
'Foo';
558 $req->password =
'Bar';
559 $req->retype =
'Bar';
565 $provider->testForAccountCreation(
$user,
$user, [] ),
566 'No password request'
571 $provider->testForAccountCreation(
$user,
$user, $reqs ),
572 'Password request, validated'
575 $req->retype =
'Baz';
578 $provider->testForAccountCreation(
$user,
$user, $reqs ),
579 'Password request, bad retype'
581 $req->retype =
'Bar';
583 $this->validity->error(
'arbitrary warning' );
585 $expect->error(
'arbitrary warning' );
588 $provider->testForAccountCreation(
$user,
$user, $reqs ),
589 'Password request, not validated'
593 $this->validity->error(
'arbitrary warning' );
596 $provider->testForAccountCreation(
$user,
$user, $reqs ),
597 'Password request, not validated, loginOnly'
610 $provider->beginPrimaryAccountCreation(
$user,
$user, [] );
611 $this->fail(
'Expected exception was not thrown' );
612 }
catch ( \BadMethodCallException $ex ) {
614 'Shouldn\'t call this when accountCreationType() is NONE', $ex->getMessage()
620 $this->fail(
'Expected exception was not thrown' );
621 }
catch ( \BadMethodCallException $ex ) {
623 'Shouldn\'t call this when accountCreationType() is NONE', $ex->getMessage()
631 $provider->beginPrimaryAccountCreation(
$user,
$user, [] )
634 $req->username =
'foo';
635 $req->password =
null;
638 $provider->beginPrimaryAccountCreation(
$user,
$user, $reqs )
641 $req->username =
null;
642 $req->password =
'bar';
645 $provider->beginPrimaryAccountCreation(
$user,
$user, $reqs )
648 $req->username =
'foo';
649 $req->password =
'bar';
652 $expect->createRequest = clone
$req;
653 $expect->createRequest->username =
'Foo';
654 $this->assertEquals( $expect, $provider->beginPrimaryAccountCreation(
$user,
$user, $reqs ) );
662 $req->password =
'NewPassword';
664 $expect->createRequest =
$req;
666 $res2 = $provider->beginPrimaryAccountCreation(
$user,
$user, $reqs );
667 $this->assertEquals( $expect, $res2,
'Sanity check' );
669 $ret = $provider->beginPrimaryAuthentication( $reqs );
672 $this->assertNull( $provider->finishAccountCreation(
$user,
$user, $res2 ) );
673 $ret = $provider->beginPrimaryAuthentication( $reqs );