21use Wikimedia\Timestamp\TimestampFormat as TS;
63 parent::__construct( $params );
65 if ( isset( $params[
'emailEnabled'] ) ) {
66 $this->emailEnabled = (bool)$params[
'emailEnabled'];
68 if ( isset( $params[
'newPasswordExpiry'] ) ) {
69 $this->newPasswordExpiry = (int)$params[
'newPasswordExpiry'];
71 if ( isset( $params[
'passwordReminderResendTime'] ) ) {
72 $this->passwordReminderResendTime = $params[
'passwordReminderResendTime'];
81 $this->passwordReminderResendTime ??=
89 'msg' =>
wfMessage(
'resetpass-temp-emailed' ),
109 isset( $options[
'username'] ) &&
110 !$this->userNameUtils->isTemp( $options[
'username'] ) &&
129 if ( !$req || $req->username ===
null || $req->password ===
null ) {
133 $username = $this->userNameUtils->getCanonical(
134 $req->username, UserRigorOptions::RIGOR_USABLE );
135 if ( $username ===
false ) {
139 [ $tempPassHash, $tempPassTime ] = $this->
getTemporaryPassword( $username, IDBAccessObject::READ_LATEST );
140 if ( !$tempPassHash ) {
145 if ( !$status->isOK() ) {
149 if ( !$tempPassHash->verify( $req->password ) ||
150 !$this->isTimestampValid( $tempPassTime )
158 $this->logger->info(
"{user} successfully logged in using temp password",
160 'provider' => static::class,
162 'requestIP' => $this->manager->getRequest()->getIP()
173 $username = $this->userNameUtils->getCanonical( $username, UserRigorOptions::RIGOR_USABLE );
174 if ( $username ===
false ) {
179 return $tempPassHash &&
188 if ( get_class( $req ) !== TemporaryPasswordAuthenticationRequest::class ) {
190 return \StatusValue::newGood(
'ignored' );
194 return \StatusValue::newGood();
197 $username = $this->userNameUtils->getCanonical(
198 $req->username, UserRigorOptions::RIGOR_USABLE );
199 if ( $username ===
false ) {
200 return \StatusValue::newGood(
'ignored' );
203 [ $tempPassHash, $tempPassTime ] = $this->
getTemporaryPassword( $username, IDBAccessObject::READ_LATEST );
204 if ( !$tempPassHash ) {
205 return \StatusValue::newGood(
'ignored' );
208 $sv = \StatusValue::newGood();
209 if ( $req->password !==
null ) {
212 if ( $req->mailpassword ) {
213 if ( !$this->emailEnabled ) {
214 return \StatusValue::newFatal(
'passwordreset-emaildisabled' );
223 $this->passwordReminderResendTime
225 && time() < (
int)
wfTimestamp( TS::UNIX, $tempPassTime )
226 + $this->passwordReminderResendTime * 3600
230 return \StatusValue::newFatal(
'throttled-mailpassword',
231 round( $this->passwordReminderResendTime, 3 ) );
234 if ( !$req->caller ) {
235 return \StatusValue::newFatal(
'passwordreset-nocaller' );
237 if ( !IPUtils::isValid( $req->caller ) ) {
238 $caller = User::newFromName( $req->caller );
240 return \StatusValue::newFatal(
'passwordreset-nosuchcaller', $req->caller );
249 $username = $req->username !==
null ?
250 $this->userNameUtils->getCanonical( $req->username, UserRigorOptions::RIGOR_USABLE ) :
false;
251 if ( $username ===
false ) {
257 get_class( $req ) === TemporaryPasswordAuthenticationRequest::class
261 $sendMail = $req->mailpassword;
263 $req->mailpassword =
false;
266 $tempPassHash = PasswordFactory::newInvalidPassword();
267 $tempPassTime =
null;
286 $reqs, TemporaryPasswordAuthenticationRequest::class
289 $ret = \StatusValue::newGood();
291 if ( $req->mailpassword ) {
292 if ( !$this->emailEnabled ) {
293 $ret->merge( \StatusValue::newFatal(
'emaildisabled' ) );
295 $ret->merge( \StatusValue::newFatal(
'noemailcreate' ) );
310 $reqs, TemporaryPasswordAuthenticationRequest::class
312 if ( $req && $req->username !==
null && $req->password !==
null ) {
314 if ( $req->username !== $user->
getName() ) {
316 $req->username = $user->
getName();
319 if ( $req->mailpassword ) {
321 $this->manager->setAuthenticationSessionData(
'no-email',
true );
325 $ret->createRequest = $req;
334 $req = $res->createRequest;
335 $mailpassword = $req->mailpassword;
337 $req->mailpassword =
false;
342 if ( $mailpassword ) {
346 return $mailpassword ?
'byemail' :
null;
357 if ( $time !==
null ) {
359 if ( time() >= $expiry ) {
379 $this->dbProvider->getPrimaryDatabase()->onTransactionCommitOrIdle(
380 function () use ( $user, $creatingUser, $password ) {
396 $ip = $creatingUser->getRequest()->getIP();
403 $this->getHookRunner()->onUser__mailPasswordInternal( $creatingUser, $ip, $user );
405 $mainPageUrl = Title::newMainPage()->getCanonicalURL();
406 $userLanguage = $this->userOptionsLookup->getOption( $user,
'language' );
407 $subjectMessage =
wfMessage(
'createaccount-title' )->inLanguage( $userLanguage );
408 $bodyMessage =
wfMessage(
'createaccount-text', $ip, $user->
getName(), $password,
409 '<' . $mainPageUrl .
'>', round( $this->newPasswordExpiry / 86400 ) )
410 ->inLanguage( $userLanguage );
412 $status = $user->
sendMail( $subjectMessage->text(), $bodyMessage->text() );
415 if ( !$status->isGood() ) {
416 $this->logger->warning(
'Could not send account creation email: ' .
417 $status->getWikiText(
false,
false,
'en' ) );
432 $this->dbProvider->getPrimaryDatabase()->onTransactionCommitOrIdle(
433 function () use ( $req ) {
434 $this->sendPasswordResetEmail( $req );
447 $user =
User::newFromName( $req->username );
451 $userLanguage = $this->userOptionsLookup->getOption( $user,
'language' );
452 $callerIsAnon = IPUtils::isValid( $req->caller );
453 $callerName = $callerIsAnon ? $req->caller : User::newFromName( $req->caller )->getName();
454 $passwordMessage =
wfMessage(
'passwordreset-emailelement', $user->
getName(),
455 $req->password )->inLanguage( $userLanguage );
456 $emailMessage =
wfMessage( $callerIsAnon ?
'passwordreset-emailtext-ip'
457 :
'passwordreset-emailtext-user' )->inLanguage( $userLanguage );
458 $body = $emailMessage->params( $callerName, $passwordMessage->text(), 1,
459 '<' . Title::newMainPage()->getCanonicalURL() .
'>',
460 round( $this->newPasswordExpiry / 86400 ) )->text();
464 !$this->userOptionsLookup->getBoolOption( $user,
'requireemail' )
466 $url = SpecialPage::getTitleFor(
'Preferences',
false,
'mw-prefsection-personal-email' )
468 $body .=
"\n\n" .
wfMessage(
'passwordreset-emailtext-require-email' )
469 ->inLanguage( $userLanguage )
474 $emailTitle =
wfMessage(
'passwordreset-emailtitle' )->inLanguage( $userLanguage );
475 $user->
sendMail( $emailTitle->text(), $body );
494 abstract protected function getTemporaryPassword(
string $username, $flags = IDBAccessObject::READ_NORMAL ): array;
wfTimestampOrNull( $outputtype=TS::UNIX, $ts=null)
Return a formatted timestamp, or null if input is null.
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
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.
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()
Parent class for all special pages.