mirror of
https://we.phorge.it/source/phorge.git
synced 2025-02-26 21:49:08 +01:00
MetaMTA - add (basic) application emails and deploy to Maniphest
Summary: Ref T5952, T3404. This lays the basic plumbing for how this will work, all the way to deploying on Maniphest. Aside from what is mentioned on T5952, I think page(s) on editing application emails could use a little more helpful text about what's going on, similar to how the config page that's getting deprecated works. Test Plan: ran migration and noted my create email address migrated successfully. used bin/mail to make a task. added another email and used bin/mail to make a task. deleted an email. edited an email. invoked various error states and they all looked good. Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin, epriestley Maniphest Tasks: T3404, T5952 Differential Revision: https://secure.phabricator.com/D11418
This commit is contained in:
parent
a15852c112
commit
53b06408f4
15 changed files with 695 additions and 21 deletions
12
resources/sql/autopatches/20150115.applicationemails.sql
Normal file
12
resources/sql/autopatches/20150115.applicationemails.sql
Normal file
|
@ -0,0 +1,12 @@
|
|||
CREATE TABLE {$NAMESPACE}_metamta.metamta_applicationemail (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
phid VARBINARY(64) NOT NULL,
|
||||
applicationPHID VARBINARY(64) NOT NULL,
|
||||
address VARCHAR(128) NOT NULL COLLATE {$COLLATE_SORT},
|
||||
configData LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
|
||||
dateCreated INT UNSIGNED NOT NULL,
|
||||
dateModified INT UNSIGNED NOT NULL,
|
||||
KEY `key_application` (applicationPHID),
|
||||
UNIQUE KEY `key_address` (address),
|
||||
UNIQUE KEY `key_phid` (phid)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT};
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
$key = 'metamta.maniphest.public-create-email';
|
||||
echo "Migrating `$key` to new application email infrastructure...\n";
|
||||
$value = PhabricatorEnv::getEnvConfigIfExists($key);
|
||||
$maniphest = new PhabricatorManiphestApplication();
|
||||
|
||||
if ($value) {
|
||||
try {
|
||||
PhabricatorMetaMTAApplicationEmail::initializeNewAppEmail(
|
||||
PhabricatorUser::getOmnipotentUser())
|
||||
->setAddress($value)
|
||||
->setApplicationPHID($maniphest->getPHID())
|
||||
->save();
|
||||
} catch (AphrontDuplicateKeyQueryException $ex) {
|
||||
// already migrated?
|
||||
}
|
||||
}
|
||||
|
||||
echo "Done.\n";
|
|
@ -1258,6 +1258,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorApplicationDatasource' => 'applications/meta/typeahead/PhabricatorApplicationDatasource.php',
|
||||
'PhabricatorApplicationDetailViewController' => 'applications/meta/controller/PhabricatorApplicationDetailViewController.php',
|
||||
'PhabricatorApplicationEditController' => 'applications/meta/controller/PhabricatorApplicationEditController.php',
|
||||
'PhabricatorApplicationEditEmailController' => 'applications/meta/controller/PhabricatorApplicationEditEmailController.php',
|
||||
'PhabricatorApplicationLaunchView' => 'applications/meta/view/PhabricatorApplicationLaunchView.php',
|
||||
'PhabricatorApplicationQuery' => 'applications/meta/query/PhabricatorApplicationQuery.php',
|
||||
'PhabricatorApplicationSearchController' => 'applications/search/controller/PhabricatorApplicationSearchController.php',
|
||||
|
@ -1946,6 +1947,9 @@ phutil_register_library_map(array(
|
|||
'PhabricatorMetaMTAActor' => 'applications/metamta/query/PhabricatorMetaMTAActor.php',
|
||||
'PhabricatorMetaMTAActorQuery' => 'applications/metamta/query/PhabricatorMetaMTAActorQuery.php',
|
||||
'PhabricatorMetaMTAApplication' => 'applications/metamta/application/PhabricatorMetaMTAApplication.php',
|
||||
'PhabricatorMetaMTAApplicationEmail' => 'applications/metamta/storage/PhabricatorMetaMTAApplicationEmail.php',
|
||||
'PhabricatorMetaMTAApplicationEmailPHIDType' => 'applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php',
|
||||
'PhabricatorMetaMTAApplicationEmailQuery' => 'applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php',
|
||||
'PhabricatorMetaMTAAttachment' => 'applications/metamta/storage/PhabricatorMetaMTAAttachment.php',
|
||||
'PhabricatorMetaMTAConfigOptions' => 'applications/config/option/PhabricatorMetaMTAConfigOptions.php',
|
||||
'PhabricatorMetaMTAController' => 'applications/metamta/controller/PhabricatorMetaMTAController.php',
|
||||
|
@ -4430,6 +4434,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorApplicationDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||
'PhabricatorApplicationDetailViewController' => 'PhabricatorApplicationsController',
|
||||
'PhabricatorApplicationEditController' => 'PhabricatorApplicationsController',
|
||||
'PhabricatorApplicationEditEmailController' => 'PhabricatorApplicationsController',
|
||||
'PhabricatorApplicationLaunchView' => 'AphrontTagView',
|
||||
'PhabricatorApplicationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorApplicationSearchController' => 'PhabricatorSearchBaseController',
|
||||
|
@ -5155,6 +5160,12 @@ phutil_register_library_map(array(
|
|||
'PhabricatorMercurialGraphStream' => 'PhabricatorRepositoryGraphStream',
|
||||
'PhabricatorMetaMTAActorQuery' => 'PhabricatorQuery',
|
||||
'PhabricatorMetaMTAApplication' => 'PhabricatorApplication',
|
||||
'PhabricatorMetaMTAApplicationEmail' => array(
|
||||
'PhabricatorMetaMTADAO',
|
||||
'PhabricatorPolicyInterface',
|
||||
),
|
||||
'PhabricatorMetaMTAApplicationEmailPHIDType' => 'PhabricatorPHIDType',
|
||||
'PhabricatorMetaMTAApplicationEmailQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'PhabricatorMetaMTAConfigOptions' => 'PhabricatorApplicationConfigOptions',
|
||||
'PhabricatorMetaMTAController' => 'PhabricatorController',
|
||||
'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO',
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* @task info Application Information
|
||||
* @task ui UI Integration
|
||||
* @task uri URI Routing
|
||||
* @task mail Email integration
|
||||
* @task fact Fact Integration
|
||||
* @task meta Application Management
|
||||
*/
|
||||
|
@ -193,6 +194,22 @@ abstract class PhabricatorApplication implements PhabricatorPolicyInterface {
|
|||
}
|
||||
|
||||
|
||||
/* -( Email Integration )-------------------------------------------------- */
|
||||
|
||||
|
||||
public function supportsEmailIntegration() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function getInboundEmailSupportLink() {
|
||||
return PhabricatorEnv::getDocLink('Configuring Inbound Email');
|
||||
}
|
||||
|
||||
public function getAppEmailBlurb() {
|
||||
throw new Exception('Not Implemented.');
|
||||
}
|
||||
|
||||
|
||||
/* -( Fact Integration )--------------------------------------------------- */
|
||||
|
||||
|
||||
|
|
|
@ -109,6 +109,20 @@ final class PhabricatorManiphestApplication extends PhabricatorApplication {
|
|||
return $items;
|
||||
}
|
||||
|
||||
public function supportsEmailIntegration() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getAppEmailBlurb() {
|
||||
return pht(
|
||||
'Send email to these addresses to create tasks. %s',
|
||||
phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $this->getInboundEmailSupportLink(),),
|
||||
pht('Learn More')));
|
||||
}
|
||||
|
||||
protected function getCustomCapabilities() {
|
||||
return array(
|
||||
ManiphestDefaultViewCapability::CAPABILITY => array(
|
||||
|
|
|
@ -294,9 +294,16 @@ EOTEXT
|
|||
'metamta.maniphest.public-create-email',
|
||||
'string',
|
||||
null)
|
||||
->setSummary(pht('Allow filing bugs via email.'))
|
||||
->setLocked(true)
|
||||
->setLockedMessage(pht(
|
||||
'This configuration is deprecated. See description for details.'))
|
||||
->setSummary(pht('DEPRECATED - Allow filing bugs via email.'))
|
||||
->setDescription(
|
||||
pht(
|
||||
'This config has been deprecated in favor of [[ '.
|
||||
'/applications/view/PhabricatorManiphestApplication/ | '.
|
||||
'application settings ]], which allow for multiple email '.
|
||||
'addresses and other functionality.'."\n\n".
|
||||
'You can configure an email address like '.
|
||||
'"bugs@phabricator.example.com" which will automatically create '.
|
||||
'Maniphest tasks when users send email to it. This relies on the '.
|
||||
|
|
|
@ -8,14 +8,20 @@ final class ManiphestCreateMailReceiver extends PhabricatorMailReceiver {
|
|||
}
|
||||
|
||||
public function canAcceptMail(PhabricatorMetaMTAReceivedMail $mail) {
|
||||
$config_key = 'metamta.maniphest.public-create-email';
|
||||
$create_address = PhabricatorEnv::getEnvConfig($config_key);
|
||||
$maniphest_app = new PhabricatorManiphestApplication();
|
||||
$application_emails = id(new PhabricatorMetaMTAApplicationEmailQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->withApplicationPHIDs(array($maniphest_app->getPHID()))
|
||||
->execute();
|
||||
|
||||
foreach ($mail->getToAddresses() as $to_address) {
|
||||
foreach ($application_emails as $application_email) {
|
||||
$create_address = $application_email->getAddress();
|
||||
if ($this->matchAddresses($create_address, $to_address)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ final class PhabricatorApplicationsApplication extends PhabricatorApplication {
|
|||
=> 'PhabricatorApplicationDetailViewController',
|
||||
'edit/(?P<application>\w+)/'
|
||||
=> 'PhabricatorApplicationEditController',
|
||||
'editemail/(?P<application>\w+)/'
|
||||
=> 'PhabricatorApplicationEditEmailController',
|
||||
'(?P<application>\w+)/(?P<action>install|uninstall)/'
|
||||
=> 'PhabricatorApplicationUninstallController',
|
||||
),
|
||||
|
|
|
@ -3,23 +3,18 @@
|
|||
final class PhabricatorApplicationDetailViewController
|
||||
extends PhabricatorApplicationsController {
|
||||
|
||||
private $application;
|
||||
|
||||
public function shouldAllowPublic() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function willProcessRequest(array $data) {
|
||||
$this->application = $data['application'];
|
||||
}
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$user = $request->getUser();
|
||||
$application = $request->getURIData('application');
|
||||
|
||||
$selected = id(new PhabricatorApplicationQuery())
|
||||
->setViewer($user)
|
||||
->withClasses(array($this->application))
|
||||
->withClasses(array($application))
|
||||
->executeOne();
|
||||
if (!$selected) {
|
||||
return new Aphront404Response();
|
||||
|
@ -119,6 +114,26 @@ final class PhabricatorApplicationDetailViewController
|
|||
idx($descriptions, $capability));
|
||||
}
|
||||
|
||||
if ($application->supportsEmailIntegration()) {
|
||||
$properties->addSectionHeader(pht('Application Emails'));
|
||||
$properties->addTextContent($application->getAppEmailBlurb());
|
||||
$email_addresses = id(new PhabricatorMetaMTAApplicationEmailQuery())
|
||||
->setViewer($viewer)
|
||||
->withApplicationPHIDs(array($application->getPHID()))
|
||||
->execute();
|
||||
if (empty($email_addresses)) {
|
||||
$properties->addProperty(
|
||||
null,
|
||||
pht('No email addresses configured.'));
|
||||
} else {
|
||||
foreach ($email_addresses as $email_address) {
|
||||
$properties->addProperty(
|
||||
null,
|
||||
$email_address->getAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
|
@ -153,6 +168,18 @@ final class PhabricatorApplicationDetailViewController
|
|||
->setWorkflow(!$can_edit)
|
||||
->setHref($edit_uri));
|
||||
|
||||
if ($selected->supportsEmailIntegration()) {
|
||||
$edit_email_uri = $this->getApplicationURI(
|
||||
'editemail/'.get_class($selected).'/');
|
||||
$view->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Edit Application Emails'))
|
||||
->setIcon('fa-envelope')
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit)
|
||||
->setHref($edit_email_uri));
|
||||
}
|
||||
|
||||
if ($selected->canUninstall()) {
|
||||
if ($selected->isInstalled()) {
|
||||
$view->addAction(
|
||||
|
|
|
@ -0,0 +1,307 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorApplicationEditEmailController
|
||||
extends PhabricatorApplicationsController {
|
||||
|
||||
public function handleRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getUser();
|
||||
$application = $request->getURIData('application');
|
||||
|
||||
$application = id(new PhabricatorApplicationQuery())
|
||||
->setViewer($viewer)
|
||||
->withClasses(array($application))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$application) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$title = $application->getName();
|
||||
|
||||
$uri = $request->getRequestURI();
|
||||
$uri->setQueryParams(array());
|
||||
|
||||
$new = $request->getStr('new');
|
||||
$edit = $request->getInt('edit');
|
||||
$delete = $request->getInt('delete');
|
||||
|
||||
if ($new) {
|
||||
return $this->returnNewAddressResponse($request, $uri, $application);
|
||||
}
|
||||
|
||||
if ($edit) {
|
||||
return $this->returnEditAddressResponse($request, $uri, $edit);
|
||||
}
|
||||
|
||||
if ($delete) {
|
||||
return $this->returnDeleteAddressResponse($request, $uri, $delete);
|
||||
}
|
||||
|
||||
$emails = id(new PhabricatorMetaMTAApplicationEmailQuery())
|
||||
->setViewer($viewer)
|
||||
->withApplicationPHIDs(array($application->getPHID()))
|
||||
->execute();
|
||||
|
||||
$highlight = $request->getInt('highlight');
|
||||
$rowc = array();
|
||||
$rows = array();
|
||||
foreach ($emails as $email) {
|
||||
|
||||
$button_edit = javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'class' => 'button small grey',
|
||||
'href' => $uri->alter('edit', $email->getID()),
|
||||
'sigil' => 'workflow',
|
||||
),
|
||||
pht('Edit'));
|
||||
|
||||
$button_remove = javelin_tag(
|
||||
'a',
|
||||
array(
|
||||
'class' => 'button small grey',
|
||||
'href' => $uri->alter('delete', $email->getID()),
|
||||
'sigil' => 'workflow',
|
||||
),
|
||||
pht('Delete'));
|
||||
|
||||
if ($highlight == $email->getID()) {
|
||||
$rowc[] = 'highlighted';
|
||||
} else {
|
||||
$rowc[] = null;
|
||||
}
|
||||
|
||||
$rows[] = array(
|
||||
$email->getAddress(),
|
||||
$button_edit,
|
||||
$button_remove,
|
||||
);
|
||||
}
|
||||
|
||||
$table = id(new AphrontTableView($rows))
|
||||
->setNoDataString(pht('No application emails created yet.'));
|
||||
$table->setHeaders(
|
||||
array(
|
||||
pht('Email'),
|
||||
pht('Edit'),
|
||||
pht('Delete'),
|
||||
));
|
||||
$table->setColumnClasses(
|
||||
array(
|
||||
'wide',
|
||||
'action',
|
||||
'action',
|
||||
));
|
||||
$table->setRowClasses($rowc);
|
||||
$table->setColumnVisibility(
|
||||
array(
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
));
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($viewer);
|
||||
|
||||
$view_uri = $this->getApplicationURI('view/'.get_class($application).'/');
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$crumbs->addTextCrumb($application->getName(), $view_uri);
|
||||
$crumbs->addTextCrumb(pht('Edit Application Emails'));
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setHeader(pht('Edit Application Emails: %s', $application->getName()));
|
||||
|
||||
$icon = id(new PHUIIconView())
|
||||
->setIconFont('fa-plus');
|
||||
$button = new PHUIButtonView();
|
||||
$button->setText(pht('Add New Address'));
|
||||
$button->setTag('a');
|
||||
$button->setHref($uri->alter('new', 'true'));
|
||||
$button->setIcon($icon);
|
||||
$button->addSigil('workflow');
|
||||
$header->addActionLink($button);
|
||||
|
||||
$object_box = id(new PHUIObjectBoxView())
|
||||
->setHeader($header)
|
||||
->appendChild($table)
|
||||
->appendChild(
|
||||
id(new PHUIBoxView())
|
||||
->appendChild($application->getAppEmailBlurb())
|
||||
->addPadding(PHUI::PADDING_MEDIUM));
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
array(
|
||||
$crumbs,
|
||||
$object_box,
|
||||
),
|
||||
array(
|
||||
'title' => $title,
|
||||
));
|
||||
}
|
||||
|
||||
private function validateApplicationEmail($email) {
|
||||
$errors = array();
|
||||
$e_email = true;
|
||||
|
||||
if (!strlen($email)) {
|
||||
$e_email = pht('Required');
|
||||
$errors[] = pht('Email is required.');
|
||||
} else if (!PhabricatorUserEmail::isValidAddress($email)) {
|
||||
$e_email = pht('Invalid');
|
||||
$errors[] = PhabricatorUserEmail::describeValidAddresses();
|
||||
} else if (!PhabricatorUserEmail::isAllowedAddress($email)) {
|
||||
$e_email = pht('Disallowed');
|
||||
$errors[] = PhabricatorUserEmail::describeAllowedAddresses();
|
||||
}
|
||||
$user_emails = id(new PhabricatorUserEmail())
|
||||
->loadAllWhere('address = %s', $email);
|
||||
if ($user_emails) {
|
||||
$e_email = pht('Duplicate');
|
||||
$errors[] = pht('A user already has this email.');
|
||||
}
|
||||
|
||||
return array($e_email, $errors);
|
||||
}
|
||||
|
||||
private function returnNewAddressResponse(
|
||||
AphrontRequest $request,
|
||||
PhutilURI $uri,
|
||||
PhabricatorApplication $application) {
|
||||
|
||||
$viewer = $request->getUser();
|
||||
$email_object =
|
||||
PhabricatorMetaMTAApplicationEmail::initializeNewAppEmail($viewer)
|
||||
->setApplicationPHID($application->getPHID());
|
||||
|
||||
return $this->returnSaveAddressResponse(
|
||||
$request,
|
||||
$uri,
|
||||
$email_object,
|
||||
$is_new = true);
|
||||
}
|
||||
|
||||
private function returnEditAddressResponse(
|
||||
AphrontRequest $request,
|
||||
PhutilURI $uri,
|
||||
$email_object_id) {
|
||||
|
||||
$viewer = $request->getUser();
|
||||
$email_object = id(new PhabricatorMetaMTAApplicationEmailQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($email_object_id))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$email_object) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
return $this->returnSaveAddressResponse(
|
||||
$request,
|
||||
$uri,
|
||||
$email_object,
|
||||
$is_new = false);
|
||||
}
|
||||
|
||||
private function returnSaveAddressResponse(
|
||||
AphrontRequest $request,
|
||||
PhutilURI $uri,
|
||||
PhabricatorMetaMTAApplicationEmail $email_object,
|
||||
$is_new) {
|
||||
|
||||
$viewer = $request->getUser();
|
||||
|
||||
$e_email = true;
|
||||
$email = null;
|
||||
$errors = array();
|
||||
if ($request->isDialogFormPost()) {
|
||||
$email = trim($request->getStr('email'));
|
||||
list($e_email, $errors) = $this->validateApplicationEmail($email);
|
||||
$email_object->setAddress($email);
|
||||
|
||||
if (!$errors) {
|
||||
try {
|
||||
$email_object->save();
|
||||
return id(new AphrontRedirectResponse())->setURI(
|
||||
$uri->alter('highlight', $email_object->getID()));
|
||||
} catch (AphrontDuplicateKeyQueryException $ex) {
|
||||
$e_email = pht('Duplicate');
|
||||
$errors[] = pht(
|
||||
'Another application is already configured to use this email '.
|
||||
'address.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($errors) {
|
||||
$errors = id(new AphrontErrorView())
|
||||
->setErrors($errors);
|
||||
}
|
||||
|
||||
$form = id(new PHUIFormLayoutView())
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setLabel(pht('Email'))
|
||||
->setName('email')
|
||||
->setValue($email_object->getAddress())
|
||||
->setCaption(PhabricatorUserEmail::describeAllowedAddresses())
|
||||
->setError($e_email));
|
||||
|
||||
$dialog = id(new AphrontDialogView())
|
||||
->setUser($viewer)
|
||||
->setTitle(pht('New Address'))
|
||||
->appendChild($errors)
|
||||
->appendChild($form)
|
||||
->addSubmitButton(pht('Save'))
|
||||
->addCancelButton($uri);
|
||||
|
||||
if ($is_new) {
|
||||
$dialog->addHiddenInput('new', 'true');
|
||||
}
|
||||
|
||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||
}
|
||||
|
||||
private function returnDeleteAddressResponse(
|
||||
AphrontRequest $request,
|
||||
PhutilURI $uri,
|
||||
$email_object_id) {
|
||||
|
||||
$viewer = $request->getUser();
|
||||
$email_object = id(new PhabricatorMetaMTAApplicationEmailQuery())
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($email_object_id))
|
||||
->requireCapabilities(
|
||||
array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
if (!$email_object) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
if ($request->isDialogFormPost()) {
|
||||
$email_object->delete();
|
||||
return id(new AphrontRedirectResponse())->setURI($uri);
|
||||
}
|
||||
|
||||
$dialog = id(new AphrontDialogView())
|
||||
->setUser($viewer)
|
||||
->addHiddenInput('delete', $email_object_id)
|
||||
->setTitle(pht('Delete Address'))
|
||||
->appendParagraph(pht(
|
||||
'Are you sure you want to delete this email address?'))
|
||||
->addSubmitButton(pht('Delete'))
|
||||
->addCancelButton($uri);
|
||||
|
||||
return id(new AphrontDialogResponse())->setDialog($dialog);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorMetaMTAApplicationEmailQuery
|
||||
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||
|
||||
private $ids;
|
||||
private $phids;
|
||||
private $addresses;
|
||||
private $applicationPHIDs;
|
||||
|
||||
public function withIDs(array $ids) {
|
||||
$this->ids = $ids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withPHIDs(array $phids) {
|
||||
$this->phids = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withAddresses(array $addresses) {
|
||||
$this->addresses = $addresses;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withApplicationPHIDs(array $phids) {
|
||||
$this->applicationPHIDs = $phids;
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function loadPage() {
|
||||
$table = new PhabricatorMetaMTAApplicationEmail();
|
||||
$conn_r = $table->establishConnection('r');
|
||||
|
||||
$data = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT * FROM %T appemail %Q %Q %Q %Q',
|
||||
$table->getTableName(),
|
||||
$this->buildWhereClause($conn_r),
|
||||
$this->buildApplicationSearchGroupClause($conn_r),
|
||||
$this->buildOrderClause($conn_r),
|
||||
$this->buildLimitClause($conn_r));
|
||||
|
||||
return $table->loadAllFromArray($data);
|
||||
}
|
||||
|
||||
protected function willFilterPage(array $app_emails) {
|
||||
$app_emails_map = mgroup($app_emails, 'getApplicationPHID');
|
||||
$applications = id(new PhabricatorApplicationQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->withPHIDs(array_keys($app_emails_map))
|
||||
->execute();
|
||||
$applications = mpull($applications, null, 'getPHID');
|
||||
|
||||
foreach ($app_emails_map as $app_phid => $app_emails_group) {
|
||||
foreach ($app_emails_group as $app_email) {
|
||||
$application = idx($applications, $app_phid);
|
||||
if (!$application) {
|
||||
unset($app_emails[$app_phid]);
|
||||
continue;
|
||||
}
|
||||
$app_email->attachApplication($application);
|
||||
}
|
||||
}
|
||||
return $app_emails;
|
||||
}
|
||||
|
||||
private function buildWhereClause($conn_r) {
|
||||
$where = array();
|
||||
|
||||
if ($this->addresses !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'appemail.address IN (%Ls)',
|
||||
$this->addresses);
|
||||
}
|
||||
|
||||
if ($this->applicationPHIDs !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'appemail.applicationPHID IN (%Ls)',
|
||||
$this->applicationPHIDs);
|
||||
}
|
||||
|
||||
if ($this->phids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'appemail.phid IN (%Ls)',
|
||||
$this->phids);
|
||||
}
|
||||
|
||||
if ($this->ids !== null) {
|
||||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'appemail.id IN (%Ld)',
|
||||
$this->ids);
|
||||
}
|
||||
|
||||
$where[] = $this->buildPagingClause($conn_r);
|
||||
|
||||
return $this->formatWhereClause($where);
|
||||
}
|
||||
|
||||
protected function getPagingColumn() {
|
||||
return 'appemail.id';
|
||||
}
|
||||
|
||||
protected function getApplicationSearchObjectPHIDColumn() {
|
||||
return 'appemail.phid';
|
||||
}
|
||||
|
||||
public function getQueryApplicationClass() {
|
||||
return 'PhabricatorMetaMTAApplication';
|
||||
}
|
||||
|
||||
}
|
|
@ -15,6 +15,10 @@ abstract class PhabricatorMailReceiver {
|
|||
$this->processReceivedMail($mail, $sender);
|
||||
}
|
||||
|
||||
public function getViewer() {
|
||||
return PhabricatorUser::getOmnipotentUser();
|
||||
}
|
||||
|
||||
public function validateSender(
|
||||
PhabricatorMetaMTAReceivedMail $mail,
|
||||
PhabricatorUser $sender) {
|
||||
|
@ -103,7 +107,7 @@ abstract class PhabricatorMailReceiver {
|
|||
if ($allow_email_users) {
|
||||
$from_obj = new PhutilEmailAddress($from);
|
||||
$xuser = id(new PhabricatorExternalAccountQuery())
|
||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
||||
->setViewer($this->getViewer())
|
||||
->withAccountTypes(array('email'))
|
||||
->withAccountDomains(array($from_obj->getDomainName(), 'self'))
|
||||
->withAccountIDs(array($from_obj->getAddress()))
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorMetaMTAApplicationEmail
|
||||
extends PhabricatorMetaMTADAO
|
||||
implements PhabricatorPolicyInterface {
|
||||
|
||||
protected $applicationPHID;
|
||||
protected $address;
|
||||
protected $configData;
|
||||
|
||||
private $application = self::ATTACHABLE;
|
||||
|
||||
protected function getConfiguration() {
|
||||
return array(
|
||||
self::CONFIG_AUX_PHID => true,
|
||||
self::CONFIG_SERIALIZATION => array(
|
||||
'configData' => self::SERIALIZATION_JSON,
|
||||
),
|
||||
self::CONFIG_COLUMN_SCHEMA => array(
|
||||
'address' => 'sort128',
|
||||
),
|
||||
self::CONFIG_KEY_SCHEMA => array(
|
||||
'key_address' => array(
|
||||
'columns' => array('address'),
|
||||
'unique' => true,
|
||||
),
|
||||
'key_application' => array(
|
||||
'columns' => array('applicationPHID'),
|
||||
),
|
||||
),
|
||||
) + parent::getConfiguration();
|
||||
}
|
||||
|
||||
public function generatePHID() {
|
||||
return PhabricatorPHID::generateNewPHID(
|
||||
PhabricatorMetaMTAApplicationEmailPHIDType::TYPECONST);
|
||||
}
|
||||
|
||||
public static function initializeNewAppEmail(PhabricatorUser $actor) {
|
||||
return id(new PhabricatorMetaMTAApplicationEmail())
|
||||
->setConfigData(array());
|
||||
}
|
||||
|
||||
public function attachApplication(PhabricatorApplication $app) {
|
||||
$this->application = $app;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getApplication() {
|
||||
return self::assertAttached($this->application);
|
||||
}
|
||||
|
||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||
|
||||
|
||||
public function getCapabilities() {
|
||||
return array(
|
||||
PhabricatorPolicyCapability::CAN_VIEW,
|
||||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
);
|
||||
}
|
||||
|
||||
public function getPolicy($capability) {
|
||||
return $this->getApplication()->getPolicy($capability);
|
||||
}
|
||||
|
||||
public function hasAutomaticCapability(
|
||||
$capability,
|
||||
PhabricatorUser $viewer) {
|
||||
|
||||
return $this->getApplication()->hasAutomaticCapability(
|
||||
$capability,
|
||||
$viewer);
|
||||
}
|
||||
|
||||
public function describeAutomaticCapability($capability) {
|
||||
return $this->getApplication()->describeAutomaticCapability($capability);
|
||||
}
|
||||
|
||||
}
|
|
@ -64,10 +64,9 @@ final class PhabricatorMetaMTAReceivedMailTestCase extends PhabricatorTestCase {
|
|||
}
|
||||
|
||||
public function testDropUnknownSenderMail() {
|
||||
$this->setManiphestCreateEmail();
|
||||
|
||||
$env = PhabricatorEnv::beginScopedEnv();
|
||||
$env->overrideEnvConfig(
|
||||
'metamta.maniphest.public-create-email',
|
||||
'bugs@example.com');
|
||||
$env->overrideEnvConfig('phabricator.allow-email-users', false);
|
||||
$env->overrideEnvConfig('metamta.maniphest.default-public-author', null);
|
||||
|
||||
|
@ -89,10 +88,7 @@ final class PhabricatorMetaMTAReceivedMailTestCase extends PhabricatorTestCase {
|
|||
|
||||
|
||||
public function testDropDisabledSenderMail() {
|
||||
$env = PhabricatorEnv::beginScopedEnv();
|
||||
$env->overrideEnvConfig(
|
||||
'metamta.maniphest.public-create-email',
|
||||
'bugs@example.com');
|
||||
$this->setManiphestCreateEmail();
|
||||
|
||||
$user = $this->generateNewTestUser()
|
||||
->setIsDisabled(true)
|
||||
|
@ -114,4 +110,15 @@ final class PhabricatorMetaMTAReceivedMailTestCase extends PhabricatorTestCase {
|
|||
$mail->getStatus());
|
||||
}
|
||||
|
||||
private function setManiphestCreateEmail() {
|
||||
$maniphest_app = new PhabricatorManiphestApplication();
|
||||
try {
|
||||
id(new PhabricatorMetaMTAApplicationEmail())
|
||||
->setApplicationPHID($maniphest_app->getPHID())
|
||||
->setAddress('bugs@example.com')
|
||||
->setConfigData(array())
|
||||
->save();
|
||||
} catch (AphrontDuplicateKeyQueryException $ex) {}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorMetaMTAApplicationEmailPHIDType
|
||||
extends PhabricatorPHIDType {
|
||||
|
||||
const TYPECONST = 'APPE';
|
||||
|
||||
public function getTypeName() {
|
||||
return pht('Application Email');
|
||||
}
|
||||
|
||||
public function getPHIDTypeApplicationClass() {
|
||||
return 'PhabricatorMetaMTAApplication';
|
||||
}
|
||||
|
||||
public function getTypeIcon() {
|
||||
return 'fa-email bluegrey';
|
||||
}
|
||||
|
||||
public function newObject() {
|
||||
return new PhabricatorMetaMTAApplicationEmail();
|
||||
}
|
||||
|
||||
protected function buildQueryForObjects(
|
||||
PhabricatorObjectQuery $query,
|
||||
array $phids) {
|
||||
|
||||
return id(new PhabricatorMetaMTAApplicationEmailQuery())
|
||||
->withPHIDs($phids);
|
||||
}
|
||||
|
||||
public function loadHandles(
|
||||
PhabricatorHandleQuery $query,
|
||||
array $handles,
|
||||
array $objects) {
|
||||
|
||||
foreach ($handles as $phid => $handle) {
|
||||
$email = $objects[$phid];
|
||||
|
||||
$handle->setName($email->getAddress());
|
||||
$handle->setFullName($email->getAddress());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue