Path: blob/master/src/applications/herald/storage/HeraldWebhook.php
12256 views
<?php12final class HeraldWebhook3extends HeraldDAO4implements5PhabricatorPolicyInterface,6PhabricatorApplicationTransactionInterface,7PhabricatorDestructibleInterface,8PhabricatorProjectInterface {910protected $name;11protected $webhookURI;12protected $viewPolicy;13protected $editPolicy;14protected $status;15protected $hmacKey;1617const HOOKSTATUS_FIREHOSE = 'firehose';18const HOOKSTATUS_ENABLED = 'enabled';19const HOOKSTATUS_DISABLED = 'disabled';2021protected function getConfiguration() {22return array(23self::CONFIG_AUX_PHID => true,24self::CONFIG_COLUMN_SCHEMA => array(25'name' => 'text128',26'webhookURI' => 'text255',27'status' => 'text32',28'hmacKey' => 'text32',29),30self::CONFIG_KEY_SCHEMA => array(31'key_status' => array(32'columns' => array('status'),33),34),35) + parent::getConfiguration();36}3738public function getPHIDType() {39return HeraldWebhookPHIDType::TYPECONST;40}4142public static function initializeNewWebhook(PhabricatorUser $viewer) {43return id(new self())44->setStatus(self::HOOKSTATUS_ENABLED)45->setViewPolicy(PhabricatorPolicies::getMostOpenPolicy())46->setEditPolicy($viewer->getPHID())47->regenerateHMACKey();48}4950public function getURI() {51return '/herald/webhook/view/'.$this->getID().'/';52}5354public function isDisabled() {55return ($this->getStatus() === self::HOOKSTATUS_DISABLED);56}5758public static function getStatusDisplayNameMap() {59$specs = self::getStatusSpecifications();60return ipull($specs, 'name', 'key');61}6263private static function getStatusSpecifications() {64$specs = array(65array(66'key' => self::HOOKSTATUS_FIREHOSE,67'name' => pht('Firehose'),68'color' => 'orange',69'icon' => 'fa-star-o',70),71array(72'key' => self::HOOKSTATUS_ENABLED,73'name' => pht('Enabled'),74'color' => 'bluegrey',75'icon' => 'fa-check',76),77array(78'key' => self::HOOKSTATUS_DISABLED,79'name' => pht('Disabled'),80'color' => 'dark',81'icon' => 'fa-ban',82),83);8485return ipull($specs, null, 'key');86}878889private static function getSpecificationForStatus($status) {90$specs = self::getStatusSpecifications();9192if (isset($specs[$status])) {93return $specs[$status];94}9596return array(97'key' => $status,98'name' => pht('Unknown ("%s")', $status),99'icon' => 'fa-question',100'color' => 'indigo',101);102}103104public static function getDisplayNameForStatus($status) {105$spec = self::getSpecificationForStatus($status);106return $spec['name'];107}108109public static function getIconForStatus($status) {110$spec = self::getSpecificationForStatus($status);111return $spec['icon'];112}113114public static function getColorForStatus($status) {115$spec = self::getSpecificationForStatus($status);116return $spec['color'];117}118119public function getStatusDisplayName() {120$status = $this->getStatus();121return self::getDisplayNameForStatus($status);122}123124public function getStatusIcon() {125$status = $this->getStatus();126return self::getIconForStatus($status);127}128129public function getStatusColor() {130$status = $this->getStatus();131return self::getColorForStatus($status);132}133134public function getErrorBackoffWindow() {135return phutil_units('5 minutes in seconds');136}137138public function getErrorBackoffThreshold() {139return 10;140}141142public function isInErrorBackoff(PhabricatorUser $viewer) {143$backoff_window = $this->getErrorBackoffWindow();144$backoff_threshold = $this->getErrorBackoffThreshold();145146$now = PhabricatorTime::getNow();147148$window_start = ($now - $backoff_window);149150$requests = id(new HeraldWebhookRequestQuery())151->setViewer($viewer)152->withWebhookPHIDs(array($this->getPHID()))153->withLastRequestEpochBetween($window_start, null)154->withLastRequestResults(155array(156HeraldWebhookRequest::RESULT_FAIL,157))158->execute();159160if (count($requests) >= $backoff_threshold) {161return true;162}163164return false;165}166167public function regenerateHMACKey() {168return $this->setHMACKey(Filesystem::readRandomCharacters(32));169}170171/* -( PhabricatorPolicyInterface )----------------------------------------- */172173174public function getCapabilities() {175return array(176PhabricatorPolicyCapability::CAN_VIEW,177PhabricatorPolicyCapability::CAN_EDIT,178);179}180181public function getPolicy($capability) {182switch ($capability) {183case PhabricatorPolicyCapability::CAN_VIEW:184return $this->getViewPolicy();185case PhabricatorPolicyCapability::CAN_EDIT:186return $this->getEditPolicy();187}188}189190public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {191return false;192}193194195/* -( PhabricatorApplicationTransactionInterface )------------------------- */196197198public function getApplicationTransactionEditor() {199return new HeraldWebhookEditor();200}201202public function getApplicationTransactionTemplate() {203return new HeraldWebhookTransaction();204}205206207/* -( PhabricatorDestructibleInterface )----------------------------------- */208209210public function destroyObjectPermanently(211PhabricatorDestructionEngine $engine) {212213while (true) {214$requests = id(new HeraldWebhookRequestQuery())215->setViewer($engine->getViewer())216->withWebhookPHIDs(array($this->getPHID()))217->setLimit(100)218->execute();219220if (!$requests) {221break;222}223224foreach ($requests as $request) {225$request->delete();226}227}228229$this->delete();230}231232233}234235236