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