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