mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-10 14:51:06 +01:00
(stable) Promote 2018 Week 17
This commit is contained in:
commit
2e76862626
30 changed files with 657 additions and 56 deletions
|
@ -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',
|
||||
|
|
|
@ -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};
|
|
@ -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".'
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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}";
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.'));
|
||||
}
|
||||
|
|
|
@ -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.'));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()) {
|
||||
|
|
74
src/applications/herald/adapter/HeraldRuleAdapter.php
Normal file
74
src/applications/herald/adapter/HeraldRuleAdapter.php
Normal 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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]');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
|
||||
}
|
14
src/applications/herald/field/rule/HeraldRuleField.php
Normal file
14
src/applications/herald/field/rule/HeraldRuleField.php
Normal 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);
|
||||
}
|
||||
|
||||
}
|
16
src/applications/herald/field/rule/HeraldRuleFieldGroup.php
Normal file
16
src/applications/herald/field/rule/HeraldRuleFieldGroup.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
28
src/applications/herald/field/rule/HeraldRuleTypeField.php
Normal file
28
src/applications/herald/field/rule/HeraldRuleTypeField.php
Normal 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();
|
||||
}
|
||||
|
||||
}
|
16
src/applications/herald/mail/HeraldRuleReplyHandler.php
Normal file
16
src/applications/herald/mail/HeraldRuleReplyHandler.php
Normal 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';
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
|
||||
}
|
|
@ -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(
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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`.
|
||||
|
|
|
@ -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.',
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue