1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-09 16:32:39 +01:00

Move "Welcome" mail generation out of PhabricatorUser

Summary:
Ref PHI1027. Currently, `PhabricatorUser` has a couple of mail-related methods which shouldn't really be there in the long term. Immediately, I want to make some adjusments to the welcome email.

Move "Welcome" mail generation to a separate class and consolidate all the error handling. (Eventually, "invite" and "verify address" email should move to similar subclasses, too.) Previously, a bunch of errors/conditions got checked in multiple places.

The only functional change is that we no longer allow you to send welcome mail to disabled users.

Test Plan:
  - Used "Send Welcome Mail" from profile pages to send mail.
  - Hit "not admin", "disabled user", "bot/mailing list" errors.
  - Used `scripts/user/add_user.php` to send welcome mail.
  - Used "Create New User" to send welcome mail.
  - Verified mail with `bin/mail show-outbound`. (Cleaned up a couple of minor display issues here.)

Reviewers: amckinley

Reviewed By: amckinley

Differential Revision: https://secure.phabricator.com/D19989
This commit is contained in:
epriestley 2019-01-17 09:39:27 -08:00
parent 98bf3a950d
commit 5537e29ee8
10 changed files with 218 additions and 64 deletions

View file

@ -59,7 +59,12 @@ id(new PhabricatorUserEditor())
->setActor($admin)
->createNewUser($user, $email_object);
$user->sendWelcomeEmail($admin);
$welcome_engine = id(new PhabricatorPeopleWelcomeMailEngine())
->setSender($admin)
->setRecipient($user);
if ($welcome_engine->canSendMail()) {
$welcome_engine->sendMail();
}
echo pht(
"Created user '%s' (realname='%s', email='%s').\n",

View file

@ -3814,6 +3814,8 @@ phutil_register_library_map(array(
'PhabricatorPeopleLogQuery' => 'applications/people/query/PhabricatorPeopleLogQuery.php',
'PhabricatorPeopleLogSearchEngine' => 'applications/people/query/PhabricatorPeopleLogSearchEngine.php',
'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php',
'PhabricatorPeopleMailEngine' => 'applications/people/mail/PhabricatorPeopleMailEngine.php',
'PhabricatorPeopleMailEngineException' => 'applications/people/mail/PhabricatorPeopleMailEngineException.php',
'PhabricatorPeopleManageProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleManageProfileMenuItem.php',
'PhabricatorPeopleManagementWorkflow' => 'applications/people/management/PhabricatorPeopleManagementWorkflow.php',
'PhabricatorPeopleNewController' => 'applications/people/controller/PhabricatorPeopleNewController.php',
@ -3841,6 +3843,7 @@ phutil_register_library_map(array(
'PhabricatorPeopleUserFunctionDatasource' => 'applications/people/typeahead/PhabricatorPeopleUserFunctionDatasource.php',
'PhabricatorPeopleUserPHIDType' => 'applications/people/phid/PhabricatorPeopleUserPHIDType.php',
'PhabricatorPeopleWelcomeController' => 'applications/people/controller/PhabricatorPeopleWelcomeController.php',
'PhabricatorPeopleWelcomeMailEngine' => 'applications/people/mail/PhabricatorPeopleWelcomeMailEngine.php',
'PhabricatorPhabricatorAuthProvider' => 'applications/auth/provider/PhabricatorPhabricatorAuthProvider.php',
'PhabricatorPhameApplication' => 'applications/phame/application/PhabricatorPhameApplication.php',
'PhabricatorPhameBlogPHIDType' => 'applications/phame/phid/PhabricatorPhameBlogPHIDType.php',
@ -9730,6 +9733,8 @@ phutil_register_library_map(array(
'PhabricatorPeopleLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorPeopleLogSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController',
'PhabricatorPeopleMailEngine' => 'Phobject',
'PhabricatorPeopleMailEngineException' => 'Exception',
'PhabricatorPeopleManageProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorPeopleManagementWorkflow' => 'PhabricatorManagementWorkflow',
'PhabricatorPeopleNewController' => 'PhabricatorPeopleController',
@ -9757,6 +9762,7 @@ phutil_register_library_map(array(
'PhabricatorPeopleUserFunctionDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'PhabricatorPeopleUserPHIDType' => 'PhabricatorPHIDType',
'PhabricatorPeopleWelcomeController' => 'PhabricatorPeopleController',
'PhabricatorPeopleWelcomeMailEngine' => 'PhabricatorPeopleMailEngine',
'PhabricatorPhabricatorAuthProvider' => 'PhabricatorOAuth2AuthProvider',
'PhabricatorPhameApplication' => 'PhabricatorApplication',
'PhabricatorPhameBlogPHIDType' => 'PhabricatorPHIDType',

View file

@ -115,7 +115,14 @@ final class PhabricatorMailManagementShowOutboundWorkflow
$info[] = $this->newSectionHeader(pht('HEADERS'));
$headers = $message->getDeliveredHeaders();
if (!$headers) {
$headers = array();
}
$unfiltered = $message->getUnfilteredHeaders();
if (!$unfiltered) {
$unfiltered = array();
}
$header_map = array();
foreach ($headers as $header) {
@ -201,6 +208,7 @@ final class PhabricatorMailManagementShowOutboundWorkflow
$info[] = null;
} else {
$info[] = pht('(This message has no HTML body.)');
$info[] = null;
}
$console->writeOut('%s', implode("\n", $info));

View file

@ -107,8 +107,13 @@ final class PhabricatorPeopleNewController
->makeMailingListUser($user, true);
}
if ($welcome_checked && !$is_bot && !$is_list) {
$user->sendWelcomeEmail($admin);
if ($welcome_checked) {
$welcome_engine = id(new PhabricatorPeopleWelcomeMailEngine())
->setSender($admin)
->setRecipient($user);
if ($welcome_engine->canSendMail()) {
$welcome_engine->sendMail();
}
}
$response = id(new AphrontRedirectResponse())

View file

@ -92,8 +92,11 @@ final class PhabricatorPeopleProfileManageController
PeopleDisableUsersCapability::CAPABILITY);
$can_disable = ($has_disable && !$is_self);
$can_welcome = ($is_admin && $user->canEstablishWebSessions());
$welcome_engine = id(new PhabricatorPeopleWelcomeMailEngine())
->setSender($viewer)
->setRecipient($user);
$can_welcome = $welcome_engine->canSendMail();
$curtain = $this->newCurtainView($user);
$curtain->addAction(

View file

@ -3,6 +3,13 @@
final class PhabricatorPeopleWelcomeController
extends PhabricatorPeopleController {
public function shouldRequireAdmin() {
// You need to be an administrator to actually send welcome email, but
// we let anyone hit this page so they can get a nice error dialog
// explaining the issue.
return false;
}
public function handleRequest(AphrontRequest $request) {
$admin = $this->getViewer();
@ -14,22 +21,24 @@ final class PhabricatorPeopleWelcomeController
return new Aphront404Response();
}
$profile_uri = '/p/'.$user->getUsername().'/';
$id = $user->getID();
$profile_uri = "/people/manage/{$id}/";
if (!$user->canEstablishWebSessions()) {
$welcome_engine = id(new PhabricatorPeopleWelcomeMailEngine())
->setSender($admin)
->setRecipient($user);
try {
$welcome_engine->validateMail();
} catch (PhabricatorPeopleMailEngineException $ex) {
return $this->newDialog()
->setTitle(pht('Not a Normal User'))
->appendParagraph(
pht(
'You can not send this user a welcome mail because they are not '.
'a normal user and can not log in to the web interface. Special '.
'users (like bots and mailing lists) are unable to establish web '.
'sessions.'))
->setTitle($ex->getTitle())
->appendParagraph($ex->getBody())
->addCancelButton($profile_uri, pht('Done'));
}
if ($request->isFormPost()) {
$user->sendWelcomeEmail($admin);
$welcome_engine->sendMail();
return id(new AphrontRedirectResponse())->setURI($profile_uri);
}

View file

@ -0,0 +1,61 @@
<?php
abstract class PhabricatorPeopleMailEngine
extends Phobject {
private $sender;
private $recipient;
final public function setSender(PhabricatorUser $sender) {
$this->sender = $sender;
return $this;
}
final public function getSender() {
if (!$this->sender) {
throw new PhutilInvalidStateException('setSender');
}
return $this->sender;
}
final public function setRecipient(PhabricatorUser $recipient) {
$this->recipient = $recipient;
return $this;
}
final public function getRecipient() {
if (!$this->recipient) {
throw new PhutilInvalidStateException('setRecipient');
}
return $this->recipient;
}
final public function canSendMail() {
try {
$this->validateMail();
return true;
} catch (PhabricatorPeopleMailEngineException $ex) {
return false;
}
}
final public function sendMail() {
$this->validateMail();
$mail = $this->newMail();
$mail
->setForceDelivery(true)
->save();
return $mail;
}
abstract public function validateMail();
abstract protected function newMail();
final protected function throwValidationException($title, $body) {
throw new PhabricatorPeopleMailEngineException($title, $body);
}
}

View file

@ -0,0 +1,24 @@
<?php
final class PhabricatorPeopleMailEngineException
extends Exception {
private $title;
private $body;
public function __construct($title, $body) {
$this->title = $title;
$this->body = $body;
parent::__construct(pht('%s: %s', $title, $body));
}
public function getTitle() {
return $this->title;
}
public function getBody() {
return $this->body;
}
}

View file

@ -0,0 +1,83 @@
<?php
final class PhabricatorPeopleWelcomeMailEngine
extends PhabricatorPeopleMailEngine {
public function validateMail() {
$sender = $this->getSender();
$recipient = $this->getRecipient();
if (!$sender->getIsAdmin()) {
$this->throwValidationException(
pht('Not an Administrator'),
pht(
'You can not send welcome mail because you are not an '.
'administrator. Only administrators may send welcome mail.'));
}
if ($recipient->getIsDisabled()) {
$this->throwValidationException(
pht('User is Disabled'),
pht(
'You can not send welcome mail to this user because their account '.
'is disabled.'));
}
if (!$recipient->canEstablishWebSessions()) {
$this->throwValidationException(
pht('Not a Normal User'),
pht(
'You can not send this user welcome mail because they are not '.
'a normal user and can not log in to the web interface. Special '.
'users (like bots and mailing lists) are unable to establish '.
'web sessions.'));
}
}
protected function newMail() {
$sender = $this->getSender();
$recipient = $this->getRecipient();
$sender_username = $sender->getUserName();
$sender_realname = $sender->getRealName();
$recipient_username = $recipient->getUserName();
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
$base_uri = PhabricatorEnv::getProductionURI('/');
$engine = new PhabricatorAuthSessionEngine();
$uri = $engine->getOneTimeLoginURI(
$recipient,
$recipient->loadPrimaryEmail(),
PhabricatorAuthSessionEngine::ONETIME_WELCOME);
$body = pht(
"Welcome to Phabricator!\n\n".
"%s (%s) has created an account for you.\n\n".
" Username: %s\n\n".
"To login to Phabricator, follow this link and set a password:\n\n".
" %s\n\n".
"After you have set a password, you can login in the future by ".
"going here:\n\n".
" %s\n",
$sender_username,
$sender_realname,
$recipient_username,
$uri,
$base_uri);
if (!$is_serious) {
$body .= sprintf(
"\n%s\n",
pht("Love,\nPhabricator"));
}
return id(new PhabricatorMetaMTAMail())
->addTos(array($recipient->getPHID()))
->setSubject(pht('[Phabricator] Welcome to Phabricator'))
->setBody($body);
}
}

View file

@ -555,56 +555,6 @@ final class PhabricatorUser
}
}
public function sendWelcomeEmail(PhabricatorUser $admin) {
if (!$this->canEstablishWebSessions()) {
throw new Exception(
pht(
'Can not send welcome mail to users who can not establish '.
'web sessions!'));
}
$admin_username = $admin->getUserName();
$admin_realname = $admin->getRealName();
$user_username = $this->getUserName();
$is_serious = PhabricatorEnv::getEnvConfig('phabricator.serious-business');
$base_uri = PhabricatorEnv::getProductionURI('/');
$engine = new PhabricatorAuthSessionEngine();
$uri = $engine->getOneTimeLoginURI(
$this,
$this->loadPrimaryEmail(),
PhabricatorAuthSessionEngine::ONETIME_WELCOME);
$body = pht(
"Welcome to Phabricator!\n\n".
"%s (%s) has created an account for you.\n\n".
" Username: %s\n\n".
"To login to Phabricator, follow this link and set a password:\n\n".
" %s\n\n".
"After you have set a password, you can login in the future by ".
"going here:\n\n".
" %s\n",
$admin_username,
$admin_realname,
$user_username,
$uri,
$base_uri);
if (!$is_serious) {
$body .= sprintf(
"\n%s\n",
pht("Love,\nPhabricator"));
}
$mail = id(new PhabricatorMetaMTAMail())
->addTos(array($this->getPHID()))
->setForceDelivery(true)
->setSubject(pht('[Phabricator] Welcome to Phabricator'))
->setBody($body)
->saveAndSend();
}
public function sendUsernameChangeEmail(
PhabricatorUser $admin,
$old_username) {