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

Use an extended policy to bind column and board policies together

Summary:
Ref T10349. Columns have the same policies as the projects they belong to.

However, the current implementation just returns the policy directly. This usually works, but if the project has a policy like "Members of (This) Project", the policy filter tries to check if the viewer is a member of //the column itself//. That doesn't work, since columns don't have members. This leads to a situation where columns on "Editable By: Project Members" projects can not be edited.

Instead, return a permissive base policy and then use an extended policy to bind the column policy to the project policy.

Test Plan:
- Edited a column on an "Editable By: Members of Project" board.
- Added and ran a unit test covering this case.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10349

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

+83 -4
+1
src/__phutil_library_map__.php
··· 7305 7305 'PhabricatorApplicationTransactionInterface', 7306 7306 'PhabricatorPolicyInterface', 7307 7307 'PhabricatorDestructibleInterface', 7308 + 'PhabricatorExtendedPolicyInterface', 7308 7309 ), 7309 7310 'PhabricatorProjectColumnDetailController' => 'PhabricatorProjectBoardController', 7310 7311 'PhabricatorProjectColumnEditController' => 'PhabricatorProjectBoardController',
+61
src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php
··· 1013 1013 $this->assertColumns($expect, $user, $board, $task); 1014 1014 } 1015 1015 1016 + public function testColumnExtendedPolicies() { 1017 + $user = $this->createUser(); 1018 + $user->save(); 1019 + 1020 + $board = $this->createProject($user); 1021 + $column = $this->addColumn($user, $board, 0); 1022 + 1023 + // At first, the user should be able to view and edit the column. 1024 + $column = $this->refreshColumn($user, $column); 1025 + $this->assertTrue((bool)$column); 1026 + 1027 + $can_edit = PhabricatorPolicyFilter::hasCapability( 1028 + $user, 1029 + $column, 1030 + PhabricatorPolicyCapability::CAN_EDIT); 1031 + $this->assertTrue($can_edit); 1032 + 1033 + // Now, set the project edit policy to "Members of Project". This should 1034 + // disable editing. 1035 + $members_policy = id(new PhabricatorProjectMembersPolicyRule()) 1036 + ->getObjectPolicyFullKey(); 1037 + $board->setEditPolicy($members_policy)->save(); 1038 + 1039 + $column = $this->refreshColumn($user, $column); 1040 + $this->assertTrue((bool)$column); 1041 + 1042 + $can_edit = PhabricatorPolicyFilter::hasCapability( 1043 + $user, 1044 + $column, 1045 + PhabricatorPolicyCapability::CAN_EDIT); 1046 + $this->assertFalse($can_edit); 1047 + 1048 + // Now, join the project. This should make the column editable again. 1049 + $this->joinProject($board, $user); 1050 + 1051 + $column = $this->refreshColumn($user, $column); 1052 + $this->assertTrue((bool)$column); 1053 + 1054 + $can_edit = PhabricatorPolicyFilter::hasCapability( 1055 + $user, 1056 + $column, 1057 + PhabricatorPolicyCapability::CAN_EDIT); 1058 + $this->assertTrue($can_edit); 1059 + } 1060 + 1016 1061 private function moveToColumn( 1017 1062 PhabricatorUser $viewer, 1018 1063 PhabricatorProject $board, ··· 1242 1287 ->needMembers($need_members) 1243 1288 ->needWatchers($need_watchers) 1244 1289 ->withIDs(array($project->getID())) 1290 + ->execute(); 1291 + 1292 + if ($results) { 1293 + return head($results); 1294 + } else { 1295 + return null; 1296 + } 1297 + } 1298 + 1299 + private function refreshColumn( 1300 + PhabricatorUser $viewer, 1301 + PhabricatorProjectColumn $column) { 1302 + 1303 + $results = id(new PhabricatorProjectColumnQuery()) 1304 + ->setViewer($viewer) 1305 + ->withIDs(array($column->getID())) 1245 1306 ->execute(); 1246 1307 1247 1308 if ($results) {
+1 -2
src/applications/project/controller/PhabricatorProjectColumnDetailController.php
··· 73 73 74 74 $header = id(new PHUIHeaderView()) 75 75 ->setUser($viewer) 76 - ->setHeader($column->getDisplayName()) 77 - ->setPolicyObject($column); 76 + ->setHeader($column->getDisplayName()); 78 77 79 78 if ($column->isHidden()) { 80 79 $header->setStatus('fa-ban', 'dark', pht('Hidden'));
+20 -2
src/applications/project/storage/PhabricatorProjectColumn.php
··· 5 5 implements 6 6 PhabricatorApplicationTransactionInterface, 7 7 PhabricatorPolicyInterface, 8 - PhabricatorDestructibleInterface { 8 + PhabricatorDestructibleInterface, 9 + PhabricatorExtendedPolicyInterface { 9 10 10 11 const STATUS_ACTIVE = 0; 11 12 const STATUS_HIDDEN = 1; ··· 219 220 } 220 221 221 222 public function getPolicy($capability) { 222 - return $this->getProject()->getPolicy($capability); 223 + // NOTE: Column policies are enforced as an extended policy which makes 224 + // them the same as the project's policies. 225 + switch ($capability) { 226 + case PhabricatorPolicyCapability::CAN_VIEW: 227 + return PhabricatorPolicies::getMostOpenPolicy(); 228 + case PhabricatorPolicyCapability::CAN_EDIT: 229 + return PhabricatorPolicies::POLICY_USER; 230 + } 223 231 } 224 232 225 233 public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { ··· 230 238 231 239 public function describeAutomaticCapability($capability) { 232 240 return pht('Users must be able to see a project to see its board.'); 241 + } 242 + 243 + 244 + /* -( PhabricatorExtendedPolicyInterface )--------------------------------- */ 245 + 246 + 247 + public function getExtendedPolicy($capability, PhabricatorUser $viewer) { 248 + return array( 249 + array($this->getProject(), $capability), 250 + ); 233 251 } 234 252 235 253