3 final class AlmanacDevice
6 PhabricatorPolicyInterface
,
7 PhabricatorApplicationTransactionInterface
,
8 PhabricatorProjectInterface
,
9 PhabricatorSSHPublicKeyInterface
,
10 AlmanacPropertyInterface
,
11 PhabricatorDestructibleInterface
,
12 PhabricatorNgramsInterface
,
13 PhabricatorConduitResultInterface
,
14 PhabricatorExtendedPolicyInterface
{
18 protected $viewPolicy;
19 protected $editPolicy;
21 protected $isBoundToClusterService;
23 private $almanacProperties = self
::ATTACHABLE
;
25 public static function initializeNewDevice() {
26 return id(new AlmanacDevice())
27 ->setViewPolicy(PhabricatorPolicies
::POLICY_USER
)
28 ->setEditPolicy(PhabricatorPolicies
::POLICY_ADMIN
)
29 ->setStatus(AlmanacDeviceStatus
::ACTIVE
)
30 ->attachAlmanacProperties(array())
31 ->setIsBoundToClusterService(0);
34 protected function getConfiguration() {
36 self
::CONFIG_AUX_PHID
=> true,
37 self
::CONFIG_COLUMN_SCHEMA
=> array(
39 'nameIndex' => 'bytes12',
41 'isBoundToClusterService' => 'bool',
43 self
::CONFIG_KEY_SCHEMA
=> array(
45 'columns' => array('nameIndex'),
48 'key_nametext' => array(
49 'columns' => array('name'),
52 ) + parent
::getConfiguration();
55 public function getPHIDType() {
56 return AlmanacDevicePHIDType
::TYPECONST
;
59 public function save() {
60 AlmanacNames
::validateName($this->getName());
62 $this->nameIndex
= PhabricatorHash
::digestForIndex($this->getName());
64 return parent
::save();
67 public function getURI() {
69 '/almanac/device/view/%s/',
73 public function rebuildClusterBindingStatus() {
74 $services = id(new AlmanacServiceQuery())
75 ->setViewer(PhabricatorUser
::getOmnipotentUser())
76 ->withDevicePHIDs(array($this->getPHID()))
80 foreach ($services as $service) {
81 if ($service->isClusterService()) {
87 if ($is_cluster != $this->getIsBoundToClusterService()) {
88 $this->setIsBoundToClusterService((int)$is_cluster);
89 $unguarded = AphrontWriteGuard
::beginScopedUnguardedWrites();
91 $this->establishConnection('w'),
92 'UPDATE %R SET isBoundToClusterService = %d WHERE id = %d',
94 $this->getIsBoundToClusterService(),
102 public function isClusterDevice() {
103 return $this->getIsBoundToClusterService();
106 public function getStatusObject() {
107 return $this->newStatusObject();
110 private function newStatusObject() {
111 return AlmanacDeviceStatus
::newStatusFromValue($this->getStatus());
114 public function isDisabled() {
115 return $this->getStatusObject()->isDisabled();
119 /* -( AlmanacPropertyInterface )------------------------------------------- */
122 public function attachAlmanacProperties(array $properties) {
123 assert_instances_of($properties, 'AlmanacProperty');
124 $this->almanacProperties
= mpull($properties, null, 'getFieldName');
128 public function getAlmanacProperties() {
129 return $this->assertAttached($this->almanacProperties
);
132 public function hasAlmanacProperty($key) {
133 $this->assertAttached($this->almanacProperties
);
134 return isset($this->almanacProperties
[$key]);
137 public function getAlmanacProperty($key) {
138 return $this->assertAttachedKey($this->almanacProperties
, $key);
141 public function getAlmanacPropertyValue($key, $default = null) {
142 if ($this->hasAlmanacProperty($key)) {
143 return $this->getAlmanacProperty($key)->getFieldValue();
149 public function getAlmanacPropertyFieldSpecifications() {
153 public function newAlmanacPropertyEditEngine() {
154 return new AlmanacDevicePropertyEditEngine();
157 public function getAlmanacPropertySetTransactionType() {
158 return AlmanacDeviceSetPropertyTransaction
::TRANSACTIONTYPE
;
161 public function getAlmanacPropertyDeleteTransactionType() {
162 return AlmanacDeviceDeletePropertyTransaction
::TRANSACTIONTYPE
;
166 /* -( PhabricatorPolicyInterface )----------------------------------------- */
169 public function getCapabilities() {
171 PhabricatorPolicyCapability
::CAN_VIEW
,
172 PhabricatorPolicyCapability
::CAN_EDIT
,
176 public function getPolicy($capability) {
177 switch ($capability) {
178 case PhabricatorPolicyCapability
::CAN_VIEW
:
179 return $this->getViewPolicy();
180 case PhabricatorPolicyCapability
::CAN_EDIT
:
181 return $this->getEditPolicy();
185 public function hasAutomaticCapability($capability, PhabricatorUser
$viewer) {
190 /* -( PhabricatorExtendedPolicyInterface )--------------------------------- */
193 public function getExtendedPolicy($capability, PhabricatorUser
$viewer) {
194 switch ($capability) {
195 case PhabricatorPolicyCapability
::CAN_EDIT
:
196 if ($this->isClusterDevice()) {
199 new PhabricatorAlmanacApplication(),
200 AlmanacManageClusterServicesCapability
::CAPABILITY
,
211 /* -( PhabricatorApplicationTransactionInterface )------------------------- */
214 public function getApplicationTransactionEditor() {
215 return new AlmanacDeviceEditor();
218 public function getApplicationTransactionTemplate() {
219 return new AlmanacDeviceTransaction();
223 /* -( PhabricatorSSHPublicKeyInterface )----------------------------------- */
226 public function getSSHPublicKeyManagementURI(PhabricatorUser
$viewer) {
227 return $this->getURI();
230 public function getSSHKeyDefaultName() {
231 return $this->getName();
234 public function getSSHKeyNotifyPHIDs() {
235 // Devices don't currently have anyone useful to notify about SSH key
236 // edits, and they're usually a difficult vector to attack since you need
237 // access to a cluster host. However, it would be nice to make them
238 // subscribable at some point.
243 /* -( PhabricatorDestructibleInterface )----------------------------------- */
246 public function destroyObjectPermanently(
247 PhabricatorDestructionEngine
$engine) {
249 $interfaces = id(new AlmanacInterfaceQuery())
250 ->setViewer($engine->getViewer())
251 ->withDevicePHIDs(array($this->getPHID()))
253 foreach ($interfaces as $interface) {
254 $engine->destroyObject($interface);
261 /* -( PhabricatorNgramsInterface )----------------------------------------- */
264 public function newNgrams() {
266 id(new AlmanacDeviceNameNgrams())
267 ->setValue($this->getName()),
272 /* -( PhabricatorConduitResultInterface )---------------------------------- */
275 public function getFieldSpecificationsForConduit() {
277 id(new PhabricatorConduitSearchFieldSpecification())
280 ->setDescription(pht('The name of the device.')),
281 id(new PhabricatorConduitSearchFieldSpecification())
283 ->setType('map<string, wild>')
284 ->setDescription(pht('Device status information.')),
285 id(new PhabricatorConduitSearchFieldSpecification())
288 ->setDescription(pht('True if device is disabled.')),
292 public function getFieldValuesForConduit() {
293 $status = $this->getStatusObject();
296 'name' => $this->getName(),
298 'value' => $status->getValue(),
299 'name' => $status->getName(),
301 'disabled' => $this->isDisabled(),
305 public function getConduitSearchAttachments() {
307 id(new AlmanacPropertiesSearchEngineAttachment())
308 ->setAttachmentKey('properties'),