Changeset View
Changeset View
Standalone View
Standalone View
src/applications/herald/storage/HeraldWebhook.php
- This file was added.
| <?php | |||||
| final class HeraldWebhook | |||||
| extends HeraldDAO | |||||
| implements | |||||
| PhabricatorPolicyInterface, | |||||
| PhabricatorApplicationTransactionInterface, | |||||
| PhabricatorDestructibleInterface { | |||||
| protected $name; | |||||
| protected $webhookURI; | |||||
| protected $viewPolicy; | |||||
| protected $editPolicy; | |||||
| protected $status; | |||||
| protected $hmacKey; | |||||
| const HOOKSTATUS_FIREHOSE = 'firehose'; | |||||
| const HOOKSTATUS_ENABLED = 'enabled'; | |||||
| const HOOKSTATUS_DISABLED = 'disabled'; | |||||
| protected function getConfiguration() { | |||||
| return array( | |||||
| self::CONFIG_AUX_PHID => true, | |||||
| self::CONFIG_COLUMN_SCHEMA => array( | |||||
| 'name' => 'text128', | |||||
| 'webhookURI' => 'text255', | |||||
| 'status' => 'text32', | |||||
| 'hmacKey' => 'text32', | |||||
| ), | |||||
| self::CONFIG_KEY_SCHEMA => array( | |||||
| 'key_status' => array( | |||||
| 'columns' => array('status'), | |||||
| ), | |||||
| ), | |||||
| ) + parent::getConfiguration(); | |||||
| } | |||||
| public function getPHIDType() { | |||||
| return HeraldWebhookPHIDType::TYPECONST; | |||||
| } | |||||
| public static function initializeNewWebhook(PhabricatorUser $viewer) { | |||||
| return id(new self()) | |||||
| ->setStatus(self::HOOKSTATUS_ENABLED) | |||||
| ->setViewPolicy(PhabricatorPolicies::getMostOpenPolicy()) | |||||
| ->setEditPolicy($viewer->getPHID()) | |||||
| ->setHmacKey(Filesystem::readRandomCharacters(32)); | |||||
| } | |||||
| public function getURI() { | |||||
| return '/herald/webhook/view/'.$this->getID().'/'; | |||||
| } | |||||
| public function isDisabled() { | |||||
| return ($this->getStatus() === self::HOOKSTATUS_DISABLED); | |||||
| } | |||||
| public static function getStatusDisplayNameMap() { | |||||
| return array( | |||||
| self::HOOKSTATUS_FIREHOSE => pht('Firehose'), | |||||
| self::HOOKSTATUS_ENABLED => pht('Enabled'), | |||||
| self::HOOKSTATUS_DISABLED => pht('Disabled'), | |||||
| ); | |||||
| } | |||||
| public function getStatusDisplayName() { | |||||
| $status = $this->getStatus(); | |||||
| return idx($this->getStatusDisplayNameMap(), $status); | |||||
| } | |||||
| public function getErrorBackoffWindow() { | |||||
| return phutil_units('5 minutes in seconds'); | |||||
| } | |||||
| public function getErrorBackoffThreshold() { | |||||
| return 10; | |||||
| } | |||||
| public function isInErrorBackoff(PhabricatorUser $viewer) { | |||||
| $backoff_window = $this->getErrorBackoffWindow(); | |||||
| $backoff_threshold = $this->getErrorBackoffThreshold(); | |||||
| $now = PhabricatorTime::getNow(); | |||||
| $window_start = ($now - $backoff_window); | |||||
| $requests = id(new HeraldWebhookRequestQuery()) | |||||
| ->setViewer($viewer) | |||||
| ->withWebhookPHIDs(array($this->getPHID())) | |||||
| ->withLastRequestEpochBetween($window_start, null) | |||||
| ->withLastRequestResults( | |||||
| array( | |||||
| HeraldWebhookRequest::RESULT_FAIL, | |||||
| )) | |||||
| ->execute(); | |||||
| if (count($requests) >= $backoff_threshold) { | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| /* -( 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; | |||||
| } | |||||
| /* -( PhabricatorApplicationTransactionInterface )------------------------- */ | |||||
| public function getApplicationTransactionEditor() { | |||||
| return new HeraldWebhookEditor(); | |||||
| } | |||||
| public function getApplicationTransactionObject() { | |||||
| return $this; | |||||
| } | |||||
| public function getApplicationTransactionTemplate() { | |||||
| return new HeraldWebhookTransaction(); | |||||
| } | |||||
| public function willRenderTimeline( | |||||
| PhabricatorApplicationTransactionView $timeline, | |||||
| AphrontRequest $request) { | |||||
| return $timeline; | |||||
| } | |||||
| /* -( PhabricatorDestructibleInterface )----------------------------------- */ | |||||
| public function destroyObjectPermanently( | |||||
| PhabricatorDestructionEngine $engine) { | |||||
| while (true) { | |||||
| $requests = id(new HeraldWebhookRequestQuery()) | |||||
| ->setViewer($engine->getViewer()) | |||||
| ->withWebhookPHIDs(array($this->getPHID())) | |||||
| ->setLimit(100) | |||||
| ->execute(); | |||||
| if (!$requests) { | |||||
| break; | |||||
| } | |||||
| foreach ($requests as $request) { | |||||
| $request->delete(); | |||||
| } | |||||
| } | |||||
| $this->delete(); | |||||
| } | |||||
| } | |||||