wiki.techinc.nl/tests/phpunit/includes/auth/AbstractPasswordPrimaryAuthenticationProviderTest.php
Daimona Eaytoy d3243571d0 Fix DB usage in non-database tests (part 2)
Mock the relevant services that need the DB instead, when possible. When
not possible, e.g. because DB access is needed for the test to make
sense, add the test to the Database group instead.

Change-Id: Iefbfe00bedc243906c6b860572568343268646cc
2023-08-06 22:57:28 +00:00

251 lines
8.4 KiB
PHP

<?php
namespace MediaWiki\Auth;
use MediaWiki\MainConfigNames;
use MediaWiki\Tests\Unit\Auth\AuthenticationProviderTestTrait;
use MediaWiki\User\UserFactory;
use MultiConfig;
use User;
use Wikimedia\TestingAccessWrapper;
/**
* @group AuthManager
* @covers \MediaWiki\Auth\AbstractPasswordPrimaryAuthenticationProvider
*/
class AbstractPasswordPrimaryAuthenticationProviderTest extends \MediaWikiIntegrationTestCase {
use AuthenticationProviderTestTrait;
public function testConstructor() {
$provider = $this->getMockForAbstractClass(
AbstractPasswordPrimaryAuthenticationProvider::class
);
$providerPriv = TestingAccessWrapper::newFromObject( $provider );
$this->assertTrue( $providerPriv->authoritative );
$provider = $this->getMockForAbstractClass(
AbstractPasswordPrimaryAuthenticationProvider::class,
[ [ 'authoritative' => false ] ]
);
$providerPriv = TestingAccessWrapper::newFromObject( $provider );
$this->assertFalse( $providerPriv->authoritative );
}
public function testGetPasswordFactory() {
$provider = $this->getMockForAbstractClass(
AbstractPasswordPrimaryAuthenticationProvider::class
);
$this->initProvider( $provider, $this->getServiceContainer()->getMainConfig() );
$providerPriv = TestingAccessWrapper::newFromObject( $provider );
$obj = $providerPriv->getPasswordFactory();
$this->assertInstanceOf( \PasswordFactory::class, $obj );
$this->assertSame( $obj, $providerPriv->getPasswordFactory() );
}
public function testGetPassword() {
$provider = $this->getMockForAbstractClass(
AbstractPasswordPrimaryAuthenticationProvider::class
);
$this->initProvider( $provider, $this->getServiceContainer()->getMainConfig() );
$providerPriv = TestingAccessWrapper::newFromObject( $provider );
$obj = $providerPriv->getPassword( null );
$this->assertInstanceOf( \Password::class, $obj );
$obj = $providerPriv->getPassword( 'invalid' );
$this->assertInstanceOf( \Password::class, $obj );
}
public function testGetNewPasswordExpiry() {
$config = new \HashConfig;
$provider = $this->getMockForAbstractClass(
AbstractPasswordPrimaryAuthenticationProvider::class
);
$this->initProvider( $provider, new MultiConfig( [ $config, $this->getServiceContainer()->getMainConfig() ] ) );
$providerPriv = TestingAccessWrapper::newFromObject( $provider );
$config->set( MainConfigNames::PasswordExpirationDays, 0 );
$this->assertNull( $providerPriv->getNewPasswordExpiry( 'UTSysop' ) );
$config->set( MainConfigNames::PasswordExpirationDays, 5 );
$this->assertEqualsWithDelta(
time() + 5 * 86400,
wfTimestamp( TS_UNIX, $providerPriv->getNewPasswordExpiry( 'UTSysop' ) ),
2 /* Fuzz */
);
$this->initProvider(
$provider,
new MultiConfig( [ $config, $this->getServiceContainer()->getMainConfig() ] ),
null,
null,
$this->createHookContainer( [
'ResetPasswordExpiration' => function ( $user, &$expires ) {
$this->assertSame( 'UTSysop', $user->getName() );
$expires = '30001231235959';
}
] )
);
$this->assertSame( '30001231235959', $providerPriv->getNewPasswordExpiry( 'UTSysop' ) );
}
public function testCheckPasswordValidity() {
$uppCalled = 0;
$uppStatus = \Status::newGood( [] );
$this->overrideConfigValue(
MainConfigNames::PasswordPolicy,
[
'policies' => [
'default' => [
'Check' => true,
],
],
'checks' => [
'Check' => static function () use ( &$uppCalled, &$uppStatus ) {
$uppCalled++;
return $uppStatus;
},
],
]
);
$provider = $this->getMockForAbstractClass(
AbstractPasswordPrimaryAuthenticationProvider::class
);
$this->initProvider( $provider, $this->getServiceContainer()->getMainConfig() );
$providerPriv = TestingAccessWrapper::newFromObject( $provider );
$username = '127.0.0.1';
$anon = new User();
$anon->setName( $username );
$userFactory = $this->createMock( UserFactory::class );
$userFactory->method( 'newFromName' )->with( $username )->willReturn( $anon );
$this->setService( 'UserFactory', $userFactory );
$this->assertEquals( $uppStatus, $providerPriv->checkPasswordValidity( $username, 'bar' ) );
$uppStatus->fatal( 'arbitrary-warning' );
$this->assertEquals( $uppStatus, $providerPriv->checkPasswordValidity( $username, 'bar' ) );
}
public function testSetPasswordResetFlag() {
$config = new \HashConfig( [
MainConfigNames::InvalidPasswordReset => true,
] );
$services = $this->getServiceContainer();
$manager = new AuthManager(
new \MediaWiki\Request\FauxRequest(),
$services->getMainConfig(),
$services->getObjectFactory(),
$services->getHookContainer(),
$services->getReadOnlyMode(),
$services->getUserNameUtils(),
$services->getBlockManager(),
$services->getWatchlistManager(),
$services->getDBLoadBalancer(),
$services->getContentLanguage(),
$services->getLanguageConverterFactory(),
$services->getBotPasswordStore(),
$services->getUserFactory(),
$services->getUserIdentityLookup(),
$services->getUserOptionsManager()
);
$provider = $this->getMockForAbstractClass(
AbstractPasswordPrimaryAuthenticationProvider::class
);
$this->initProvider( $provider, $config, null, $manager, $services->getHookContainer() );
$providerPriv = TestingAccessWrapper::newFromObject( $provider );
$manager->removeAuthenticationSessionData( null );
$status = \Status::newGood();
$providerPriv->setPasswordResetFlag( 'Foo', $status );
$this->assertNull( $manager->getAuthenticationSessionData( 'reset-pass' ) );
$manager->removeAuthenticationSessionData( null );
$status = \Status::newGood( [ 'suggestChangeOnLogin' => true ] );
$status->error( 'testing' );
$providerPriv->setPasswordResetFlag( 'Foo', $status );
$ret = $manager->getAuthenticationSessionData( 'reset-pass' );
$this->assertNotNull( $ret );
$this->assertSame( 'resetpass-validity-soft', $ret->msg->getKey() );
$this->assertFalse( $ret->hard );
$config->set( MainConfigNames::InvalidPasswordReset, false );
$manager->removeAuthenticationSessionData( null );
$providerPriv->setPasswordResetFlag( 'Foo', $status );
$ret = $manager->getAuthenticationSessionData( 'reset-pass' );
$this->assertNull( $ret );
}
public function testFailResponse() {
$provider = $this->getMockForAbstractClass(
AbstractPasswordPrimaryAuthenticationProvider::class,
[ [ 'authoritative' => false ] ]
);
$providerPriv = TestingAccessWrapper::newFromObject( $provider );
$req = new PasswordAuthenticationRequest;
$ret = $providerPriv->failResponse( $req );
$this->assertSame( AuthenticationResponse::ABSTAIN, $ret->status );
$provider = $this->getMockForAbstractClass(
AbstractPasswordPrimaryAuthenticationProvider::class,
[ [ 'authoritative' => true ] ]
);
$providerPriv = TestingAccessWrapper::newFromObject( $provider );
$req->password = '';
$ret = $providerPriv->failResponse( $req );
$this->assertSame( AuthenticationResponse::FAIL, $ret->status );
$this->assertSame( 'wrongpasswordempty', $ret->message->getKey() );
$req->password = 'X';
$ret = $providerPriv->failResponse( $req );
$this->assertSame( AuthenticationResponse::FAIL, $ret->status );
$this->assertSame( 'wrongpassword', $ret->message->getKey() );
}
/**
* @dataProvider provideGetAuthenticationRequests
* @param string $action
* @param array $response
*/
public function testGetAuthenticationRequests( $action, $response ) {
$provider = $this->getMockForAbstractClass(
AbstractPasswordPrimaryAuthenticationProvider::class
);
$this->assertEquals( $response, $provider->getAuthenticationRequests( $action, [] ) );
}
public static function provideGetAuthenticationRequests() {
return [
[ AuthManager::ACTION_LOGIN, [ new PasswordAuthenticationRequest() ] ],
[ AuthManager::ACTION_CREATE, [ new PasswordAuthenticationRequest() ] ],
[ AuthManager::ACTION_LINK, [] ],
[ AuthManager::ACTION_CHANGE, [ new PasswordAuthenticationRequest() ] ],
[ AuthManager::ACTION_REMOVE, [ new PasswordAuthenticationRequest() ] ],
];
}
public function testProviderRevokeAccessForUser() {
$req = new PasswordAuthenticationRequest;
$req->action = AuthManager::ACTION_REMOVE;
$req->username = 'foo';
$req->password = null;
$provider = $this->getMockForAbstractClass(
AbstractPasswordPrimaryAuthenticationProvider::class
);
$provider->expects( $this->once() )
->method( 'providerChangeAuthenticationData' )
->with( $req );
$provider->providerRevokeAccessForUser( 'foo' );
}
}