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

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

+105 -3
+14 -1
src/applications/files/controller/PhabricatorFileInfoController.php
··· 27 27 ->withObjectPHIDs(array($phid)) 28 28 ->execute(); 29 29 30 - $this->loadHandles(array($file->getAuthorPHID())); 30 + $handle_phids = array_merge( 31 + array($file->getAuthorPHID()), 32 + $file->getObjectPHIDs()); 33 + 34 + $this->loadHandles($handle_phids); 31 35 $header = id(new PHUIHeaderView()) 32 36 ->setHeader($file->getName()); 33 37 ··· 206 210 $value); 207 211 } 208 212 } 213 + 214 + $phids = $file->getObjectPHIDs(); 215 + if ($phids) { 216 + $view->addSectionHeader(pht('Attached')); 217 + $view->addProperty( 218 + pht('Attached To'), 219 + $this->renderHandlesForPHIDs($phids)); 220 + } 221 + 209 222 210 223 if ($file->isViewableImage()) { 211 224
+42 -1
src/applications/files/query/PhabricatorFileQuery.php
··· 104 104 $this->buildOrderClause($conn_r), 105 105 $this->buildLimitClause($conn_r)); 106 106 107 - return $table->loadAllFromArray($data); 107 + $files = $table->loadAllFromArray($data); 108 + 109 + if (!$files) { 110 + return $files; 111 + } 112 + 113 + // We need to load attached objects to perform policy checks for files. 114 + // First, load the edges. 115 + 116 + $edge_type = PhabricatorEdgeConfig::TYPE_FILE_HAS_OBJECT; 117 + $phids = mpull($files, 'getPHID'); 118 + $edges = id(new PhabricatorEdgeQuery()) 119 + ->withSourcePHIDs($phids) 120 + ->withEdgeTypes(array($edge_type)) 121 + ->execute(); 122 + 123 + $object_phids = array(); 124 + foreach ($files as $file) { 125 + $phids = array_keys($edges[$file->getPHID()][$edge_type]); 126 + $file->attachObjectPHIDs($phids); 127 + foreach ($phids as $phid) { 128 + $object_phids[$phid] = true; 129 + } 130 + } 131 + 132 + // Now, load the objects. 133 + 134 + $objects = array(); 135 + if ($object_phids) { 136 + $objects = id(new PhabricatorObjectQuery()) 137 + ->setViewer($this->getViewer()) 138 + ->withPHIDs($object_phids) 139 + ->execute(); 140 + $objects = mpull($objects, null, 'getPHID'); 141 + } 142 + 143 + foreach ($files as $file) { 144 + $file_objects = array_select_keys($objects, $file->getObjectPHIDs()); 145 + $file->attachObjects($file_objects); 146 + } 147 + 148 + return $files; 108 149 } 109 150 110 151 private function buildJoinClause(AphrontDatabaseConnection $conn_r) {
+49 -1
src/applications/files/storage/PhabricatorFile.php
··· 31 31 protected $ttl; 32 32 protected $isExplicitUpload = 1; 33 33 34 + private $objects = self::ATTACHABLE; 35 + private $objectPHIDs = self::ATTACHABLE; 36 + 34 37 public function getConfiguration() { 35 38 return array( 36 39 self::CONFIG_AUX_PHID => true, ··· 803 806 ->save(); 804 807 unset($unguarded); 805 808 809 + $file->attachObjectPHIDs(array()); 810 + $file->attachObjects(array()); 811 + 806 812 $files[$name] = $file; 807 813 } 808 814 ··· 821 827 return idx(self::loadBuiltins($user, array($name)), $name); 822 828 } 823 829 830 + public function getObjects() { 831 + return $this->assertAttached($this->objects); 832 + } 833 + 834 + public function attachObjects(array $objects) { 835 + $this->objects = $objects; 836 + return $this; 837 + } 838 + 839 + public function getObjectPHIDs() { 840 + return $this->assertAttached($this->objectPHIDs); 841 + } 842 + 843 + public function attachObjectPHIDs(array $object_phids) { 844 + $this->objectPHIDs = $object_phids; 845 + return $this; 846 + } 847 + 824 848 825 849 /* -( PhabricatorPolicyInterface Implementation )-------------------------- */ 826 850 ··· 838 862 } 839 863 840 864 public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 865 + $viewer_phid = $viewer->getPHID(); 866 + if ($viewer_phid) { 867 + if ($this->getAuthorPHID() == $viewer_phid) { 868 + return true; 869 + } 870 + } 871 + 872 + switch ($capability) { 873 + case PhabricatorPolicyCapability::CAN_VIEW: 874 + // If you can see any object this file is attached to, you can see 875 + // the file. 876 + return (count($this->getObjects()) > 0); 877 + } 878 + 841 879 return false; 842 880 } 843 881 844 882 public function describeAutomaticCapability($capability) { 845 - return null; 883 + $out = array(); 884 + $out[] = pht('The user who uploaded a file can always view and edit it.'); 885 + switch ($capability) { 886 + case PhabricatorPolicyCapability::CAN_VIEW: 887 + $out[] = pht( 888 + 'Files attached to objects are visible to users who can view '. 889 + 'those objects.'); 890 + break; 891 + } 892 + 893 + return $out; 846 894 } 847 895 848 896