60 private $loadBalancer;
63 private $userOptionsLookup;
79 parent::__construct( $params );
81 if ( isset( $params[
'emailEnabled'] ) ) {
82 $this->emailEnabled = (bool)$params[
'emailEnabled'];
84 if ( isset( $params[
'newPasswordExpiry'] ) ) {
85 $this->newPasswordExpiry = (int)$params[
'newPasswordExpiry'];
87 if ( isset( $params[
'passwordReminderResendTime'] ) ) {
88 $this->passwordReminderResendTime = $params[
'passwordReminderResendTime'];
90 if ( isset( $params[
'allowRequiringEmailForResets'] ) ) {
91 $this->allowRequiringEmail = $params[
'allowRequiringEmailForResets'];
93 $this->loadBalancer = $loadBalancer;
94 $this->userOptionsLookup = $userOptionsLookup;
100 $this->passwordReminderResendTime ??=
102 $this->allowRequiringEmail ??=
109 'msg' =>
wfMessage(
'resetpass-temp-emailed' ),
123 if ( isset( $options[
'username'] ) && $this->emailEnabled ) {
142 if ( !$req || $req->username ===
null || $req->password ===
null ) {
146 $username = $this->userNameUtils->getCanonical(
147 $req->username, UserRigorOptions::RIGOR_USABLE );
148 if ( $username ===
false ) {
152 $row = $this->loadBalancer->getConnection(
DB_REPLICA )->newSelectQueryBuilder()
153 ->select( [
'user_id',
'user_newpassword',
'user_newpass_time' ] )
155 ->where( [
'user_name' => $username ] )
156 ->caller( __METHOD__ )->fetchRow();
162 if ( !$status->isOK() ) {
167 $pwhash = $this->
getPassword( $row->user_newpassword );
168 if ( !$pwhash->verify( $req->password ) ) {
179 $this->logger->info(
"{user} successfully logged in using temp password",
182 'requestIP' => $this->manager->getRequest()->getIP()
192 $username = $this->userNameUtils->getCanonical( $username, UserRigorOptions::RIGOR_USABLE );
193 if ( $username ===
false ) {
197 $row = $this->loadBalancer->getConnection(
DB_REPLICA )->newSelectQueryBuilder()
198 ->select( [
'user_newpassword',
'user_newpass_time' ] )
200 ->where( [
'user_name' => $username ] )
201 ->caller( __METHOD__ )->fetchRow();
218 $username = $this->userNameUtils->getCanonical( $username, UserRigorOptions::RIGOR_USABLE );
219 if ( $username ===
false ) {
223 [ $db, $options ] = \DBAccessObjectUtils::getDBOptions( $flags );
224 return (
bool)$this->loadBalancer->getConnection( $db )->newSelectQueryBuilder()
225 ->select( [
'user_id' ] )
227 ->where( [
'user_name' => $username ] )
228 ->options( $options )
229 ->caller( __METHOD__ )->fetchField();
235 if ( get_class( $req ) !== TemporaryPasswordAuthenticationRequest::class ) {
237 return \StatusValue::newGood(
'ignored' );
241 return \StatusValue::newGood();
244 $username = $this->userNameUtils->getCanonical(
245 $req->username, UserRigorOptions::RIGOR_USABLE );
246 if ( $username ===
false ) {
247 return \StatusValue::newGood(
'ignored' );
250 $row = $this->loadBalancer->getConnection(
DB_PRIMARY )->newSelectQueryBuilder()
251 ->select( [
'user_id',
'user_newpass_time' ] )
253 ->where( [
'user_name' => $username ] )
254 ->caller( __METHOD__ )->fetchRow();
256 return \StatusValue::newGood(
'ignored' );
259 $sv = \StatusValue::newGood();
260 if ( $req->password !==
null ) {
263 if ( $req->mailpassword ) {
264 if ( !$this->emailEnabled ) {
265 return \StatusValue::newFatal(
'passwordreset-emaildisabled' );
274 $this->passwordReminderResendTime
275 && $row->user_newpass_time
276 && time() < (
int)
wfTimestamp( TS_UNIX, $row->user_newpass_time )
277 + $this->passwordReminderResendTime * 3600
281 return \StatusValue::newFatal(
'throttled-mailpassword',
282 round( $this->passwordReminderResendTime, 3 ) );
285 if ( !$req->caller ) {
286 return \StatusValue::newFatal(
'passwordreset-nocaller' );
288 if ( !IPUtils::isValid( $req->caller ) ) {
291 return \StatusValue::newFatal(
'passwordreset-nosuchcaller', $req->caller );
300 $username = $req->username !==
null ?
301 $this->userNameUtils->getCanonical( $req->username, UserRigorOptions::RIGOR_USABLE ) :
false;
302 if ( $username ===
false ) {
306 $dbw = $this->loadBalancer->getConnectionRef(
DB_PRIMARY );
310 get_class( $req ) === TemporaryPasswordAuthenticationRequest::class
313 $newpassTime = $dbw->timestamp();
314 $sendMail = $req->mailpassword;
324 'user_newpassword' => $pwhash->toString(),
325 'user_newpass_time' => $newpassTime,
327 [
'user_name' => $username ],
333 $dbw->onTransactionCommitOrIdle(
334 function () use ( $req ) {
350 $reqs, TemporaryPasswordAuthenticationRequest::class
353 $ret = \StatusValue::newGood();
355 if ( $req->mailpassword ) {
356 if ( !$this->emailEnabled ) {
357 $ret->merge( \StatusValue::newFatal(
'emaildisabled' ) );
358 } elseif ( !$user->getEmail() ) {
359 $ret->merge( \StatusValue::newFatal(
'noemailcreate' ) );
373 $reqs, TemporaryPasswordAuthenticationRequest::class
375 if ( $req && $req->username !==
null && $req->password !==
null ) {
377 if ( $req->username !== $user->getName() ) {
379 $req->username = $user->getName();
382 if ( $req->mailpassword ) {
384 $this->manager->setAuthenticationSessionData(
'no-email',
true );
388 $ret->createRequest = $req;
396 $req =
$res->createRequest;
397 $mailpassword = $req->mailpassword;
398 $req->mailpassword =
false;
403 if ( $mailpassword ) {
405 $this->loadBalancer->getConnectionRef(
DB_PRIMARY )->onTransactionCommitOrIdle(
406 function () use ( $user, $creator, $req ) {
413 return $mailpassword ?
'byemail' :
null;
423 if ( $time !==
null ) {
425 if ( time() >= $expiry ) {
443 return \Status::newFatal(
'badipaddress' );
447 $this->
getHookRunner()->onUser__mailPasswordInternal( $creatingUser, $ip, $user );
450 $userLanguage = $this->userOptionsLookup->getOption( $user,
'language' );
451 $subjectMessage =
wfMessage(
'createaccount-title' )->inLanguage( $userLanguage );
452 $bodyMessage =
wfMessage(
'createaccount-text', $ip, $user->
getName(), $password,
453 '<' . $mainPageUrl .
'>', round( $this->newPasswordExpiry / 86400 ) )
454 ->inLanguage( $userLanguage );
456 $status = $user->
sendMail( $subjectMessage->text(), $bodyMessage->text() );
460 if ( !$status->isGood() ) {
461 $this->logger->warning(
'Could not send account creation email: ' .
462 $status->getWikiText(
false,
false,
'en' ) );
476 return \Status::newFatal(
'noname' );
478 $userLanguage = $this->userOptionsLookup->getOption( $user,
'language' );
479 $callerIsAnon = IPUtils::isValid( $req->caller );
480 $callerName = $callerIsAnon ? $req->caller :
User::newFromName( $req->caller )->getName();
481 $passwordMessage =
wfMessage(
'passwordreset-emailelement', $user->getName(),
482 $req->password )->inLanguage( $userLanguage );
483 $emailMessage =
wfMessage( $callerIsAnon ?
'passwordreset-emailtext-ip'
484 :
'passwordreset-emailtext-user' )->inLanguage( $userLanguage );
485 $body = $emailMessage->params( $callerName, $passwordMessage->text(), 1,
487 round( $this->newPasswordExpiry / 86400 ) )->text();
489 if ( $this->allowRequiringEmail && !$this->userOptionsLookup
490 ->getBoolOption( $user,
'requireemail' )
495 $body .=
wfMessage(
'passwordreset-emailtext-require-email' )
496 ->inLanguage( $userLanguage )
501 $emailTitle =
wfMessage(
'passwordreset-emailtitle' )->inLanguage( $userLanguage );
502 return $user->sendMail( $emailTitle->text(), $body );
wfTimestampOrNull( $outputtype=TS_UNIX, $ts=null)
Return a formatted timestamp, or null if input is null.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Represents an invalid password hash.
A class containing constants representing the names of configuration variables.
const PasswordReminderResendTime
Name constant for the PasswordReminderResendTime setting, for use with Config::get()
const EnableEmail
Name constant for the EnableEmail setting, for use with Config::get()
const NewPasswordExpiry
Name constant for the NewPasswordExpiry setting, for use with Config::get()
const AllowRequiringEmailForResets
Name constant for the AllowRequiringEmailForResets setting, for use with Config::get()
Parent class for all special pages.
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,...
getRequest()
Get the WebRequest object to use with this object.
getName()
Get the user name, or the IP of an anonymous user.
static newFromName( $name, $validate='valid')
sendMail( $subject, $body, $from=null, $replyto=null)
Send an e-mail to this user's account.