@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Clean up some EditEngine meta-policies

Summary:
Ref T9908. Simplify some of the policies here:

- If you can edit an application (currently, always "Administrators"), you can view and edit all of its forms.
- You must be able to edit an application to create new forms.
- Improve some error messages.
- Get about halfway through letting users reorder forms in the "Create" menu if they want to sort by something weird since it'll need schema changes and I can do them all in one go here.

Test Plan:
- Tried to create and edit forms as an unprivileged user.
- Created and edited forms as an administrator.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9908

Differential Revision: https://secure.phabricator.com/D14700

+207 -30
+11
resources/sql/autopatches/20151207.editengine.1.sql
··· 1 + ALTER TABLE {$NAMESPACE}_search.search_editengineconfiguration 2 + DROP editPolicy; 3 + 4 + ALTER TABLE {$NAMESPACE}_search.search_editengineconfiguration 5 + ADD isEdit BOOL NOT NULL; 6 + 7 + ALTER TABLE {$NAMESPACE}_search.search_editengineconfiguration 8 + ADD createOrder INT UNSIGNED NOT NULL; 9 + 10 + ALTER TABLE {$NAMESPACE}_search.search_editengineconfiguration 11 + ADD editOrder INT UNSIGNED NOT NULL;
+1 -1
src/applications/base/PhabricatorApplication.php
··· 624 624 '(?P<id>[0-9]\d*)/)?'. 625 625 '(?:'. 626 626 '(?:'. 627 - '(?P<editAction>parameters|nodefault|comment)'. 627 + '(?P<editAction>parameters|nodefault|nocreate|nomanage|comment)'. 628 628 '|'. 629 629 '(?:form/(?P<formKey>[^/]+))'. 630 630 ')'.
+1 -1
src/applications/transactions/controller/PhabricatorEditEngineConfigurationViewController.php
··· 10 10 public function handleRequest(AphrontRequest $request) { 11 11 $viewer = $this->getViewer(); 12 12 13 - $config = $this->loadConfigForEdit(); 13 + $config = $this->loadConfigForView(); 14 14 if (!$config) { 15 15 return id(new Aphront404Response()); 16 16 }
+20 -6
src/applications/transactions/controller/PhabricatorEditEngineController.php
··· 35 35 } 36 36 37 37 protected function loadConfigForEdit() { 38 + return $this->loadConfig($need_edit = true); 39 + } 40 + 41 + protected function loadConfigForView() { 42 + return $this->loadConfig($need_edit = false); 43 + } 44 + 45 + private function loadConfig($need_edit) { 38 46 $request = $this->getRequest(); 39 47 $viewer = $this->getViewer(); 40 48 ··· 43 51 44 52 $key = $request->getURIData('key'); 45 53 54 + if ($need_edit) { 55 + $capabilities = array( 56 + PhabricatorPolicyCapability::CAN_VIEW, 57 + PhabricatorPolicyCapability::CAN_EDIT, 58 + ); 59 + } else { 60 + $capabilities = array( 61 + PhabricatorPolicyCapability::CAN_VIEW, 62 + ); 63 + } 64 + 46 65 $config = id(new PhabricatorEditEngineConfigurationQuery()) 47 66 ->setViewer($viewer) 48 67 ->withEngineKeys(array($engine_key)) 49 68 ->withIdentifiers(array($key)) 50 - ->requireCapabilities( 51 - array( 52 - PhabricatorPolicyCapability::CAN_VIEW, 53 - PhabricatorPolicyCapability::CAN_EDIT, 54 - )) 69 + ->requireCapabilities($capabilities) 55 70 ->executeOne(); 56 - 57 71 if ($config) { 58 72 $engine = $config->getEngine(); 59 73
+120 -14
src/applications/transactions/editengine/PhabricatorEditEngine.php
··· 628 628 629 629 $capabilities = array(); 630 630 $use_default = false; 631 + $require_create = true; 631 632 switch ($action) { 632 633 case 'comment': 633 634 $capabilities = array( ··· 637 638 break; 638 639 case 'parameters': 639 640 $use_default = true; 641 + break; 642 + case 'nodefault': 643 + case 'nocreate': 644 + case 'nomanage': 645 + $require_create = false; 640 646 break; 641 647 default: 642 648 break; ··· 661 667 return new Aphront404Response(); 662 668 } 663 669 } else { 670 + // Make sure the viewer has permission to create new objects of 671 + // this type if we're going to create a new object. 672 + if ($require_create) { 673 + $this->requireCreateCapability(); 674 + } 675 + 664 676 $this->setIsCreate(true); 665 677 $object = $this->newEditableObject(); 666 678 } ··· 672 684 return $this->buildParametersResponse($object); 673 685 case 'nodefault': 674 686 return $this->buildNoDefaultResponse($object); 687 + case 'nocreate': 688 + return $this->buildNoCreateResponse($object); 689 + case 'nomanage': 690 + return $this->buildNoManageResponse($object); 675 691 case 'comment': 676 692 return $this->buildCommentResponse($object); 677 693 default: ··· 757 773 758 774 $editor->applyTransactions($object, $xactions); 759 775 760 - return id(new AphrontRedirectResponse()) 761 - ->setURI($this->getObjectViewURI($object)); 776 + return $this->newEditResponse($request, $object, $xactions); 762 777 } catch (PhabricatorApplicationTransactionValidationException $ex) { 763 778 $validation_exception = $ex; 764 779 ··· 847 862 ->appendChild($box); 848 863 } 849 864 865 + protected function newEditResponse( 866 + AphrontRequest $request, 867 + $object, 868 + array $xactions) { 869 + return id(new AphrontRedirectResponse()) 870 + ->setURI($this->getObjectViewURI($object)); 871 + } 872 + 850 873 private function buildEditForm($object, array $fields) { 851 874 $viewer = $this->getViewer(); 852 875 ··· 896 919 private function buildEditFormActions($object) { 897 920 $actions = array(); 898 921 922 + $actions[] = id(new PhabricatorActionView()) 923 + ->setName(pht('Show HTTP Parameters')) 924 + ->setIcon('fa-crosshairs') 925 + ->setHref($this->getEditURI($object, 'parameters/')); 926 + 899 927 if ($this->supportsEditEngineConfiguration()) { 900 928 $engine_key = $this->getEngineKey(); 901 929 $config = $this->getEditEngineConfiguration(); 902 930 931 + $can_manage = PhabricatorPolicyFilter::hasCapability( 932 + $this->getViewer(), 933 + $config, 934 + PhabricatorPolicyCapability::CAN_EDIT); 935 + 936 + if ($can_manage) { 937 + $manage_uri = $config->getURI(); 938 + } else { 939 + $manage_uri = $this->getEditURI(null, 'nomanage/'); 940 + } 941 + 942 + $view_uri = "/transactions/editengine/{$engine_key}/"; 943 + 903 944 $actions[] = id(new PhabricatorActionView()) 904 - ->setName(pht('Manage Form Configurations')) 945 + ->setName(pht('View Form Configurations')) 905 946 ->setIcon('fa-list-ul') 906 - ->setHref("/transactions/editengine/{$engine_key}/"); 947 + ->setHref($view_uri); 948 + 907 949 $actions[] = id(new PhabricatorActionView()) 908 950 ->setName(pht('Edit Form Configuration')) 909 951 ->setIcon('fa-pencil') 910 - ->setHref($config->getURI()); 952 + ->setHref($manage_uri) 953 + ->setDisabled(!$can_manage) 954 + ->setWorkflow(!$can_manage); 911 955 } 912 956 913 - $actions[] = id(new PhabricatorActionView()) 914 - ->setName(pht('Show HTTP Parameters')) 915 - ->setIcon('fa-crosshairs') 916 - ->setHref($this->getEditURI($object, 'parameters/')); 917 957 918 958 return $actions; 919 959 } ··· 921 961 final public function addActionToCrumbs(PHUICrumbsView $crumbs) { 922 962 $viewer = $this->getViewer(); 923 963 924 - $configs = $this->loadUsableConfigurationsForCreate(); 964 + $can_create = $this->hasCreateCapability(); 965 + if ($can_create) { 966 + $configs = $this->loadUsableConfigurationsForCreate(); 967 + } else { 968 + $configs = array(); 969 + } 925 970 926 971 $dropdown = null; 927 972 $disabled = false; ··· 938 983 $disabled = false; 939 984 } 940 985 $workflow = true; 941 - $create_uri = $this->getEditURI(null, 'nodefault/'); 986 + 987 + if ($can_create) { 988 + $create_uri = $this->getEditURI(null, 'nodefault/'); 989 + } else { 990 + $create_uri = $this->getEditURI(null, 'nocreate/'); 991 + } 942 992 } else { 943 993 $config = head($configs); 944 994 $form_key = $config->getIdentifier(); ··· 1109 1159 ->addCancelButton($cancel_uri); 1110 1160 } 1111 1161 1162 + private function buildNoCreateResponse($object) { 1163 + $cancel_uri = $this->getObjectCreateCancelURI($object); 1164 + 1165 + return $this->getController() 1166 + ->newDialog() 1167 + ->setTitle(pht('No Create Permission')) 1168 + ->appendParagraph( 1169 + pht( 1170 + 'You do not have permission to create these objects.')) 1171 + ->addCancelButton($cancel_uri); 1172 + } 1173 + 1174 + private function buildNoManageResponse($object) { 1175 + $cancel_uri = $this->getObjectCreateCancelURI($object); 1176 + 1177 + return $this->getController() 1178 + ->newDialog() 1179 + ->setTitle(pht('No Manage Permission')) 1180 + ->appendParagraph( 1181 + pht( 1182 + 'You do not have permission to configure forms for this '. 1183 + 'application.')) 1184 + ->addCancelButton($cancel_uri); 1185 + } 1186 + 1112 1187 private function buildCommentResponse($object) { 1113 1188 $viewer = $this->getViewer(); 1114 1189 ··· 1266 1341 $this->setIsCreate(false); 1267 1342 $object = $this->newObjectFromIdentifier($identifier); 1268 1343 } else { 1344 + $this->requireCreateCapability(); 1345 + 1269 1346 $this->setIsCreate(true); 1270 1347 $object = $this->newEditableObject(); 1271 1348 } ··· 1429 1506 } 1430 1507 1431 1508 public function loadQuickCreateItems() { 1432 - $configs = $this->loadUsableConfigurationsForCreate(); 1509 + $items = array(); 1510 + 1511 + if (!$this->hasCreateCapability()) { 1512 + return $items; 1513 + } 1433 1514 1434 - $items = array(); 1515 + $configs = $this->loadUsableConfigurationsForCreate(); 1435 1516 1436 1517 if (!$configs) { 1437 1518 // No items to add. ··· 1456 1537 private function loadUsableConfigurationsForCreate() { 1457 1538 $viewer = $this->getViewer(); 1458 1539 1459 - return id(new PhabricatorEditEngineConfigurationQuery()) 1540 + $configs = id(new PhabricatorEditEngineConfigurationQuery()) 1460 1541 ->setViewer($viewer) 1461 1542 ->withEngineKeys(array($this->getEngineKey())) 1462 1543 ->withIsDefault(true) 1463 1544 ->withIsDisabled(false) 1464 1545 ->execute(); 1546 + 1547 + $configs = msort($configs, 'getCreateSortKey'); 1548 + 1549 + return $configs; 1465 1550 } 1466 1551 1467 1552 private function newQuickCreateItem( ··· 1478 1563 ->setHref($item_uri); 1479 1564 } 1480 1565 1566 + protected function getCreateNewObjectPolicy() { 1567 + return PhabricatorPolicies::POLICY_USER; 1568 + } 1569 + 1570 + private function requireCreateCapability() { 1571 + PhabricatorPolicyFilter::requireCapability( 1572 + $this->getViewer(), 1573 + $this, 1574 + PhabricatorPolicyCapability::CAN_EDIT); 1575 + } 1576 + 1577 + private function hasCreateCapability() { 1578 + return PhabricatorPolicyFilter::hasCapability( 1579 + $this->getViewer(), 1580 + $this, 1581 + PhabricatorPolicyCapability::CAN_EDIT); 1582 + } 1583 + 1481 1584 1482 1585 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 1483 1586 ··· 1489 1592 public function getCapabilities() { 1490 1593 return array( 1491 1594 PhabricatorPolicyCapability::CAN_VIEW, 1595 + PhabricatorPolicyCapability::CAN_EDIT, 1492 1596 ); 1493 1597 } 1494 1598 ··· 1496 1600 switch ($capability) { 1497 1601 case PhabricatorPolicyCapability::CAN_VIEW: 1498 1602 return PhabricatorPolicies::getMostOpenPolicy(); 1603 + case PhabricatorPolicyCapability::CAN_EDIT: 1604 + return $this->getCreateNewObjectPolicy(); 1499 1605 } 1500 1606 } 1501 1607
+6
src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditEngine.php
··· 19 19 return $this->targetEngine; 20 20 } 21 21 22 + protected function getCreateNewObjectPolicy() { 23 + return $this->getTargetEngine() 24 + ->getApplication() 25 + ->getPolicy(PhabricatorPolicyCapability::CAN_EDIT); 26 + } 27 + 22 28 public function getEngineName() { 23 29 return pht('Edit Configurations'); 24 30 }
-1
src/applications/transactions/editor/PhabricatorEditEngineConfigurationEditor.php
··· 15 15 $types = parent::getTransactionTypes(); 16 16 17 17 $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; 18 - $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; 19 18 20 19 $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_NAME; 21 20 $types[] = PhabricatorEditEngineConfigurationTransaction::TYPE_PREAMBLE;
+48 -7
src/applications/transactions/storage/PhabricatorEditEngineConfiguration.php
··· 10 10 protected $builtinKey; 11 11 protected $name; 12 12 protected $viewPolicy; 13 - protected $editPolicy; 14 13 protected $properties = array(); 15 14 protected $isDisabled = 0; 16 15 protected $isDefault = 0; 16 + protected $isEdit = 0; 17 + protected $createOrder = 0; 18 + protected $editOrder = 0; 17 19 18 20 private $engine = self::ATTACHABLE; 19 21 ··· 29 31 PhabricatorUser $actor, 30 32 PhabricatorEditEngine $engine) { 31 33 32 - // TODO: This should probably be controlled by a new default capability. 33 - $edit_policy = PhabricatorPolicies::POLICY_ADMIN; 34 - 35 34 return id(new PhabricatorEditEngineConfiguration()) 36 35 ->setEngineKey($engine->getEngineKey()) 37 36 ->attachEngine($engine) 38 - ->setViewPolicy(PhabricatorPolicies::getMostOpenPolicy()) 39 - ->setEditPolicy($edit_policy); 37 + ->setViewPolicy(PhabricatorPolicies::getMostOpenPolicy()); 40 38 } 41 39 42 40 public function generatePHID() { ··· 44 42 PhabricatorEditEngineConfigurationPHIDType::TYPECONST); 45 43 } 46 44 45 + public function getCreateSortKey() { 46 + return $this->getSortKey($this->createOrder); 47 + } 48 + 49 + public function getEditSortKey() { 50 + return $this->getSortKey($this->editOrder); 51 + } 52 + 53 + private function getSortKey($order) { 54 + // Put objects at the bottom by default if they haven't previously been 55 + // reordered. When they're explicitly reordered, the smallest sort key we 56 + // assign is 1, so if the object has a value of 0 it means it hasn't been 57 + // ordered yet. 58 + if ($order != 0) { 59 + $group = 'A'; 60 + } else { 61 + $group = 'B'; 62 + } 63 + 64 + return sprintf( 65 + "%s%012d%s\0%012d", 66 + $group, 67 + $order, 68 + $this->getName(), 69 + $this->getID()); 70 + } 71 + 47 72 protected function getConfiguration() { 48 73 return array( 49 74 self::CONFIG_AUX_PHID => true, ··· 56 81 'name' => 'text255', 57 82 'isDisabled' => 'bool', 58 83 'isDefault' => 'bool', 84 + 'isEdit' => 'bool', 85 + 'createOrder' => 'uint32', 86 + 'editOrder' => 'uint32', 59 87 ), 60 88 self::CONFIG_KEY_SCHEMA => array( 61 89 'key_engine' => array( ··· 64 92 ), 65 93 'key_default' => array( 66 94 'columns' => array('engineKey', 'isDefault', 'isDisabled'), 95 + ), 96 + 'key_edit' => array( 97 + 'columns' => array('engineKey', 'isEdit', 'isDisabled'), 67 98 ), 68 99 ), 69 100 ) + parent::getConfiguration(); ··· 233 264 case PhabricatorPolicyCapability::CAN_VIEW: 234 265 return $this->getViewPolicy(); 235 266 case PhabricatorPolicyCapability::CAN_EDIT: 236 - return $this->getEditPolicy(); 267 + return $this->getEngine() 268 + ->getApplication() 269 + ->getPolicy($capability); 237 270 } 238 271 } 239 272 240 273 public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 274 + switch ($capability) { 275 + case PhabricatorPolicyCapability::CAN_VIEW: 276 + return PhabricatorPolicyFilter::hasCapability( 277 + $viewer, 278 + $this->getEngine()->getApplication(), 279 + PhabricatorPolicyCapability::CAN_EDIT); 280 + } 281 + 241 282 return false; 242 283 } 243 284