MediaWiki master
SpecialConfirmEmail.php
Go to the documentation of this file.
1<?php
24namespace MediaWiki\Specials;
25
36use Profiler;
39use Wikimedia\ScopedCallback;
40
50
51 private UserFactory $userFactory;
52
56 public function __construct( UserFactory $userFactory ) {
57 parent::__construct( 'Confirmemail', 'editmyprivateinfo' );
58
59 $this->userFactory = $userFactory;
60 }
61
62 public function doesWrites() {
63 return true;
64 }
65
74 public function execute( $code ) {
75 // Ignore things like primary queries/connections on GET requests.
76 // It's very convenient to just allow formless link usage.
77 $trxProfiler = Profiler::instance()->getTransactionProfiler();
78
79 $this->setHeaders();
80 $this->checkReadOnly();
81 $this->checkPermissions();
82
83 // This could also let someone check the current email address, so
84 // require both permissions.
85 if ( !$this->getAuthority()->isAllowed( 'viewmyprivateinfo' ) ) {
86 throw new PermissionsError( 'viewmyprivateinfo' );
87 }
88
89 if ( $code === null || $code === '' ) {
90 $this->requireNamedUser( 'confirmemail_needlogin' );
91 if ( Sanitizer::validateEmail( $this->getUser()->getEmail() ) ) {
92 $this->showRequestForm();
93 } else {
94 $this->getOutput()->addWikiMsg( 'confirmemail_noemail' );
95 }
96 } else {
97 $scope = $trxProfiler->silenceForScope( $trxProfiler::EXPECTATION_REPLICAS_ONLY );
98 $this->attemptConfirm( $code );
99 ScopedCallback::consume( $scope );
100 }
101 }
102
106 private function showRequestForm() {
107 $user = $this->getUser();
108 $out = $this->getOutput();
109
110 if ( !$user->isEmailConfirmed() ) {
111 $descriptor = [];
112 if ( $user->isEmailConfirmationPending() ) {
113 $descriptor += [
114 'pending' => [
115 'type' => 'info',
116 'raw' => true,
117 'default' => "<div class=\"error mw-confirmemail-pending\">\n" .
118 $this->msg( 'confirmemail_pending' )->escaped() .
119 "\n</div>",
120 ],
121 ];
122 }
123
124 $out->addWikiMsg( 'confirmemail_text' );
125 $form = HTMLForm::factory( 'ooui', $descriptor, $this->getContext() );
126 $form
127 ->setAction( $this->getPageTitle()->getLocalURL() )
128 ->setSubmitTextMsg( 'confirmemail_send' )
129 ->setSubmitCallback( [ $this, 'submitSend' ] );
130
131 $retval = $form->show();
132
133 if ( $retval === true ) {
134 // should never happen, but if so, don't let the user without any message
135 $out->addWikiMsg( 'confirmemail_sent' );
136 } elseif ( $retval instanceof Status && $retval->isGood() ) {
137 $out->addWikiTextAsInterface( $retval->getValue() );
138 }
139 } else {
140 // date and time are separate parameters to facilitate localisation.
141 // $time is kept for backward compat reasons.
142 // 'emailauthenticated' is also used in SpecialPreferences.php
143 $lang = $this->getLanguage();
144 $emailAuthenticated = $user->getEmailAuthenticationTimestamp();
145 $time = $lang->userTimeAndDate( $emailAuthenticated, $user );
146 $d = $lang->userDate( $emailAuthenticated, $user );
147 $t = $lang->userTime( $emailAuthenticated, $user );
148 $out->addWikiMsg( 'emailauthenticated', $time, $d, $t );
149 }
150 }
151
157 public function submitSend() {
158 $status = $this->getUser()->sendConfirmationMail();
159 if ( $status->isGood() ) {
160 return Status::newGood( $this->msg( 'confirmemail_sent' )->text() );
161 } else {
162 return Status::newFatal( new RawMessage(
163 $status->getWikiText( 'confirmemail_sendfailed', false, $this->getLanguage() )
164 ) );
165 }
166 }
167
174 private function attemptConfirm( $code ) {
175 $user = $this->userFactory->newFromConfirmationCode(
176 $code,
177 IDBAccessObject::READ_LATEST
178 );
179
180 if ( !is_object( $user ) ) {
181 if ( User::isWellFormedConfirmationToken( $code ) ) {
182 $this->getOutput()->addWikiMsg( 'confirmemail_invalid' );
183 } else {
184 $this->getOutput()->addWikiMsg( 'confirmemail_invalid_format' );
185 }
186
187 return;
188 }
189
190 // rate limit email confirmations
191 if ( $user->pingLimiter( 'confirmemail' ) ) {
192 $this->getOutput()->addWikiMsg( 'actionthrottledtext' );
193
194 return;
195 }
196
197 $userLatest = $user->getInstanceForUpdate();
198 $userLatest->confirmEmail();
199 $userLatest->saveSettings();
200 $message = $this->getUser()->isNamed() ? 'confirmemail_loggedin' : 'confirmemail_success';
201 $this->getOutput()->addWikiMsg( $message );
202
203 if ( !$this->getUser()->isNamed() ) {
204 $title = SpecialPage::getTitleFor( 'Userlogin' );
205 $this->getOutput()->returnToMain( true, $title );
206 }
207 }
208}
209
213class_alias( SpecialConfirmEmail::class, 'SpecialConfirmEmail' );
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition HTMLForm.php:206
Variant of the Message class.
HTML sanitizer for MediaWiki.
Definition Sanitizer.php:46
Parent class for all special pages.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
getUser()
Shortcut to get the User executing this instance.
getPageTitle( $subpage=false)
Get a self-referential title object.
checkPermissions()
Checks if userCanExecute, and if not throws a PermissionsError.
checkReadOnly()
If the wiki is currently in readonly mode, throws a ReadOnlyError.
getContext()
Gets the context this SpecialPage is executed in.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
requireNamedUser( $reasonMsg='exception-nologin-text', $titleMsg='exception-nologin')
If the user is not logged in or is a temporary user, throws UserNotLoggedIn.
getOutput()
Get the OutputPage being used for this instance.
getAuthority()
Shortcut to get the Authority executing this instance.
getLanguage()
Shortcut to get user's language.
Shortcut to construct a special page which is unlisted by default.
Special page allows users to request email confirmation message, and handles processing of the confir...
doesWrites()
Indicates whether this special page may perform database writes.
submitSend()
Callback for HTMLForm send confirmation mail.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:54
Creates User objects.
internal since 1.36
Definition User.php:93
Show an error when a user tries to do something they do not have the necessary permissions for.
Profiler base class that defines the interface and some shared functionality.
Definition Profiler.php:37
static instance()
Definition Profiler.php:105
Show an error when the wiki is locked/read-only and the user tries to do something that requires writ...
Redirect a user to the login page.
Interface for database access objects.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...