diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 1e9e4281f8..7d3e5553fd 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -4026,7 +4026,9 @@ phutil_register_library_map(array( 'PhabricatorProjectWorkboardBackgroundTransaction' => 'applications/project/xaction/PhabricatorProjectWorkboardBackgroundTransaction.php', 'PhabricatorProjectWorkboardProfileMenuItem' => 'applications/project/menuitem/PhabricatorProjectWorkboardProfileMenuItem.php', 'PhabricatorProjectWorkboardTransaction' => 'applications/project/xaction/PhabricatorProjectWorkboardTransaction.php', + 'PhabricatorProjectsAllPolicyRule' => 'applications/project/policyrule/PhabricatorProjectsAllPolicyRule.php', 'PhabricatorProjectsAncestorsSearchEngineAttachment' => 'applications/project/engineextension/PhabricatorProjectsAncestorsSearchEngineAttachment.php', + 'PhabricatorProjectsBasePolicyRule' => 'applications/project/policyrule/PhabricatorProjectsBasePolicyRule.php', 'PhabricatorProjectsCurtainExtension' => 'applications/project/engineextension/PhabricatorProjectsCurtainExtension.php', 'PhabricatorProjectsEditEngineExtension' => 'applications/project/engineextension/PhabricatorProjectsEditEngineExtension.php', 'PhabricatorProjectsEditField' => 'applications/transactions/editfield/PhabricatorProjectsEditField.php', @@ -9893,7 +9895,9 @@ phutil_register_library_map(array( 'PhabricatorProjectWorkboardBackgroundTransaction' => 'PhabricatorProjectTransactionType', 'PhabricatorProjectWorkboardProfileMenuItem' => 'PhabricatorProfileMenuItem', 'PhabricatorProjectWorkboardTransaction' => 'PhabricatorProjectTransactionType', + 'PhabricatorProjectsAllPolicyRule' => 'PhabricatorProjectsBasePolicyRule', 'PhabricatorProjectsAncestorsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', + 'PhabricatorProjectsBasePolicyRule' => 'PhabricatorPolicyRule', 'PhabricatorProjectsCurtainExtension' => 'PHUICurtainExtension', 'PhabricatorProjectsEditEngineExtension' => 'PhabricatorEditEngineExtension', 'PhabricatorProjectsEditField' => 'PhabricatorTokenizerEditField', @@ -9902,7 +9906,7 @@ phutil_register_library_map(array( 'PhabricatorProjectsMailEngineExtension' => 'PhabricatorMailEngineExtension', 'PhabricatorProjectsMembersSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorProjectsMembershipIndexEngineExtension' => 'PhabricatorIndexEngineExtension', - 'PhabricatorProjectsPolicyRule' => 'PhabricatorPolicyRule', + 'PhabricatorProjectsPolicyRule' => 'PhabricatorProjectsBasePolicyRule', 'PhabricatorProjectsSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', 'PhabricatorProjectsSearchEngineExtension' => 'PhabricatorSearchEngineExtension', 'PhabricatorProjectsWatchersSearchEngineAttachment' => 'PhabricatorSearchEngineAttachment', diff --git a/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php b/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php index f34f224521..e50c83ab5a 100644 --- a/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php +++ b/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php @@ -1177,6 +1177,100 @@ final class PhabricatorProjectCoreTestCase extends PhabricatorTestCase { $this->assertTrue($can_edit); } + public function testProjectPolicyRules() { + $author = $this->generateNewTestUser(); + + $proj_a = PhabricatorProject::initializeNewProject($author) + ->setName('Policy A') + ->save(); + $proj_b = PhabricatorProject::initializeNewProject($author) + ->setName('Policy B') + ->save(); + + $user_none = $this->generateNewTestUser(); + $user_any = $this->generateNewTestUser(); + $user_all = $this->generateNewTestUser(); + + $this->joinProject($proj_a, $user_any); + $this->joinProject($proj_a, $user_all); + $this->joinProject($proj_b, $user_all); + + $any_policy = id(new PhabricatorPolicy()) + ->setRules( + array( + array( + 'action' => PhabricatorPolicy::ACTION_ALLOW, + 'rule' => 'PhabricatorProjectsPolicyRule', + 'value' => array( + $proj_a->getPHID(), + $proj_b->getPHID(), + ), + ), + )) + ->save(); + + $all_policy = id(new PhabricatorPolicy()) + ->setRules( + array( + array( + 'action' => PhabricatorPolicy::ACTION_ALLOW, + 'rule' => 'PhabricatorProjectsAllPolicyRule', + 'value' => array( + $proj_a->getPHID(), + $proj_b->getPHID(), + ), + ), + )) + ->save(); + + $any_task = ManiphestTask::initializeNewTask($author) + ->setViewPolicy($any_policy->getPHID()) + ->save(); + + $all_task = ManiphestTask::initializeNewTask($author) + ->setViewPolicy($all_policy->getPHID()) + ->save(); + + $map = array( + array( + pht('Project policy rule; user in no projects'), + $user_none, + false, + false, + ), + array( + pht('Project policy rule; user in some projects'), + $user_any, + true, + false, + ), + array( + pht('Project policy rule; user in all projects'), + $user_all, + true, + true, + ), + ); + + foreach ($map as $test_case) { + list($label, $user, $expect_any, $expect_all) = $test_case; + + $can_any = PhabricatorPolicyFilter::hasCapability( + $user, + $any_task, + PhabricatorPolicyCapability::CAN_VIEW); + + $can_all = PhabricatorPolicyFilter::hasCapability( + $user, + $all_task, + PhabricatorPolicyCapability::CAN_VIEW); + + $this->assertEqual($expect_any, $can_any, pht('%s / Any', $label)); + $this->assertEqual($expect_all, $can_all, pht('%s / All', $label)); + } + } + + private function moveToColumn( PhabricatorUser $viewer, PhabricatorProject $board, diff --git a/src/applications/project/policyrule/PhabricatorProjectsAllPolicyRule.php b/src/applications/project/policyrule/PhabricatorProjectsAllPolicyRule.php new file mode 100644 index 0000000000..25b7cf7c4e --- /dev/null +++ b/src/applications/project/policyrule/PhabricatorProjectsAllPolicyRule.php @@ -0,0 +1,29 @@ +getMemberships($viewer->getPHID()); + foreach ($value as $project_phid) { + if (empty($memberships[$project_phid])) { + return false; + } + } + + return true; + } + + public function getRuleOrder() { + return 205; + } + +} diff --git a/src/applications/project/policyrule/PhabricatorProjectsBasePolicyRule.php b/src/applications/project/policyrule/PhabricatorProjectsBasePolicyRule.php new file mode 100644 index 0000000000..fed217779b --- /dev/null +++ b/src/applications/project/policyrule/PhabricatorProjectsBasePolicyRule.php @@ -0,0 +1,64 @@ +memberships, $viewer_phid, array()); + } + + public function willApplyRules( + PhabricatorUser $viewer, + array $values, + array $objects) { + + $values = array_unique(array_filter(array_mergev($values))); + if (!$values) { + return; + } + + $projects = id(new PhabricatorProjectQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->withMemberPHIDs(array($viewer->getPHID())) + ->withPHIDs($values) + ->execute(); + foreach ($projects as $project) { + $this->memberships[$viewer->getPHID()][$project->getPHID()] = true; + } + } + + public function getValueControlType() { + return self::CONTROL_TYPE_TOKENIZER; + } + + public function getValueControlTemplate() { + $datasource = id(new PhabricatorProjectDatasource()) + ->setParameters( + array( + 'policy' => 1, + )); + + return $this->getDatasourceTemplate($datasource); + } + + public function getValueForStorage($value) { + PhutilTypeSpec::newFromString('list')->check($value); + return array_values($value); + } + + public function getValueForDisplay(PhabricatorUser $viewer, $value) { + $handles = id(new PhabricatorHandleQuery()) + ->setViewer($viewer) + ->withPHIDs($value) + ->execute(); + + return mpull($handles, 'getFullName', 'getPHID'); + } + + public function ruleHasEffect($value) { + return (bool)$value; + } + +} diff --git a/src/applications/project/policyrule/PhabricatorProjectsPolicyRule.php b/src/applications/project/policyrule/PhabricatorProjectsPolicyRule.php index 3977b542c1..b7ad734641 100644 --- a/src/applications/project/policyrule/PhabricatorProjectsPolicyRule.php +++ b/src/applications/project/policyrule/PhabricatorProjectsPolicyRule.php @@ -1,32 +1,10 @@ setViewer(PhabricatorUser::getOmnipotentUser()) - ->withMemberPHIDs(array($viewer->getPHID())) - ->withPHIDs($values) - ->execute(); - foreach ($projects as $project) { - $this->memberships[$viewer->getPHID()][$project->getPHID()] = true; - } + return pht('members of any project'); } public function applyRule( @@ -34,8 +12,9 @@ final class PhabricatorProjectsPolicyRule $value, PhabricatorPolicyInterface $object) { + $memberships = $this->getMemberships($viewer->getPHID()); foreach ($value as $project_phid) { - if (isset($this->memberships[$viewer->getPHID()][$project_phid])) { + if (isset($memberships[$project_phid])) { return true; } } @@ -43,40 +22,8 @@ final class PhabricatorProjectsPolicyRule return false; } - public function getValueControlType() { - return self::CONTROL_TYPE_TOKENIZER; - } - - public function getValueControlTemplate() { - $datasource = id(new PhabricatorProjectDatasource()) - ->setParameters( - array( - 'policy' => 1, - )); - - return $this->getDatasourceTemplate($datasource); - } - public function getRuleOrder() { return 200; } - public function getValueForStorage($value) { - PhutilTypeSpec::newFromString('list')->check($value); - return array_values($value); - } - - public function getValueForDisplay(PhabricatorUser $viewer, $value) { - $handles = id(new PhabricatorHandleQuery()) - ->setViewer($viewer) - ->withPHIDs($value) - ->execute(); - - return mpull($handles, 'getFullName', 'getPHID'); - } - - public function ruleHasEffect($value) { - return (bool)$value; - } - }