Avoid 'message' in log context in AuthManager
[lhc/web/wiklou.git] / tests / phpunit / includes / auth / ThrottlePreAuthenticationProviderTest.php
1 <?php
2
3 namespace MediaWiki\Auth;
4
5 /**
6 * @group AuthManager
7 * @group Database
8 * @covers MediaWiki\Auth\ThrottlePreAuthenticationProvider
9 */
10 class ThrottlePreAuthenticationProviderTest extends \MediaWikiTestCase {
11 public function testConstructor() {
12 $provider = new ThrottlePreAuthenticationProvider();
13 $providerPriv = \TestingAccessWrapper::newFromObject( $provider );
14 $config = new \HashConfig( [
15 'AccountCreationThrottle' => 123,
16 'PasswordAttemptThrottle' => [ [
17 'count' => 5,
18 'seconds' => 300,
19 ] ],
20 ] );
21 $provider->setConfig( $config );
22 $this->assertSame( [
23 'accountCreationThrottle' => [ [ 'count' => 123, 'seconds' => 86400 ] ],
24 'passwordAttemptThrottle' => [ [ 'count' => 5, 'seconds' => 300 ] ]
25 ], $providerPriv->throttleSettings );
26 $accountCreationThrottle = \TestingAccessWrapper::newFromObject(
27 $providerPriv->accountCreationThrottle );
28 $this->assertSame( [ [ 'count' => 123, 'seconds' => 86400 ] ],
29 $accountCreationThrottle->conditions );
30 $passwordAttemptThrottle = \TestingAccessWrapper::newFromObject(
31 $providerPriv->passwordAttemptThrottle );
32 $this->assertSame( [ [ 'count' => 5, 'seconds' => 300 ] ],
33 $passwordAttemptThrottle->conditions );
34
35 $provider = new ThrottlePreAuthenticationProvider( [
36 'accountCreationThrottle' => [ [ 'count' => 43, 'seconds' => 10000 ] ],
37 'passwordAttemptThrottle' => [ [ 'count' => 11, 'seconds' => 100 ] ],
38 ] );
39 $providerPriv = \TestingAccessWrapper::newFromObject( $provider );
40 $config = new \HashConfig( [
41 'AccountCreationThrottle' => 123,
42 'PasswordAttemptThrottle' => [ [
43 'count' => 5,
44 'seconds' => 300,
45 ] ],
46 ] );
47 $provider->setConfig( $config );
48 $this->assertSame( [
49 'accountCreationThrottle' => [ [ 'count' => 43, 'seconds' => 10000 ] ],
50 'passwordAttemptThrottle' => [ [ 'count' => 11, 'seconds' => 100 ] ],
51 ], $providerPriv->throttleSettings );
52
53 $cache = new \HashBagOStuff();
54 $provider = new ThrottlePreAuthenticationProvider( [ 'cache' => $cache ] );
55 $providerPriv = \TestingAccessWrapper::newFromObject( $provider );
56 $provider->setConfig( new \HashConfig( [
57 'AccountCreationThrottle' => [ [ 'count' => 1, 'seconds' => 1 ] ],
58 'PasswordAttemptThrottle' => [ [ 'count' => 1, 'seconds' => 1 ] ],
59 ] ) );
60 $accountCreationThrottle = \TestingAccessWrapper::newFromObject(
61 $providerPriv->accountCreationThrottle );
62 $this->assertSame( $cache, $accountCreationThrottle->cache );
63 $passwordAttemptThrottle = \TestingAccessWrapper::newFromObject(
64 $providerPriv->passwordAttemptThrottle );
65 $this->assertSame( $cache, $passwordAttemptThrottle->cache );
66 }
67
68 public function testDisabled() {
69 $provider = new ThrottlePreAuthenticationProvider( [
70 'accountCreationThrottle' => [],
71 'passwordAttemptThrottle' => [],
72 'cache' => new \HashBagOStuff(),
73 ] );
74 $provider->setLogger( new \Psr\Log\NullLogger() );
75 $provider->setConfig( new \HashConfig( [
76 'AccountCreationThrottle' => null,
77 'PasswordAttemptThrottle' => null,
78 ] ) );
79 $provider->setManager( AuthManager::singleton() );
80
81 $this->assertEquals(
82 \StatusValue::newGood(),
83 $provider->testForAccountCreation(
84 \User::newFromName( 'Created' ),
85 \User::newFromName( 'Creator' ),
86 []
87 )
88 );
89 $this->assertEquals(
90 \StatusValue::newGood(),
91 $provider->testForAuthentication( [] )
92 );
93 }
94
95 /**
96 * @dataProvider provideTestForAccountCreation
97 * @param string $creatorname
98 * @param bool $succeed
99 * @param bool $hook
100 */
101 public function testTestForAccountCreation( $creatorname, $succeed, $hook ) {
102 $provider = new ThrottlePreAuthenticationProvider( [
103 'accountCreationThrottle' => [ [ 'count' => 2, 'seconds' => 86400 ] ],
104 'cache' => new \HashBagOStuff(),
105 ] );
106 $provider->setLogger( new \Psr\Log\NullLogger() );
107 $provider->setConfig( new \HashConfig( [
108 'AccountCreationThrottle' => null,
109 'PasswordAttemptThrottle' => null,
110 ] ) );
111 $provider->setManager( AuthManager::singleton() );
112
113 $user = \User::newFromName( 'RandomUser' );
114 $creator = \User::newFromName( $creatorname );
115 if ( $hook ) {
116 $mock = $this->getMock( 'stdClass', [ 'onExemptFromAccountCreationThrottle' ] );
117 $mock->expects( $this->any() )->method( 'onExemptFromAccountCreationThrottle' )
118 ->will( $this->returnValue( false ) );
119 $this->mergeMwGlobalArrayValue( 'wgHooks', [
120 'ExemptFromAccountCreationThrottle' => [ $mock ],
121 ] );
122 }
123
124 $this->assertEquals(
125 \StatusValue::newGood(),
126 $provider->testForAccountCreation( $user, $creator, [] ),
127 'attempt #1'
128 );
129 $this->assertEquals(
130 \StatusValue::newGood(),
131 $provider->testForAccountCreation( $user, $creator, [] ),
132 'attempt #2'
133 );
134 $this->assertEquals(
135 $succeed ? \StatusValue::newGood() : \StatusValue::newFatal( 'acct_creation_throttle_hit', 2 ),
136 $provider->testForAccountCreation( $user, $creator, [] ),
137 'attempt #3'
138 );
139 }
140
141 public static function provideTestForAccountCreation() {
142 return [
143 'Normal user' => [ 'NormalUser', false, false ],
144 'Sysop' => [ 'UTSysop', true, false ],
145 'Normal user with hook' => [ 'NormalUser', true, true ],
146 ];
147 }
148
149 public function testTestForAuthentication() {
150 $provider = new ThrottlePreAuthenticationProvider( [
151 'passwordAttemptThrottle' => [ [ 'count' => 2, 'seconds' => 86400 ] ],
152 'cache' => new \HashBagOStuff(),
153 ] );
154 $provider->setLogger( new \Psr\Log\NullLogger() );
155 $provider->setConfig( new \HashConfig( [
156 'AccountCreationThrottle' => null,
157 'PasswordAttemptThrottle' => null,
158 ] ) );
159 $provider->setManager( AuthManager::singleton() );
160
161 $req = new UsernameAuthenticationRequest;
162 $req->username = 'SomeUser';
163 for ( $i = 1; $i <= 3; $i++ ) {
164 $status = $provider->testForAuthentication( [ $req ] );
165 $this->assertEquals( $i < 3, $status->isGood(), "attempt #$i" );
166 }
167 $this->assertCount( 1, $status->getErrors() );
168 $msg = new \Message( $status->getErrors()[0]['message'], $status->getErrors()[0]['params'] );
169 $this->assertEquals( 'login-throttled', $msg->getKey() );
170
171 $provider->postAuthentication( \User::newFromName( 'SomeUser' ),
172 AuthenticationResponse::newFail( wfMessage( 'foo' ) ) );
173 $this->assertFalse( $provider->testForAuthentication( [ $req ] )->isGood(), 'after FAIL' );
174
175 $provider->postAuthentication( \User::newFromName( 'SomeUser' ),
176 AuthenticationResponse::newPass() );
177 $this->assertTrue( $provider->testForAuthentication( [ $req ] )->isGood(), 'after PASS' );
178
179 $req1 = new UsernameAuthenticationRequest;
180 $req1->username = 'foo';
181 $req2 = new UsernameAuthenticationRequest;
182 $req2->username = 'bar';
183 $this->assertTrue( $provider->testForAuthentication( [ $req1, $req2 ] )->isGood() );
184
185 $req = new UsernameAuthenticationRequest;
186 $req->username = 'Some user';
187 $provider->testForAuthentication( [ $req ] );
188 $req->username = 'Some_user';
189 $provider->testForAuthentication( [ $req ] );
190 $req->username = 'some user';
191 $status = $provider->testForAuthentication( [ $req ] );
192 $this->assertFalse( $status->isGood(), 'denormalized usernames are normalized' );
193 }
194
195 public function testPostAuthentication() {
196 $provider = new ThrottlePreAuthenticationProvider( [
197 'passwordAttemptThrottle' => [],
198 'cache' => new \HashBagOStuff(),
199 ] );
200 $provider->setLogger( new \TestLogger );
201 $provider->setConfig( new \HashConfig( [
202 'AccountCreationThrottle' => null,
203 'PasswordAttemptThrottle' => null,
204 ] ) );
205 $provider->setManager( AuthManager::singleton() );
206 $provider->postAuthentication( \User::newFromName( 'SomeUser' ),
207 AuthenticationResponse::newPass() );
208
209 $provider = new ThrottlePreAuthenticationProvider( [
210 'passwordAttemptThrottle' => [ [ 'count' => 2, 'seconds' => 86400 ] ],
211 'cache' => new \HashBagOStuff(),
212 ] );
213 $logger = new \TestLogger( true );
214 $provider->setLogger( $logger );
215 $provider->setConfig( new \HashConfig( [
216 'AccountCreationThrottle' => null,
217 'PasswordAttemptThrottle' => null,
218 ] ) );
219 $provider->setManager( AuthManager::singleton() );
220 $provider->postAuthentication( \User::newFromName( 'SomeUser' ),
221 AuthenticationResponse::newPass() );
222 $this->assertSame( [
223 [ \Psr\Log\LogLevel::ERROR, 'throttler data not found for {user}' ],
224 ], $logger->getBuffer() );
225 }
226 }