X-Git-Url: https://scripts.mit.edu/gitweb/autoinstallsdev/mediawiki.git/blobdiff_plain/19e297c21b10b1b8a3acad5e73fc71dcb35db44a..6932310fd58ebef145fa01eb76edf7150284d8ea:/tests/phpunit/includes/auth/ResetPasswordSecondaryAuthenticationProviderTest.php diff --git a/tests/phpunit/includes/auth/ResetPasswordSecondaryAuthenticationProviderTest.php b/tests/phpunit/includes/auth/ResetPasswordSecondaryAuthenticationProviderTest.php new file mode 100644 index 00000000..f454a96a --- /dev/null +++ b/tests/phpunit/includes/auth/ResetPasswordSecondaryAuthenticationProviderTest.php @@ -0,0 +1,310 @@ +assertEquals( $response, $provider->getAuthenticationRequests( $action, [] ) ); + } + + public static function provideGetAuthenticationRequests() { + return [ + [ AuthManager::ACTION_LOGIN, [] ], + [ AuthManager::ACTION_CREATE, [] ], + [ AuthManager::ACTION_LINK, [] ], + [ AuthManager::ACTION_CHANGE, [] ], + [ AuthManager::ACTION_REMOVE, [] ], + ]; + } + + public function testBasics() { + $user = \User::newFromName( 'UTSysop' ); + $user2 = new \User; + $obj = new \stdClass; + $reqs = [ new \stdClass ]; + + $mb = $this->getMockBuilder( ResetPasswordSecondaryAuthenticationProvider::class ) + ->setMethods( [ 'tryReset' ] ); + + $methods = [ + 'beginSecondaryAuthentication' => [ $user, $reqs ], + 'continueSecondaryAuthentication' => [ $user, $reqs ], + 'beginSecondaryAccountCreation' => [ $user, $user2, $reqs ], + 'continueSecondaryAccountCreation' => [ $user, $user2, $reqs ], + ]; + foreach ( $methods as $method => $args ) { + $mock = $mb->getMock(); + $mock->expects( $this->once() )->method( 'tryReset' ) + ->with( $this->identicalTo( $user ), $this->identicalTo( $reqs ) ) + ->will( $this->returnValue( $obj ) ); + $this->assertSame( $obj, call_user_func_array( [ $mock, $method ], $args ) ); + } + } + + public function testTryReset() { + $user = \User::newFromName( 'UTSysop' ); + + $provider = $this->getMockBuilder( + ResetPasswordSecondaryAuthenticationProvider::class + ) + ->setMethods( [ + 'providerAllowsAuthenticationDataChange', 'providerChangeAuthenticationData' + ] ) + ->getMock(); + $provider->expects( $this->any() )->method( 'providerAllowsAuthenticationDataChange' ) + ->will( $this->returnCallback( function ( $req ) { + $this->assertSame( 'UTSysop', $req->username ); + return $req->allow; + } ) ); + $provider->expects( $this->any() )->method( 'providerChangeAuthenticationData' ) + ->will( $this->returnCallback( function ( $req ) { + $this->assertSame( 'UTSysop', $req->username ); + $req->done = true; + } ) ); + $config = new \HashConfig( [ + 'AuthManagerConfig' => [ + 'preauth' => [], + 'primaryauth' => [], + 'secondaryauth' => [ + [ 'factory' => function () use ( $provider ) { + return $provider; + } ], + ], + ], + ] ); + $manager = new AuthManager( new \FauxRequest, $config ); + $provider->setManager( $manager ); + $provider = TestingAccessWrapper::newFromObject( $provider ); + + $msg = wfMessage( 'foo' ); + $skipReq = new ButtonAuthenticationRequest( + 'skipReset', + wfMessage( 'authprovider-resetpass-skip-label' ), + wfMessage( 'authprovider-resetpass-skip-help' ) + ); + $passReq = new PasswordAuthenticationRequest(); + $passReq->action = AuthManager::ACTION_CHANGE; + $passReq->password = 'Foo'; + $passReq->retype = 'Bar'; + $passReq->allow = \StatusValue::newGood(); + $passReq->done = false; + + $passReq2 = $this->getMockBuilder( PasswordAuthenticationRequest::class ) + ->enableProxyingToOriginalMethods() + ->getMock(); + $passReq2->action = AuthManager::ACTION_CHANGE; + $passReq2->password = 'Foo'; + $passReq2->retype = 'Foo'; + $passReq2->allow = \StatusValue::newGood(); + $passReq2->done = false; + + $passReq3 = new PasswordAuthenticationRequest(); + $passReq3->action = AuthManager::ACTION_LOGIN; + $passReq3->password = 'Foo'; + $passReq3->retype = 'Foo'; + $passReq3->allow = \StatusValue::newGood(); + $passReq3->done = false; + + $this->assertEquals( + AuthenticationResponse::newAbstain(), + $provider->tryReset( $user, [] ) + ); + + $manager->setAuthenticationSessionData( 'reset-pass', 'foo' ); + try { + $provider->tryReset( $user, [] ); + $this->fail( 'Expected exception not thrown' ); + } catch ( \UnexpectedValueException $ex ) { + $this->assertSame( 'reset-pass is not valid', $ex->getMessage() ); + } + + $manager->setAuthenticationSessionData( 'reset-pass', (object)[] ); + try { + $provider->tryReset( $user, [] ); + $this->fail( 'Expected exception not thrown' ); + } catch ( \UnexpectedValueException $ex ) { + $this->assertSame( 'reset-pass msg is missing', $ex->getMessage() ); + } + + $manager->setAuthenticationSessionData( 'reset-pass', [ + 'msg' => 'foo', + ] ); + try { + $provider->tryReset( $user, [] ); + $this->fail( 'Expected exception not thrown' ); + } catch ( \UnexpectedValueException $ex ) { + $this->assertSame( 'reset-pass msg is not valid', $ex->getMessage() ); + } + + $manager->setAuthenticationSessionData( 'reset-pass', [ + 'msg' => $msg, + ] ); + try { + $provider->tryReset( $user, [] ); + $this->fail( 'Expected exception not thrown' ); + } catch ( \UnexpectedValueException $ex ) { + $this->assertSame( 'reset-pass hard is missing', $ex->getMessage() ); + } + + $manager->setAuthenticationSessionData( 'reset-pass', [ + 'msg' => $msg, + 'hard' => true, + 'req' => 'foo', + ] ); + try { + $provider->tryReset( $user, [] ); + $this->fail( 'Expected exception not thrown' ); + } catch ( \UnexpectedValueException $ex ) { + $this->assertSame( 'reset-pass req is not valid', $ex->getMessage() ); + } + + $manager->setAuthenticationSessionData( 'reset-pass', [ + 'msg' => $msg, + 'hard' => false, + 'req' => $passReq3, + ] ); + try { + $provider->tryReset( $user, [ $passReq ] ); + $this->fail( 'Expected exception not thrown' ); + } catch ( \UnexpectedValueException $ex ) { + $this->assertSame( 'reset-pass req is not valid', $ex->getMessage() ); + } + + $manager->setAuthenticationSessionData( 'reset-pass', [ + 'msg' => $msg, + 'hard' => true, + ] ); + $res = $provider->tryReset( $user, [] ); + $this->assertInstanceOf( AuthenticationResponse::class, $res ); + $this->assertSame( AuthenticationResponse::UI, $res->status ); + $this->assertEquals( $msg, $res->message ); + $this->assertCount( 1, $res->neededRequests ); + $this->assertInstanceOf( + PasswordAuthenticationRequest::class, + $res->neededRequests[0] + ); + $this->assertNotNull( $manager->getAuthenticationSessionData( 'reset-pass' ) ); + $this->assertFalse( $passReq->done ); + + $manager->setAuthenticationSessionData( 'reset-pass', [ + 'msg' => $msg, + 'hard' => false, + 'req' => $passReq, + ] ); + $res = $provider->tryReset( $user, [] ); + $this->assertInstanceOf( AuthenticationResponse::class, $res ); + $this->assertSame( AuthenticationResponse::UI, $res->status ); + $this->assertEquals( $msg, $res->message ); + $this->assertCount( 2, $res->neededRequests ); + $expectedPassReq = clone $passReq; + $expectedPassReq->required = AuthenticationRequest::OPTIONAL; + $this->assertEquals( $expectedPassReq, $res->neededRequests[0] ); + $this->assertEquals( $skipReq, $res->neededRequests[1] ); + $this->assertNotNull( $manager->getAuthenticationSessionData( 'reset-pass' ) ); + $this->assertFalse( $passReq->done ); + + $passReq->retype = 'Bad'; + $manager->setAuthenticationSessionData( 'reset-pass', [ + 'msg' => $msg, + 'hard' => false, + 'req' => $passReq, + ] ); + $res = $provider->tryReset( $user, [ $skipReq, $passReq ] ); + $this->assertEquals( AuthenticationResponse::newPass(), $res ); + $this->assertNull( $manager->getAuthenticationSessionData( 'reset-pass' ) ); + $this->assertFalse( $passReq->done ); + + $passReq->retype = 'Bad'; + $manager->setAuthenticationSessionData( 'reset-pass', [ + 'msg' => $msg, + 'hard' => true, + ] ); + $res = $provider->tryReset( $user, [ $skipReq, $passReq ] ); + $this->assertSame( AuthenticationResponse::UI, $res->status ); + $this->assertSame( 'badretype', $res->message->getKey() ); + $this->assertCount( 1, $res->neededRequests ); + $this->assertInstanceOf( + PasswordAuthenticationRequest::class, + $res->neededRequests[0] + ); + $this->assertNotNull( $manager->getAuthenticationSessionData( 'reset-pass' ) ); + $this->assertFalse( $passReq->done ); + + $manager->setAuthenticationSessionData( 'reset-pass', [ + 'msg' => $msg, + 'hard' => true, + ] ); + $res = $provider->tryReset( $user, [ $skipReq, $passReq3 ] ); + $this->assertSame( AuthenticationResponse::UI, $res->status ); + $this->assertEquals( $msg, $res->message ); + $this->assertCount( 1, $res->neededRequests ); + $this->assertInstanceOf( + PasswordAuthenticationRequest::class, + $res->neededRequests[0] + ); + $this->assertNotNull( $manager->getAuthenticationSessionData( 'reset-pass' ) ); + $this->assertFalse( $passReq->done ); + + $passReq->retype = $passReq->password; + $passReq->allow = \StatusValue::newFatal( 'arbitrary-fail' ); + $res = $provider->tryReset( $user, [ $skipReq, $passReq ] ); + $this->assertSame( AuthenticationResponse::UI, $res->status ); + $this->assertSame( 'arbitrary-fail', $res->message->getKey() ); + $this->assertCount( 1, $res->neededRequests ); + $this->assertInstanceOf( + PasswordAuthenticationRequest::class, + $res->neededRequests[0] + ); + $this->assertNotNull( $manager->getAuthenticationSessionData( 'reset-pass' ) ); + $this->assertFalse( $passReq->done ); + + $passReq->allow = \StatusValue::newGood(); + $res = $provider->tryReset( $user, [ $skipReq, $passReq ] ); + $this->assertEquals( AuthenticationResponse::newPass(), $res ); + $this->assertNull( $manager->getAuthenticationSessionData( 'reset-pass' ) ); + $this->assertTrue( $passReq->done ); + + $manager->setAuthenticationSessionData( 'reset-pass', [ + 'msg' => $msg, + 'hard' => false, + 'req' => $passReq2, + ] ); + $res = $provider->tryReset( $user, [ $passReq2 ] ); + $this->assertEquals( AuthenticationResponse::newPass(), $res ); + $this->assertNull( $manager->getAuthenticationSessionData( 'reset-pass' ) ); + $this->assertTrue( $passReq2->done ); + + $passReq->done = false; + $passReq2->done = false; + $manager->setAuthenticationSessionData( 'reset-pass', [ + 'msg' => $msg, + 'hard' => false, + 'req' => $passReq2, + ] ); + $res = $provider->tryReset( $user, [ $passReq ] ); + $this->assertInstanceOf( AuthenticationResponse::class, $res ); + $this->assertSame( AuthenticationResponse::UI, $res->status ); + $this->assertEquals( $msg, $res->message ); + $this->assertCount( 2, $res->neededRequests ); + $expectedPassReq = clone $passReq2; + $expectedPassReq->required = AuthenticationRequest::OPTIONAL; + $this->assertEquals( $expectedPassReq, $res->neededRequests[0] ); + $this->assertEquals( $skipReq, $res->neededRequests[1] ); + $this->assertNotNull( $manager->getAuthenticationSessionData( 'reset-pass' ) ); + $this->assertFalse( $passReq->done ); + $this->assertFalse( $passReq2->done ); + } +}