diff --git a/resources/sql/autopatches/20210316.almanac.01.device-mailkey.php b/resources/sql/autopatches/20210316.almanac.01.device-mailkey.php new file mode 100644 index 0000000000..7c10d1ae76 --- /dev/null +++ b/resources/sql/autopatches/20210316.almanac.01.device-mailkey.php @@ -0,0 +1,28 @@ +establishConnection('w'); + +$properties_table = new PhabricatorMetaMTAMailProperties(); +$conn = $properties_table->establishConnection('w'); + +$iterator = new LiskRawMigrationIterator( + $device_conn, + $device_table->getTableName()); + +foreach ($iterator as $row) { + queryfx( + $conn, + 'INSERT IGNORE INTO %R + (objectPHID, mailProperties, dateCreated, dateModified) + VALUES + (%s, %s, %d, %d)', + $properties_table, + $row['phid'], + phutil_json_encode( + array( + 'mailKey' => $row['mailKey'], + )), + PhabricatorTime::getNow(), + PhabricatorTime::getNow()); +} diff --git a/resources/sql/autopatches/20210316.almanac.02.device-dropmailkey.sql b/resources/sql/autopatches/20210316.almanac.02.device-dropmailkey.sql new file mode 100644 index 0000000000..47079ef296 --- /dev/null +++ b/resources/sql/autopatches/20210316.almanac.02.device-dropmailkey.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_almanac.almanac_device + DROP mailKey; diff --git a/src/applications/almanac/storage/AlmanacDevice.php b/src/applications/almanac/storage/AlmanacDevice.php index 1d1010733a..8529285dc0 100644 --- a/src/applications/almanac/storage/AlmanacDevice.php +++ b/src/applications/almanac/storage/AlmanacDevice.php @@ -1,286 +1,280 @@ setViewPolicy(PhabricatorPolicies::POLICY_USER) ->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN) ->attachAlmanacProperties(array()) ->setIsBoundToClusterService(0); } protected function getConfiguration() { return array( self::CONFIG_AUX_PHID => true, self::CONFIG_COLUMN_SCHEMA => array( 'name' => 'text128', 'nameIndex' => 'bytes12', - 'mailKey' => 'bytes20', 'isBoundToClusterService' => 'bool', ), self::CONFIG_KEY_SCHEMA => array( 'key_name' => array( 'columns' => array('nameIndex'), 'unique' => true, ), 'key_nametext' => array( 'columns' => array('name'), ), ), ) + parent::getConfiguration(); } public function generatePHID() { return PhabricatorPHID::generateNewPHID(AlmanacDevicePHIDType::TYPECONST); } public function save() { AlmanacNames::validateName($this->getName()); $this->nameIndex = PhabricatorHash::digestForIndex($this->getName()); - if (!$this->mailKey) { - $this->mailKey = Filesystem::readRandomCharacters(20); - } - return parent::save(); } public function getURI() { return '/almanac/device/view/'.$this->getName().'/'; } public function rebuildClusterBindingStatus() { $services = id(new AlmanacServiceQuery()) ->setViewer(PhabricatorUser::getOmnipotentUser()) ->withDevicePHIDs(array($this->getPHID())) ->execute(); $is_cluster = false; foreach ($services as $service) { if ($service->isClusterService()) { $is_cluster = true; break; } } if ($is_cluster != $this->getIsBoundToClusterService()) { $this->setIsBoundToClusterService((int)$is_cluster); $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); queryfx( $this->establishConnection('w'), 'UPDATE %T SET isBoundToClusterService = %d WHERE id = %d', $this->getTableName(), $this->getIsBoundToClusterService(), $this->getID()); unset($unguarded); } return $this; } public function isClusterDevice() { return $this->getIsBoundToClusterService(); } /* -( AlmanacPropertyInterface )------------------------------------------- */ public function attachAlmanacProperties(array $properties) { assert_instances_of($properties, 'AlmanacProperty'); $this->almanacProperties = mpull($properties, null, 'getFieldName'); return $this; } public function getAlmanacProperties() { return $this->assertAttached($this->almanacProperties); } public function hasAlmanacProperty($key) { $this->assertAttached($this->almanacProperties); return isset($this->almanacProperties[$key]); } public function getAlmanacProperty($key) { return $this->assertAttachedKey($this->almanacProperties, $key); } public function getAlmanacPropertyValue($key, $default = null) { if ($this->hasAlmanacProperty($key)) { return $this->getAlmanacProperty($key)->getFieldValue(); } else { return $default; } } public function getAlmanacPropertyFieldSpecifications() { return array(); } public function newAlmanacPropertyEditEngine() { return new AlmanacDevicePropertyEditEngine(); } public function getAlmanacPropertySetTransactionType() { return AlmanacDeviceSetPropertyTransaction::TRANSACTIONTYPE; } public function getAlmanacPropertyDeleteTransactionType() { return AlmanacDeviceDeletePropertyTransaction::TRANSACTIONTYPE; } /* -( PhabricatorPolicyInterface )----------------------------------------- */ public function getCapabilities() { return array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, ); } public function getPolicy($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: return $this->getViewPolicy(); case PhabricatorPolicyCapability::CAN_EDIT: return $this->getEditPolicy(); } } public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { return false; } /* -( PhabricatorExtendedPolicyInterface )--------------------------------- */ public function getExtendedPolicy($capability, PhabricatorUser $viewer) { switch ($capability) { case PhabricatorPolicyCapability::CAN_EDIT: if ($this->isClusterDevice()) { return array( array( new PhabricatorAlmanacApplication(), AlmanacManageClusterServicesCapability::CAPABILITY, ), ); } break; } return array(); } /* -( PhabricatorApplicationTransactionInterface )------------------------- */ public function getApplicationTransactionEditor() { return new AlmanacDeviceEditor(); } public function getApplicationTransactionTemplate() { return new AlmanacDeviceTransaction(); } /* -( PhabricatorSSHPublicKeyInterface )----------------------------------- */ public function getSSHPublicKeyManagementURI(PhabricatorUser $viewer) { return $this->getURI(); } public function getSSHKeyDefaultName() { return $this->getName(); } public function getSSHKeyNotifyPHIDs() { // Devices don't currently have anyone useful to notify about SSH key // edits, and they're usually a difficult vector to attack since you need // access to a cluster host. However, it would be nice to make them // subscribable at some point. return array(); } /* -( PhabricatorDestructibleInterface )----------------------------------- */ public function destroyObjectPermanently( PhabricatorDestructionEngine $engine) { $interfaces = id(new AlmanacInterfaceQuery()) ->setViewer($engine->getViewer()) ->withDevicePHIDs(array($this->getPHID())) ->execute(); foreach ($interfaces as $interface) { $engine->destroyObject($interface); } $this->delete(); } /* -( PhabricatorNgramsInterface )----------------------------------------- */ public function newNgrams() { return array( id(new AlmanacDeviceNameNgrams()) ->setValue($this->getName()), ); } /* -( PhabricatorConduitResultInterface )---------------------------------- */ public function getFieldSpecificationsForConduit() { return array( id(new PhabricatorConduitSearchFieldSpecification()) ->setKey('name') ->setType('string') ->setDescription(pht('The name of the device.')), ); } public function getFieldValuesForConduit() { return array( 'name' => $this->getName(), ); } public function getConduitSearchAttachments() { return array( id(new AlmanacPropertiesSearchEngineAttachment()) ->setAttachmentKey('properties'), ); } }