MediaWiki  master
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 
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  }
127 
128  public function onSubmit( array $data ) {
129  $status = $this->attemptChange( $this->getUser(), $data['NewEmail'] );
130 
131  $this->status = $status;
132 
133  return $status;
134  }
135 
136  public function onSuccess() {
137  $request = $this->getRequest();
138 
139  $returnto = $request->getVal( 'returnto' );
140  $titleObj = $returnto !== null ? Title::newFromText( $returnto ) : null;
141  if ( !$titleObj instanceof Title ) {
142  $titleObj = Title::newMainPage();
143  }
144  $query = $request->getVal( 'returntoquery' );
145 
146  if ( $this->status->value === true ) {
147  $this->getOutput()->redirect( $titleObj->getFullUrlForRedirect( $query ) );
148  } elseif ( $this->status->value === 'eauth' ) {
149  # Notify user that a confirmation email has been sent...
150  $out = $this->getOutput();
151  $out->addHTML(
153  $out->msg( 'eauthentsent', $this->getUser()->getName() )->parse()
154  )
155  );
156  // just show the link to go back
157  $this->getOutput()->addReturnTo( $titleObj, wfCgiToArray( $query ) );
158  }
159  }
160 
166  private function attemptChange( User $user, $newaddr ) {
167  if ( $newaddr != '' && !Sanitizer::validateEmail( $newaddr ) ) {
168  return Status::newFatal( 'invalidemailaddress' );
169  }
170 
171  $oldaddr = $user->getEmail();
172  if ( $newaddr === $oldaddr ) {
173  return Status::newFatal( 'changeemail-nochange' );
174  }
175 
176  if ( strlen( $newaddr ) > 255 ) {
177  return Status::newFatal( 'changeemail-maxlength' );
178  }
179 
180  // To prevent spam, rate limit adding a new address, but do
181  // not rate limit removing an address.
182  if ( $newaddr !== '' && $user->pingLimiter( 'changeemail' ) ) {
183  return Status::newFatal( 'actionthrottledtext' );
184  }
185 
186  $userLatest = $user->getInstanceForUpdate();
187  $status = $userLatest->setEmailWithConfirmation( $newaddr );
188  if ( !$status->isGood() ) {
189  return $status;
190  }
191 
192  LoggerFactory::getInstance( 'authentication' )->info(
193  'Changing email address for {user} from {oldemail} to {newemail}', [
194  'user' => $userLatest->getName(),
195  'oldemail' => $oldaddr,
196  'newemail' => $newaddr,
197  ]
198  );
199 
200  $this->getHookRunner()->onPrefsEmailAudit( $userLatest, $oldaddr, $newaddr );
201 
202  $userLatest->saveSettings();
203 
204  return $status;
205  }
206 
207  public function requiresUnblock() {
208  return false;
209  }
210 
211  protected function getGroupName() {
212  return 'users';
213  }
214 }
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.
Definition: HTMLForm.php:1743
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
Definition: HTMLForm.php:1604
setId( $id)
Definition: HTMLForm.php:1754
addHeaderText( $msg, $section=null)
Add HTML to the header, inside the form.
Definition: HTMLForm.php:929
addHiddenFields(array $fields)
Add an array of hidden fields to the output.
Definition: HTMLForm.php:1143
static warningBox( $html, $className='')
Return a warning box.
Definition: Html.php:775
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.
static validateEmail( $addr)
Does a string look like an e-mail address?
Definition: Sanitizer.php:1878
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.
Definition: StatusValue.php:70
isGood()
Returns whether the operation completed and didn't have any error or warnings.
Represents a title within MediaWiki.
Definition: Title.php:49
static newMainPage(MessageLocalizer $localizer=null)
Create a new Title for the Main Page.
Definition: Title.php:700
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:370
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:70
getName()
Get the user name, or the IP of an anonymous user.
Definition: User.php:1702
pingLimiter( $action='edit', $incrBy=1)
Primitive rate limits: enforce maximum actions per time period to put a brake on flooding.
Definition: User.php:1478
getEmail()
Get the user's e-mail address.
Definition: User.php:2020
getInstanceForUpdate()
Get a new instance of this user that was loaded from the primary DB via a locking read.
Definition: User.php:3442