Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/src/applications/herald/storage/HeraldWebhook.php
12256 views
1
<?php
2
3
final class HeraldWebhook
4
extends HeraldDAO
5
implements
6
PhabricatorPolicyInterface,
7
PhabricatorApplicationTransactionInterface,
8
PhabricatorDestructibleInterface,
9
PhabricatorProjectInterface {
10
11
protected $name;
12
protected $webhookURI;
13
protected $viewPolicy;
14
protected $editPolicy;
15
protected $status;
16
protected $hmacKey;
17
18
const HOOKSTATUS_FIREHOSE = 'firehose';
19
const HOOKSTATUS_ENABLED = 'enabled';
20
const HOOKSTATUS_DISABLED = 'disabled';
21
22
protected function getConfiguration() {
23
return array(
24
self::CONFIG_AUX_PHID => true,
25
self::CONFIG_COLUMN_SCHEMA => array(
26
'name' => 'text128',
27
'webhookURI' => 'text255',
28
'status' => 'text32',
29
'hmacKey' => 'text32',
30
),
31
self::CONFIG_KEY_SCHEMA => array(
32
'key_status' => array(
33
'columns' => array('status'),
34
),
35
),
36
) + parent::getConfiguration();
37
}
38
39
public function getPHIDType() {
40
return HeraldWebhookPHIDType::TYPECONST;
41
}
42
43
public static function initializeNewWebhook(PhabricatorUser $viewer) {
44
return id(new self())
45
->setStatus(self::HOOKSTATUS_ENABLED)
46
->setViewPolicy(PhabricatorPolicies::getMostOpenPolicy())
47
->setEditPolicy($viewer->getPHID())
48
->regenerateHMACKey();
49
}
50
51
public function getURI() {
52
return '/herald/webhook/view/'.$this->getID().'/';
53
}
54
55
public function isDisabled() {
56
return ($this->getStatus() === self::HOOKSTATUS_DISABLED);
57
}
58
59
public static function getStatusDisplayNameMap() {
60
$specs = self::getStatusSpecifications();
61
return ipull($specs, 'name', 'key');
62
}
63
64
private static function getStatusSpecifications() {
65
$specs = array(
66
array(
67
'key' => self::HOOKSTATUS_FIREHOSE,
68
'name' => pht('Firehose'),
69
'color' => 'orange',
70
'icon' => 'fa-star-o',
71
),
72
array(
73
'key' => self::HOOKSTATUS_ENABLED,
74
'name' => pht('Enabled'),
75
'color' => 'bluegrey',
76
'icon' => 'fa-check',
77
),
78
array(
79
'key' => self::HOOKSTATUS_DISABLED,
80
'name' => pht('Disabled'),
81
'color' => 'dark',
82
'icon' => 'fa-ban',
83
),
84
);
85
86
return ipull($specs, null, 'key');
87
}
88
89
90
private static function getSpecificationForStatus($status) {
91
$specs = self::getStatusSpecifications();
92
93
if (isset($specs[$status])) {
94
return $specs[$status];
95
}
96
97
return array(
98
'key' => $status,
99
'name' => pht('Unknown ("%s")', $status),
100
'icon' => 'fa-question',
101
'color' => 'indigo',
102
);
103
}
104
105
public static function getDisplayNameForStatus($status) {
106
$spec = self::getSpecificationForStatus($status);
107
return $spec['name'];
108
}
109
110
public static function getIconForStatus($status) {
111
$spec = self::getSpecificationForStatus($status);
112
return $spec['icon'];
113
}
114
115
public static function getColorForStatus($status) {
116
$spec = self::getSpecificationForStatus($status);
117
return $spec['color'];
118
}
119
120
public function getStatusDisplayName() {
121
$status = $this->getStatus();
122
return self::getDisplayNameForStatus($status);
123
}
124
125
public function getStatusIcon() {
126
$status = $this->getStatus();
127
return self::getIconForStatus($status);
128
}
129
130
public function getStatusColor() {
131
$status = $this->getStatus();
132
return self::getColorForStatus($status);
133
}
134
135
public function getErrorBackoffWindow() {
136
return phutil_units('5 minutes in seconds');
137
}
138
139
public function getErrorBackoffThreshold() {
140
return 10;
141
}
142
143
public function isInErrorBackoff(PhabricatorUser $viewer) {
144
$backoff_window = $this->getErrorBackoffWindow();
145
$backoff_threshold = $this->getErrorBackoffThreshold();
146
147
$now = PhabricatorTime::getNow();
148
149
$window_start = ($now - $backoff_window);
150
151
$requests = id(new HeraldWebhookRequestQuery())
152
->setViewer($viewer)
153
->withWebhookPHIDs(array($this->getPHID()))
154
->withLastRequestEpochBetween($window_start, null)
155
->withLastRequestResults(
156
array(
157
HeraldWebhookRequest::RESULT_FAIL,
158
))
159
->execute();
160
161
if (count($requests) >= $backoff_threshold) {
162
return true;
163
}
164
165
return false;
166
}
167
168
public function regenerateHMACKey() {
169
return $this->setHMACKey(Filesystem::readRandomCharacters(32));
170
}
171
172
/* -( PhabricatorPolicyInterface )----------------------------------------- */
173
174
175
public function getCapabilities() {
176
return array(
177
PhabricatorPolicyCapability::CAN_VIEW,
178
PhabricatorPolicyCapability::CAN_EDIT,
179
);
180
}
181
182
public function getPolicy($capability) {
183
switch ($capability) {
184
case PhabricatorPolicyCapability::CAN_VIEW:
185
return $this->getViewPolicy();
186
case PhabricatorPolicyCapability::CAN_EDIT:
187
return $this->getEditPolicy();
188
}
189
}
190
191
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
192
return false;
193
}
194
195
196
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
197
198
199
public function getApplicationTransactionEditor() {
200
return new HeraldWebhookEditor();
201
}
202
203
public function getApplicationTransactionTemplate() {
204
return new HeraldWebhookTransaction();
205
}
206
207
208
/* -( PhabricatorDestructibleInterface )----------------------------------- */
209
210
211
public function destroyObjectPermanently(
212
PhabricatorDestructionEngine $engine) {
213
214
while (true) {
215
$requests = id(new HeraldWebhookRequestQuery())
216
->setViewer($engine->getViewer())
217
->withWebhookPHIDs(array($this->getPHID()))
218
->setLimit(100)
219
->execute();
220
221
if (!$requests) {
222
break;
223
}
224
225
foreach ($requests as $request) {
226
$request->delete();
227
}
228
}
229
230
$this->delete();
231
}
232
233
234
}
235
236