Page MenuHomePhabricator

D19323.diff
No OneTemporary

D19323.diff

diff --git a/resources/sql/autopatches/20180410.almanac.01.iface.xaction.sql b/resources/sql/autopatches/20180410.almanac.01.iface.xaction.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20180410.almanac.01.iface.xaction.sql
@@ -0,0 +1,19 @@
+CREATE TABLE {$NAMESPACE}_almanac.almanac_interfacetransaction (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARBINARY(64) NOT NULL,
+ authorPHID VARBINARY(64) NOT NULL,
+ objectPHID VARBINARY(64) NOT NULL,
+ viewPolicy VARBINARY(64) NOT NULL,
+ editPolicy VARBINARY(64) NOT NULL,
+ commentPHID VARBINARY(64) DEFAULT NULL,
+ commentVersion INT UNSIGNED NOT NULL,
+ transactionType VARCHAR(32) COLLATE {$COLLATE_TEXT} NOT NULL,
+ oldValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
+ newValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
+ contentSource LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
+ metadata LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
+ dateCreated INT UNSIGNED NOT NULL,
+ dateModified INT UNSIGNED NOT NULL,
+ UNIQUE KEY `key_phid` (`phid`),
+ KEY `key_object` (`objectPHID`)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
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
@@ -57,12 +57,19 @@
'AlmanacDrydockPoolServiceType' => 'applications/almanac/servicetype/AlmanacDrydockPoolServiceType.php',
'AlmanacEditor' => 'applications/almanac/editor/AlmanacEditor.php',
'AlmanacInterface' => 'applications/almanac/storage/AlmanacInterface.php',
+ 'AlmanacInterfaceAddressTransaction' => 'applications/almanac/xaction/AlmanacInterfaceAddressTransaction.php',
'AlmanacInterfaceDatasource' => 'applications/almanac/typeahead/AlmanacInterfaceDatasource.php',
'AlmanacInterfaceDeleteController' => 'applications/almanac/controller/AlmanacInterfaceDeleteController.php',
+ 'AlmanacInterfaceDeviceTransaction' => 'applications/almanac/xaction/AlmanacInterfaceDeviceTransaction.php',
'AlmanacInterfaceEditController' => 'applications/almanac/controller/AlmanacInterfaceEditController.php',
+ 'AlmanacInterfaceEditor' => 'applications/almanac/editor/AlmanacInterfaceEditor.php',
+ 'AlmanacInterfaceNetworkTransaction' => 'applications/almanac/xaction/AlmanacInterfaceNetworkTransaction.php',
'AlmanacInterfacePHIDType' => 'applications/almanac/phid/AlmanacInterfacePHIDType.php',
+ 'AlmanacInterfacePortTransaction' => 'applications/almanac/xaction/AlmanacInterfacePortTransaction.php',
'AlmanacInterfaceQuery' => 'applications/almanac/query/AlmanacInterfaceQuery.php',
'AlmanacInterfaceTableView' => 'applications/almanac/view/AlmanacInterfaceTableView.php',
+ 'AlmanacInterfaceTransaction' => 'applications/almanac/storage/AlmanacInterfaceTransaction.php',
+ 'AlmanacInterfaceTransactionType' => 'applications/almanac/xaction/AlmanacInterfaceTransactionType.php',
'AlmanacKeys' => 'applications/almanac/util/AlmanacKeys.php',
'AlmanacManageClusterServicesCapability' => 'applications/almanac/capability/AlmanacManageClusterServicesCapability.php',
'AlmanacManagementRegisterWorkflow' => 'applications/almanac/management/AlmanacManagementRegisterWorkflow.php',
@@ -5243,13 +5250,21 @@
'PhabricatorPolicyInterface',
'PhabricatorDestructibleInterface',
'PhabricatorExtendedPolicyInterface',
+ 'PhabricatorApplicationTransactionInterface',
),
+ 'AlmanacInterfaceAddressTransaction' => 'AlmanacNetworkTransactionType',
'AlmanacInterfaceDatasource' => 'PhabricatorTypeaheadDatasource',
'AlmanacInterfaceDeleteController' => 'AlmanacDeviceController',
+ 'AlmanacInterfaceDeviceTransaction' => 'AlmanacNetworkTransactionType',
'AlmanacInterfaceEditController' => 'AlmanacDeviceController',
+ 'AlmanacInterfaceEditor' => 'PhabricatorApplicationTransactionEditor',
+ 'AlmanacInterfaceNetworkTransaction' => 'AlmanacNetworkTransactionType',
'AlmanacInterfacePHIDType' => 'PhabricatorPHIDType',
+ 'AlmanacInterfacePortTransaction' => 'AlmanacNetworkTransactionType',
'AlmanacInterfaceQuery' => 'AlmanacQuery',
'AlmanacInterfaceTableView' => 'AphrontView',
+ 'AlmanacInterfaceTransaction' => 'PhabricatorModularTransaction',
+ 'AlmanacInterfaceTransactionType' => 'AlmanacTransactionType',
'AlmanacKeys' => 'Phobject',
'AlmanacManageClusterServicesCapability' => 'PhabricatorPolicyCapability',
'AlmanacManagementRegisterWorkflow' => 'AlmanacManagementWorkflow',
diff --git a/src/applications/almanac/editor/AlmanacInterfaceEditor.php b/src/applications/almanac/editor/AlmanacInterfaceEditor.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/editor/AlmanacInterfaceEditor.php
@@ -0,0 +1,22 @@
+<?php
+
+final class AlmanacInterfaceEditor
+ extends PhabricatorApplicationTransactionEditor {
+
+ public function getEditorApplicationClass() {
+ return 'PhabricatorAlmanacApplication';
+ }
+
+ public function getEditorObjectsDescription() {
+ return pht('Almanac Interface');
+ }
+
+ public function getCreateObjectTitle($author, $object) {
+ return pht('%s created this interface.', $author);
+ }
+
+ public function getCreateObjectTitleForFeed($author, $object) {
+ return pht('%s created %s.', $author, $object);
+ }
+
+}
diff --git a/src/applications/almanac/storage/AlmanacInterface.php b/src/applications/almanac/storage/AlmanacInterface.php
--- a/src/applications/almanac/storage/AlmanacInterface.php
+++ b/src/applications/almanac/storage/AlmanacInterface.php
@@ -5,7 +5,8 @@
implements
PhabricatorPolicyInterface,
PhabricatorDestructibleInterface,
- PhabricatorExtendedPolicyInterface {
+ PhabricatorExtendedPolicyInterface,
+ PhabricatorApplicationTransactionInterface {
protected $devicePHID;
protected $networkPHID;
@@ -154,4 +155,26 @@
$this->delete();
}
+
+/* -( PhabricatorApplicationTransactionInterface )------------------------- */
+
+
+ public function getApplicationTransactionEditor() {
+ return new AlmanacInterfaceEditor();
+ }
+
+ public function getApplicationTransactionObject() {
+ return $this;
+ }
+
+ public function getApplicationTransactionTemplate() {
+ return new AlmanacInterfaceTransaction();
+ }
+
+ public function willRenderTimeline(
+ PhabricatorApplicationTransactionView $timeline,
+ AphrontRequest $request) {
+ return $timeline;
+ }
+
}
diff --git a/src/applications/almanac/storage/AlmanacInterfaceTransaction.php b/src/applications/almanac/storage/AlmanacInterfaceTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/storage/AlmanacInterfaceTransaction.php
@@ -0,0 +1,22 @@
+<?php
+
+final class AlmanacInterfaceTransaction
+ extends PhabricatorModularTransaction {
+
+ public function getApplicationName() {
+ return 'almanac';
+ }
+
+ public function getApplicationTransactionType() {
+ return AlmanacInterfacePHIDType::TYPECONST;
+ }
+
+ public function getApplicationTransactionCommentObject() {
+ return null;
+ }
+
+ public function getBaseTransactionClass() {
+ return 'AlmanacInterfaceTransactionType';
+ }
+
+}
diff --git a/src/applications/almanac/xaction/AlmanacInterfaceAddressTransaction.php b/src/applications/almanac/xaction/AlmanacInterfaceAddressTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/xaction/AlmanacInterfaceAddressTransaction.php
@@ -0,0 +1,44 @@
+<?php
+
+final class AlmanacInterfaceAddressTransaction
+ extends AlmanacNetworkTransactionType {
+
+ const TRANSACTIONTYPE = 'almanac:interface:address';
+
+ public function generateOldValue($object) {
+ return $object->getAddress();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setAddress($value);
+ }
+
+ public function getTitle() {
+ return pht(
+ '%s changed the address for this interface from %s to %s.',
+ $this->renderAuthor(),
+ $this->renderOldValue(),
+ $this->renderNewValue());
+ }
+
+ public function validateTransactions($object, array $xactions) {
+ $errors = array();
+
+ if ($this->isEmptyTextTransaction($object->getAddress(), $xactions)) {
+ $errors[] = $this->newRequiredError(
+ pht('Interfaces must have an address.'));
+ }
+
+ foreach ($xactions as $xaction) {
+
+ // NOTE: For now, we don't validate addresses. We generally expect users
+ // to provide IPv4 addresses, but it's reasonable for them to provide
+ // IPv6 addresses, and some installs currently use DNS names. This is
+ // off-label but works today.
+
+ }
+
+ return $errors;
+ }
+
+}
diff --git a/src/applications/almanac/xaction/AlmanacInterfaceDeviceTransaction.php b/src/applications/almanac/xaction/AlmanacInterfaceDeviceTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/xaction/AlmanacInterfaceDeviceTransaction.php
@@ -0,0 +1,60 @@
+<?php
+
+final class AlmanacInterfaceDeviceTransaction
+ extends AlmanacNetworkTransactionType {
+
+ const TRANSACTIONTYPE = 'almanac:interface:device';
+
+ public function generateOldValue($object) {
+ return $object->getDevicePHID();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setDevicePHID($value);
+ }
+
+ public function getTitle() {
+ return pht(
+ '%s changed the device for this interface from %s to %s.',
+ $this->renderAuthor(),
+ $this->renderOldHandle(),
+ $this->renderNewHandle());
+ }
+
+ public function validateTransactions($object, array $xactions) {
+ $errors = array();
+
+ if ($this->isEmptyTextTransaction($object->getAddress(), $xactions)) {
+ $errors[] = $this->newRequiredError(
+ pht('Interfaces must have a device.'));
+ }
+
+ foreach ($xactions as $xaction) {
+ if (!$this->isNewObject()) {
+ $errors[] = $this->newInvalidError(
+ pht(
+ 'The device for an interface can not be changed once it has '.
+ 'been created.'),
+ $xaction);
+ continue;
+ }
+
+ $device_phid = $xaction->getNewValue();
+ $devices = id(new AlmanacDeviceQuery())
+ ->setViewer($this->getActor())
+ ->withPHIDs(array($device_phid))
+ ->execute();
+ if (!$devices) {
+ $errors[] = $this->newInvalidError(
+ pht(
+ 'You can not attach an interface to a nonexistent or restricted '.
+ 'device.'),
+ $xaction);
+ continue;
+ }
+ }
+
+ return $errors;
+ }
+
+}
diff --git a/src/applications/almanac/xaction/AlmanacInterfaceNetworkTransaction.php b/src/applications/almanac/xaction/AlmanacInterfaceNetworkTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/xaction/AlmanacInterfaceNetworkTransaction.php
@@ -0,0 +1,53 @@
+<?php
+
+final class AlmanacInterfaceNetworkTransaction
+ extends AlmanacNetworkTransactionType {
+
+ const TRANSACTIONTYPE = 'almanac:interface:network';
+
+ public function generateOldValue($object) {
+ return $object->getNetworkPHID();
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setNetworkPHID($value);
+ }
+
+ public function getTitle() {
+ return pht(
+ '%s changed the network for this interface from %s to %s.',
+ $this->renderAuthor(),
+ $this->renderOldHandle(),
+ $this->renderNewHandle());
+ }
+
+ public function validateTransactions($object, array $xactions) {
+ $errors = array();
+
+ $network_phid = $object->getNetworkPHID();
+ if ($this->isEmptyTextTransaction($network_phid, $xactions)) {
+ $errors[] = $this->newRequiredError(
+ pht('Interfaces must have a network.'));
+ }
+
+ foreach ($xactions as $xaction) {
+ $network_phid = $xaction->getNewValue();
+
+ $networks = id(new AlmanacNetworkQuery())
+ ->setViewer($this->getActor())
+ ->withPHIDs(array($network_phid))
+ ->execute();
+ if (!$networks) {
+ $errors[] = $this->newInvalidError(
+ pht(
+ 'You can not put an interface on a nonexistent or restricted '.
+ 'network.'),
+ $xaction);
+ continue;
+ }
+ }
+
+ return $errors;
+ }
+
+}
diff --git a/src/applications/almanac/xaction/AlmanacInterfacePortTransaction.php b/src/applications/almanac/xaction/AlmanacInterfacePortTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/xaction/AlmanacInterfacePortTransaction.php
@@ -0,0 +1,53 @@
+<?php
+
+final class AlmanacInterfacePortTransaction
+ extends AlmanacNetworkTransactionType {
+
+ const TRANSACTIONTYPE = 'almanac:interface:port';
+
+ public function generateOldValue($object) {
+ $port = $object->getPort();
+
+ if ($port !== null) {
+ $port = (int)$port;
+ }
+
+ return $port;
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setPort((int)$value);
+ }
+
+ public function getTitle() {
+ return pht(
+ '%s changed the port for this interface from %s to %s.',
+ $this->renderAuthor(),
+ $this->renderOldValue(),
+ $this->renderNewValue());
+ }
+
+ public function validateTransactions($object, array $xactions) {
+ $errors = array();
+
+ if ($this->isEmptyTextTransaction($object->getName(), $xactions)) {
+ $errors[] = $this->newRequiredError(
+ pht('Interfaces must have a port number.'));
+ }
+
+ foreach ($xactions as $xaction) {
+ $port = $xaction->getNewValue();
+
+ $port = (int)$port;
+ if ($port < 1 || $port > 65535) {
+ $errors[] = $this->newInvalidError(
+ pht('Port numbers must be between 1 and 65535, inclusive.'),
+ $xaction);
+ continue;
+ }
+ }
+
+ return $errors;
+ }
+
+}
diff --git a/src/applications/almanac/xaction/AlmanacInterfaceTransactionType.php b/src/applications/almanac/xaction/AlmanacInterfaceTransactionType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/xaction/AlmanacInterfaceTransactionType.php
@@ -0,0 +1,4 @@
+<?php
+
+abstract class AlmanacInterfaceTransactionType
+ extends AlmanacTransactionType {}

File Metadata

Mime Type
text/plain
Expires
Thu, May 9, 8:33 PM (3 w, 1 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6276935
Default Alt Text
D19323.diff (13 KB)

Event Timeline