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

Add a "members of all projects" (vs "...any project") custom policy rule to the upstream

Summary:
Ref T13151. See PHI702. An install is interested in a "members of all projects" (vs "members of any project", which is currently implemented) rule.

Although this is fairly niche, I think it's reasonable and doesn't have much of a maintenance cost.

This could already be implemented as an extension, but it would have to copy/paste a bunch of code.

Test Plan:
- Ran unit tests.
- Used the UI to select this policy for a task, with various values. Joined/left projects to satisfy/fail the rule. Behavior seemed correct.
- Used the UI to select the existing policy rule ("any project"), joined/left projects to satisfy/fail the rule. Doesn't look like I broke anything.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13151

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

+196 -58
+5 -1
src/__phutil_library_map__.php
··· 4026 4026 'PhabricatorProjectWorkboardBackgroundTransaction' => 'applications/project/xaction/PhabricatorProjectWorkboardBackgroundTransaction.php', 4027 4027 'PhabricatorProjectWorkboardProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php', 4028 4028 'PhabricatorProjectWorkboardTransaction' => 'applications/project/xaction/PhabricatorProjectWorkboardTransaction.php', 4029 + 'PhabricatorProjectsAllPolicyRule' => 'applications/project/policyrule/PhabricatorProjectsAllPolicyRule.php', 4029 4030 'PhabricatorProjectsAncestorsSearchEngineAttachment' => 'applications/project/engineextension/PhabricatorProjectsAncestorsSearchEngineAttachment.php', 4031 + 'PhabricatorProjectsBasePolicyRule' => 'applications/project/policyrule/PhabricatorProjectsBasePolicyRule.php', 4030 4032 'PhabricatorProjectsCurtainExtension' => 'applications/project/engineextension/PhabricatorProjectsCurtainExtension.php', 4031 4033 'PhabricatorProjectsEditEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php', 4032 4034 'PhabricatorProjectsEditField' => 'applications/transactions/editfield/PhabricatorProjectsEditField.php', ··· 9893 9895 'PhabricatorProjectWorkboardBackgroundTransaction' => 'PhabricatorProjectTransactionType', 9894 9896 'PhabricatorProjectWorkboardProfileMenuItem' => 'PhabricatorProfileMenuItem', 9895 9897 'PhabricatorProjectWorkboardTransaction' => 'PhabricatorProjectTransactionType', 9898 + 'PhabricatorProjectsAllPolicyRule' => 'PhabricatorProjectsBasePolicyRule', 9896 9899 'PhabricatorProjectsAncestorsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 9900 + 'PhabricatorProjectsBasePolicyRule' => 'PhabricatorPolicyRule', 9897 9901 'PhabricatorProjectsCurtainExtension' => 'PHUICurtainExtension', 9898 9902 'PhabricatorProjectsEditEngineExtension' => 'PhabricatorEditEngineExtension', 9899 9903 'PhabricatorProjectsEditField' => 'PhabricatorTokenizerEditField', ··· 9902 9906 'PhabricatorProjectsMailEngineExtension' => 'PhabricatorMailEngineExtension', 9903 9907 'PhabricatorProjectsMembersSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 9904 9908 'PhabricatorProjectsMembershipIndexEngineExtension' => 'PhabricatorIndexEngineExtension', 9905 - 'PhabricatorProjectsPolicyRule' => 'PhabricatorPolicyRule', 9909 + 'PhabricatorProjectsPolicyRule' => 'PhabricatorProjectsBasePolicyRule', 9906 9910 'PhabricatorProjectsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 9907 9911 'PhabricatorProjectsSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 9908 9912 'PhabricatorProjectsWatchersSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment',
+94
src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php
··· 1177 1177 $this->assertTrue($can_edit); 1178 1178 } 1179 1179 1180 + public function testProjectPolicyRules() { 1181 + $author = $this->generateNewTestUser(); 1182 + 1183 + $proj_a = PhabricatorProject::initializeNewProject($author) 1184 + ->setName('Policy A') 1185 + ->save(); 1186 + $proj_b = PhabricatorProject::initializeNewProject($author) 1187 + ->setName('Policy B') 1188 + ->save(); 1189 + 1190 + $user_none = $this->generateNewTestUser(); 1191 + $user_any = $this->generateNewTestUser(); 1192 + $user_all = $this->generateNewTestUser(); 1193 + 1194 + $this->joinProject($proj_a, $user_any); 1195 + $this->joinProject($proj_a, $user_all); 1196 + $this->joinProject($proj_b, $user_all); 1197 + 1198 + $any_policy = id(new PhabricatorPolicy()) 1199 + ->setRules( 1200 + array( 1201 + array( 1202 + 'action' => PhabricatorPolicy::ACTION_ALLOW, 1203 + 'rule' => 'PhabricatorProjectsPolicyRule', 1204 + 'value' => array( 1205 + $proj_a->getPHID(), 1206 + $proj_b->getPHID(), 1207 + ), 1208 + ), 1209 + )) 1210 + ->save(); 1211 + 1212 + $all_policy = id(new PhabricatorPolicy()) 1213 + ->setRules( 1214 + array( 1215 + array( 1216 + 'action' => PhabricatorPolicy::ACTION_ALLOW, 1217 + 'rule' => 'PhabricatorProjectsAllPolicyRule', 1218 + 'value' => array( 1219 + $proj_a->getPHID(), 1220 + $proj_b->getPHID(), 1221 + ), 1222 + ), 1223 + )) 1224 + ->save(); 1225 + 1226 + $any_task = ManiphestTask::initializeNewTask($author) 1227 + ->setViewPolicy($any_policy->getPHID()) 1228 + ->save(); 1229 + 1230 + $all_task = ManiphestTask::initializeNewTask($author) 1231 + ->setViewPolicy($all_policy->getPHID()) 1232 + ->save(); 1233 + 1234 + $map = array( 1235 + array( 1236 + pht('Project policy rule; user in no projects'), 1237 + $user_none, 1238 + false, 1239 + false, 1240 + ), 1241 + array( 1242 + pht('Project policy rule; user in some projects'), 1243 + $user_any, 1244 + true, 1245 + false, 1246 + ), 1247 + array( 1248 + pht('Project policy rule; user in all projects'), 1249 + $user_all, 1250 + true, 1251 + true, 1252 + ), 1253 + ); 1254 + 1255 + foreach ($map as $test_case) { 1256 + list($label, $user, $expect_any, $expect_all) = $test_case; 1257 + 1258 + $can_any = PhabricatorPolicyFilter::hasCapability( 1259 + $user, 1260 + $any_task, 1261 + PhabricatorPolicyCapability::CAN_VIEW); 1262 + 1263 + $can_all = PhabricatorPolicyFilter::hasCapability( 1264 + $user, 1265 + $all_task, 1266 + PhabricatorPolicyCapability::CAN_VIEW); 1267 + 1268 + $this->assertEqual($expect_any, $can_any, pht('%s / Any', $label)); 1269 + $this->assertEqual($expect_all, $can_all, pht('%s / All', $label)); 1270 + } 1271 + } 1272 + 1273 + 1180 1274 private function moveToColumn( 1181 1275 PhabricatorUser $viewer, 1182 1276 PhabricatorProject $board,
+29
src/applications/project/policyrule/PhabricatorProjectsAllPolicyRule.php
··· 1 + <?php 2 + 3 + final class PhabricatorProjectsAllPolicyRule 4 + extends PhabricatorProjectsBasePolicyRule { 5 + 6 + public function getRuleDescription() { 7 + return pht('members of all projects'); 8 + } 9 + 10 + public function applyRule( 11 + PhabricatorUser $viewer, 12 + $value, 13 + PhabricatorPolicyInterface $object) { 14 + 15 + $memberships = $this->getMemberships($viewer->getPHID()); 16 + foreach ($value as $project_phid) { 17 + if (empty($memberships[$project_phid])) { 18 + return false; 19 + } 20 + } 21 + 22 + return true; 23 + } 24 + 25 + public function getRuleOrder() { 26 + return 205; 27 + } 28 + 29 + }
+64
src/applications/project/policyrule/PhabricatorProjectsBasePolicyRule.php
··· 1 + <?php 2 + 3 + abstract class PhabricatorProjectsBasePolicyRule 4 + extends PhabricatorPolicyRule { 5 + 6 + private $memberships = array(); 7 + 8 + protected function getMemberships($viewer_phid) { 9 + return idx($this->memberships, $viewer_phid, array()); 10 + } 11 + 12 + public function willApplyRules( 13 + PhabricatorUser $viewer, 14 + array $values, 15 + array $objects) { 16 + 17 + $values = array_unique(array_filter(array_mergev($values))); 18 + if (!$values) { 19 + return; 20 + } 21 + 22 + $projects = id(new PhabricatorProjectQuery()) 23 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 24 + ->withMemberPHIDs(array($viewer->getPHID())) 25 + ->withPHIDs($values) 26 + ->execute(); 27 + foreach ($projects as $project) { 28 + $this->memberships[$viewer->getPHID()][$project->getPHID()] = true; 29 + } 30 + } 31 + 32 + public function getValueControlType() { 33 + return self::CONTROL_TYPE_TOKENIZER; 34 + } 35 + 36 + public function getValueControlTemplate() { 37 + $datasource = id(new PhabricatorProjectDatasource()) 38 + ->setParameters( 39 + array( 40 + 'policy' => 1, 41 + )); 42 + 43 + return $this->getDatasourceTemplate($datasource); 44 + } 45 + 46 + public function getValueForStorage($value) { 47 + PhutilTypeSpec::newFromString('list<string>')->check($value); 48 + return array_values($value); 49 + } 50 + 51 + public function getValueForDisplay(PhabricatorUser $viewer, $value) { 52 + $handles = id(new PhabricatorHandleQuery()) 53 + ->setViewer($viewer) 54 + ->withPHIDs($value) 55 + ->execute(); 56 + 57 + return mpull($handles, 'getFullName', 'getPHID'); 58 + } 59 + 60 + public function ruleHasEffect($value) { 61 + return (bool)$value; 62 + } 63 + 64 + }
+4 -57
src/applications/project/policyrule/PhabricatorProjectsPolicyRule.php
··· 1 1 <?php 2 2 3 3 final class PhabricatorProjectsPolicyRule 4 - extends PhabricatorPolicyRule { 5 - 6 - private $memberships = array(); 4 + extends PhabricatorProjectsBasePolicyRule { 7 5 8 6 public function getRuleDescription() { 9 - return pht('members of projects'); 10 - } 11 - 12 - public function willApplyRules( 13 - PhabricatorUser $viewer, 14 - array $values, 15 - array $objects) { 16 - 17 - $values = array_unique(array_filter(array_mergev($values))); 18 - if (!$values) { 19 - return; 20 - } 21 - 22 - $projects = id(new PhabricatorProjectQuery()) 23 - ->setViewer(PhabricatorUser::getOmnipotentUser()) 24 - ->withMemberPHIDs(array($viewer->getPHID())) 25 - ->withPHIDs($values) 26 - ->execute(); 27 - foreach ($projects as $project) { 28 - $this->memberships[$viewer->getPHID()][$project->getPHID()] = true; 29 - } 7 + return pht('members of any project'); 30 8 } 31 9 32 10 public function applyRule( ··· 34 12 $value, 35 13 PhabricatorPolicyInterface $object) { 36 14 15 + $memberships = $this->getMemberships($viewer->getPHID()); 37 16 foreach ($value as $project_phid) { 38 - if (isset($this->memberships[$viewer->getPHID()][$project_phid])) { 17 + if (isset($memberships[$project_phid])) { 39 18 return true; 40 19 } 41 20 } ··· 43 22 return false; 44 23 } 45 24 46 - public function getValueControlType() { 47 - return self::CONTROL_TYPE_TOKENIZER; 48 - } 49 - 50 - public function getValueControlTemplate() { 51 - $datasource = id(new PhabricatorProjectDatasource()) 52 - ->setParameters( 53 - array( 54 - 'policy' => 1, 55 - )); 56 - 57 - return $this->getDatasourceTemplate($datasource); 58 - } 59 - 60 25 public function getRuleOrder() { 61 26 return 200; 62 - } 63 - 64 - public function getValueForStorage($value) { 65 - PhutilTypeSpec::newFromString('list<string>')->check($value); 66 - return array_values($value); 67 - } 68 - 69 - public function getValueForDisplay(PhabricatorUser $viewer, $value) { 70 - $handles = id(new PhabricatorHandleQuery()) 71 - ->setViewer($viewer) 72 - ->withPHIDs($value) 73 - ->execute(); 74 - 75 - return mpull($handles, 'getFullName', 'getPHID'); 76 - } 77 - 78 - public function ruleHasEffect($value) { 79 - return (bool)$value; 80 27 } 81 28 82 29 }