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