Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 88 |
|
0.00% |
0 / 14 |
CRAP | |
0.00% |
0 / 1 |
SpecialChangeEmail | |
0.00% |
0 / 87 |
|
0.00% |
0 / 14 |
812 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
doesWrites | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
isListed | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
execute | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
getLoginSecurityLevel | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
checkExecutePermissions | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
getFormFields | |
0.00% |
0 / 20 |
|
0.00% |
0 / 1 |
6 | |||
getDisplayFormat | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
alterForm | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
onSubmit | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
onSuccess | |
0.00% |
0 / 16 |
|
0.00% |
0 / 1 |
30 | |||
attemptChange | |
0.00% |
0 / 25 |
|
0.00% |
0 / 1 |
72 | |||
requiresUnblock | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getGroupName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * This program is free software; you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by |
5 | * the Free Software Foundation; either version 2 of the License, or |
6 | * (at your option) any later version. |
7 | * |
8 | * This program is distributed in the hope that it will be useful, |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
11 | * GNU General Public License for more details. |
12 | * |
13 | * You should have received a copy of the GNU General Public License along |
14 | * with this program; if not, write to the Free Software Foundation, Inc., |
15 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
16 | * http://www.gnu.org/copyleft/gpl.html |
17 | * |
18 | * @file |
19 | */ |
20 | |
21 | namespace MediaWiki\Specials; |
22 | |
23 | use ErrorPageError; |
24 | use MediaWiki\Auth\AuthManager; |
25 | use MediaWiki\Html\Html; |
26 | use MediaWiki\HTMLForm\HTMLForm; |
27 | use MediaWiki\Logger\LoggerFactory; |
28 | use MediaWiki\Parser\Sanitizer; |
29 | use MediaWiki\SpecialPage\FormSpecialPage; |
30 | use MediaWiki\Status\Status; |
31 | use MediaWiki\Title\Title; |
32 | use MediaWiki\User\User; |
33 | use PermissionsError; |
34 | |
35 | /** |
36 | * Let users change their email address. |
37 | * |
38 | * @ingroup SpecialPage |
39 | */ |
40 | class SpecialChangeEmail extends FormSpecialPage { |
41 | /** |
42 | * @var Status |
43 | */ |
44 | private $status; |
45 | |
46 | /** |
47 | * @param AuthManager $authManager |
48 | */ |
49 | public function __construct( AuthManager $authManager ) { |
50 | parent::__construct( 'ChangeEmail', 'editmyprivateinfo' ); |
51 | |
52 | $this->setAuthManager( $authManager ); |
53 | } |
54 | |
55 | public function doesWrites() { |
56 | return true; |
57 | } |
58 | |
59 | /** |
60 | * @return bool |
61 | */ |
62 | public function isListed() { |
63 | return $this->getAuthManager()->allowsPropertyChange( 'emailaddress' ); |
64 | } |
65 | |
66 | /** |
67 | * Main execution point |
68 | * @param string|null $par |
69 | */ |
70 | public function execute( $par ) { |
71 | $out = $this->getOutput(); |
72 | $out->disallowUserJs(); |
73 | $out->addModules( 'mediawiki.special.changeemail' ); |
74 | parent::execute( $par ); |
75 | } |
76 | |
77 | protected function getLoginSecurityLevel() { |
78 | return $this->getName(); |
79 | } |
80 | |
81 | protected function checkExecutePermissions( User $user ) { |
82 | if ( !$this->getAuthManager()->allowsPropertyChange( 'emailaddress' ) ) { |
83 | throw new ErrorPageError( 'changeemail', 'cannotchangeemail' ); |
84 | } |
85 | |
86 | $this->requireNamedUser( 'changeemail-no-info', 'exception-nologin', true ); |
87 | |
88 | // This could also let someone check the current email address, so |
89 | // require both permissions. |
90 | if ( !$this->getAuthority()->isAllowed( 'viewmyprivateinfo' ) ) { |
91 | throw new PermissionsError( 'viewmyprivateinfo' ); |
92 | } |
93 | |
94 | parent::checkExecutePermissions( $user ); |
95 | } |
96 | |
97 | protected function getFormFields() { |
98 | $user = $this->getUser(); |
99 | |
100 | return [ |
101 | 'Name' => [ |
102 | 'type' => 'info', |
103 | 'label-message' => 'username', |
104 | 'default' => $user->getName(), |
105 | ], |
106 | 'OldEmail' => [ |
107 | 'type' => 'info', |
108 | 'label-message' => 'changeemail-oldemail', |
109 | 'default' => $user->getEmail() ?: $this->msg( 'changeemail-none' )->text(), |
110 | ], |
111 | 'NewEmail' => [ |
112 | 'type' => 'email', |
113 | 'label-message' => 'changeemail-newemail', |
114 | 'autofocus' => true, |
115 | 'maxlength' => 255, |
116 | 'help-message' => 'changeemail-newemail-help', |
117 | ], |
118 | ]; |
119 | } |
120 | |
121 | protected function getDisplayFormat() { |
122 | return 'ooui'; |
123 | } |
124 | |
125 | protected function alterForm( HTMLForm $form ) { |
126 | $form->setId( 'mw-changeemail-form' ); |
127 | $form->setTableId( 'mw-changeemail-table' ); |
128 | $form->setSubmitTextMsg( 'changeemail-submit' ); |
129 | $form->addHiddenFields( $this->getRequest()->getValues( 'returnto', 'returntoquery' ) ); |
130 | |
131 | $form->addHeaderHtml( $this->msg( 'changeemail-header' )->parseAsBlock() ); |
132 | $form->setSubmitID( 'change_email_submit' ); |
133 | } |
134 | |
135 | public function onSubmit( array $data ) { |
136 | $this->status = $this->attemptChange( $this->getUser(), $data['NewEmail'] ); |
137 | |
138 | return $this->status; |
139 | } |
140 | |
141 | public function onSuccess() { |
142 | $request = $this->getRequest(); |
143 | |
144 | $returnTo = $request->getVal( 'returnto' ); |
145 | $titleObj = $returnTo !== null ? Title::newFromText( $returnTo ) : null; |
146 | if ( !$titleObj instanceof Title ) { |
147 | $titleObj = Title::newMainPage(); |
148 | } |
149 | $query = $request->getVal( 'returntoquery', '' ); |
150 | |
151 | if ( $this->status->value === true ) { |
152 | $this->getOutput()->redirect( $titleObj->getFullUrlForRedirect( $query ) ); |
153 | } elseif ( $this->status->value === 'eauth' ) { |
154 | # Notify user that a confirmation email has been sent... |
155 | $out = $this->getOutput(); |
156 | $out->addHTML( |
157 | Html::warningBox( |
158 | $out->msg( 'eauthentsent', $this->getUser()->getName() )->parse() |
159 | ) |
160 | ); |
161 | // just show the link to go back |
162 | $this->getOutput()->addReturnTo( $titleObj, wfCgiToArray( $query ) ); |
163 | } |
164 | } |
165 | |
166 | /** |
167 | * @param User $user |
168 | * @param string $newAddr |
169 | * |
170 | * @return Status |
171 | */ |
172 | private function attemptChange( User $user, $newAddr ) { |
173 | if ( $newAddr !== '' && !Sanitizer::validateEmail( $newAddr ) ) { |
174 | return Status::newFatal( 'invalidemailaddress' ); |
175 | } |
176 | |
177 | $oldAddr = $user->getEmail(); |
178 | if ( $newAddr === $oldAddr ) { |
179 | return Status::newFatal( 'changeemail-nochange' ); |
180 | } |
181 | |
182 | if ( strlen( $newAddr ) > 255 ) { |
183 | return Status::newFatal( 'changeemail-maxlength' ); |
184 | } |
185 | |
186 | // To prevent spam, rate limit adding a new address, but do |
187 | // not rate limit removing an address. |
188 | if ( $newAddr !== '' ) { |
189 | // Enforce permissions, user blocks, and rate limits |
190 | $status = $this->authorizeAction( 'changeemail' ); |
191 | if ( !$status->isGood() ) { |
192 | return Status::wrap( $status ); |
193 | } |
194 | } |
195 | |
196 | $userLatest = $user->getInstanceForUpdate(); |
197 | $status = $userLatest->setEmailWithConfirmation( $newAddr ); |
198 | if ( !$status->isGood() ) { |
199 | return $status; |
200 | } |
201 | |
202 | LoggerFactory::getInstance( 'authentication' )->info( |
203 | 'Changing email address for {user} from {oldemail} to {newemail}', [ |
204 | 'user' => $userLatest->getName(), |
205 | 'oldemail' => $oldAddr, |
206 | 'newemail' => $newAddr, |
207 | ] |
208 | ); |
209 | |
210 | $this->getHookRunner()->onPrefsEmailAudit( $userLatest, $oldAddr, $newAddr ); |
211 | |
212 | $userLatest->saveSettings(); |
213 | |
214 | return $status; |
215 | } |
216 | |
217 | public function requiresUnblock() { |
218 | return false; |
219 | } |
220 | |
221 | protected function getGroupName() { |
222 | return 'login'; |
223 | } |
224 | } |
225 | |
226 | /** @deprecated class alias since 1.41 */ |
227 | class_alias( SpecialChangeEmail::class, 'SpecialChangeEmail' ); |