Page MenuHomePhabricator

D10714.diff
No OneTemporary

D10714.diff

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

Mime Type
text/plain
Expires
Mon, Nov 18, 7:38 PM (2 h, 14 m ago)
Storage Engine
amazon-s3
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
phabricator/secure/gb/zp/hkc4t5urpzco3uiw
Default Alt Text
D10714.diff (35 KB)

Event Timeline