MediaWiki  master
SpecialChangeEmail.php
Go to the documentation of this file.
1 <?php
27 
37  private $status;
38 
39  public function __construct() {
40  parent::__construct( 'ChangeEmail', 'editmyprivateinfo' );
41  }
42 
43  public function doesWrites() {
44  return true;
45  }
46 
50  public function isListed() {
51  return AuthManager::singleton()->allowsPropertyChange( 'emailaddress' );
52  }
53 
58  function execute( $par ) {
59  $out = $this->getOutput();
60  $out->disallowUserJs();
61 
62  parent::execute( $par );
63  }
64 
65  protected function getLoginSecurityLevel() {
66  return $this->getName();
67  }
68 
69  protected function checkExecutePermissions( User $user ) {
70  if ( !AuthManager::singleton()->allowsPropertyChange( 'emailaddress' ) ) {
71  throw new ErrorPageError( 'changeemail', 'cannotchangeemail' );
72  }
73 
74  $this->requireLogin( 'changeemail-no-info' );
75 
76  // This could also let someone check the current email address, so
77  // require both permissions.
78  if ( !MediaWikiServices::getInstance()
80  ->userHasRight( $this->getUser(), 'viewmyprivateinfo' )
81  ) {
82  throw new PermissionsError( 'viewmyprivateinfo' );
83  }
84 
85  parent::checkExecutePermissions( $user );
86  }
87 
88  protected function getFormFields() {
89  $user = $this->getUser();
90 
91  $fields = [
92  'Name' => [
93  'type' => 'info',
94  'label-message' => 'username',
95  'default' => $user->getName(),
96  ],
97  'OldEmail' => [
98  'type' => 'info',
99  'label-message' => 'changeemail-oldemail',
100  'default' => $user->getEmail() ?: $this->msg( 'changeemail-none' )->text(),
101  ],
102  'NewEmail' => [
103  'type' => 'email',
104  'label-message' => 'changeemail-newemail',
105  'autofocus' => true,
106  'help-message' => 'changeemail-newemail-help',
107  ],
108  ];
109 
110  return $fields;
111  }
112 
113  protected function getDisplayFormat() {
114  return 'ooui';
115  }
116 
117  protected function alterForm( HTMLForm $form ) {
118  $form->setId( 'mw-changeemail-form' );
119  $form->setTableId( 'mw-changeemail-table' );
120  $form->setSubmitTextMsg( 'changeemail-submit' );
121  $form->addHiddenFields( $this->getRequest()->getValues( 'returnto', 'returntoquery' ) );
122 
123  $form->addHeaderText( $this->msg( 'changeemail-header' )->parseAsBlock() );
124  }
125 
126  public function onSubmit( array $data ) {
127  $status = $this->attemptChange( $this->getUser(), $data['NewEmail'] );
128 
129  $this->status = $status;
130 
131  return $status;
132  }
133 
134  public function onSuccess() {
135  $request = $this->getRequest();
136 
137  $returnto = $request->getVal( 'returnto' );
138  $titleObj = $returnto !== null ? Title::newFromText( $returnto ) : null;
139  if ( !$titleObj instanceof Title ) {
140  $titleObj = Title::newMainPage();
141  }
142  $query = $request->getVal( 'returntoquery' );
143 
144  if ( $this->status->value === true ) {
145  $this->getOutput()->redirect( $titleObj->getFullUrlForRedirect( $query ) );
146  } elseif ( $this->status->value === 'eauth' ) {
147  # Notify user that a confirmation email has been sent...
148  $this->getOutput()->wrapWikiMsg( "<div class='error' style='clear: both;'>\n$1\n</div>",
149  'eauthentsent', $this->getUser()->getName() );
150  // just show the link to go back
151  $this->getOutput()->addReturnTo( $titleObj, wfCgiToArray( $query ) );
152  }
153  }
154 
160  private function attemptChange( User $user, $newaddr ) {
161  if ( $newaddr != '' && !Sanitizer::validateEmail( $newaddr ) ) {
162  return Status::newFatal( 'invalidemailaddress' );
163  }
164 
165  if ( $newaddr === $user->getEmail() ) {
166  return Status::newFatal( 'changeemail-nochange' );
167  }
168 
169  // To prevent spam, rate limit adding a new address, but do
170  // not rate limit removing an address.
171  if ( $newaddr !== '' && $user->pingLimiter( 'changeemail' ) ) {
172  return Status::newFatal( 'actionthrottledtext' );
173  }
174 
175  $oldaddr = $user->getEmail();
176  $status = $user->setEmailWithConfirmation( $newaddr );
177  if ( !$status->isGood() ) {
178  return $status;
179  }
180 
181  LoggerFactory::getInstance( 'authentication' )->info(
182  'Changing email address for {user} from {oldemail} to {newemail}', [
183  'user' => $user->getName(),
184  'oldemail' => $oldaddr,
185  'newemail' => $newaddr,
186  ]
187  );
188 
189  Hooks::run( 'PrefsEmailAudit', [ $user, $oldaddr, $newaddr ] );
190 
191  $user->saveSettings();
192 
193  return $status;
194  }
195 
196  public function requiresUnblock() {
197  return false;
198  }
199 
200  protected function getGroupName() {
201  return 'users';
202  }
203 }
getEmail()
Get the user&#39;s e-mail address.
Definition: User.php:2798
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:69
saveSettings()
Save this user&#39;s settings into the database.
Definition: User.php:3918
static newMainPage(MessageLocalizer $localizer=null)
Create a new Title for the Main Page.
Definition: Title.php:648
isGood()
Returns whether the operation completed and didn&#39;t have any error or warnings.
checkExecutePermissions(User $user)
getOutput()
Get the OutputPage being used for this instance.
Let users change their email address.
Special page which uses an HTMLForm to handle processing.
getName()
Get the user name, or the IP of an anonymous user.
Definition: User.php:2229
setId( $id)
Definition: HTMLForm.php:1524
addHiddenFields(array $fields)
Add an array of hidden fields to the output.
Definition: HTMLForm.php:960
static validateEmail( $addr)
Does a string look like an e-mail address?
Definition: Sanitizer.php:2165
The User object encapsulates all of the user-specific settings (user_id, name, rights, email address, options, last login time).
Definition: User.php:51
attemptChange(User $user, $newaddr)
getPermissionManager()
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
execute( $par)
Main execution point.
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.
setTableId( $id)
Set the id of the <table> or outermost <div> element.
Definition: HTMLForm.php:1513
alterForm(HTMLForm $form)
string null $par
The sub-page of the special page.
getName()
Get the name of this Special Page.
pingLimiter( $action='edit', $incrBy=1)
Primitive rate limits: enforce maximum actions per time period to put a brake on flooding.
Definition: User.php:1908
requireLogin( $reasonMsg='exception-nologin-text', $titleMsg='exception-nologin')
If the user is not logged in, throws UserNotLoggedIn error.
getUser()
Shortcut to get the User executing this instance.
Show an error when a user tries to do something they do not have the necessary permissions for...
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
Definition: HTMLForm.php:1392
setEmailWithConfirmation( $str)
Set the user&#39;s e-mail address and a confirmation mail if needed.
Definition: User.php:2835
getRequest()
Get the WebRequest being used for this instance.
addHeaderText( $msg, $section=null)
Add HTML to the header, inside the form.
Definition: HTMLForm.php:806
static run( $event, array $args=[], $deprecatedVersion=null)
Call hook functions defined in Hooks::register and $wgHooks.
Definition: Hooks.php:200
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:319