Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15475031
D10714.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
35 KB
Referenced Files
None
Subscribers
None
D10714.diff
View Options
diff --git a/resources/sql/autopatches/20141016.almanac.device.sql b/resources/sql/autopatches/20141016.almanac.device.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20141016.almanac.device.sql
@@ -0,0 +1,22 @@
+TRUNCATE TABLE {$NAMESPACE}_almanac.almanac_device;
+
+ALTER TABLE {$NAMESPACE}_almanac.almanac_device
+ CHANGE name name VARCHAR(128) NOT NULL COLLATE utf8_bin;
+
+ALTER TABLE {$NAMESPACE}_almanac.almanac_device
+ ADD nameIndex BINARY(12) NOT NULL;
+
+ALTER TABLE {$NAMESPACE}_almanac.almanac_device
+ ADD mailKey BINARY(20) NOT NULL;
+
+ALTER TABLE {$NAMESPACE}_almanac.almanac_device
+ ADD UNIQUE KEY `key_name` (nameIndex);
+
+ALTER TABLE {$NAMESPACE}_almanac.almanac_device
+ ADD KEY `key_nametext` (name);
+
+ALTER TABLE {$NAMESPACE}_almanac.almanac_device
+ ADD viewPolicy VARBINARY(64) NOT NULL;
+
+ALTER TABLE {$NAMESPACE}_almanac.almanac_device
+ ADD editPolicy VARBINARY(64) NOT NULL;
diff --git a/resources/sql/autopatches/20141016.almanac.dxaction.sql b/resources/sql/autopatches/20141016.almanac.dxaction.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20141016.almanac.dxaction.sql
@@ -0,0 +1,19 @@
+CREATE TABLE {$NAMESPACE}_almanac.almanac_devicetransaction (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARCHAR(64) COLLATE utf8_bin NOT NULL,
+ authorPHID VARCHAR(64) COLLATE utf8_bin NOT NULL,
+ objectPHID VARCHAR(64) COLLATE utf8_bin NOT NULL,
+ viewPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL,
+ editPolicy VARCHAR(64) COLLATE utf8_bin NOT NULL,
+ commentPHID VARCHAR(64) COLLATE utf8_bin DEFAULT NULL,
+ commentVersion INT UNSIGNED NOT NULL,
+ transactionType VARCHAR(32) COLLATE utf8_bin NOT NULL,
+ oldValue LONGTEXT COLLATE utf8_bin NOT NULL,
+ newValue LONGTEXT COLLATE utf8_bin NOT NULL,
+ contentSource LONGTEXT COLLATE utf8_bin NOT NULL,
+ metadata LONGTEXT COLLATE utf8_bin NOT NULL,
+ dateCreated INT UNSIGNED NOT NULL,
+ dateModified INT UNSIGNED NOT NULL,
+ UNIQUE KEY `key_phid` (`phid`),
+ KEY `key_object` (`objectPHID`)
+) ENGINE=InnoDB, COLLATE utf8_general_ci;
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -12,14 +12,25 @@
'AlmanacConduitUtil' => 'applications/almanac/util/AlmanacConduitUtil.php',
'AlmanacConsoleController' => 'applications/almanac/controller/AlmanacConsoleController.php',
'AlmanacController' => 'applications/almanac/controller/AlmanacController.php',
+ 'AlmanacCreateDevicesCapability' => 'applications/almanac/capability/AlmanacCreateDevicesCapability.php',
'AlmanacCreateServicesCapability' => 'applications/almanac/capability/AlmanacCreateServicesCapability.php',
'AlmanacDAO' => 'applications/almanac/storage/AlmanacDAO.php',
'AlmanacDevice' => 'applications/almanac/storage/AlmanacDevice.php',
+ 'AlmanacDeviceController' => 'applications/almanac/controller/AlmanacDeviceController.php',
+ 'AlmanacDeviceEditController' => 'applications/almanac/controller/AlmanacDeviceEditController.php',
+ 'AlmanacDeviceEditor' => 'applications/almanac/editor/AlmanacDeviceEditor.php',
+ 'AlmanacDeviceListController' => 'applications/almanac/controller/AlmanacDeviceListController.php',
'AlmanacDevicePHIDType' => 'applications/almanac/phid/AlmanacDevicePHIDType.php',
'AlmanacDeviceProperty' => 'applications/almanac/storage/AlmanacDeviceProperty.php',
'AlmanacDeviceQuery' => 'applications/almanac/query/AlmanacDeviceQuery.php',
+ 'AlmanacDeviceSearchEngine' => 'applications/almanac/query/AlmanacDeviceSearchEngine.php',
+ 'AlmanacDeviceTransaction' => 'applications/almanac/storage/AlmanacDeviceTransaction.php',
+ 'AlmanacDeviceTransactionQuery' => 'applications/almanac/query/AlmanacDeviceTransactionQuery.php',
+ 'AlmanacDeviceViewController' => 'applications/almanac/controller/AlmanacDeviceViewController.php',
'AlmanacManagementRegisterWorkflow' => 'applications/almanac/management/AlmanacManagementRegisterWorkflow.php',
'AlmanacManagementWorkflow' => 'applications/almanac/management/AlmanacManagementWorkflow.php',
+ 'AlmanacNames' => 'applications/almanac/util/AlmanacNames.php',
+ 'AlmanacNamesTestCase' => 'applications/almanac/util/__tests__/AlmanacNamesTestCase.php',
'AlmanacService' => 'applications/almanac/storage/AlmanacService.php',
'AlmanacServiceController' => 'applications/almanac/controller/AlmanacServiceController.php',
'AlmanacServiceEditController' => 'applications/almanac/controller/AlmanacServiceEditController.php',
@@ -28,7 +39,6 @@
'AlmanacServicePHIDType' => 'applications/almanac/phid/AlmanacServicePHIDType.php',
'AlmanacServiceQuery' => 'applications/almanac/query/AlmanacServiceQuery.php',
'AlmanacServiceSearchEngine' => 'applications/almanac/query/AlmanacServiceSearchEngine.php',
- 'AlmanacServiceTestCase' => 'applications/almanac/storage/__tests__/AlmanacServiceTestCase.php',
'AlmanacServiceTransaction' => 'applications/almanac/storage/AlmanacServiceTransaction.php',
'AlmanacServiceTransactionQuery' => 'applications/almanac/query/AlmanacServiceTransactionQuery.php',
'AlmanacServiceViewController' => 'applications/almanac/controller/AlmanacServiceViewController.php',
@@ -2921,17 +2931,28 @@
'AlmanacConduitUtil' => 'Phobject',
'AlmanacConsoleController' => 'AlmanacController',
'AlmanacController' => 'PhabricatorController',
+ 'AlmanacCreateDevicesCapability' => 'PhabricatorPolicyCapability',
'AlmanacCreateServicesCapability' => 'PhabricatorPolicyCapability',
'AlmanacDAO' => 'PhabricatorLiskDAO',
'AlmanacDevice' => array(
'AlmanacDAO',
'PhabricatorPolicyInterface',
),
+ 'AlmanacDeviceController' => 'AlmanacController',
+ 'AlmanacDeviceEditController' => 'AlmanacDeviceController',
+ 'AlmanacDeviceEditor' => 'PhabricatorApplicationTransactionEditor',
+ 'AlmanacDeviceListController' => 'AlmanacDeviceController',
'AlmanacDevicePHIDType' => 'PhabricatorPHIDType',
'AlmanacDeviceProperty' => 'AlmanacDAO',
'AlmanacDeviceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+ 'AlmanacDeviceSearchEngine' => 'PhabricatorApplicationSearchEngine',
+ 'AlmanacDeviceTransaction' => 'PhabricatorApplicationTransaction',
+ 'AlmanacDeviceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
+ 'AlmanacDeviceViewController' => 'AlmanacDeviceController',
'AlmanacManagementRegisterWorkflow' => 'AlmanacManagementWorkflow',
'AlmanacManagementWorkflow' => 'PhabricatorManagementWorkflow',
+ 'AlmanacNames' => 'Phobject',
+ 'AlmanacNamesTestCase' => 'PhabricatorTestCase',
'AlmanacService' => array(
'AlmanacDAO',
'PhabricatorPolicyInterface',
@@ -2943,7 +2964,6 @@
'AlmanacServicePHIDType' => 'PhabricatorPHIDType',
'AlmanacServiceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'AlmanacServiceSearchEngine' => 'PhabricatorApplicationSearchEngine',
- 'AlmanacServiceTestCase' => 'PhabricatorTestCase',
'AlmanacServiceTransaction' => 'PhabricatorApplicationTransaction',
'AlmanacServiceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'AlmanacServiceViewController' => 'AlmanacServiceController',
diff --git a/src/applications/almanac/application/PhabricatorAlmanacApplication.php b/src/applications/almanac/application/PhabricatorAlmanacApplication.php
--- a/src/applications/almanac/application/PhabricatorAlmanacApplication.php
+++ b/src/applications/almanac/application/PhabricatorAlmanacApplication.php
@@ -39,6 +39,11 @@
'edit/(?:(?P<id>\d+)/)?' => 'AlmanacServiceEditController',
'view/(?P<name>[^/]+)/' => 'AlmanacServiceViewController',
),
+ 'device/' => array(
+ '(?:query/(?P<queryKey>[^/]+)/)?' => 'AlmanacDeviceListController',
+ 'edit/(?:(?P<id>\d+)/)?' => 'AlmanacDeviceEditController',
+ 'view/(?P<name>[^/]+)/' => 'AlmanacDeviceViewController',
+ ),
),
);
}
@@ -48,6 +53,9 @@
AlmanacCreateServicesCapability::CAPABILITY => array(
'default' => PhabricatorPolicies::POLICY_ADMIN,
),
+ AlmanacCreateDevicesCapability::CAPABILITY => array(
+ 'default' => PhabricatorPolicies::POLICY_ADMIN,
+ ),
);
}
diff --git a/src/applications/almanac/capability/AlmanacCreateDevicesCapability.php b/src/applications/almanac/capability/AlmanacCreateDevicesCapability.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/capability/AlmanacCreateDevicesCapability.php
@@ -0,0 +1,16 @@
+<?php
+
+final class AlmanacCreateDevicesCapability
+ extends PhabricatorPolicyCapability {
+
+ const CAPABILITY = 'almanac.devices';
+
+ public function getCapabilityName() {
+ return pht('Can Create Devices');
+ }
+
+ public function describeCapabilityRejection() {
+ return pht('You do not have permission to create Almanac devices.');
+ }
+
+}
diff --git a/src/applications/almanac/controller/AlmanacConsoleController.php b/src/applications/almanac/controller/AlmanacConsoleController.php
--- a/src/applications/almanac/controller/AlmanacConsoleController.php
+++ b/src/applications/almanac/controller/AlmanacConsoleController.php
@@ -20,6 +20,14 @@
pht(
'Manage Almanac services.')));
+ $menu->addItem(
+ id(new PHUIObjectItemView())
+ ->setHeader(pht('Devices'))
+ ->setHref($this->getApplicationURI('device/'))
+ ->addAttribute(
+ pht(
+ 'Manage Almanac devices.')));
+
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Console'));
diff --git a/src/applications/almanac/controller/AlmanacDeviceController.php b/src/applications/almanac/controller/AlmanacDeviceController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/controller/AlmanacDeviceController.php
@@ -0,0 +1,14 @@
+<?php
+
+abstract class AlmanacDeviceController extends AlmanacController {
+
+ public function buildApplicationCrumbs() {
+ $crumbs = parent::buildApplicationCrumbs();
+
+ $list_uri = $this->getApplicationURI('device/');
+ $crumbs->addTextCrumb(pht('Devices'), $list_uri);
+
+ return $crumbs;
+ }
+
+}
diff --git a/src/applications/almanac/controller/AlmanacDeviceEditController.php b/src/applications/almanac/controller/AlmanacDeviceEditController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/controller/AlmanacDeviceEditController.php
@@ -0,0 +1,142 @@
+<?php
+
+final class AlmanacDeviceEditController
+ extends AlmanacDeviceController {
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $request->getViewer();
+
+ $list_uri = $this->getApplicationURI('device/');
+
+ $id = $request->getURIData('id');
+ if ($id) {
+ $device = id(new AlmanacDeviceQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($id))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
+ if (!$device) {
+ return new Aphront404Response();
+ }
+
+ $is_new = false;
+ $device_uri = $device->getURI();
+ $cancel_uri = $device_uri;
+ $title = pht('Edit Device');
+ $save_button = pht('Save Changes');
+ } else {
+ $this->requireApplicationCapability(
+ AlmanacCreateDevicesCapability::CAPABILITY);
+
+ $device = AlmanacDevice::initializeNewDevice();
+ $is_new = true;
+
+ $cancel_uri = $list_uri;
+ $title = pht('Create Device');
+ $save_button = pht('Create Device');
+ }
+
+ $v_name = $device->getName();
+ $e_name = true;
+ $validation_exception = null;
+
+ if ($request->isFormPost()) {
+ $v_name = $request->getStr('name');
+ $v_view = $request->getStr('viewPolicy');
+ $v_edit = $request->getStr('editPolicy');
+
+ $type_name = AlmanacDeviceTransaction::TYPE_NAME;
+ $type_view = PhabricatorTransactions::TYPE_VIEW_POLICY;
+ $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY;
+
+ $xactions = array();
+
+ $xactions[] = id(new AlmanacDeviceTransaction())
+ ->setTransactionType($type_name)
+ ->setNewValue($v_name);
+
+ $xactions[] = id(new AlmanacDeviceTransaction())
+ ->setTransactionType($type_view)
+ ->setNewValue($v_view);
+
+ $xactions[] = id(new AlmanacDeviceTransaction())
+ ->setTransactionType($type_edit)
+ ->setNewValue($v_edit);
+
+ $editor = id(new AlmanacDeviceEditor())
+ ->setActor($viewer)
+ ->setContentSourceFromRequest($request)
+ ->setContinueOnNoEffect(true);
+
+ try {
+ $editor->applyTransactions($device, $xactions);
+
+ $device_uri = $device->getURI();
+ return id(new AphrontRedirectResponse())->setURI($device_uri);
+ } catch (PhabricatorApplicationTransactionValidationException $ex) {
+ $validation_exception = $ex;
+ $e_name = $ex->getShortMessage($type_name);
+
+ $device->setViewPolicy($v_view);
+ $device->setEditPolicy($v_edit);
+ }
+ }
+
+ $policies = id(new PhabricatorPolicyQuery())
+ ->setViewer($viewer)
+ ->setObject($device)
+ ->execute();
+
+ $form = id(new AphrontFormView())
+ ->setUser($viewer)
+ ->appendChild(
+ id(new AphrontFormTextControl())
+ ->setLabel(pht('Name'))
+ ->setName('name')
+ ->setValue($v_name)
+ ->setError($e_name))
+ ->appendChild(
+ id(new AphrontFormPolicyControl())
+ ->setName('viewPolicy')
+ ->setPolicyObject($device)
+ ->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
+ ->setPolicies($policies))
+ ->appendChild(
+ id(new AphrontFormPolicyControl())
+ ->setName('editPolicy')
+ ->setPolicyObject($device)
+ ->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
+ ->setPolicies($policies))
+ ->appendChild(
+ id(new AphrontFormSubmitControl())
+ ->addCancelButton($cancel_uri)
+ ->setValue($save_button));
+
+ $box = id(new PHUIObjectBoxView())
+ ->setValidationException($validation_exception)
+ ->setHeaderText($title)
+ ->appendChild($form);
+
+ $crumbs = $this->buildApplicationCrumbs();
+ if ($is_new) {
+ $crumbs->addTextCrumb(pht('Create Device'));
+ } else {
+ $crumbs->addTextCrumb($device->getName(), $device_uri);
+ $crumbs->addTextCrumb(pht('Edit'));
+ }
+
+ return $this->buildApplicationPage(
+ array(
+ $crumbs,
+ $box,
+ ),
+ array(
+ 'title' => $title,
+ ));
+ }
+
+}
diff --git a/src/applications/almanac/controller/AlmanacDeviceListController.php b/src/applications/almanac/controller/AlmanacDeviceListController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/controller/AlmanacDeviceListController.php
@@ -0,0 +1,52 @@
+<?php
+
+final class AlmanacDeviceListController
+ extends AlmanacDeviceController {
+
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+ public function handleRequest(AphrontRequest $request) {
+ $controller = id(new PhabricatorApplicationSearchController())
+ ->setQueryKey($request->getURIData('queryKey'))
+ ->setSearchEngine(new AlmanacDeviceSearchEngine())
+ ->setNavigation($this->buildSideNavView());
+
+ return $this->delegateToController($controller);
+ }
+
+ public function buildApplicationCrumbs() {
+ $crumbs = parent::buildApplicationCrumbs();
+
+ $can_create = $this->hasApplicationCapability(
+ AlmanacCreateDevicesCapability::CAPABILITY);
+
+ $crumbs->addAction(
+ id(new PHUIListItemView())
+ ->setName(pht('Create Device'))
+ ->setHref($this->getApplicationURI('device/edit/'))
+ ->setIcon('fa-plus-square')
+ ->setDisabled(!$can_create)
+ ->setWorkflow(!$can_create));
+
+ return $crumbs;
+ }
+
+ public function buildSideNavView() {
+ $viewer = $this->getViewer();
+
+ $nav = new AphrontSideNavFilterView();
+ $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
+
+ id(new AlmanacDeviceSearchEngine())
+ ->setViewer($viewer)
+ ->addNavigationItems($nav->getMenu());
+
+ $nav->selectFilter(null);
+
+ return $nav;
+ }
+
+
+}
diff --git a/src/applications/almanac/controller/AlmanacDeviceViewController.php b/src/applications/almanac/controller/AlmanacDeviceViewController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/controller/AlmanacDeviceViewController.php
@@ -0,0 +1,95 @@
+<?php
+
+final class AlmanacDeviceViewController
+ extends AlmanacDeviceController {
+
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $request->getViewer();
+
+ $name = $request->getURIData('name');
+
+ $device = id(new AlmanacDeviceQuery())
+ ->setViewer($viewer)
+ ->withNames(array($name))
+ ->executeOne();
+ if (!$device) {
+ return new Aphront404Response();
+ }
+
+ $title = pht('Device %s', $device->getName());
+
+ $property_list = $this->buildPropertyList($device);
+ $action_list = $this->buildActionList($device);
+ $property_list->setActionList($action_list);
+
+ $header = id(new PHUIHeaderView())
+ ->setUser($viewer)
+ ->setHeader($device->getName())
+ ->setPolicyObject($device);
+
+ $box = id(new PHUIObjectBoxView())
+ ->setHeader($header)
+ ->addPropertyList($property_list);
+
+ $crumbs = $this->buildApplicationCrumbs();
+ $crumbs->addTextCrumb($device->getName());
+
+ $xactions = id(new AlmanacDeviceTransactionQuery())
+ ->setViewer($viewer)
+ ->withObjectPHIDs(array($device->getPHID()))
+ ->execute();
+
+ $xaction_view = id(new PhabricatorApplicationTransactionView())
+ ->setUser($viewer)
+ ->setObjectPHID($device->getPHID())
+ ->setTransactions($xactions)
+ ->setShouldTerminate(true);
+
+ return $this->buildApplicationPage(
+ array(
+ $crumbs,
+ $box,
+ $xaction_view,
+ ),
+ array(
+ 'title' => $title,
+ ));
+ }
+
+ private function buildPropertyList(AlmanacDevice $device) {
+ $viewer = $this->getViewer();
+
+ $properties = id(new PHUIPropertyListView())
+ ->setUser($viewer);
+
+ return $properties;
+ }
+
+ private function buildActionList(AlmanacDevice $device) {
+ $viewer = $this->getViewer();
+ $id = $device->getID();
+
+ $can_edit = PhabricatorPolicyFilter::hasCapability(
+ $viewer,
+ $device,
+ PhabricatorPolicyCapability::CAN_EDIT);
+
+ $actions = id(new PhabricatorActionListView())
+ ->setUser($viewer);
+
+ $actions->addAction(
+ id(new PhabricatorActionView())
+ ->setIcon('fa-pencil')
+ ->setName(pht('Edit Device'))
+ ->setHref($this->getApplicationURI("device/edit/{$id}/"))
+ ->setWorkflow(!$can_edit)
+ ->setDisabled(!$can_edit));
+
+ return $actions;
+ }
+
+}
diff --git a/src/applications/almanac/editor/AlmanacServiceEditor.php b/src/applications/almanac/editor/AlmanacDeviceEditor.php
copy from src/applications/almanac/editor/AlmanacServiceEditor.php
copy to src/applications/almanac/editor/AlmanacDeviceEditor.php
--- a/src/applications/almanac/editor/AlmanacServiceEditor.php
+++ b/src/applications/almanac/editor/AlmanacDeviceEditor.php
@@ -1,6 +1,6 @@
<?php
-final class AlmanacServiceEditor
+final class AlmanacDeviceEditor
extends PhabricatorApplicationTransactionEditor {
public function getEditorApplicationClass() {
@@ -8,13 +8,13 @@
}
public function getEditorObjectsDescription() {
- return pht('Almanac Service');
+ return pht('Almanac Device');
}
public function getTransactionTypes() {
$types = parent::getTransactionTypes();
- $types[] = AlmanacServiceTransaction::TYPE_NAME;
+ $types[] = AlmanacDeviceTransaction::TYPE_NAME;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
@@ -25,7 +25,7 @@
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
- case AlmanacServiceTransaction::TYPE_NAME:
+ case AlmanacDeviceTransaction::TYPE_NAME:
return $object->getName();
}
@@ -37,7 +37,7 @@
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
- case AlmanacServiceTransaction::TYPE_NAME:
+ case AlmanacDeviceTransaction::TYPE_NAME:
return $xaction->getNewValue();
}
@@ -49,7 +49,7 @@
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
- case AlmanacServiceTransaction::TYPE_NAME:
+ case AlmanacDeviceTransaction::TYPE_NAME:
$object->setName($xaction->getNewValue());
return;
case PhabricatorTransactions::TYPE_VIEW_POLICY:
@@ -65,7 +65,7 @@
PhabricatorApplicationTransaction $xaction) {
switch ($xaction->getTransactionType()) {
- case AlmanacServiceTransaction::TYPE_NAME:
+ case AlmanacDeviceTransaction::TYPE_NAME:
case PhabricatorTransactions::TYPE_VIEW_POLICY:
case PhabricatorTransactions::TYPE_EDIT_POLICY:
return;
@@ -82,7 +82,7 @@
$errors = parent::validateTransaction($object, $type, $xactions);
switch ($type) {
- case AlmanacServiceTransaction::TYPE_NAME:
+ case AlmanacDeviceTransaction::TYPE_NAME:
$missing = $this->validateIsEmptyTextField(
$object->getName(),
$xactions);
@@ -91,7 +91,7 @@
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Required'),
- pht('Service name is required.'),
+ pht('Device name is required.'),
nonempty(last($xactions), null));
$error->setIsMissingFieldError(true);
@@ -99,9 +99,10 @@
} else {
foreach ($xactions as $xaction) {
$message = null;
+ $name = $xaction->getNewValue();
try {
- AlmanacService::validateServiceName($xaction->getNewValue());
+ AlmanacNames::validateServiceOrDeviceName($name);
} catch (Exception $ex) {
$message = $ex->getMessage();
}
@@ -118,7 +119,7 @@
}
if ($xactions) {
- $duplicate = id(new AlmanacServiceQuery())
+ $duplicate = id(new AlmanacDeviceQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withNames(array(last($xactions)->getNewValue()))
->executeOne();
@@ -126,7 +127,7 @@
$error = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Not Unique'),
- pht('Almanac services must have unique names.'),
+ pht('Almanac devices must have unique names.'),
last($xactions));
$errors[] = $error;
}
diff --git a/src/applications/almanac/editor/AlmanacServiceEditor.php b/src/applications/almanac/editor/AlmanacServiceEditor.php
--- a/src/applications/almanac/editor/AlmanacServiceEditor.php
+++ b/src/applications/almanac/editor/AlmanacServiceEditor.php
@@ -100,8 +100,10 @@
foreach ($xactions as $xaction) {
$message = null;
+ $name = $xaction->getNewValue();
+
try {
- AlmanacService::validateServiceName($xaction->getNewValue());
+ AlmanacNames::validateServiceOrDeviceName($name);
} catch (Exception $ex) {
$message = $ex->getMessage();
}
diff --git a/src/applications/almanac/query/AlmanacDeviceQuery.php b/src/applications/almanac/query/AlmanacDeviceQuery.php
--- a/src/applications/almanac/query/AlmanacDeviceQuery.php
+++ b/src/applications/almanac/query/AlmanacDeviceQuery.php
@@ -5,6 +5,7 @@
private $ids;
private $phids;
+ private $names;
public function withIDs(array $ids) {
$this->ids = $ids;
@@ -16,6 +17,11 @@
return $this;
}
+ public function withNames(array $names) {
+ $this->names = $names;
+ return $this;
+ }
+
protected function loadPage() {
$table = new AlmanacDevice();
$conn_r = $table->establishConnection('r');
@@ -48,6 +54,17 @@
$this->phids);
}
+ if ($this->names !== null) {
+ $hashes = array();
+ foreach ($this->names as $name) {
+ $hashes[] = PhabricatorHash::digestForIndex($name);
+ }
+ $where[] = qsprintf(
+ $conn_r,
+ 'nameIndex IN (%Ls)',
+ $hashes);
+ }
+
$where[] = $this->buildPagingClause($conn_r);
return $this->formatWhereClause($where);
diff --git a/src/applications/almanac/query/AlmanacDeviceSearchEngine.php b/src/applications/almanac/query/AlmanacDeviceSearchEngine.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/query/AlmanacDeviceSearchEngine.php
@@ -0,0 +1,79 @@
+<?php
+
+final class AlmanacDeviceSearchEngine
+ extends PhabricatorApplicationSearchEngine {
+
+ public function getResultTypeDescription() {
+ return pht('Almanac Devices');
+ }
+
+ public function buildSavedQueryFromRequest(AphrontRequest $request) {
+ $saved = new PhabricatorSavedQuery();
+
+ return $saved;
+ }
+
+ public function buildQueryFromSavedQuery(PhabricatorSavedQuery $saved) {
+ $query = id(new AlmanacDeviceQuery());
+
+ return $query;
+ }
+
+ public function buildSearchForm(
+ AphrontFormView $form,
+ PhabricatorSavedQuery $saved_query) {}
+
+ protected function getURI($path) {
+ return '/almanac/device/'.$path;
+ }
+
+ public function getBuiltinQueryNames() {
+ $names = array(
+ 'all' => pht('All Devices'),
+ );
+
+ return $names;
+ }
+
+ public function buildSavedQueryFromBuiltin($query_key) {
+
+ $query = $this->newSavedQuery();
+ $query->setQueryKey($query_key);
+
+ switch ($query_key) {
+ case 'all':
+ return $query;
+ }
+
+ return parent::buildSavedQueryFromBuiltin($query_key);
+ }
+
+ protected function getRequiredHandlePHIDsForResultList(
+ array $devices,
+ PhabricatorSavedQuery $query) {
+ return array();
+ }
+
+ protected function renderResultList(
+ array $devices,
+ PhabricatorSavedQuery $query,
+ array $handles) {
+ assert_instances_of($devices, 'AlmanacDevice');
+
+ $viewer = $this->requireViewer();
+
+ $list = new PHUIObjectItemListView();
+ $list->setUser($viewer);
+ foreach ($devices as $device) {
+ $item = id(new PHUIObjectItemView())
+ ->setObjectName(pht('Device %d', $device->getID()))
+ ->setHeader($device->getName())
+ ->setHref($device->getURI())
+ ->setObject($device);
+
+ $list->addItem($item);
+ }
+
+ return $list;
+ }
+}
diff --git a/src/applications/almanac/query/AlmanacDeviceTransactionQuery.php b/src/applications/almanac/query/AlmanacDeviceTransactionQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/query/AlmanacDeviceTransactionQuery.php
@@ -0,0 +1,10 @@
+<?php
+
+final class AlmanacDeviceTransactionQuery
+ extends PhabricatorApplicationTransactionQuery {
+
+ public function getTemplateApplicationTransaction() {
+ return new AlmanacDeviceTransaction();
+ }
+
+}
diff --git a/src/applications/almanac/storage/AlmanacDevice.php b/src/applications/almanac/storage/AlmanacDevice.php
--- a/src/applications/almanac/storage/AlmanacDevice.php
+++ b/src/applications/almanac/storage/AlmanacDevice.php
@@ -5,12 +5,32 @@
implements PhabricatorPolicyInterface {
protected $name;
+ protected $nameIndex;
+ protected $mailKey;
+ protected $viewPolicy;
+ protected $editPolicy;
+
+ public static function initializeNewDevice() {
+ return id(new AlmanacDevice())
+ ->setViewPolicy(PhabricatorPolicies::POLICY_USER)
+ ->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN);
+ }
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_COLUMN_SCHEMA => array(
- 'name' => 'text255',
+ 'name' => 'text128',
+ 'nameIndex' => 'bytes12',
+ ),
+ self::CONFIG_KEY_SCHEMA => array(
+ 'key_name' => array(
+ 'columns' => array('nameIndex'),
+ 'unique' => true,
+ ),
+ 'key_nametext' => array(
+ 'columns' => array('name'),
+ ),
),
) + parent::getConfiguration();
}
@@ -19,6 +39,22 @@
return PhabricatorPHID::generateNewPHID(AlmanacDevicePHIDType::TYPECONST);
}
+ public function save() {
+ AlmanacNames::validateServiceOrDeviceName($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().'/';
+ }
+
/* -( PhabricatorPolicyInterface )----------------------------------------- */
@@ -26,16 +62,16 @@
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
- // Until we get a clearer idea on what's going to be stored in this
- // table, don't allow anyone (other than the omnipotent user) to find
- // these objects.
- return PhabricatorPolicies::POLICY_NOONE;
+ return $this->getViewPolicy();
+ case PhabricatorPolicyCapability::CAN_EDIT:
+ return $this->getEditPolicy();
}
}
diff --git a/src/applications/almanac/storage/AlmanacDeviceTransaction.php b/src/applications/almanac/storage/AlmanacDeviceTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/storage/AlmanacDeviceTransaction.php
@@ -0,0 +1,45 @@
+<?php
+
+final class AlmanacDeviceTransaction
+ extends PhabricatorApplicationTransaction {
+
+ const TYPE_NAME = 'almanac:device:name';
+
+ public function getApplicationName() {
+ return 'almanac';
+ }
+
+ public function getApplicationTransactionType() {
+ return AlmanacDevicePHIDType::TYPECONST;
+ }
+
+ public function getApplicationTransactionCommentObject() {
+ return null;
+ }
+
+ public function getTitle() {
+ $author_phid = $this->getAuthorPHID();
+
+ $old = $this->getOldValue();
+ $new = $this->getNewValue();
+
+ switch ($this->getTransactionType()) {
+ case self::TYPE_NAME:
+ if ($old === null) {
+ return pht(
+ '%s created this device.',
+ $this->renderHandleLink($author_phid));
+ } else {
+ return pht(
+ '%s renamed this device from "%s" to "%s".',
+ $this->renderHandleLink($author_phid),
+ $old,
+ $new);
+ }
+ break;
+ }
+
+ return parent::getTitle();
+ }
+
+}
diff --git a/src/applications/almanac/storage/AlmanacService.php b/src/applications/almanac/storage/AlmanacService.php
--- a/src/applications/almanac/storage/AlmanacService.php
+++ b/src/applications/almanac/storage/AlmanacService.php
@@ -41,7 +41,8 @@
}
public function save() {
- self::validateServiceName($this->getName());
+ AlmanacNames::validateServiceOrDeviceName($this->getName());
+
$this->nameIndex = PhabricatorHash::digestForIndex($this->getName());
if (!$this->mailKey) {
@@ -55,53 +56,6 @@
return '/almanac/service/view/'.$this->getName().'/';
}
- public static function validateServiceName($name) {
- if (strlen($name) < 3) {
- throw new Exception(
- pht('Almanac service names must be at least 3 characters long.'));
- }
-
- if (!preg_match('/^[a-z0-9.-]+\z/', $name)) {
- throw new Exception(
- pht(
- 'Almanac service names may only contain lowercase letters, numbers, '.
- 'hyphens, and periods.'));
- }
-
- if (preg_match('/(^|\\.)\d+(\z|\\.)/', $name)) {
- throw new Exception(
- pht(
- 'Almanac service names may not have any segments containing only '.
- 'digits.'));
- }
-
- if (preg_match('/\.\./', $name)) {
- throw new Exception(
- pht(
- 'Almanac service names may not contain multiple consecutive '.
- 'periods.'));
- }
-
- if (preg_match('/\\.-|-\\./', $name)) {
- throw new Exception(
- pht(
- 'Amanac service names may not contain hyphens adjacent to periods.'));
- }
-
- if (preg_match('/--/', $name)) {
- throw new Exception(
- pht(
- 'Almanac service names may not contain multiple consecutive '.
- 'hyphens.'));
- }
-
- if (!preg_match('/^[a-z0-9].*[a-z0-9]\z/', $name)) {
- throw new Exception(
- pht(
- 'Almanac service names must begin and end with a letter or number.'));
- }
- }
-
/* -( PhabricatorPolicyInterface )----------------------------------------- */
diff --git a/src/applications/almanac/util/AlmanacNames.php b/src/applications/almanac/util/AlmanacNames.php
new file mode 100644
--- /dev/null
+++ b/src/applications/almanac/util/AlmanacNames.php
@@ -0,0 +1,56 @@
+<?php
+
+final class AlmanacNames extends Phobject {
+
+ public static function validateServiceOrDeviceName($name) {
+ if (strlen($name) < 3) {
+ throw new Exception(
+ pht(
+ 'Almanac service and device names must be at least 3 '.
+ 'characters long.'));
+ }
+
+ if (!preg_match('/^[a-z0-9.-]+\z/', $name)) {
+ throw new Exception(
+ pht(
+ 'Almanac service and device names may only contain lowercase '.
+ 'letters, numbers, hyphens, and periods.'));
+ }
+
+ if (preg_match('/(^|\\.)\d+(\z|\\.)/', $name)) {
+ throw new Exception(
+ pht(
+ 'Almanac service and device names may not have any segments '.
+ 'containing only digits.'));
+ }
+
+ if (preg_match('/\.\./', $name)) {
+ throw new Exception(
+ pht(
+ 'Almanac service and device names may not contain multiple '.
+ 'consecutive periods.'));
+ }
+
+ if (preg_match('/\\.-|-\\./', $name)) {
+ throw new Exception(
+ pht(
+ 'Amanac service and device names may not contain hyphens adjacent '.
+ 'to periods.'));
+ }
+
+ if (preg_match('/--/', $name)) {
+ throw new Exception(
+ pht(
+ 'Almanac service and device names may not contain multiple '.
+ 'consecutive hyphens.'));
+ }
+
+ if (!preg_match('/^[a-z0-9].*[a-z0-9]\z/', $name)) {
+ throw new Exception(
+ pht(
+ 'Almanac service and device names must begin and end with a letter '.
+ 'or number.'));
+ }
+ }
+
+}
diff --git a/src/applications/almanac/storage/__tests__/AlmanacServiceTestCase.php b/src/applications/almanac/util/__tests__/AlmanacNamesTestCase.php
rename from src/applications/almanac/storage/__tests__/AlmanacServiceTestCase.php
rename to src/applications/almanac/util/__tests__/AlmanacNamesTestCase.php
--- a/src/applications/almanac/storage/__tests__/AlmanacServiceTestCase.php
+++ b/src/applications/almanac/util/__tests__/AlmanacNamesTestCase.php
@@ -1,8 +1,8 @@
<?php
-final class AlmanacServiceTestCase extends PhabricatorTestCase {
+final class AlmanacNamesTestCase extends PhabricatorTestCase {
- public function testServiceNames() {
+ public function testServiceOrDeviceNames() {
$map = array(
'' => false,
'a' => false,
@@ -38,7 +38,7 @@
foreach ($map as $input => $expect) {
$caught = null;
try {
- AlmanacService::validateServiceName($input);
+ AlmanacNames::validateServiceOrDeviceName($input);
} catch (Exception $ex) {
$caught = $ex;
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 7, 2:53 PM (1 w, 1 d ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/bb/ns/wygwquxblaafgb4p
Default Alt Text
D10714.diff (35 KB)
Attached To
Mode
D10714: Build AlmanacDevice UI
Attached
Detach File
Event Timeline
Log In to Comment