Provide an attached-to-visible-object policy exception for files
Summary: Ref T603. This uses the existing edges (from Conpherence) to record that a file is attached to an object, and uses those edges to create a policy exception: if you can view an attached object, you can view a file. I'm going to combine this with restrictive defaults to satisfy the other half of the equation (that files you attach to a conpherence usually shouldn't be public by default). Test Plan: - Loaded `/files/`. - Uploaded a file to a Conpherence, looked at it in Files, saw the attachment. Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T603 Differential Revision: https://secure.phabricator.com/D7182
This commit is contained in:
@@ -27,7 +27,11 @@ final class PhabricatorFileInfoController extends PhabricatorFileController {
|
|||||||
->withObjectPHIDs(array($phid))
|
->withObjectPHIDs(array($phid))
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
$this->loadHandles(array($file->getAuthorPHID()));
|
$handle_phids = array_merge(
|
||||||
|
array($file->getAuthorPHID()),
|
||||||
|
$file->getObjectPHIDs());
|
||||||
|
|
||||||
|
$this->loadHandles($handle_phids);
|
||||||
$header = id(new PHUIHeaderView())
|
$header = id(new PHUIHeaderView())
|
||||||
->setHeader($file->getName());
|
->setHeader($file->getName());
|
||||||
|
|
||||||
@@ -207,6 +211,15 @@ final class PhabricatorFileInfoController extends PhabricatorFileController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$phids = $file->getObjectPHIDs();
|
||||||
|
if ($phids) {
|
||||||
|
$view->addSectionHeader(pht('Attached'));
|
||||||
|
$view->addProperty(
|
||||||
|
pht('Attached To'),
|
||||||
|
$this->renderHandlesForPHIDs($phids));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($file->isViewableImage()) {
|
if ($file->isViewableImage()) {
|
||||||
|
|
||||||
$image = phutil_tag(
|
$image = phutil_tag(
|
||||||
|
|||||||
@@ -104,7 +104,48 @@ final class PhabricatorFileQuery
|
|||||||
$this->buildOrderClause($conn_r),
|
$this->buildOrderClause($conn_r),
|
||||||
$this->buildLimitClause($conn_r));
|
$this->buildLimitClause($conn_r));
|
||||||
|
|
||||||
return $table->loadAllFromArray($data);
|
$files = $table->loadAllFromArray($data);
|
||||||
|
|
||||||
|
if (!$files) {
|
||||||
|
return $files;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to load attached objects to perform policy checks for files.
|
||||||
|
// First, load the edges.
|
||||||
|
|
||||||
|
$edge_type = PhabricatorEdgeConfig::TYPE_FILE_HAS_OBJECT;
|
||||||
|
$phids = mpull($files, 'getPHID');
|
||||||
|
$edges = id(new PhabricatorEdgeQuery())
|
||||||
|
->withSourcePHIDs($phids)
|
||||||
|
->withEdgeTypes(array($edge_type))
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$object_phids = array();
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$phids = array_keys($edges[$file->getPHID()][$edge_type]);
|
||||||
|
$file->attachObjectPHIDs($phids);
|
||||||
|
foreach ($phids as $phid) {
|
||||||
|
$object_phids[$phid] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now, load the objects.
|
||||||
|
|
||||||
|
$objects = array();
|
||||||
|
if ($object_phids) {
|
||||||
|
$objects = id(new PhabricatorObjectQuery())
|
||||||
|
->setViewer($this->getViewer())
|
||||||
|
->withPHIDs($object_phids)
|
||||||
|
->execute();
|
||||||
|
$objects = mpull($objects, null, 'getPHID');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$file_objects = array_select_keys($objects, $file->getObjectPHIDs());
|
||||||
|
$file->attachObjects($file_objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $files;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildJoinClause(AphrontDatabaseConnection $conn_r) {
|
private function buildJoinClause(AphrontDatabaseConnection $conn_r) {
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
|||||||
protected $ttl;
|
protected $ttl;
|
||||||
protected $isExplicitUpload = 1;
|
protected $isExplicitUpload = 1;
|
||||||
|
|
||||||
|
private $objects = self::ATTACHABLE;
|
||||||
|
private $objectPHIDs = self::ATTACHABLE;
|
||||||
|
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
return array(
|
return array(
|
||||||
self::CONFIG_AUX_PHID => true,
|
self::CONFIG_AUX_PHID => true,
|
||||||
@@ -803,6 +806,9 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
|||||||
->save();
|
->save();
|
||||||
unset($unguarded);
|
unset($unguarded);
|
||||||
|
|
||||||
|
$file->attachObjectPHIDs(array());
|
||||||
|
$file->attachObjects(array());
|
||||||
|
|
||||||
$files[$name] = $file;
|
$files[$name] = $file;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -821,6 +827,24 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
|||||||
return idx(self::loadBuiltins($user, array($name)), $name);
|
return idx(self::loadBuiltins($user, array($name)), $name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getObjects() {
|
||||||
|
return $this->assertAttached($this->objects);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attachObjects(array $objects) {
|
||||||
|
$this->objects = $objects;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getObjectPHIDs() {
|
||||||
|
return $this->assertAttached($this->objectPHIDs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attachObjectPHIDs(array $object_phids) {
|
||||||
|
$this->objectPHIDs = $object_phids;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
|
/* -( PhabricatorPolicyInterface Implementation )-------------------------- */
|
||||||
|
|
||||||
@@ -838,11 +862,35 @@ final class PhabricatorFile extends PhabricatorFileDAO
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
||||||
|
$viewer_phid = $viewer->getPHID();
|
||||||
|
if ($viewer_phid) {
|
||||||
|
if ($this->getAuthorPHID() == $viewer_phid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($capability) {
|
||||||
|
case PhabricatorPolicyCapability::CAN_VIEW:
|
||||||
|
// If you can see any object this file is attached to, you can see
|
||||||
|
// the file.
|
||||||
|
return (count($this->getObjects()) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function describeAutomaticCapability($capability) {
|
public function describeAutomaticCapability($capability) {
|
||||||
return null;
|
$out = array();
|
||||||
|
$out[] = pht('The user who uploaded a file can always view and edit it.');
|
||||||
|
switch ($capability) {
|
||||||
|
case PhabricatorPolicyCapability::CAN_VIEW:
|
||||||
|
$out[] = pht(
|
||||||
|
'Files attached to objects are visible to users who can view '.
|
||||||
|
'those objects.');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user