Page MenuHomePhabricator

D14869.diff
No OneTemporary

D14869.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2859,6 +2859,7 @@
'PhabricatorProjectMemberOfProjectEdgeType' => 'applications/project/edge/PhabricatorProjectMemberOfProjectEdgeType.php',
'PhabricatorProjectMembersDatasource' => 'applications/project/typeahead/PhabricatorProjectMembersDatasource.php',
'PhabricatorProjectMembersEditController' => 'applications/project/controller/PhabricatorProjectMembersEditController.php',
+ 'PhabricatorProjectMembersPolicyRule' => 'applications/project/policyrule/PhabricatorProjectMembersPolicyRule.php',
'PhabricatorProjectMembersRemoveController' => 'applications/project/controller/PhabricatorProjectMembersRemoveController.php',
'PhabricatorProjectMoveController' => 'applications/project/controller/PhabricatorProjectMoveController.php',
'PhabricatorProjectNoProjectsDatasource' => 'applications/project/typeahead/PhabricatorProjectNoProjectsDatasource.php',
@@ -7195,6 +7196,7 @@
'PhabricatorProjectMemberOfProjectEdgeType' => 'PhabricatorEdgeType',
'PhabricatorProjectMembersDatasource' => 'PhabricatorTypeaheadCompositeDatasource',
'PhabricatorProjectMembersEditController' => 'PhabricatorProjectController',
+ 'PhabricatorProjectMembersPolicyRule' => 'PhabricatorPolicyRule',
'PhabricatorProjectMembersRemoveController' => 'PhabricatorProjectController',
'PhabricatorProjectMoveController' => 'PhabricatorProjectController',
'PhabricatorProjectNoProjectsDatasource' => 'PhabricatorTypeaheadDatasource',
diff --git a/src/applications/policy/filter/PhabricatorPolicyFilter.php b/src/applications/policy/filter/PhabricatorPolicyFilter.php
--- a/src/applications/policy/filter/PhabricatorPolicyFilter.php
+++ b/src/applications/policy/filter/PhabricatorPolicyFilter.php
@@ -608,6 +608,11 @@
$rules = PhabricatorPolicyQuery::getObjectPolicyRules(null);
+ // Make sure we have clean, empty policy rule objects.
+ foreach ($rules as $key => $rule) {
+ $rules[$key] = clone $rule;
+ }
+
$results = array();
foreach ($map as $key => $object_list) {
$rule = idx($rules, $key);
diff --git a/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php b/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php
--- a/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php
+++ b/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php
@@ -287,7 +287,6 @@
// In this second case, set the name first and then the slugs separately.
$name2 = 'slugproject2';
-
$xactions = array();
$xactions[] = id(new PhabricatorProjectTransaction())
@@ -396,6 +395,51 @@
$this->assertTrue((bool)$caught);
}
+ public function testProjectMembersVisibility() {
+ // This is primarily testing that you can create a project and set the
+ // visibility or edit policy to "Project Members" immediately.
+
+ $user1 = $this->createUser();
+ $user1->save();
+
+ $user2 = $this->createUser();
+ $user2->save();
+
+ $project = PhabricatorProject::initializeNewProject($user1);
+ $name = pht('Test Project %d', mt_rand());
+
+ $xactions = array();
+
+ $xactions[] = id(new PhabricatorProjectTransaction())
+ ->setTransactionType(PhabricatorProjectTransaction::TYPE_NAME)
+ ->setNewValue($name);
+
+ $xactions[] = id(new PhabricatorProjectTransaction())
+ ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
+ ->setNewValue(
+ id(new PhabricatorProjectMembersPolicyRule())
+ ->getObjectPolicyFullKey());
+
+ $edge_type = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST;
+
+ $xactions[] = id(new PhabricatorProjectTransaction())
+ ->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
+ ->setMetadataValue('edge:type', $edge_type)
+ ->setNewValue(
+ array(
+ '=' => array($user1->getPHID() => $user1->getPHID()),
+ ));
+
+ $this->applyTransactions($project, $user1, $xactions);
+
+ $this->assertTrue((bool)$this->refreshProject($project, $user1));
+ $this->assertFalse((bool)$this->refreshProject($project, $user2));
+
+ $this->leaveProject($project, $user1);
+
+ $this->assertFalse((bool)$this->refreshProject($project, $user1));
+ }
+
public function testParentProject() {
$user = $this->createUser();
$user->save();
diff --git a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
--- a/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
+++ b/src/applications/project/editor/PhabricatorProjectTransactionEditor.php
@@ -692,4 +692,53 @@
return $slugs;
}
+ protected function adjustObjectForPolicyChecks(
+ PhabricatorLiskDAO $object,
+ array $xactions) {
+
+ $copy = parent::adjustObjectForPolicyChecks($object, $xactions);
+
+ $type_edge = PhabricatorTransactions::TYPE_EDGE;
+ $edgetype_member = PhabricatorProjectProjectHasMemberEdgeType::EDGECONST;
+
+ $member_xaction = null;
+ foreach ($xactions as $xaction) {
+ if ($xaction->getTransactionType() !== $type_edge) {
+ continue;
+ }
+
+ $edgetype = $xaction->getMetadataValue('edge:type');
+ if ($edgetype !== $edgetype_member) {
+ continue;
+ }
+
+ $member_xaction = $xaction;
+ }
+
+ if ($member_xaction) {
+ $object_phid = $object->getPHID();
+
+ if ($object_phid) {
+ $members = PhabricatorEdgeQuery::loadDestinationPHIDs(
+ $object_phid,
+ PhabricatorProjectProjectHasMemberEdgeType::EDGECONST);
+ } else {
+ $members = array();
+ }
+
+ $clone_xaction = clone $member_xaction;
+ $hint = $this->getPHIDTransactionNewValue($clone_xaction, $members);
+ $rule = new PhabricatorProjectMembersPolicyRule();
+
+ $hint = array_fuse($hint);
+
+ PhabricatorPolicyRule::passTransactionHintToRule(
+ $copy,
+ $rule,
+ $hint);
+ }
+
+ return $copy;
+ }
+
}
diff --git a/src/applications/project/policyrule/PhabricatorProjectMembersPolicyRule.php b/src/applications/project/policyrule/PhabricatorProjectMembersPolicyRule.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/policyrule/PhabricatorProjectMembersPolicyRule.php
@@ -0,0 +1,97 @@
+<?php
+
+final class PhabricatorProjectMembersPolicyRule extends PhabricatorPolicyRule {
+
+ private $memberships = array();
+
+ public function getRuleDescription() {
+ return pht('members of project');
+ }
+
+ public function willApplyRules(
+ PhabricatorUser $viewer,
+ array $values,
+ array $objects) {
+
+ $viewer_phid = $viewer->getPHID();
+ if (!$viewer_phid) {
+ return;
+ }
+
+ if (empty($this->memberships[$viewer_phid])) {
+ $this->memberships[$viewer_phid] = array();
+ }
+
+ foreach ($objects as $key => $object) {
+ $cache = $this->getTransactionHint($object);
+ if ($cache === null) {
+ continue;
+ }
+
+ unset($objects[$key]);
+
+ if (isset($cache[$viewer_phid])) {
+ $this->memberships[$viewer_phid][$object->getPHID()] = true;
+ }
+ }
+
+ if (!$objects) {
+ return;
+ }
+
+ $object_phids = mpull($objects, 'getPHID');
+ $edge_query = id(new PhabricatorEdgeQuery())
+ ->withSourcePHIDs(array($viewer_phid))
+ ->withDestinationPHIDs($object_phids)
+ ->withEdgeTypes(
+ array(
+ PhabricatorProjectMemberOfProjectEdgeType::EDGECONST,
+ ));
+ $edge_query->execute();
+
+ $memberships = $edge_query->getDestinationPHIDs();
+ if (!$memberships) {
+ return;
+ }
+
+ $this->memberships[$viewer_phid] += array_fill_keys($memberships, true);
+ }
+
+ public function applyRule(
+ PhabricatorUser $viewer,
+ $value,
+ PhabricatorPolicyInterface $object) {
+ $viewer_phid = $viewer->getPHID();
+ if (!$viewer_phid) {
+ return false;
+ }
+
+ $memberships = idx($this->memberships, $viewer_phid);
+ return isset($memberships[$object->getPHID()]);
+ }
+
+ public function getValueControlType() {
+ return self::CONTROL_TYPE_NONE;
+ }
+
+ public function canApplyToObject(PhabricatorPolicyInterface $object) {
+ return ($object instanceof PhabricatorProject);
+ }
+
+ public function getObjectPolicyKey() {
+ return 'project.members';
+ }
+
+ public function getObjectPolicyName() {
+ return pht('Project Members');
+ }
+
+ public function getObjectPolicyIcon() {
+ return 'fa-users';
+ }
+
+ public function getPolicyExplanation() {
+ return pht('Project members can take this action.');
+ }
+
+}
diff --git a/src/applications/project/query/PhabricatorProjectQuery.php b/src/applications/project/query/PhabricatorProjectQuery.php
--- a/src/applications/project/query/PhabricatorProjectQuery.php
+++ b/src/applications/project/query/PhabricatorProjectQuery.php
@@ -95,10 +95,6 @@
return $this;
}
- public function getProperty() {
- return $this->property;
- }
-
public function withDepthBetween($min, $max) {
$this->minDepth = $min;
$this->maxDepth = $max;

File Metadata

Mime Type
text/plain
Expires
Sat, Mar 8, 4:30 AM (2 w, 1 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7278107
Default Alt Text
D14869.diff (9 KB)

Event Timeline