Localisation updates from https://translatewiki.net.
[mediawiki.git] / tests / phpunit / includes / auth / ThrottlePreAuthenticationProviderTest.php
blob1ef33658f5cb8c2d1feca64441e76c594a88ca71
1 <?php
3 namespace MediaWiki\Tests\Auth;
5 use MediaWiki\Auth\AuthenticationResponse;
6 use MediaWiki\Auth\ThrottlePreAuthenticationProvider;
7 use MediaWiki\Auth\UsernameAuthenticationRequest;
8 use MediaWiki\Config\HashConfig;
9 use MediaWiki\MainConfigNames;
10 use MediaWiki\Tests\Unit\Auth\AuthenticationProviderTestTrait;
11 use MediaWiki\User\User;
12 use MediaWikiIntegrationTestCase;
13 use Psr\Log\LogLevel;
14 use StatusValue;
15 use stdClass;
16 use TestLogger;
17 use Wikimedia\ObjectCache\HashBagOStuff;
18 use Wikimedia\TestingAccessWrapper;
20 /**
21 * @group AuthManager
22 * @group Database
23 * @covers \MediaWiki\Auth\ThrottlePreAuthenticationProvider
25 class ThrottlePreAuthenticationProviderTest extends MediaWikiIntegrationTestCase {
26 use AuthenticationProviderTestTrait;
28 public function testConstructor() {
29 $provider = new ThrottlePreAuthenticationProvider();
30 $providerPriv = TestingAccessWrapper::newFromObject( $provider );
31 $config = new HashConfig( [
32 MainConfigNames::AccountCreationThrottle => [ [
33 'count' => 123,
34 'seconds' => 86400,
35 ] ],
36 MainConfigNames::PasswordAttemptThrottle => [ [
37 'count' => 5,
38 'seconds' => 300,
39 ] ],
40 ] );
41 $this->initProvider( $provider, $config );
42 $this->assertSame( [
43 'accountCreationThrottle' => [ [ 'count' => 123, 'seconds' => 86400 ] ],
44 'passwordAttemptThrottle' => [ [ 'count' => 5, 'seconds' => 300 ] ]
45 ], $providerPriv->throttleSettings );
46 $accountCreationThrottle = TestingAccessWrapper::newFromObject(
47 $providerPriv->accountCreationThrottle );
48 $this->assertSame( [ [ 'count' => 123, 'seconds' => 86400 ] ],
49 $accountCreationThrottle->conditions );
50 $passwordAttemptThrottle = TestingAccessWrapper::newFromObject(
51 $providerPriv->passwordAttemptThrottle );
52 $this->assertSame( [ [ 'count' => 5, 'seconds' => 300 ] ],
53 $passwordAttemptThrottle->conditions );
55 $provider = new ThrottlePreAuthenticationProvider( [
56 'accountCreationThrottle' => [ [ 'count' => 43, 'seconds' => 10000 ] ],
57 'passwordAttemptThrottle' => [ [ 'count' => 11, 'seconds' => 100 ] ],
58 ] );
59 $providerPriv = TestingAccessWrapper::newFromObject( $provider );
60 $config = new HashConfig( [
61 MainConfigNames::AccountCreationThrottle => [ [
62 'count' => 123,
63 'seconds' => 86400,
64 ] ],
65 MainConfigNames::PasswordAttemptThrottle => [ [
66 'count' => 5,
67 'seconds' => 300,
68 ] ],
69 ] );
70 $this->initProvider( $provider, $config );
71 $this->assertSame( [
72 'accountCreationThrottle' => [ [ 'count' => 43, 'seconds' => 10000 ] ],
73 'passwordAttemptThrottle' => [ [ 'count' => 11, 'seconds' => 100 ] ],
74 ], $providerPriv->throttleSettings );
76 $cache = new HashBagOStuff();
77 $provider = new ThrottlePreAuthenticationProvider( [ 'cache' => $cache ] );
78 $providerPriv = TestingAccessWrapper::newFromObject( $provider );
79 $config = new HashConfig( [
80 MainConfigNames::AccountCreationThrottle => [ [ 'count' => 1, 'seconds' => 1 ] ],
81 MainConfigNames::PasswordAttemptThrottle => [ [ 'count' => 1, 'seconds' => 1 ] ],
82 ] );
83 $this->initProvider( $provider, $config );
84 $accountCreationThrottle = TestingAccessWrapper::newFromObject(
85 $providerPriv->accountCreationThrottle );
86 $this->assertSame( $cache, $accountCreationThrottle->cache );
87 $passwordAttemptThrottle = TestingAccessWrapper::newFromObject(
88 $providerPriv->passwordAttemptThrottle );
89 $this->assertSame( $cache, $passwordAttemptThrottle->cache );
92 public function testDisabled() {
93 $provider = new ThrottlePreAuthenticationProvider( [
94 'accountCreationThrottle' => [],
95 'passwordAttemptThrottle' => [],
96 'cache' => new HashBagOStuff(),
97 ] );
98 $this->initProvider(
99 $provider,
100 new HashConfig( [
101 MainConfigNames::AccountCreationThrottle => null,
102 MainConfigNames::PasswordAttemptThrottle => null,
103 ] ),
104 null,
105 $this->getServiceContainer()->getAuthManager()
108 $this->assertEquals(
109 StatusValue::newGood(),
110 $provider->testForAccountCreation(
111 User::newFromName( 'Created' ),
112 User::newFromName( 'Creator' ),
116 $this->assertEquals(
117 StatusValue::newGood(),
118 $provider->testForAuthentication( [] )
123 * @dataProvider provideTestForAccountCreation
124 * @param bool $creatorIsSysop
125 * @param bool $succeed
126 * @param bool $hook
128 public function testTestForAccountCreation( bool $creatorIsSysop, $succeed, $hook ) {
129 if ( $hook ) {
130 $mock = $this->getMockBuilder( stdClass::class )
131 ->addMethods( [ 'onExemptFromAccountCreationThrottle' ] )
132 ->getMock();
133 $mock->method( 'onExemptFromAccountCreationThrottle' )
134 ->willReturn( false );
135 $this->setTemporaryHook( 'ExemptFromAccountCreationThrottle', $mock );
138 $provider = new ThrottlePreAuthenticationProvider( [
139 'accountCreationThrottle' => [ [ 'count' => 2, 'seconds' => 86400 ] ],
140 'cache' => new HashBagOStuff(),
141 ] );
142 $this->initProvider(
143 $provider,
144 new HashConfig( [
145 MainConfigNames::AccountCreationThrottle => null,
146 MainConfigNames::PasswordAttemptThrottle => null,
147 ] ),
148 null,
149 $this->getServiceContainer()->getAuthManager(),
150 $this->getServiceContainer()->getHookContainer()
153 $user = User::newFromName( 'RandomUser' );
154 $creator = $creatorIsSysop ? $this->getTestSysop()->getUser() : $this->getTestUser()->getUser();
156 $this->assertTrue(
158 $provider->testForAccountCreation( $user, $creator, [] )->isOK(),
159 'attempt #1'
161 $this->assertTrue(
163 $provider->testForAccountCreation( $user, $creator, [] )->isOK(),
164 'attempt #2'
166 $this->assertEquals(
167 (bool)$succeed,
168 $provider->testForAccountCreation( $user, $creator, [] )->isOK(),
169 'attempt #3'
173 public static function provideTestForAccountCreation() {
174 return [
175 'Normal user' => [ false, false, false ],
176 'Sysop' => [ true, true, false ],
177 'Normal user with hook' => [ false, true, true ],
181 public function testTestForAuthentication() {
182 $provider = new ThrottlePreAuthenticationProvider( [
183 'passwordAttemptThrottle' => [ [ 'count' => 2, 'seconds' => 86400 ] ],
184 'cache' => new HashBagOStuff(),
185 ] );
186 $this->initProvider(
187 $provider,
188 new HashConfig( [
189 MainConfigNames::AccountCreationThrottle => null,
190 MainConfigNames::PasswordAttemptThrottle => null,
191 ] ),
192 null,
193 $this->getServiceContainer()->getAuthManager()
196 $req = new UsernameAuthenticationRequest;
197 $req->username = 'SomeUser';
198 for ( $i = 1; $i <= 3; $i++ ) {
199 $status = $provider->testForAuthentication( [ $req ] );
200 $this->assertEquals( $i < 3, $status->isGood(), "attempt #$i" );
202 $this->assertStatusError( 'login-throttled', $status );
204 $provider->postAuthentication( User::newFromName( 'SomeUser' ),
205 AuthenticationResponse::newFail( wfMessage( 'foo' ) ) );
206 $this->assertStatusNotOk( $provider->testForAuthentication( [ $req ] ), 'after FAIL' );
208 $provider->postAuthentication( User::newFromName( 'SomeUser' ),
209 AuthenticationResponse::newPass() );
210 $this->assertStatusGood( $provider->testForAuthentication( [ $req ] ), 'after PASS' );
212 $req1 = new UsernameAuthenticationRequest;
213 $req1->username = 'foo';
214 $req2 = new UsernameAuthenticationRequest;
215 $req2->username = 'bar';
216 $this->assertStatusGood( $provider->testForAuthentication( [ $req1, $req2 ] ) );
218 $req = new UsernameAuthenticationRequest;
219 $req->username = 'Some user';
220 $provider->testForAuthentication( [ $req ] );
221 $req->username = 'Some_user';
222 $provider->testForAuthentication( [ $req ] );
223 $req->username = 'some user';
224 $status = $provider->testForAuthentication( [ $req ] );
225 $this->assertStatusNotOk( $status, 'denormalized usernames are normalized' );
228 public function testPostAuthentication() {
229 $provider = new ThrottlePreAuthenticationProvider( [
230 'passwordAttemptThrottle' => [],
231 'cache' => new HashBagOStuff(),
232 ] );
233 $this->initProvider(
234 $provider,
235 new HashConfig( [
236 MainConfigNames::AccountCreationThrottle => null,
237 MainConfigNames::PasswordAttemptThrottle => null,
238 ] ),
239 null,
240 $this->getServiceContainer()->getAuthManager()
242 $provider->postAuthentication( User::newFromName( 'SomeUser' ),
243 AuthenticationResponse::newPass() );
245 $provider = new ThrottlePreAuthenticationProvider( [
246 'passwordAttemptThrottle' => [ [ 'count' => 2, 'seconds' => 86400 ] ],
247 'cache' => new HashBagOStuff(),
248 ] );
249 $logger = new TestLogger( true );
250 $this->initProvider(
251 $provider,
252 new HashConfig( [
253 MainConfigNames::AccountCreationThrottle => null,
254 MainConfigNames::PasswordAttemptThrottle => null,
255 ] ),
256 $logger,
257 $this->getServiceContainer()->getAuthManager()
259 $provider->postAuthentication( User::newFromName( 'SomeUser' ),
260 AuthenticationResponse::newPass() );
261 $this->assertSame( [
262 [ LogLevel::INFO, 'throttler data not found for {user}' ],
263 ], $logger->getBuffer() );