1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-10 23:01:04 +01:00

(stable) Promote 2018 Week 17

This commit is contained in:
epriestley 2018-04-27 15:54:30 -07:00
commit 2e76862626
30 changed files with 657 additions and 56 deletions

View file

@ -391,7 +391,7 @@ return array(
'rsrc/js/application/files/behavior-document-engine.js' => 'ee0deff8',
'rsrc/js/application/files/behavior-icon-composer.js' => '8499b6ab',
'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888',
'rsrc/js/application/harbormaster/behavior-harbormaster-log.js' => '191b4909',
'rsrc/js/application/harbormaster/behavior-harbormaster-log.js' => '549459b8',
'rsrc/js/application/herald/HeraldRuleEditor.js' => 'dca75c0e',
'rsrc/js/application/herald/PathTypeahead.js' => '662e9cea',
'rsrc/js/application/herald/herald-rule-editor.js' => '7ebaeed3',
@ -609,7 +609,7 @@ return array(
'javelin-behavior-event-all-day' => 'b41537c9',
'javelin-behavior-fancy-datepicker' => 'ecf4e799',
'javelin-behavior-global-drag-and-drop' => '960f6a39',
'javelin-behavior-harbormaster-log' => '191b4909',
'javelin-behavior-harbormaster-log' => '549459b8',
'javelin-behavior-herald-rule-editor' => '7ebaeed3',
'javelin-behavior-high-security-warning' => 'a464fe03',
'javelin-behavior-history-install' => '7ee2b591',
@ -960,9 +960,6 @@ return array(
'185bbd53' => array(
'javelin-install',
),
'191b4909' => array(
'javelin-behavior',
),
'1ad0a787' => array(
'javelin-install',
'javelin-reactor',
@ -1257,6 +1254,9 @@ return array(
'javelin-vector',
'javelin-typeahead-static-source',
),
'549459b8' => array(
'javelin-behavior',
),
'54b612ba' => array(
'javelin-color',
'javelin-install',

View file

@ -0,0 +1,8 @@
CREATE TABLE {$NAMESPACE}_metamta.metamta_mailproperties (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
objectPHID VARBINARY(64) NOT NULL,
mailProperties LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL,
UNIQUE KEY `key_object` (objectPHID)
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};

View file

@ -5,9 +5,22 @@ confirm() {
read -e ignored
}
GIT='git'
INSTALL_URI=" https://phurl.io/u/install"
failed() {
echo
echo
echo "Installation has failed."
echo "Text above this message might be useful to understanding what exactly failed."
echo
echo "Please follow this guide to manually complete installation:"
echo
echo $INSTALL_URI
echo
echo "We apologize for the inconvenience."
exit 3
}
LTS="Ubuntu 10.04"
ISSUE=`cat /etc/issue`
if [[ $ISSUE != Ubuntu* ]]
then
@ -15,20 +28,13 @@ then
echo "to be something else. Your results may vary.";
echo
confirm
elif [[ `expr match "$ISSUE" "$LTS"` -eq ${#LTS} ]]
then
GIT='git-core'
fi
echo "PHABRICATOR UBUNTU INSTALL SCRIPT";
echo "This script will install Phabricator and all of its core dependencies.";
echo "This script will install Apache, Phabricator and its core dependencies.";
echo "Run it from the directory you want to install into.";
echo
ROOT=`pwd`
echo "Phabricator will be installed to: ${ROOT}.";
confirm
echo "Testing sudo..."
sudo true
if [ $? -ne 0 ]
@ -37,31 +43,56 @@ then
exit 1;
fi;
echo "Installing dependencies: git, apache, mysql, php...";
echo
echo 'Testing Ubuntu version...'
set +x
VERSION=`lsb_release -rs`
MAJOR=`expr match "$VERSION" '\([0-9]*\)'`
sudo apt-get -qq update
sudo apt-get install \
$GIT mysql-server apache2 dpkg-dev \
php5 php5-mysqlnd php5-gd php5-dev php5-curl php-apc php5-cli php5-json
# Enable mod_rewrite
sudo a2enmod rewrite
HAVEPCNTL=`php -r "echo extension_loaded('pcntl');"`
if [ $HAVEPCNTL != "1" ]
if [ "$MAJOR" -lt 16 ]
then
echo "Installing pcntl...";
echo 'This script is intented to install on modern operating systems; Your '
echo 'operating system is too old for this script.'
echo 'You can still install Phabricator manually - please consult the installation'
echo 'guide to see how:'
echo
apt-get source php5
PHP5=`ls -1F | grep '^php5-.*/$'`
(cd $PHP5/ext/pcntl && phpize && ./configure && make && sudo make install)
else
echo "pcntl already installed";
echo $INSTALL_URI
echo
exit 2
fi
# Ubuntu 16.04 LTS only has php 7.0 in their repos, so they need this extra ppa.
# Ubuntu 17.4 and up have official 7.2 builds.
if [ "$MAJOR" -eq 16 ]
then
echo 'This version of Ubuntu requires additional resources in order to install'
echo 'and run Phabricator.'
echo 'We will now add a the following package repository to your system:'
echo ' https://launchpad.net/~ondrej/+archive/ubuntu/php'
echo
echo 'This repository is generally considered safe to use.'
confirm
sudo add-apt-repository -y ppa:ondrej/php || failed
fi
ROOT=`pwd`
echo "Phabricator will be installed to: ${ROOT}.";
confirm
echo "Installing dependencies: git, apache, mysql, php...";
echo
sudo apt-get -qq update
sudo apt-get install \
git mysql-server apache2 libapache2-mod-php \
php php-mysql php-gd php-curl php-apcu php-cli php-json php-mbstring \
|| failed
echo "Enabling mod_rewrite in Apache..."
echo
sudo a2enmod rewrite || failed
echo "Downloading Phabricator and dependencies..."
echo
if [ ! -e libphutil ]
then
git clone https://github.com/phacility/libphutil.git
@ -89,4 +120,4 @@ echo "Install probably worked mostly correctly. Continue with the 'Configuration
echo
echo " https://secure.phabricator.com/book/phabricator/article/configuration_guide/";
echo
echo "You can delete any php5-* stuff that's left over in this directory if you want.";
echo 'Next step is "Configuring Apache webserver".'

View file

@ -1430,6 +1430,7 @@ phutil_register_library_map(array(
'HeraldActionGroup' => 'applications/herald/action/HeraldActionGroup.php',
'HeraldActionRecord' => 'applications/herald/storage/HeraldActionRecord.php',
'HeraldAdapter' => 'applications/herald/adapter/HeraldAdapter.php',
'HeraldAdapterDatasource' => 'applications/herald/typeahead/HeraldAdapterDatasource.php',
'HeraldAlwaysField' => 'applications/herald/field/HeraldAlwaysField.php',
'HeraldAnotherRuleField' => 'applications/herald/field/HeraldAnotherRuleField.php',
'HeraldApplicationActionGroup' => 'applications/herald/action/HeraldApplicationActionGroup.php',
@ -1485,12 +1486,17 @@ phutil_register_library_map(array(
'HeraldRemarkupFieldValue' => 'applications/herald/value/HeraldRemarkupFieldValue.php',
'HeraldRemarkupRule' => 'applications/herald/remarkup/HeraldRemarkupRule.php',
'HeraldRule' => 'applications/herald/storage/HeraldRule.php',
'HeraldRuleAdapter' => 'applications/herald/adapter/HeraldRuleAdapter.php',
'HeraldRuleAdapterField' => 'applications/herald/field/rule/HeraldRuleAdapterField.php',
'HeraldRuleController' => 'applications/herald/controller/HeraldRuleController.php',
'HeraldRuleDatasource' => 'applications/herald/typeahead/HeraldRuleDatasource.php',
'HeraldRuleEditor' => 'applications/herald/editor/HeraldRuleEditor.php',
'HeraldRuleField' => 'applications/herald/field/rule/HeraldRuleField.php',
'HeraldRuleFieldGroup' => 'applications/herald/field/rule/HeraldRuleFieldGroup.php',
'HeraldRuleListController' => 'applications/herald/controller/HeraldRuleListController.php',
'HeraldRulePHIDType' => 'applications/herald/phid/HeraldRulePHIDType.php',
'HeraldRuleQuery' => 'applications/herald/query/HeraldRuleQuery.php',
'HeraldRuleReplyHandler' => 'applications/herald/mail/HeraldRuleReplyHandler.php',
'HeraldRuleSearchEngine' => 'applications/herald/query/HeraldRuleSearchEngine.php',
'HeraldRuleSerializer' => 'applications/herald/editor/HeraldRuleSerializer.php',
'HeraldRuleTestCase' => 'applications/herald/storage/__tests__/HeraldRuleTestCase.php',
@ -1498,6 +1504,8 @@ phutil_register_library_map(array(
'HeraldRuleTransactionComment' => 'applications/herald/storage/HeraldRuleTransactionComment.php',
'HeraldRuleTranscript' => 'applications/herald/storage/transcript/HeraldRuleTranscript.php',
'HeraldRuleTypeConfig' => 'applications/herald/config/HeraldRuleTypeConfig.php',
'HeraldRuleTypeDatasource' => 'applications/herald/typeahead/HeraldRuleTypeDatasource.php',
'HeraldRuleTypeField' => 'applications/herald/field/rule/HeraldRuleTypeField.php',
'HeraldRuleViewController' => 'applications/herald/controller/HeraldRuleViewController.php',
'HeraldSchemaSpec' => 'applications/herald/storage/HeraldSchemaSpec.php',
'HeraldSelectFieldValue' => 'applications/herald/value/HeraldSelectFieldValue.php',
@ -3346,6 +3354,7 @@ phutil_register_library_map(array(
'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingSelfEmailHeraldAction.php',
'PhabricatorMailOutboundRoutingSelfNotificationHeraldAction' => 'applications/metamta/herald/PhabricatorMailOutboundRoutingSelfNotificationHeraldAction.php',
'PhabricatorMailOutboundStatus' => 'applications/metamta/constants/PhabricatorMailOutboundStatus.php',
'PhabricatorMailPropertiesDestructionEngineExtension' => 'applications/metamta/engineextension/PhabricatorMailPropertiesDestructionEngineExtension.php',
'PhabricatorMailReceiver' => 'applications/metamta/receiver/PhabricatorMailReceiver.php',
'PhabricatorMailReceiverTestCase' => 'applications/metamta/receiver/__tests__/PhabricatorMailReceiverTestCase.php',
'PhabricatorMailReplyHandler' => 'applications/metamta/replyhandler/PhabricatorMailReplyHandler.php',
@ -3403,6 +3412,8 @@ phutil_register_library_map(array(
'PhabricatorMetaMTAMailHasRecipientEdgeType' => 'applications/metamta/edge/PhabricatorMetaMTAMailHasRecipientEdgeType.php',
'PhabricatorMetaMTAMailListController' => 'applications/metamta/controller/PhabricatorMetaMTAMailListController.php',
'PhabricatorMetaMTAMailPHIDType' => 'applications/metamta/phid/PhabricatorMetaMTAMailPHIDType.php',
'PhabricatorMetaMTAMailProperties' => 'applications/metamta/storage/PhabricatorMetaMTAMailProperties.php',
'PhabricatorMetaMTAMailPropertiesQuery' => 'applications/metamta/query/PhabricatorMetaMTAMailPropertiesQuery.php',
'PhabricatorMetaMTAMailQuery' => 'applications/metamta/query/PhabricatorMetaMTAMailQuery.php',
'PhabricatorMetaMTAMailSearchEngine' => 'applications/metamta/query/PhabricatorMetaMTAMailSearchEngine.php',
'PhabricatorMetaMTAMailSection' => 'applications/metamta/view/PhabricatorMetaMTAMailSection.php',
@ -6847,6 +6858,7 @@ phutil_register_library_map(array(
'HeraldActionGroup' => 'HeraldGroup',
'HeraldActionRecord' => 'HeraldDAO',
'HeraldAdapter' => 'Phobject',
'HeraldAdapterDatasource' => 'PhabricatorTypeaheadDatasource',
'HeraldAlwaysField' => 'HeraldField',
'HeraldAnotherRuleField' => 'HeraldField',
'HeraldApplicationActionGroup' => 'HeraldActionGroup',
@ -6915,12 +6927,17 @@ phutil_register_library_map(array(
'PhabricatorDestructibleInterface',
'PhabricatorSubscribableInterface',
),
'HeraldRuleAdapter' => 'HeraldAdapter',
'HeraldRuleAdapterField' => 'HeraldRuleField',
'HeraldRuleController' => 'HeraldController',
'HeraldRuleDatasource' => 'PhabricatorTypeaheadDatasource',
'HeraldRuleEditor' => 'PhabricatorApplicationTransactionEditor',
'HeraldRuleField' => 'HeraldField',
'HeraldRuleFieldGroup' => 'HeraldFieldGroup',
'HeraldRuleListController' => 'HeraldController',
'HeraldRulePHIDType' => 'PhabricatorPHIDType',
'HeraldRuleQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'HeraldRuleReplyHandler' => 'PhabricatorApplicationTransactionReplyHandler',
'HeraldRuleSearchEngine' => 'PhabricatorApplicationSearchEngine',
'HeraldRuleSerializer' => 'Phobject',
'HeraldRuleTestCase' => 'PhabricatorTestCase',
@ -6928,6 +6945,8 @@ phutil_register_library_map(array(
'HeraldRuleTransactionComment' => 'PhabricatorApplicationTransactionComment',
'HeraldRuleTranscript' => 'Phobject',
'HeraldRuleTypeConfig' => 'Phobject',
'HeraldRuleTypeDatasource' => 'PhabricatorTypeaheadDatasource',
'HeraldRuleTypeField' => 'HeraldRuleField',
'HeraldRuleViewController' => 'HeraldController',
'HeraldSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'HeraldSelectFieldValue' => 'HeraldFieldValue',
@ -9038,6 +9057,7 @@ phutil_register_library_map(array(
'PhabricatorMailOutboundRoutingSelfEmailHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction',
'PhabricatorMailOutboundRoutingSelfNotificationHeraldAction' => 'PhabricatorMailOutboundRoutingHeraldAction',
'PhabricatorMailOutboundStatus' => 'Phobject',
'PhabricatorMailPropertiesDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension',
'PhabricatorMailReceiver' => 'Phobject',
'PhabricatorMailReceiverTestCase' => 'PhabricatorTestCase',
'PhabricatorMailReplyHandler' => 'Phobject',
@ -9106,6 +9126,11 @@ phutil_register_library_map(array(
'PhabricatorMetaMTAMailHasRecipientEdgeType' => 'PhabricatorEdgeType',
'PhabricatorMetaMTAMailListController' => 'PhabricatorMetaMTAController',
'PhabricatorMetaMTAMailPHIDType' => 'PhabricatorPHIDType',
'PhabricatorMetaMTAMailProperties' => array(
'PhabricatorMetaMTADAO',
'PhabricatorPolicyInterface',
),
'PhabricatorMetaMTAMailPropertiesQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorMetaMTAMailQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorMetaMTAMailSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorMetaMTAMailSection' => 'Phobject',

View file

@ -113,6 +113,7 @@ abstract class AphrontResponse extends Phobject {
try {
$cdn = PhabricatorEnv::getEnvConfig('security.alternate-file-domain');
$base_uri = PhabricatorEnv::getURI('/');
} catch (Exception $ex) {
return null;
}
@ -124,8 +125,6 @@ abstract class AphrontResponse extends Phobject {
// If an alternate file domain is not configured and the user is viewing
// a Phame blog on a custom domain or some other custom site, we'll still
// serve resources from the main site. Include the main site explicitly.
$base_uri = PhabricatorEnv::getURI('/');
$base_uri = $this->newContentSecurityPolicySource($base_uri);
$default = "'self' {$base_uri}";

View file

@ -70,12 +70,6 @@ final class PhabricatorAuthSSHKey
return parent::save();
}
public function getMailKey() {
// NOTE: We don't actually receive mail for these objects. It's OK for
// the mail key to be predictable until we do.
return PhabricatorHash::digestForIndex($this->getPHID());
}
public function toPublicKey() {
return PhabricatorAuthSSHPublicKey::newFromStoredKey($this);
}

View file

@ -7,7 +7,7 @@ final class DifferentialRevisionAcceptTransaction
const ACTIONKEY = 'accept';
protected function getRevisionActionLabel() {
return pht("Accept Revision \xE2\x9C\x94");
return pht('Accept Revision');
}
protected function getRevisionActionDescription(
@ -162,7 +162,7 @@ final class DifferentialRevisionAcceptTransaction
'closed. Only open revisions can be accepted.'));
}
if ($object->isDraft()) {
if ($object->isDraft() || !$object->getShouldBroadcast()) {
throw new Exception(
pht('You can not accept a draft revision.'));
}

View file

@ -7,7 +7,7 @@ final class DifferentialRevisionRejectTransaction
const ACTIONKEY = 'reject';
protected function getRevisionActionLabel() {
return pht("Request Changes \xE2\x9C\x98");
return pht('Request Changes');
}
protected function getRevisionActionDescription(
@ -73,7 +73,7 @@ final class DifferentialRevisionRejectTransaction
'not own.'));
}
if ($object->isDraft()) {
if ($object->isDraft() || !$object->getShouldBroadcast()) {
throw new Exception(
pht('You can not request changes to a draft revision.'));
}

View file

@ -247,7 +247,14 @@ final class PhabricatorFaviconRef extends Phobject {
$src_w = $template['width'];
$src_h = $template['height'];
$template_data = $template['file']->loadFileData();
try {
$template_data = $template['file']->loadFileData();
} catch (Exception $ex) {
// In rare cases, we can end up with a corrupted or inaccessible file.
// If we do, just give up: otherwise, it's impossible to get pages to
// generate and not obvious how to fix it.
return null;
}
if (!function_exists('imagecreatefromstring')) {
return $template_data;

View file

@ -46,7 +46,13 @@ final class HarbormasterTargetWorker extends HarbormasterWorker {
$build = $target->getBuild();
$viewer = $this->getViewer();
$target->setDateStarted(time());
// If this is the first time we're starting work on this target, mark the
// current time as the start time. If the target yields or waits, we may
// end up here again later, so we don't want to overwrite the start time if
// we already have a value.
if (!$target->getDateStarted()) {
$target->setDateStarted(PhabricatorTime::getNow());
}
try {
if ($target->getBuildGeneration() !== $build->getBuildGeneration()) {

View file

@ -0,0 +1,74 @@
<?php
final class HeraldRuleAdapter extends HeraldAdapter {
private $rule;
protected function newObject() {
return new HeraldRule();
}
public function getAdapterApplicationClass() {
return 'PhabricatorHeraldApplication';
}
public function getAdapterContentDescription() {
return pht('React to Herald rules being created or updated.');
}
public function isTestAdapterForObject($object) {
return ($object instanceof HeraldRule);
}
public function getAdapterTestDescription() {
return pht(
'Test rules which run when another Herald rule is created or '.
'updated.');
}
protected function initializeNewAdapter() {
$this->rule = $this->newObject();
}
public function supportsApplicationEmail() {
return true;
}
public function supportsRuleType($rule_type) {
switch ($rule_type) {
case HeraldRuleTypeConfig::RULE_TYPE_GLOBAL:
case HeraldRuleTypeConfig::RULE_TYPE_PERSONAL:
return true;
case HeraldRuleTypeConfig::RULE_TYPE_OBJECT:
default:
return false;
}
}
public function setRule(HeraldRule $rule) {
$this->rule = $rule;
return $this;
}
public function getRule() {
return $this->rule;
}
public function setObject($object) {
$this->rule = $object;
return $this;
}
public function getObject() {
return $this->rule;
}
public function getAdapterContentName() {
return pht('Herald Rules');
}
public function getHeraldName() {
return $this->getRule()->getMonogram();
}
}

View file

@ -38,8 +38,10 @@ final class HeraldTestConsoleController extends HeraldController {
$object = $this->getTestObject();
$adapter = $this->getTestAdapter();
$source = $this->newContentSource($object);
$adapter
->setContentSource($source)
->setIsNewObject(false)
->setActingAsPHID($viewer->getPHID())
->setViewer($viewer);
@ -218,4 +220,29 @@ final class HeraldTestConsoleController extends HeraldController {
->appendChild($view);
}
private function newContentSource($object) {
$viewer = $this->getViewer();
// Try using the content source associated with the most recent transaction
// on the object.
$query = PhabricatorApplicationTransactionQuery::newQueryForObject($object);
$xaction = $query
->setViewer($viewer)
->withObjectPHIDs(array($object->getPHID()))
->setLimit(1)
->setOrder('newest')
->executeOne();
if ($xaction) {
return $xaction->getContentSource();
}
// If we couldn't find a transaction (which should be rare), fall back to
// building a new content source from the test console request itself.
$request = $this->getRequest();
return PhabricatorContentSource::newFromRequest($request);
}
}

View file

@ -87,4 +87,54 @@ final class HeraldRuleEditor
return;
}
protected function shouldApplyHeraldRules(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function buildHeraldAdapter(
PhabricatorLiskDAO $object,
array $xactions) {
return id(new HeraldRuleAdapter())
->setRule($object);
}
protected function shouldSendMail(
PhabricatorLiskDAO $object,
array $xactions) {
return true;
}
protected function getMailTo(PhabricatorLiskDAO $object) {
$phids = array();
$phids[] = $this->getActingAsPHID();
if ($object->isPersonalRule()) {
$phids[] = $object->getAuthorPHID();
}
return $phids;
}
protected function buildReplyHandler(PhabricatorLiskDAO $object) {
return id(new HeraldRuleReplyHandler())
->setMailReceiver($object);
}
protected function buildMailTemplate(PhabricatorLiskDAO $object) {
$monogram = $object->getMonogram();
$name = $object->getName();
$subject = pht('%s: %s', $monogram, $name);
return id(new PhabricatorMetaMTAMail())
->setSubject($subject);
}
protected function getMailSubjectPrefix() {
return pht('[Herald]');
}
}

View file

@ -0,0 +1,29 @@
<?php
final class HeraldRuleAdapterField
extends HeraldRuleField {
const FIELDCONST = 'adapter';
public function getHeraldFieldName() {
return pht('Content type');
}
public function getHeraldFieldValue($object) {
return $object->getContentType();
}
protected function getHeraldFieldStandardType() {
return self::STANDARD_PHID;
}
protected function getDatasource() {
return new HeraldAdapterDatasource();
}
protected function getDatasourceValueMap() {
$adapters = HeraldAdapter::getAllAdapters();
return mpull($adapters, 'getAdapterContentName', 'getAdapterContentType');
}
}

View file

@ -0,0 +1,14 @@
<?php
abstract class HeraldRuleField
extends HeraldField {
public function getFieldGroupKey() {
return ManiphestTaskHeraldFieldGroup::FIELDGROUPKEY;
}
public function supportsObject($object) {
return ($object instanceof HeraldRule);
}
}

View file

@ -0,0 +1,16 @@
<?php
final class HeraldRuleFieldGroup
extends HeraldFieldGroup {
const FIELDGROUPKEY = 'herald.rule';
public function getGroupLabel() {
return pht('Rule Fields');
}
protected function getGroupOrder() {
return 500;
}
}

View file

@ -0,0 +1,28 @@
<?php
final class HeraldRuleTypeField
extends HeraldRuleField {
const FIELDCONST = 'rule-type';
public function getHeraldFieldName() {
return pht('Rule type');
}
public function getHeraldFieldValue($object) {
return $object->getRuleType();
}
protected function getHeraldFieldStandardType() {
return self::STANDARD_PHID;
}
protected function getDatasource() {
return new HeraldRuleTypeDatasource();
}
protected function getDatasourceValueMap() {
return HeraldRuleTypeConfig::getRuleTypeMap();
}
}

View file

@ -0,0 +1,16 @@
<?php
final class HeraldRuleReplyHandler
extends PhabricatorApplicationTransactionReplyHandler {
public function validateMailReceiver($mail_receiver) {
if (!($mail_receiver instanceof HeraldRule)) {
throw new Exception(pht('Mail receiver is not a %s!', 'HeraldRule'));
}
}
public function getObjectPrefix() {
return 'H';
}
}

View file

@ -0,0 +1,45 @@
<?php
final class HeraldAdapterDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Herald Adapters');
}
public function getPlaceholderText() {
return pht('Type an adapter name...');
}
public function getDatasourceApplicationClass() {
return 'PhabricatorHeraldApplication';
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$results = array();
$adapters = HeraldAdapter::getAllAdapters();
foreach ($adapters as $adapter) {
$value = $adapter->getAdapterContentType();
$name = $adapter->getAdapterContentName();
$result = id(new PhabricatorTypeaheadResult())
->setPHID($value)
->setName($name);
$results[$value] = $result;
}
return $results;
}
}

View file

@ -0,0 +1,42 @@
<?php
final class HeraldRuleTypeDatasource
extends PhabricatorTypeaheadDatasource {
public function getBrowseTitle() {
return pht('Browse Rule Types');
}
public function getPlaceholderText() {
return pht('Type a rule type...');
}
public function getDatasourceApplicationClass() {
return 'PhabricatorHeraldApplication';
}
public function loadResults() {
$results = $this->buildResults();
return $this->filterResultsAgainstTokens($results);
}
protected function renderSpecialTokens(array $values) {
return $this->renderTokensFromResults($this->buildResults(), $values);
}
private function buildResults() {
$results = array();
$type_map = HeraldRuleTypeConfig::getRuleTypeMap();
foreach ($type_map as $type => $name) {
$result = id(new PhabricatorTypeaheadResult())
->setPHID($type)
->setName($name);
$results[$type] = $result;
}
return $results;
}
}

View file

@ -0,0 +1,28 @@
<?php
final class PhabricatorMailPropertiesDestructionEngineExtension
extends PhabricatorDestructionEngineExtension {
const EXTENSIONKEY = 'mail.properties';
public function getExtensionName() {
return pht('Mail Properties');
}
public function destroyObject(
PhabricatorDestructionEngine $engine,
$object) {
$object_phid = $object->getPHID();
$viewer = $engine->getViewer();
$properties = id(new PhabricatorMetaMTAMailPropertiesQuery())
->setViewer($viewer)
->withObjectPHIDs(array($object_phid))
->executeOne();
if ($properties) {
$properties->delete();
}
}
}

View file

@ -139,8 +139,10 @@ final class PhabricatorMailManagementReceiveTestWorkflow
throw new Exception(pht("No such object '%s'!", $to));
}
$mail_key = PhabricatorMetaMTAMailProperties::loadMailKey($object);
$hash = PhabricatorObjectMailReceiver::computeMailHash(
$object->getMailKey(),
$mail_key,
$user->getPHID());
$header_content['to'] = $to.'+'.$user->getID().'+'.$hash.'@test.com';

View file

@ -0,0 +1,51 @@
<?php
final class PhabricatorMetaMTAMailPropertiesQuery
extends PhabricatorCursorPagedPolicyAwareQuery {
private $ids;
private $objectPHIDs;
public function withIDs(array $ids) {
$this->ids = $ids;
return $this;
}
public function withObjectPHIDs(array $object_phids) {
$this->objectPHIDs = $object_phids;
return $this;
}
public function newResultObject() {
return new PhabricatorMetaMTAMailProperties();
}
protected function loadPage() {
return $this->loadStandardPage($this->newResultObject());
}
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
$where = parent::buildWhereClauseParts($conn);
if ($this->ids !== null) {
$where[] = qsprintf(
$conn,
'id IN (%Ld)',
$this->ids);
}
if ($this->objectPHIDs !== null) {
$where[] = qsprintf(
$conn,
'objectPHID IN (%Ls)',
$this->objectPHIDs);
}
return $where;
}
public function getQueryApplicationClass() {
return 'PhabricatorMetaMTAApplication';
}
}

View file

@ -124,7 +124,8 @@ abstract class PhabricatorObjectMailReceiver extends PhabricatorMailReceiver {
$check_phid = $sender->getPHID();
}
$expect_hash = self::computeMailHash($object->getMailKey(), $check_phid);
$mail_key = PhabricatorMetaMTAMailProperties::loadMailKey($object);
$expect_hash = self::computeMailHash($mail_key, $check_phid);
if (!phutil_hashes_are_identical($expect_hash, $parts['hash'])) {
throw new PhabricatorMetaMTAReceivedMailProcessingException(

View file

@ -98,8 +98,11 @@ final class PhabricatorObjectMailReceiverTestCase
if ($is_bad_hash) {
$hash = PhabricatorObjectMailReceiver::computeMailHash('x', 'y');
} else {
$mail_key = PhabricatorMetaMTAMailProperties::loadMailKey($task);
$hash = PhabricatorObjectMailReceiver::computeMailHash(
$task->getMailKey(),
$mail_key,
$is_public ? $task->getPHID() : $user->getPHID());
}

View file

@ -136,8 +136,11 @@ abstract class PhabricatorMailReplyHandler extends Phobject {
// We compute a hash using the object's own PHID to prevent an attacker
// from blindly interacting with objects that they haven't ever received
// mail about by just sending to D1@, D2@, etc...
$mail_key = PhabricatorMetaMTAMailProperties::loadMailKey($receiver);
$hash = PhabricatorObjectMailReceiver::computeMailHash(
$receiver->getMailKey(),
$mail_key,
$receiver->getPHID());
$address = "{$prefix}{$receiver_id}+public+{$hash}@{$domain}";
@ -159,8 +162,11 @@ abstract class PhabricatorMailReplyHandler extends Phobject {
$receiver = $this->getMailReceiver();
$receiver_id = $receiver->getID();
$user_id = $user->getID();
$mail_key = PhabricatorMetaMTAMailProperties::loadMailKey($receiver);
$hash = PhabricatorObjectMailReceiver::computeMailHash(
$receiver->getMailKey(),
$mail_key,
$user->getPHID());
$domain = $this->getReplyHandlerDomain();

View file

@ -0,0 +1,91 @@
<?php
final class PhabricatorMetaMTAMailProperties
extends PhabricatorMetaMTADAO
implements PhabricatorPolicyInterface {
protected $objectPHID;
protected $mailProperties = array();
protected function getConfiguration() {
return array(
self::CONFIG_SERIALIZATION => array(
'mailProperties' => self::SERIALIZATION_JSON,
),
self::CONFIG_COLUMN_SCHEMA => array(),
self::CONFIG_KEY_SCHEMA => array(
'key_object' => array(
'columns' => array('objectPHID'),
'unique' => true,
),
),
) + parent::getConfiguration();
}
public function getMailProperty($key, $default = null) {
return idx($this->mailProperties, $key, $default);
}
public function setMailProperty($key, $value) {
$this->mailProperties[$key] = $value;
return $this;
}
public static function loadMailKey($object) {
// If this is an older object with an onboard "mailKey" property, just
// use it.
// TODO: We should eventually get rid of these and get rid of this
// piece of code.
if ($object->hasProperty('mailKey')) {
return $object->getMailKey();
}
$viewer = PhabricatorUser::getOmnipotentUser();
$object_phid = $object->getPHID();
$properties = id(new PhabricatorMetaMTAMailPropertiesQuery())
->setViewer($viewer)
->withObjectPHIDs(array($object_phid))
->executeOne();
if (!$properties) {
$properties = id(new self())
->setObjectPHID($object_phid);
}
$mail_key = $properties->getMailProperty('mailKey');
if ($mail_key !== null) {
return $mail_key;
}
$mail_key = Filesystem::readRandomCharacters(20);
$properties->setMailProperty('mailKey', $mail_key);
$unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
$properties->save();
unset($unguarded);
return $mail_key;
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return PhabricatorPolicies::POLICY_NOONE;
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return false;
}
}

View file

@ -47,7 +47,7 @@ There are two primary ways to import an existing repository:
Once the import completes, change the "I/O Type" on the **Observe** URI to
"No I/O" mode to automatically convert it into a hosted repository.
**Push to Empty Repository**: Create an activate an empty repository, then push
**Push to Empty Repository**: Create and activate an empty repository, then push
all of your changes to the empty repository.
In Git and Mercurial, you can do this with `git push` or `hg push`.

View file

@ -1659,6 +1659,14 @@ final class PhabricatorUSEnglishTranslation
'you can no longer see were discarded.',
),
'This draft revision will be sent for review once %s '.
'build(s) pass: %s.' => array(
'This draft revision will be sent for review once this build '.
'passes: %2$s.',
'This draft revision will be sent for review once these builds '.
'pass: %2$s.',
),
);
}

View file

@ -16,7 +16,7 @@ JX.behavior('harbormaster-log', function(config) {
e.kill();
expand(e.getTarget(), true);
expand(e.getNode('harbormaster-log-expand'), true);
});
function expand(node, is_action) {