Merge "changes: Fix wrong typehint"
[lhc/web/wiklou.git] / tests / phpunit / includes / user / PasswordResetTest.php
1 <?php
2
3 use MediaWiki\Auth\AuthManager;
4 use MediaWiki\Block\DatabaseBlock;
5 use MediaWiki\Block\CompositeBlock;
6 use MediaWiki\Block\SystemBlock;
7 use MediaWiki\Permissions\PermissionManager;
8
9 /**
10 * @covers PasswordReset
11 * @group Database
12 */
13 class PasswordResetTest extends MediaWikiTestCase {
14 /**
15 * @dataProvider provideIsAllowed
16 */
17 public function testIsAllowed( $passwordResetRoutes, $enableEmail,
18 $allowsAuthenticationDataChange, $canEditPrivate, $block, $globalBlock, $isAllowed
19 ) {
20 $config = new HashConfig( [
21 'PasswordResetRoutes' => $passwordResetRoutes,
22 'EnableEmail' => $enableEmail,
23 ] );
24
25 $authManager = $this->getMockBuilder( AuthManager::class )->disableOriginalConstructor()
26 ->getMock();
27 $authManager->expects( $this->any() )->method( 'allowsAuthenticationDataChange' )
28 ->willReturn( $allowsAuthenticationDataChange ? Status::newGood() : Status::newFatal( 'foo' ) );
29
30 $user = $this->getMockBuilder( User::class )->getMock();
31 $user->expects( $this->any() )->method( 'getName' )->willReturn( 'Foo' );
32 $user->expects( $this->any() )->method( 'getBlock' )->willReturn( $block );
33 $user->expects( $this->any() )->method( 'getGlobalBlock' )->willReturn( $globalBlock );
34
35 $permissionManager = $this->getMockBuilder( PermissionManager::class )
36 ->disableOriginalConstructor()
37 ->getMock();
38 $permissionManager->method( 'userHasRight' )
39 ->with( $user, 'editmyprivateinfo' )
40 ->willReturn( $canEditPrivate );
41
42 $passwordReset = new PasswordReset(
43 $config,
44 $authManager,
45 $permissionManager
46 );
47
48 $this->assertSame( $isAllowed, $passwordReset->isAllowed( $user )->isGood() );
49 }
50
51 public function provideIsAllowed() {
52 return [
53 'no routes' => [
54 'passwordResetRoutes' => [],
55 'enableEmail' => true,
56 'allowsAuthenticationDataChange' => true,
57 'canEditPrivate' => true,
58 'block' => null,
59 'globalBlock' => null,
60 'isAllowed' => false,
61 ],
62 'email disabled' => [
63 'passwordResetRoutes' => [ 'username' => true ],
64 'enableEmail' => false,
65 'allowsAuthenticationDataChange' => true,
66 'canEditPrivate' => true,
67 'block' => null,
68 'globalBlock' => null,
69 'isAllowed' => false,
70 ],
71 'auth data change disabled' => [
72 'passwordResetRoutes' => [ 'username' => true ],
73 'enableEmail' => true,
74 'allowsAuthenticationDataChange' => false,
75 'canEditPrivate' => true,
76 'block' => null,
77 'globalBlock' => null,
78 'isAllowed' => false,
79 ],
80 'cannot edit private data' => [
81 'passwordResetRoutes' => [ 'username' => true ],
82 'enableEmail' => true,
83 'allowsAuthenticationDataChange' => true,
84 'canEditPrivate' => false,
85 'block' => null,
86 'globalBlock' => null,
87 'isAllowed' => false,
88 ],
89 'blocked with account creation disabled' => [
90 'passwordResetRoutes' => [ 'username' => true ],
91 'enableEmail' => true,
92 'allowsAuthenticationDataChange' => true,
93 'canEditPrivate' => true,
94 'block' => new DatabaseBlock( [ 'createAccount' => true ] ),
95 'globalBlock' => null,
96 'isAllowed' => false,
97 ],
98 'blocked w/o account creation disabled' => [
99 'passwordResetRoutes' => [ 'username' => true ],
100 'enableEmail' => true,
101 'allowsAuthenticationDataChange' => true,
102 'canEditPrivate' => true,
103 'block' => new DatabaseBlock( [] ),
104 'globalBlock' => null,
105 'isAllowed' => true,
106 ],
107 'using blocked proxy' => [
108 'passwordResetRoutes' => [ 'username' => true ],
109 'enableEmail' => true,
110 'allowsAuthenticationDataChange' => true,
111 'canEditPrivate' => true,
112 'block' => new SystemBlock(
113 [ 'systemBlock' => 'proxy' ]
114 ),
115 'globalBlock' => null,
116 'isAllowed' => false,
117 ],
118 'globally blocked with account creation not disabled' => [
119 'passwordResetRoutes' => [ 'username' => true ],
120 'enableEmail' => true,
121 'allowsAuthenticationDataChange' => true,
122 'canEditPrivate' => true,
123 'block' => null,
124 'globalBlock' => new SystemBlock(
125 [ 'systemBlock' => 'global-block' ]
126 ),
127 'isAllowed' => true,
128 ],
129 'blocked via wgSoftBlockRanges' => [
130 'passwordResetRoutes' => [ 'username' => true ],
131 'enableEmail' => true,
132 'allowsAuthenticationDataChange' => true,
133 'canEditPrivate' => true,
134 'block' => new SystemBlock(
135 [ 'systemBlock' => 'wgSoftBlockRanges', 'anonOnly' => true ]
136 ),
137 'globalBlock' => null,
138 'isAllowed' => true,
139 ],
140 'blocked with an unknown system block type' => [
141 'passwordResetRoutes' => [ 'username' => true ],
142 'enableEmail' => true,
143 'allowsAuthenticationDataChange' => true,
144 'canEditPrivate' => true,
145 'block' => new SystemBlock( [ 'systemBlock' => 'unknown' ] ),
146 'globalBlock' => null,
147 'isAllowed' => false,
148 ],
149 'blocked with multiple blocks, all allowing password reset' => [
150 'passwordResetRoutes' => [ 'username' => true ],
151 'enableEmail' => true,
152 'allowsAuthenticationDataChange' => true,
153 'canEditPrivate' => true,
154 'block' => new CompositeBlock( [
155 'originalBlocks' => [
156 new SystemBlock( [ 'systemBlock' => 'wgSoftBlockRanges', 'anonOnly' => true ] ),
157 new Block( [] ),
158 ]
159 ] ),
160 'globalBlock' => null,
161 'isAllowed' => true,
162 ],
163 'blocked with multiple blocks, not all allowing password reset' => [
164 'passwordResetRoutes' => [ 'username' => true ],
165 'enableEmail' => true,
166 'allowsAuthenticationDataChange' => true,
167 'canEditPrivate' => true,
168 'block' => new CompositeBlock( [
169 'originalBlocks' => [
170 new SystemBlock( [ 'systemBlock' => 'wgSoftBlockRanges', 'anonOnly' => true ] ),
171 new SystemBlock( [ 'systemBlock' => 'proxy' ] ),
172 ]
173 ] ),
174 'globalBlock' => null,
175 'isAllowed' => false,
176 ],
177 'all OK' => [
178 'passwordResetRoutes' => [ 'username' => true ],
179 'enableEmail' => true,
180 'allowsAuthenticationDataChange' => true,
181 'canEditPrivate' => true,
182 'block' => null,
183 'globalBlock' => null,
184 'isAllowed' => true,
185 ],
186 ];
187 }
188
189 public function testExecute_email() {
190 $config = new HashConfig( [
191 'PasswordResetRoutes' => [ 'username' => true, 'email' => true ],
192 'EnableEmail' => true,
193 ] );
194
195 // Unregister the hooks for proper unit testing
196 $this->mergeMwGlobalArrayValue( 'wgHooks', [
197 'User::mailPasswordInternal' => [],
198 'SpecialPasswordResetOnSubmit' => [],
199 ] );
200
201 $authManager = $this->getMockBuilder( AuthManager::class )->disableOriginalConstructor()
202 ->getMock();
203 $authManager->expects( $this->any() )->method( 'allowsAuthenticationDataChange' )
204 ->willReturn( Status::newGood() );
205 $authManager->expects( $this->exactly( 2 ) )->method( 'changeAuthenticationData' );
206
207 $request = new FauxRequest();
208 $request->setIP( '1.2.3.4' );
209 $performingUser = $this->getMockBuilder( User::class )->getMock();
210 $performingUser->expects( $this->any() )->method( 'getRequest' )->willReturn( $request );
211 $performingUser->expects( $this->any() )->method( 'getName' )->willReturn( 'Performer' );
212
213 $permissionManager = $this->getMockBuilder( PermissionManager::class )
214 ->disableOriginalConstructor()
215 ->getMock();
216 $permissionManager->expects( $this->once() )
217 ->method( 'userHasRight' )
218 ->with( $performingUser, 'editmyprivateinfo' )
219 ->willReturn( true );
220
221 $targetUser1 = $this->getMockBuilder( User::class )->getMock();
222 $targetUser2 = $this->getMockBuilder( User::class )->getMock();
223 $targetUser1->expects( $this->any() )->method( 'getName' )->willReturn( 'User1' );
224 $targetUser2->expects( $this->any() )->method( 'getName' )->willReturn( 'User2' );
225 $targetUser1->expects( $this->any() )->method( 'getId' )->willReturn( 1 );
226 $targetUser2->expects( $this->any() )->method( 'getId' )->willReturn( 2 );
227 $targetUser1->expects( $this->any() )->method( 'getEmail' )->willReturn( 'foo@bar.baz' );
228 $targetUser2->expects( $this->any() )->method( 'getEmail' )->willReturn( 'foo@bar.baz' );
229
230 $passwordReset = $this->getMockBuilder( PasswordReset::class )
231 ->setConstructorArgs( [ $config, $authManager, $permissionManager ] )
232 ->setMethods( [ 'getUsersByEmail' ] )
233 ->getMock();
234 $passwordReset->expects( $this->any() )->method( 'getUsersByEmail' )->with( 'foo@bar.baz' )
235 ->willReturn( [ $targetUser1, $targetUser2 ] );
236
237 $status = $passwordReset->isAllowed( $performingUser );
238 $this->assertTrue( $status->isGood() );
239
240 $status = $passwordReset->execute( $performingUser, null, 'foo@bar.baz' );
241 $this->assertTrue( $status->isGood() );
242 }
243 }