Page MenuHomePhabricator

D3219.id6214.diff
No OneTemporary

D3219.id6214.diff

Index: resources/sql/patches/policy-project.sql
===================================================================
--- /dev/null
+++ resources/sql/patches/policy-project.sql
@@ -0,0 +1,8 @@
+ALTER TABLE `{$NAMESPACE}_project`.`project`
+ ADD `viewPolicy` varchar(64) COLLATE utf8_bin;
+
+ALTER TABLE `{$NAMESPACE}_project`.`project`
+ ADD `editPolicy` varchar(64) COLLATE utf8_bin;
+
+ALTER TABLE `{$NAMESPACE}_project`.`project`
+ ADD `joinPolicy` varchar(64) COLLATE utf8_bin;
Index: src/applications/project/query/PhabricatorProjectQuery.php
===================================================================
--- src/applications/project/query/PhabricatorProjectQuery.php
+++ src/applications/project/query/PhabricatorProjectQuery.php
@@ -68,18 +68,28 @@
$table = new PhabricatorProject();
$conn_r = $table->establishConnection('r');
+ // NOTE: Because visibility checks for projects depend on whether or not
+ // the user is a project member, we always load their membership.
+
$data = queryfx_all(
$conn_r,
- 'SELECT p.* FROM %T p %Q %Q %Q %Q %Q',
+ 'SELECT p.*, vm.dst viewerIsMember FROM %T p %Q %Q %Q %Q %Q',
$table->getTableName(),
$this->buildJoinClause($conn_r),
$this->buildWhereClause($conn_r),
$this->buildGroupClause($conn_r),
- 'ORDER BY name',
+ $this->buildOrderClause($conn_r),
$this->buildLimitClause($conn_r));
$projects = $table->loadAllFromArray($data);
+ $viewer_phid = $this->getViewer()->getPHID();
+ foreach ($data as $row) {
+ $projects[$row['id']]->setIsUserMember(
+ $viewer_phid,
+ ($row['viewerIsMember'] !== null));
+ }
+
if ($projects && $this->needMembers) {
$etype = PhabricatorEdgeConfig::TYPE_PROJ_MEMBER;
$members = id(new PhabricatorEdgeQuery())
@@ -139,8 +149,7 @@
if ($this->memberPHIDs) {
$where[] = qsprintf(
$conn_r,
- 'e.type = %s AND e.dst IN (%Ls)',
- PhabricatorEdgeConfig::TYPE_PROJ_MEMBER,
+ 'e.dst IN (%Ls)',
$this->memberPHIDs);
}
@@ -160,11 +169,19 @@
private function buildJoinClause($conn_r) {
$joins = array();
+ $joins[] = qsprintf(
+ $conn_r,
+ 'LEFT JOIN %T vm ON vm.src = p.phid AND vm.type = %d AND vm.dst = %s',
+ PhabricatorEdgeConfig::TABLE_NAME_EDGE,
+ PhabricatorEdgeConfig::TYPE_PROJ_MEMBER,
+ $this->getViewer()->getPHID());
+
if ($this->memberPHIDs) {
$joins[] = qsprintf(
$conn_r,
- 'JOIN %T e ON e.src = p.phid',
- PhabricatorEdgeConfig::TABLE_NAME_EDGE);
+ 'JOIN %T e ON e.src = p.phid AND e.type = %d',
+ PhabricatorEdgeConfig::TABLE_NAME_EDGE,
+ PhabricatorEdgeConfig::TYPE_PROJ_MEMBER);
}
return implode(' ', $joins);
Index: src/applications/project/storage/PhabricatorProject.php
===================================================================
--- src/applications/project/storage/PhabricatorProject.php
+++ src/applications/project/storage/PhabricatorProject.php
@@ -26,23 +26,69 @@
protected $subprojectPHIDs = array();
protected $phrictionSlug;
+ protected $viewPolicy;
+ protected $editPolicy;
+ protected $joinPolicy;
+
private $subprojectsNeedUpdate;
private $memberPHIDs;
+ private $sparseMembers = array();
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ PhabricatorPolicyCapability::CAN_JOIN,
);
}
public function getPolicy($capability) {
- return PhabricatorPolicies::POLICY_USER;
+ switch ($capability) {
+ case PhabricatorPolicyCapability::CAN_VIEW:
+ return $this->getViewPolicy();
+ case PhabricatorPolicyCapability::CAN_EDIT:
+ return $this->getEditPolicy();
+ case PhabricatorPolicyCapability::CAN_JOIN:
+ return $this->getJoinPolicy();
+ }
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
+
+ switch ($capability) {
+ case PhabricatorPolicyCapability::CAN_VIEW:
+ if ($this->isUserMember($viewer->getPHID())) {
+ // Project members can always view a project.
+ return true;
+ }
+ break;
+ case PhabricatorPolicyCapability::CAN_EDIT:
+ break;
+ case PhabricatorPolicyCapability::CAN_JOIN:
+ $can_edit = PhabricatorPolicyCapability::CAN_EDIT;
+ if (PhabricatorPolicyFilter::hasCapability($viewer, $this, $can_edit)) {
+ // Project editors can always join a project.
+ return true;
+ }
+ break;
+ }
+
return false;
}
+ public function isUserMember($user_phid) {
+ if (!isset($this->sparseMembers[$user_phid])) {
+ throw new Exception(
+ "Call setIsUserMember() before isUserMember()!");
+ }
+ return $this->sparseMembers[$user_phid];
+ }
+
+ public function setIsUserMember($user_phid, $is_member) {
+ $this->sparseMembers[$user_phid] = $is_member;
+ return $this;
+ }
+
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
Index: src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
===================================================================
--- src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
+++ src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php
@@ -944,6 +944,10 @@
'type' => 'php',
'name' => $this->getPatchPath('migrate-project-edges.php'),
),
+ 'policy-project.sql' => array(
+ 'type' => 'sql',
+ 'name' => $this->getPatchPath('policy-project.sql'),
+ ),
);
}

File Metadata

Mime Type
text/plain
Expires
Sun, Mar 30, 11:21 PM (1 w, 6 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7727634
Default Alt Text
D3219.id6214.diff (5 KB)

Event Timeline