Page MenuHomePhabricator

D11418.id27480.diff
No OneTemporary

D11418.id27480.diff

diff --git a/resources/sql/autopatches/20150115.applicationemails.sql b/resources/sql/autopatches/20150115.applicationemails.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20150115.applicationemails.sql
@@ -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};
diff --git a/resources/sql/autopatches/20150116.maniphestapplicationemails.php b/resources/sql/autopatches/20150116.maniphestapplicationemails.php
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20150116.maniphestapplicationemails.php
@@ -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";
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1258,6 +1258,7 @@
'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',
@@ -1945,6 +1946,9 @@
'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',
@@ -4418,6 +4422,7 @@
'PhabricatorApplicationDatasource' => 'PhabricatorTypeaheadDatasource',
'PhabricatorApplicationDetailViewController' => 'PhabricatorApplicationsController',
'PhabricatorApplicationEditController' => 'PhabricatorApplicationsController',
+ 'PhabricatorApplicationEditEmailController' => 'PhabricatorApplicationsController',
'PhabricatorApplicationLaunchView' => 'AphrontTagView',
'PhabricatorApplicationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorApplicationSearchController' => 'PhabricatorSearchBaseController',
@@ -5142,6 +5147,12 @@
'PhabricatorMercurialGraphStream' => 'PhabricatorRepositoryGraphStream',
'PhabricatorMetaMTAActorQuery' => 'PhabricatorQuery',
'PhabricatorMetaMTAApplication' => 'PhabricatorApplication',
+ 'PhabricatorMetaMTAApplicationEmail' => array(
+ 'PhabricatorMetaMTADAO',
+ 'PhabricatorPolicyInterface',
+ ),
+ 'PhabricatorMetaMTAApplicationEmailPHIDType' => 'PhabricatorPHIDType',
+ 'PhabricatorMetaMTAApplicationEmailQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorMetaMTAConfigOptions' => 'PhabricatorApplicationConfigOptions',
'PhabricatorMetaMTAController' => 'PhabricatorController',
'PhabricatorMetaMTADAO' => 'PhabricatorLiskDAO',
diff --git a/src/applications/base/PhabricatorApplication.php b/src/applications/base/PhabricatorApplication.php
--- a/src/applications/base/PhabricatorApplication.php
+++ b/src/applications/base/PhabricatorApplication.php
@@ -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 @@
}
+/* -( 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 )--------------------------------------------------- */
diff --git a/src/applications/maniphest/application/PhabricatorManiphestApplication.php b/src/applications/maniphest/application/PhabricatorManiphestApplication.php
--- a/src/applications/maniphest/application/PhabricatorManiphestApplication.php
+++ b/src/applications/maniphest/application/PhabricatorManiphestApplication.php
@@ -109,6 +109,20 @@
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(
diff --git a/src/applications/maniphest/config/PhabricatorManiphestConfigOptions.php b/src/applications/maniphest/config/PhabricatorManiphestConfigOptions.php
--- a/src/applications/maniphest/config/PhabricatorManiphestConfigOptions.php
+++ b/src/applications/maniphest/config/PhabricatorManiphestConfigOptions.php
@@ -294,9 +294,16 @@
'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 '.
diff --git a/src/applications/maniphest/mail/ManiphestCreateMailReceiver.php b/src/applications/maniphest/mail/ManiphestCreateMailReceiver.php
--- a/src/applications/maniphest/mail/ManiphestCreateMailReceiver.php
+++ b/src/applications/maniphest/mail/ManiphestCreateMailReceiver.php
@@ -8,12 +8,18 @@
}
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) {
- if ($this->matchAddresses($create_address, $to_address)) {
- return true;
+ foreach ($application_emails as $application_email) {
+ $create_address = $application_email->getAddress();
+ if ($this->matchAddresses($create_address, $to_address)) {
+ return true;
+ }
}
}
diff --git a/src/applications/meta/application/PhabricatorApplicationsApplication.php b/src/applications/meta/application/PhabricatorApplicationsApplication.php
--- a/src/applications/meta/application/PhabricatorApplicationsApplication.php
+++ b/src/applications/meta/application/PhabricatorApplicationsApplication.php
@@ -41,6 +41,8 @@
=> 'PhabricatorApplicationDetailViewController',
'edit/(?P<application>\w+)/'
=> 'PhabricatorApplicationEditController',
+ 'editemail/(?P<application>\w+)/'
+ => 'PhabricatorApplicationEditEmailController',
'(?P<application>\w+)/(?P<action>install|uninstall)/'
=> 'PhabricatorApplicationUninstallController',
),
diff --git a/src/applications/meta/controller/PhabricatorApplicationDetailViewController.php b/src/applications/meta/controller/PhabricatorApplicationDetailViewController.php
--- a/src/applications/meta/controller/PhabricatorApplicationDetailViewController.php
+++ b/src/applications/meta/controller/PhabricatorApplicationDetailViewController.php
@@ -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 @@
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 @@
->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(
diff --git a/src/applications/meta/controller/PhabricatorApplicationEditEmailController.php b/src/applications/meta/controller/PhabricatorApplicationEditEmailController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/meta/controller/PhabricatorApplicationEditEmailController.php
@@ -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);
+ }
+
+}
diff --git a/src/applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php b/src/applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/metamta/query/PhabricatorMetaMTAApplicationEmailQuery.php
@@ -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';
+ }
+
+}
diff --git a/src/applications/metamta/receiver/PhabricatorMailReceiver.php b/src/applications/metamta/receiver/PhabricatorMailReceiver.php
--- a/src/applications/metamta/receiver/PhabricatorMailReceiver.php
+++ b/src/applications/metamta/receiver/PhabricatorMailReceiver.php
@@ -15,6 +15,10 @@
$this->processReceivedMail($mail, $sender);
}
+ public function getViewer() {
+ return PhabricatorUser::getOmnipotentUser();
+ }
+
public function validateSender(
PhabricatorMetaMTAReceivedMail $mail,
PhabricatorUser $sender) {
@@ -103,7 +107,7 @@
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()))
diff --git a/src/applications/metamta/storage/PhabricatorMetaMTAApplicationEmail.php b/src/applications/metamta/storage/PhabricatorMetaMTAApplicationEmail.php
new file mode 100644
--- /dev/null
+++ b/src/applications/metamta/storage/PhabricatorMetaMTAApplicationEmail.php
@@ -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);
+ }
+
+}
diff --git a/src/applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php b/src/applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php
--- a/src/applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php
+++ b/src/applications/metamta/storage/__tests__/PhabricatorMetaMTAReceivedMailTestCase.php
@@ -64,10 +64,9 @@
}
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 @@
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 @@
$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) {}
+ }
+
}
diff --git a/src/applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php b/src/applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/phid/PhabricatorMetaMTAApplicationEmailPHIDType.php
@@ -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());
+ }
+ }
+}

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 23, 11:04 PM (19 h, 24 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6780046
Default Alt Text
D11418.id27480.diff (30 KB)

Event Timeline