mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-23 14:00:56 +01:00
Move "Password Reset" email to "PeopleMailEngine"
Summary: Ref T13343. This makes "Password Reset" email a little more consistent with other modern types of email. My expectation is that this patch has no functional changes, just organizes code a little more consistently. The new `setRecipientAddress()` mechanism deals with the case where the user types a secondary (but still verified) address. Test Plan: - Sent a normal "login with email" email. - Sent a "login with email to set password" email by trying to set a password on an account with no password yet. - Tried to email reset a bot account (no dice: they can't do web logins so this operation isn't valid). - Tested existing "PeopleMailEngine" subclasses: - Created a new user and sent a "welcome" email. - Renamed a user and sent a "username changed" email. - Reviewed all generated mail with `bin/mail list-outbound`. Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13343 Differential Revision: https://secure.phabricator.com/D20662
This commit is contained in:
parent
f55aac49f4
commit
5dd4895001
6 changed files with 151 additions and 65 deletions
|
@ -4001,6 +4001,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPeopleDeleteController' => 'applications/people/controller/PhabricatorPeopleDeleteController.php',
|
||||
'PhabricatorPeopleDetailsProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleDetailsProfileMenuItem.php',
|
||||
'PhabricatorPeopleDisableController' => 'applications/people/controller/PhabricatorPeopleDisableController.php',
|
||||
'PhabricatorPeopleEmailLoginMailEngine' => 'applications/people/mail/PhabricatorPeopleEmailLoginMailEngine.php',
|
||||
'PhabricatorPeopleEmpowerController' => 'applications/people/controller/PhabricatorPeopleEmpowerController.php',
|
||||
'PhabricatorPeopleExternalPHIDType' => 'applications/people/phid/PhabricatorPeopleExternalPHIDType.php',
|
||||
'PhabricatorPeopleIconSet' => 'applications/people/icon/PhabricatorPeopleIconSet.php',
|
||||
|
@ -10231,6 +10232,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorPeopleDeleteController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleDetailsProfileMenuItem' => 'PhabricatorProfileMenuItem',
|
||||
'PhabricatorPeopleDisableController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleEmailLoginMailEngine' => 'PhabricatorPeopleMailEngine',
|
||||
'PhabricatorPeopleEmpowerController' => 'PhabricatorPeopleController',
|
||||
'PhabricatorPeopleExternalPHIDType' => 'PhabricatorPHIDType',
|
||||
'PhabricatorPeopleIconSet' => 'PhabricatorIconSet',
|
||||
|
|
|
@ -94,29 +94,34 @@ final class PhabricatorEmailLoginController
|
|||
}
|
||||
|
||||
if (!$errors) {
|
||||
$body = $this->newAccountLoginMailBody(
|
||||
$target_user,
|
||||
$is_logged_in);
|
||||
$target_address = new PhutilEmailAddress($target_email->getAddress());
|
||||
|
||||
$mail_engine = id(new PhabricatorPeopleEmailLoginMailEngine())
|
||||
->setSender($viewer)
|
||||
->setRecipient($target_user)
|
||||
->setRecipientAddress($target_address);
|
||||
|
||||
try {
|
||||
$mail_engine->validateMail();
|
||||
} catch (PhabricatorPeopleMailEngineException $ex) {
|
||||
return $this->newDialog()
|
||||
->setTitle($ex->getTitle())
|
||||
->appendParagraph($ex->getBody())
|
||||
->addCancelButton('/auth/start/', pht('Done'));
|
||||
}
|
||||
|
||||
$mail_engine->sendMail();
|
||||
|
||||
if ($is_logged_in) {
|
||||
$subject = pht('[Phabricator] Account Password Link');
|
||||
$instructions = pht(
|
||||
'An email has been sent containing a link you can use to set '.
|
||||
'a password for your account.');
|
||||
} else {
|
||||
$subject = pht('[Phabricator] Account Login Link');
|
||||
$instructions = pht(
|
||||
'An email has been sent containing a link you can use to log '.
|
||||
'in to your account.');
|
||||
}
|
||||
|
||||
$mail = id(new PhabricatorMetaMTAMail())
|
||||
->setSubject($subject)
|
||||
->setForceDelivery(true)
|
||||
->addRawTos(array($target_email->getAddress()))
|
||||
->setBody($body)
|
||||
->saveAndSend();
|
||||
|
||||
return $this->newDialog()
|
||||
->setTitle(pht('Check Your Email'))
|
||||
->setShortTitle(pht('Email Sent'))
|
||||
|
@ -182,55 +187,6 @@ final class PhabricatorEmailLoginController
|
|||
->addSubmitButton(pht('Send Email'));
|
||||
}
|
||||
|
||||
private function newAccountLoginMailBody(
|
||||
PhabricatorUser $user,
|
||||
$is_logged_in) {
|
||||
|
||||
$engine = new PhabricatorAuthSessionEngine();
|
||||
$uri = $engine->getOneTimeLoginURI(
|
||||
$user,
|
||||
null,
|
||||
PhabricatorAuthSessionEngine::ONETIME_RESET);
|
||||
|
||||
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
|
||||
$have_passwords = $this->isPasswordAuthEnabled();
|
||||
|
||||
if ($have_passwords) {
|
||||
if ($is_logged_in) {
|
||||
$body = pht(
|
||||
'You can use this link to set a password on your account:'.
|
||||
"\n\n %s\n",
|
||||
$uri);
|
||||
} else if ($is_serious) {
|
||||
$body = pht(
|
||||
"You can use this link to reset your Phabricator password:".
|
||||
"\n\n %s\n",
|
||||
$uri);
|
||||
} else {
|
||||
$body = pht(
|
||||
"Condolences on forgetting your password. You can use this ".
|
||||
"link to reset it:\n\n".
|
||||
" %s\n\n".
|
||||
"After you set a new password, consider writing it down on a ".
|
||||
"sticky note and attaching it to your monitor so you don't ".
|
||||
"forget again! Choosing a very short, easy-to-remember password ".
|
||||
"like \"cat\" or \"1234\" might also help.\n\n".
|
||||
"Best Wishes,\nPhabricator\n",
|
||||
$uri);
|
||||
|
||||
}
|
||||
} else {
|
||||
$body = pht(
|
||||
"You can use this login link to regain access to your Phabricator ".
|
||||
"account:".
|
||||
"\n\n".
|
||||
" %s\n",
|
||||
$uri);
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
private function isPasswordAuthEnabled() {
|
||||
return (bool)PhabricatorPasswordAuthProvider::getPasswordProvider();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorPeopleEmailLoginMailEngine
|
||||
extends PhabricatorPeopleMailEngine {
|
||||
|
||||
public function validateMail() {
|
||||
$recipient = $this->getRecipient();
|
||||
|
||||
if ($recipient->getIsDisabled()) {
|
||||
$this->throwValidationException(
|
||||
pht('User is Disabled'),
|
||||
pht(
|
||||
'You can not send an email login link to this email address '.
|
||||
'because the associated user account is disabled.'));
|
||||
}
|
||||
|
||||
if (!$recipient->canEstablishWebSessions()) {
|
||||
$this->throwValidationException(
|
||||
pht('Not a Normal User'),
|
||||
pht(
|
||||
'You can not send an email login link to this email address '.
|
||||
'because the associated user account is not a normal user account '.
|
||||
'and can not log in to the web interface.'));
|
||||
}
|
||||
}
|
||||
|
||||
protected function newMail() {
|
||||
$is_set_password = $this->isSetPasswordWorkflow();
|
||||
|
||||
if ($is_set_password) {
|
||||
$subject = pht('[Phabricator] Account Password Link');
|
||||
} else {
|
||||
$subject = pht('[Phabricator] Account Login Link');
|
||||
}
|
||||
|
||||
$recipient = $this->getRecipient();
|
||||
$engine = new PhabricatorAuthSessionEngine();
|
||||
$login_uri = $engine->getOneTimeLoginURI(
|
||||
$recipient,
|
||||
null,
|
||||
PhabricatorAuthSessionEngine::ONETIME_RESET);
|
||||
|
||||
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
|
||||
$have_passwords = $this->isPasswordAuthEnabled();
|
||||
|
||||
if ($have_passwords) {
|
||||
if ($is_set_password) {
|
||||
$body = pht(
|
||||
'You can use this link to set a password on your account:'.
|
||||
"\n\n %s\n",
|
||||
$login_uri);
|
||||
} else if ($is_serious) {
|
||||
$body = pht(
|
||||
"You can use this link to reset your Phabricator password:".
|
||||
"\n\n %s\n",
|
||||
$login_uri);
|
||||
} else {
|
||||
$body = pht(
|
||||
"Condolences on forgetting your password. You can use this ".
|
||||
"link to reset it:\n\n".
|
||||
" %s\n\n".
|
||||
"After you set a new password, consider writing it down on a ".
|
||||
"sticky note and attaching it to your monitor so you don't ".
|
||||
"forget again! Choosing a very short, easy-to-remember password ".
|
||||
"like \"cat\" or \"1234\" might also help.\n\n".
|
||||
"Best Wishes,\nPhabricator\n",
|
||||
$login_uri);
|
||||
|
||||
}
|
||||
} else {
|
||||
$body = pht(
|
||||
"You can use this login link to regain access to your Phabricator ".
|
||||
"account:".
|
||||
"\n\n".
|
||||
" %s\n",
|
||||
$login_uri);
|
||||
}
|
||||
|
||||
return id(new PhabricatorMetaMTAMail())
|
||||
->setSubject($subject)
|
||||
->setBody($body);
|
||||
}
|
||||
|
||||
private function isPasswordAuthEnabled() {
|
||||
return (bool)PhabricatorPasswordAuthProvider::getPasswordProvider();
|
||||
}
|
||||
|
||||
private function isSetPasswordWorkflow() {
|
||||
$sender = $this->getSender();
|
||||
$recipient = $this->getRecipient();
|
||||
|
||||
// Users can hit the "login with an email link" workflow while trying to
|
||||
// set a password on an account which does not yet have a password. We
|
||||
// require they verify that they own the email address and send them
|
||||
// through the email login flow. In this case, the messaging is slightly
|
||||
// different.
|
||||
|
||||
if ($sender->getPHID()) {
|
||||
if ($sender->getPHID() === $recipient->getPHID()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -5,6 +5,7 @@ abstract class PhabricatorPeopleMailEngine
|
|||
|
||||
private $sender;
|
||||
private $recipient;
|
||||
private $recipientAddress;
|
||||
|
||||
final public function setSender(PhabricatorUser $sender) {
|
||||
$this->sender = $sender;
|
||||
|
@ -30,6 +31,22 @@ abstract class PhabricatorPeopleMailEngine
|
|||
return $this->recipient;
|
||||
}
|
||||
|
||||
final public function setRecipientAddress(PhutilEmailAddress $address) {
|
||||
$this->recipientAddress = $address;
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function getRecipientAddress() {
|
||||
if (!$this->recipientAddress) {
|
||||
throw new PhutilInvalidStateException('recipientAddress');
|
||||
}
|
||||
return $this->recipientAddress;
|
||||
}
|
||||
|
||||
final public function hasRecipientAddress() {
|
||||
return ($this->recipientAddress !== null);
|
||||
}
|
||||
|
||||
final public function canSendMail() {
|
||||
try {
|
||||
$this->validateMail();
|
||||
|
@ -43,6 +60,14 @@ abstract class PhabricatorPeopleMailEngine
|
|||
$this->validateMail();
|
||||
$mail = $this->newMail();
|
||||
|
||||
if ($this->hasRecipientAddress()) {
|
||||
$recipient_address = $this->getRecipientAddress();
|
||||
$mail->addRawTos(array($recipient_address->getAddress()));
|
||||
} else {
|
||||
$recipient = $this->getRecipient();
|
||||
$mail->addTos(array($recipient->getPHID()));
|
||||
}
|
||||
|
||||
$mail
|
||||
->setForceDelivery(true)
|
||||
->save();
|
||||
|
@ -53,7 +78,6 @@ abstract class PhabricatorPeopleMailEngine
|
|||
abstract public function validateMail();
|
||||
abstract protected function newMail();
|
||||
|
||||
|
||||
final protected function throwValidationException($title, $body) {
|
||||
throw new PhabricatorPeopleMailEngineException($title, $body);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ final class PhabricatorPeopleUsernameMailEngine
|
|||
|
||||
protected function newMail() {
|
||||
$sender = $this->getSender();
|
||||
$recipient = $this->getRecipient();
|
||||
|
||||
$sender_username = $sender->getUsername();
|
||||
$sender_realname = $sender->getRealName();
|
||||
|
@ -52,7 +51,6 @@ final class PhabricatorPeopleUsernameMailEngine
|
|||
$new_username));
|
||||
|
||||
return id(new PhabricatorMetaMTAMail())
|
||||
->addTos(array($recipient->getPHID()))
|
||||
->setSubject(pht('[Phabricator] Username Changed'))
|
||||
->setBody($body);
|
||||
}
|
||||
|
|
|
@ -104,7 +104,6 @@ final class PhabricatorPeopleWelcomeMailEngine
|
|||
$message = implode("\n\n", $message);
|
||||
|
||||
return id(new PhabricatorMetaMTAMail())
|
||||
->addTos(array($recipient->getPHID()))
|
||||
->setSubject(pht('[Phabricator] Welcome to Phabricator'))
|
||||
->setBody($message);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue