MediaWiki REL1_39
SpecialChangeEmail.php
Go to the documentation of this file.
1<?php
26
36 private $status;
37
41 public function __construct( AuthManager $authManager ) {
42 parent::__construct( 'ChangeEmail', 'editmyprivateinfo' );
43
44 $this->setAuthManager( $authManager );
45 }
46
47 public function doesWrites() {
48 return true;
49 }
50
54 public function isListed() {
55 return $this->getAuthManager()->allowsPropertyChange( 'emailaddress' );
56 }
57
62 public function execute( $par ) {
63 $out = $this->getOutput();
64 $out->disallowUserJs();
65 $out->addModules( 'mediawiki.special.changeemail' );
66 parent::execute( $par );
67 }
68
69 protected function getLoginSecurityLevel() {
70 return $this->getName();
71 }
72
73 protected function checkExecutePermissions( User $user ) {
74 if ( !$this->getAuthManager()->allowsPropertyChange( 'emailaddress' ) ) {
75 throw new ErrorPageError( 'changeemail', 'cannotchangeemail' );
76 }
77
78 $this->requireNamedUser( 'changeemail-no-info' );
79
80 // This could also let someone check the current email address, so
81 // require both permissions.
82 if ( !$this->getAuthority()->isAllowed( 'viewmyprivateinfo' ) ) {
83 throw new PermissionsError( 'viewmyprivateinfo' );
84 }
85
86 parent::checkExecutePermissions( $user );
87 }
88
89 protected function getFormFields() {
90 $user = $this->getUser();
91
92 $fields = [
93 'Name' => [
94 'type' => 'info',
95 'label-message' => 'username',
96 'default' => $user->getName(),
97 ],
98 'OldEmail' => [
99 'type' => 'info',
100 'label-message' => 'changeemail-oldemail',
101 'default' => $user->getEmail() ?: $this->msg( 'changeemail-none' )->text(),
102 ],
103 'NewEmail' => [
104 'type' => 'email',
105 'label-message' => 'changeemail-newemail',
106 'autofocus' => true,
107 'maxlength' => 255,
108 'help-message' => 'changeemail-newemail-help',
109 ],
110 ];
111
112 return $fields;
113 }
114
115 protected function getDisplayFormat() {
116 return 'ooui';
117 }
118
119 protected function alterForm( HTMLForm $form ) {
120 $form->setId( 'mw-changeemail-form' );
121 $form->setTableId( 'mw-changeemail-table' );
122 $form->setSubmitTextMsg( 'changeemail-submit' );
123 $form->addHiddenFields( $this->getRequest()->getValues( 'returnto', 'returntoquery' ) );
124
125 $form->addHeaderText( $this->msg( 'changeemail-header' )->parseAsBlock() );
126 $form->setSubmitID( 'change_email_submit' );
127 }
128
129 public function onSubmit( array $data ) {
130 $status = $this->attemptChange( $this->getUser(), $data['NewEmail'] );
131
132 $this->status = $status;
133
134 return $status;
135 }
136
137 public function onSuccess() {
138 $request = $this->getRequest();
139
140 $returnto = $request->getVal( 'returnto' );
141 $titleObj = $returnto !== null ? Title::newFromText( $returnto ) : null;
142 if ( !$titleObj instanceof Title ) {
143 $titleObj = Title::newMainPage();
144 }
145 $query = $request->getVal( 'returntoquery', '' );
146
147 if ( $this->status->value === true ) {
148 $this->getOutput()->redirect( $titleObj->getFullUrlForRedirect( $query ) );
149 } elseif ( $this->status->value === 'eauth' ) {
150 # Notify user that a confirmation email has been sent...
151 $out = $this->getOutput();
152 $out->addHTML(
153 Html::warningBox(
154 $out->msg( 'eauthentsent', $this->getUser()->getName() )->parse()
155 )
156 );
157 // just show the link to go back
158 $this->getOutput()->addReturnTo( $titleObj, wfCgiToArray( $query ) );
159 }
160 }
161
167 private function attemptChange( User $user, $newaddr ) {
168 if ( $newaddr != '' && !Sanitizer::validateEmail( $newaddr ) ) {
169 return Status::newFatal( 'invalidemailaddress' );
170 }
171
172 $oldaddr = $user->getEmail();
173 if ( $newaddr === $oldaddr ) {
174 return Status::newFatal( 'changeemail-nochange' );
175 }
176
177 if ( strlen( $newaddr ) > 255 ) {
178 return Status::newFatal( 'changeemail-maxlength' );
179 }
180
181 // To prevent spam, rate limit adding a new address, but do
182 // not rate limit removing an address.
183 if ( $newaddr !== '' && $user->pingLimiter( 'changeemail' ) ) {
184 return Status::newFatal( 'actionthrottledtext' );
185 }
186
187 $userLatest = $user->getInstanceForUpdate();
188 $status = $userLatest->setEmailWithConfirmation( $newaddr );
189 if ( !$status->isGood() ) {
190 return $status;
191 }
192
193 LoggerFactory::getInstance( 'authentication' )->info(
194 'Changing email address for {user} from {oldemail} to {newemail}', [
195 'user' => $userLatest->getName(),
196 'oldemail' => $oldaddr,
197 'newemail' => $newaddr,
198 ]
199 );
200
201 $this->getHookRunner()->onPrefsEmailAudit( $userLatest, $oldaddr, $newaddr );
202
203 $userLatest->saveSettings();
204
205 return $status;
206 }
207
208 public function requiresUnblock() {
209 return false;
210 }
211
212 protected function getGroupName() {
213 return 'users';
214 }
215}
wfCgiToArray( $query)
This is the logical opposite of wfArrayToCgi(): it accepts a query string as its argument and returns...
An error page which can definitely be safely rendered using the OutputPage.
Special page which uses an HTMLForm to handle processing.
string null $par
The sub-page of the special page.
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition HTMLForm.php:150
setTableId( $id)
Set the id of the <table> or outermost <div> element.
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
setId( $id)
setSubmitID( $t)
Set the id for the submit button.
addHeaderText( $msg, $section=null)
Add HTML to the header, inside the form.
Definition HTMLForm.php:937
addHiddenFields(array $fields)
Add an array of hidden fields to the output.
This serves as the entry point to the authentication system.
PSR-3 logger instance factory.
Show an error when a user tries to do something they do not have the necessary permissions for.
Let users change their email address.
doesWrites()
Indicates whether this special page may perform database writes.
requiresUnblock()
Whether this action cannot be executed by a blocked user.
getDisplayFormat()
Get display format for the form.
onSuccess()
Do something exciting on successful processing of the form, most likely to show a confirmation messag...
alterForm(HTMLForm $form)
Play with the HTMLForm if you need to more substantially.
getFormFields()
Get an HTMLForm descriptor array.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
checkExecutePermissions(User $user)
Called from execute() to check if the given user can perform this action.
__construct(AuthManager $authManager)
execute( $par)
Main execution point.
getLoginSecurityLevel()
Tells if the special page does something security-sensitive and needs extra defense against a stolen ...
onSubmit(array $data)
Process the form on POST submission.
getName()
Get the name of this Special Page.
getOutput()
Get the OutputPage being used for this instance.
getUser()
Shortcut to get the User executing this instance.
requireNamedUser( $reasonMsg='exception-nologin-text', $titleMsg='exception-nologin')
If the user is not logged in or is a temporary user, throws UserNotLoggedIn.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getAuthority()
Shortcut to get the Authority executing this instance.
getRequest()
Get the WebRequest being used for this instance.
setAuthManager(AuthManager $authManager)
Set the injected AuthManager from the special page constructor.
static newFatal( $message,... $parameters)
Factory function for fatal errors.
isGood()
Returns whether the operation completed and didn't have any error or warnings.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:44
Represents a title within MediaWiki.
Definition Title.php:49
internal since 1.36
Definition User.php:70
getName()
Get the user name, or the IP of an anonymous user.
Definition User.php:1679
pingLimiter( $action='edit', $incrBy=1)
Primitive rate limits: enforce maximum actions per time period to put a brake on flooding.
Definition User.php:1480
getEmail()
Get the user's e-mail address.
Definition User.php:1997
getInstanceForUpdate()
Get a new instance of this user that was loaded from the primary DB via a locking read.
Definition User.php:3428