@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.

Modernize policies in Paste and Macro

Summary:
Ref T603. Fixes T2823. This updates Paste and Macro.

- **Paste**
- Added default view policy.
- I didn't add a "create" policy, since I can't come up with any realistic scenario where you'd give users access to pastes but not let them create them.
- **Macro**
- Added a "manage" policy, which covers creating and editing macros. This lets an install only allow "People With An Approved Sense of Humor" or whatever to create macros.
- Removed the "edit" policy, since giving individual users access to specific macros doesn't make much sense to me.
- Changed the view policy to the "most public" policy the install allows.
- Added view policy information to the header.

Also fix a couple of minor things in Maniphest.

Test Plan:
- Set Paste policy, created pastes via web and Conduit, saw they got the right default policies.
- Set Macro policy, tried to create/edit macros with valid and unauthorized users.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2823, T603

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

+160 -49
+4
src/__phutil_library_map__.php
··· 803 803 'PackageDeleteMail' => 'applications/owners/mail/PackageDeleteMail.php', 804 804 'PackageMail' => 'applications/owners/mail/PackageMail.php', 805 805 'PackageModifyMail' => 'applications/owners/mail/PackageModifyMail.php', 806 + 'PasteCapabilityDefaultView' => 'applications/paste/capability/PasteCapabilityDefaultView.php', 806 807 'PasteCreateMailReceiver' => 'applications/paste/mail/PasteCreateMailReceiver.php', 807 808 'PasteEmbedView' => 'applications/paste/view/PasteEmbedView.php', 808 809 'PasteMockMailReceiver' => 'applications/paste/mail/PasteMockMailReceiver.php', ··· 1292 1293 'PhabricatorLocalTimeTestCase' => 'view/__tests__/PhabricatorLocalTimeTestCase.php', 1293 1294 'PhabricatorLogoutController' => 'applications/auth/controller/PhabricatorLogoutController.php', 1294 1295 'PhabricatorMacroAudioController' => 'applications/macro/controller/PhabricatorMacroAudioController.php', 1296 + 'PhabricatorMacroCapabilityManage' => 'applications/macro/capability/PhabricatorMacroCapabilityManage.php', 1295 1297 'PhabricatorMacroCommentController' => 'applications/macro/controller/PhabricatorMacroCommentController.php', 1296 1298 'PhabricatorMacroConfigOptions' => 'applications/macro/config/PhabricatorMacroConfigOptions.php', 1297 1299 'PhabricatorMacroController' => 'applications/macro/controller/PhabricatorMacroController.php', ··· 2943 2945 'PackageDeleteMail' => 'PackageMail', 2944 2946 'PackageMail' => 'PhabricatorMail', 2945 2947 'PackageModifyMail' => 'PackageMail', 2948 + 'PasteCapabilityDefaultView' => 'PhabricatorPolicyCapability', 2946 2949 'PasteCreateMailReceiver' => 'PhabricatorMailReceiver', 2947 2950 'PasteEmbedView' => 'AphrontView', 2948 2951 'PasteMockMailReceiver' => 'PhabricatorObjectMailReceiver', ··· 3482 3485 'PhabricatorLocalTimeTestCase' => 'PhabricatorTestCase', 3483 3486 'PhabricatorLogoutController' => 'PhabricatorAuthController', 3484 3487 'PhabricatorMacroAudioController' => 'PhabricatorMacroController', 3488 + 'PhabricatorMacroCapabilityManage' => 'PhabricatorPolicyCapability', 3485 3489 'PhabricatorMacroCommentController' => 'PhabricatorMacroController', 3486 3490 'PhabricatorMacroConfigOptions' => 'PhabricatorApplicationConfigOptions', 3487 3491 'PhabricatorMacroController' => 'PhabricatorController',
+1 -5
src/applications/base/PhabricatorApplication.php
··· 349 349 350 350 switch ($capability) { 351 351 case PhabricatorPolicyCapability::CAN_VIEW: 352 - if (PhabricatorEnv::getEnvConfig('policy.allow-public')) { 353 - return PhabricatorPolicies::POLICY_PUBLIC; 354 - } else { 355 - return PhabricatorPolicies::POLICY_USER; 356 - } 352 + return PhabricatorPolicies::getMostOpenPolicy(); 357 353 case PhabricatorPolicyCapability::CAN_EDIT: 358 354 return PhabricatorPolicies::POLICY_ADMIN; 359 355 default:
+8
src/applications/macro/application/PhabricatorApplicationMacro.php
··· 42 42 ); 43 43 } 44 44 45 + protected function getCustomCapabilities() { 46 + return array( 47 + PhabricatorMacroCapabilityManage::CAPABILITY => array( 48 + 'caption' => pht('Allows creating and editing macros.') 49 + ), 50 + ); 51 + } 52 + 45 53 }
+20
src/applications/macro/capability/PhabricatorMacroCapabilityManage.php
··· 1 + <?php 2 + 3 + final class PhabricatorMacroCapabilityManage 4 + extends PhabricatorPolicyCapability { 5 + 6 + const CAPABILITY = 'macro.manage'; 7 + 8 + public function getCapabilityKey() { 9 + return self::CAPABILITY; 10 + } 11 + 12 + public function getCapabilityName() { 13 + return pht('Can Manage Macros'); 14 + } 15 + 16 + public function describeCapabilityRejection() { 17 + return pht('You do not have permission to manage image macros.'); 18 + } 19 + 20 + }
+4
src/applications/macro/controller/PhabricatorMacroAudioController.php
··· 10 10 } 11 11 12 12 public function processRequest() { 13 + 14 + $this->requireApplicationCapability( 15 + PhabricatorMacroCapabilityManage::CAPABILITY); 16 + 13 17 $request = $this->getRequest(); 14 18 $viewer = $request->getUser(); 15 19
+6 -1
src/applications/macro/controller/PhabricatorMacroController.php
··· 28 28 protected function buildApplicationCrumbs() { 29 29 $crumbs = parent::buildApplicationCrumbs(); 30 30 31 + $can_manage = $this->hasApplicationCapability( 32 + PhabricatorMacroCapabilityManage::CAPABILITY); 33 + 31 34 $crumbs->addAction( 32 35 id(new PHUIListItemView()) 33 36 ->setName(pht('Create Macro')) 34 37 ->setHref($this->getApplicationURI('/create/')) 35 - ->setIcon('create')); 38 + ->setIcon('create') 39 + ->setDisabled(!$can_manage) 40 + ->setWorkflow(!$can_manage)); 36 41 37 42 return $crumbs; 38 43 }
+4
src/applications/macro/controller/PhabricatorMacroDisableController.php
··· 10 10 } 11 11 12 12 public function processRequest() { 13 + 14 + $this->requireApplicationCapability( 15 + PhabricatorMacroCapabilityManage::CAPABILITY); 16 + 13 17 $request = $this->getRequest(); 14 18 $user = $request->getUser(); 15 19
+3 -5
src/applications/macro/controller/PhabricatorMacroEditController.php
··· 11 11 12 12 public function processRequest() { 13 13 14 + $this->requireApplicationCapability( 15 + PhabricatorMacroCapabilityManage::CAPABILITY); 16 + 14 17 $request = $this->getRequest(); 15 18 $user = $request->getUser(); 16 19 17 20 if ($this->id) { 18 21 $macro = id(new PhabricatorMacroQuery()) 19 22 ->setViewer($user) 20 - ->requireCapabilities( 21 - array( 22 - PhabricatorPolicyCapability::CAN_VIEW, 23 - PhabricatorPolicyCapability::CAN_EDIT, 24 - )) 25 23 ->withIDs(array($this->id)) 26 24 ->executeOne(); 27 25 if (!$macro) {
+12
src/applications/macro/controller/PhabricatorMacroViewController.php
··· 70 70 ->setMarkupEngine($engine); 71 71 72 72 $header = id(new PHUIHeaderView()) 73 + ->setUser($user) 74 + ->setPolicyObject($macro) 73 75 ->setHeader($title_long); 74 76 75 77 if ($macro->getIsDisabled()) { ··· 128 130 } 129 131 130 132 private function buildActionView(PhabricatorFileImageMacro $macro) { 133 + 134 + $can_manage = $this->hasApplicationCapability( 135 + PhabricatorMacroCapabilityManage::CAPABILITY); 136 + 131 137 $request = $this->getRequest(); 132 138 $view = id(new PhabricatorActionListView()) 133 139 ->setUser($request->getUser()) ··· 137 143 id(new PhabricatorActionView()) 138 144 ->setName(pht('Edit Macro')) 139 145 ->setHref($this->getApplicationURI('/edit/'.$macro->getID().'/')) 146 + ->setDisabled(!$can_manage) 147 + ->setWorkflow(!$can_manage) 140 148 ->setIcon('edit')); 141 149 142 150 $view->addAction( 143 151 id(new PhabricatorActionView()) 144 152 ->setName(pht('Edit Audio')) 145 153 ->setHref($this->getApplicationURI('/audio/'.$macro->getID().'/')) 154 + ->setDisabled(!$can_manage) 155 + ->setWorkflow(!$can_manage) 146 156 ->setIcon('herald')); 147 157 148 158 if ($macro->getIsDisabled()) { ··· 151 161 ->setName(pht('Restore Macro')) 152 162 ->setHref($this->getApplicationURI('/disable/'.$macro->getID().'/')) 153 163 ->setWorkflow(true) 164 + ->setDisabled(!$can_manage) 154 165 ->setIcon('undo')); 155 166 } else { 156 167 $view->addAction( ··· 158 169 ->setName(pht('Disable Macro')) 159 170 ->setHref($this->getApplicationURI('/disable/'.$macro->getID().'/')) 160 171 ->setWorkflow(true) 172 + ->setDisabled(!$can_manage) 161 173 ->setIcon('delete')); 162 174 } 163 175
+1 -2
src/applications/macro/storage/PhabricatorFileImageMacro.php
··· 64 64 public function getCapabilities() { 65 65 return array( 66 66 PhabricatorPolicyCapability::CAN_VIEW, 67 - PhabricatorPolicyCapability::CAN_EDIT, 68 67 ); 69 68 } 70 69 71 70 public function getPolicy($capability) { 72 - return PhabricatorPolicies::POLICY_USER; 71 + return PhabricatorPolicies::getMostOpenPolicy(); 73 72 } 74 73 75 74 public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
+1 -1
src/applications/maniphest/controller/ManiphestTaskDetailController.php
··· 462 462 ->setWorkflow(true) 463 463 ->setIcon('merge') 464 464 ->setDisabled(!$can_edit) 465 - ->setWorkflow(!$can_edit)); 465 + ->setWorkflow(true)); 466 466 467 467 $view->addAction( 468 468 id(new PhabricatorActionView())
+9 -3
src/applications/paste/application/PhabricatorApplicationPaste.php
··· 1 1 <?php 2 2 3 - /** 4 - * group paste 5 - */ 6 3 final class PhabricatorApplicationPaste extends PhabricatorApplication { 7 4 8 5 public function getBaseURI() { ··· 40 37 'create/' => 'PhabricatorPasteEditController', 41 38 'edit/(?P<id>[1-9]\d*)/' => 'PhabricatorPasteEditController', 42 39 'comment/(?P<id>[1-9]\d*)/' => 'PhabricatorPasteCommentController', 40 + ), 41 + ); 42 + } 43 + 44 + protected function getCustomCapabilities() { 45 + return array( 46 + PasteCapabilityDefaultView::CAPABILITY => array( 47 + 'caption' => pht( 48 + 'Default view policy for newly created pastes.') 43 49 ), 44 50 ); 45 51 }
+20
src/applications/paste/capability/PasteCapabilityDefaultView.php
··· 1 + <?php 2 + 3 + final class PasteCapabilityDefaultView 4 + extends PhabricatorPolicyCapability { 5 + 6 + const CAPABILITY = 'paste.default.view'; 7 + 8 + public function getCapabilityKey() { 9 + return self::CAPABILITY; 10 + } 11 + 12 + public function getCapabilityName() { 13 + return pht('Default View Policy'); 14 + } 15 + 16 + public function shouldAllowPublicPolicySetting() { 17 + return true; 18 + } 19 + 20 + }
+1 -3
src/applications/paste/conduit/ConduitAPI_paste_create_Method.php
··· 51 51 52 52 // TODO: This should use PhabricatorPasteEditor. 53 53 54 - $paste = new PhabricatorPaste(); 54 + $paste = PhabricatorPaste::initializeNewPaste($user); 55 55 $paste->setTitle($title); 56 56 $paste->setLanguage($language); 57 57 $paste->setFilePHID($paste_file->getPHID()); 58 - $paste->setAuthorPHID($user->getPHID()); 59 - $paste->setViewPolicy(PhabricatorPolicies::POLICY_USER); 60 58 $paste->save(); 61 59 62 60 $paste_file->attachToObject($user, $paste->getPHID());
+1 -1
src/applications/paste/controller/PhabricatorPasteEditController.php
··· 21 21 if (!$this->id) { 22 22 $is_create = true; 23 23 24 - $paste = new PhabricatorPaste(); 24 + $paste = PhabricatorPaste::initializeNewPaste($user); 25 25 26 26 $parent_id = $request->getStr('parent'); 27 27 if ($parent_id) {
+8 -1
src/applications/paste/query/PhabricatorPasteQuery.php
··· 175 175 unset($pastes[$key]); 176 176 continue; 177 177 } 178 - $paste->attachRawContent($file->loadFileData()); 178 + try { 179 + $paste->attachRawContent($file->loadFileData()); 180 + } catch (Exception $ex) { 181 + // We can hit various sorts of file storage issues here. Just drop the 182 + // paste if the file is dead. 183 + unset($pastes[$key]); 184 + continue; 185 + } 179 186 } 180 187 181 188 return $pastes;
+42 -27
src/applications/paste/storage/PhabricatorPaste.php
··· 1 1 <?php 2 2 3 - /** 4 - * @group paste 5 - */ 6 3 final class PhabricatorPaste extends PhabricatorPasteDAO 7 4 implements 8 5 PhabricatorSubscribableInterface, ··· 20 17 private $content = self::ATTACHABLE; 21 18 private $rawContent = self::ATTACHABLE; 22 19 20 + public static function initializeNewPaste(PhabricatorUser $actor) { 21 + $app = id(new PhabricatorApplicationQuery()) 22 + ->setViewer($actor) 23 + ->withClasses(array('PhabricatorApplicationPaste')) 24 + ->executeOne(); 25 + 26 + $view_policy = $app->getPolicy(PasteCapabilityDefaultView::CAPABILITY); 27 + 28 + return id(new PhabricatorPaste()) 29 + ->setTitle('') 30 + ->setAuthorPHID($actor->getPHID()) 31 + ->setViewPolicy($view_policy); 32 + } 33 + 23 34 public function getURI() { 24 35 return '/P'.$this->getID(); 25 36 } ··· 42 53 return parent::save(); 43 54 } 44 55 45 - public function getCapabilities() { 46 - return array( 47 - PhabricatorPolicyCapability::CAN_VIEW, 48 - PhabricatorPolicyCapability::CAN_EDIT, 49 - ); 50 - } 51 - 52 - public function getPolicy($capability) { 53 - if ($capability == PhabricatorPolicyCapability::CAN_VIEW) { 54 - return $this->viewPolicy; 55 - } 56 - return PhabricatorPolicies::POLICY_NOONE; 57 - } 58 - 59 - public function hasAutomaticCapability($capability, PhabricatorUser $user) { 60 - return ($user->getPHID() == $this->getAuthorPHID()); 61 - } 62 - 63 - public function describeAutomaticCapability($capability) { 64 - return pht( 65 - 'The author of a paste can always view and edit it.'); 66 - } 67 - 68 56 public function getFullName() { 69 57 $title = $this->getTitle(); 70 58 if (!$title) { ··· 91 79 return $this; 92 80 } 93 81 94 - /* -( PhabricatorSubscribableInterface Implementation )-------------------- */ 82 + /* -( PhabricatorSubscribableInterface )----------------------------------- */ 95 83 96 84 97 85 public function isAutomaticallySubscribed($phid) { ··· 106 94 $this->getAuthorPHID(), 107 95 ); 108 96 } 97 + 98 + 99 + /* -( PhabricatorPolicyInterface )----------------------------------------- */ 100 + 101 + 102 + public function getCapabilities() { 103 + return array( 104 + PhabricatorPolicyCapability::CAN_VIEW, 105 + PhabricatorPolicyCapability::CAN_EDIT, 106 + ); 107 + } 108 + 109 + public function getPolicy($capability) { 110 + if ($capability == PhabricatorPolicyCapability::CAN_VIEW) { 111 + return $this->viewPolicy; 112 + } 113 + return PhabricatorPolicies::POLICY_NOONE; 114 + } 115 + 116 + public function hasAutomaticCapability($capability, PhabricatorUser $user) { 117 + return ($user->getPHID() == $this->getAuthorPHID()); 118 + } 119 + 120 + public function describeAutomaticCapability($capability) { 121 + return pht('The author of a paste can always view and edit it.'); 122 + } 123 + 109 124 110 125 }
+15
src/applications/policy/constants/PhabricatorPolicies.php
··· 7 7 const POLICY_ADMIN = 'admin'; 8 8 const POLICY_NOONE = 'no-one'; 9 9 10 + /** 11 + * Returns the most public policy this install's configuration permits. 12 + * This is either "public" (if available) or "all users" (if not). 13 + * 14 + * @return const Most open working policy constant. 15 + */ 16 + public static function getMostOpenPolicy() { 17 + if (PhabricatorEnv::getEnvConfig('policy.allow-public')) { 18 + return PhabricatorPolicies::POLICY_PUBLIC; 19 + } else { 20 + return PhabricatorPolicies::POLICY_USER; 21 + } 22 + } 23 + 24 + 10 25 }