Skip to content

Commit c4abf16

Browse files
author
epriestley
committed
Fix some file policy issues and add a "Query Workspace"
Summary: Ref T603. Several issues here: 1. Currently, `FileQuery` does not actually respect object attachment edges when doing policy checks. Everything else works fine, but this was missing an `array_keys()`. 2. Once that's fixed, we hit a bunch of recursion issues. For example, when loading a User we load the profile picture, and then that loads the User, and that loads the profile picture, etc. 3. Introduce a "Query Workspace", which holds objects we know we've loaded and know we can see but haven't finished filtering and/or attaching data to. This allows subqueries to look up objects instead of querying for them. - We can probably generalize this a bit to make a few other queries more efficient. Pholio currently has a similar (but less general) "mock cache". However, it's keyed by ID instead of PHID so it's not easy to reuse this right now. This is a bit complex for the problem being solved, but I think it's the cleanest approach and I believe the primitive will be useful in the future. Test Plan: Looked at pastes, macros, mocks and projects as a logged-in and logged-out user. Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T603 Differential Revision: https://secure.phabricator.com/D7309
1 parent 073cb0e commit c4abf16

File tree

10 files changed

+238
-62
lines changed

10 files changed

+238
-62
lines changed

src/applications/files/query/PhabricatorFileQuery.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,14 @@ protected function loadPage() {
128128
$object_phids[$phid] = true;
129129
}
130130
}
131+
$object_phids = array_keys($object_phids);
131132

132133
// Now, load the objects.
133134

134135
$objects = array();
135136
if ($object_phids) {
136137
$objects = id(new PhabricatorObjectQuery())
138+
->setParentQuery($this)
137139
->setViewer($this->getViewer())
138140
->withPHIDs($object_phids)
139141
->execute();

src/applications/files/storage/PhabricatorFile.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,8 +764,10 @@ public static function loadBuiltins(PhabricatorUser $user, array $names) {
764764
);
765765
}
766766

767+
// NOTE: Anyone is allowed to access builtin files.
768+
767769
$files = id(new PhabricatorFileQuery())
768-
->setViewer($user)
770+
->setViewer(PhabricatorUser::getOmnipotentUser())
769771
->withTransforms($specs)
770772
->execute();
771773

src/applications/macro/query/PhabricatorMacroQuery.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,11 @@ protected function buildWhereClause(AphrontDatabaseConnection $conn) {
191191
return $this->formatWhereClause($where);
192192
}
193193

194-
protected function willFilterPage(array $macros) {
194+
protected function didFilterPage(array $macros) {
195195
$file_phids = mpull($macros, 'getFilePHID');
196196
$files = id(new PhabricatorFileQuery())
197197
->setViewer($this->getViewer())
198+
->setParentQuery($this)
198199
->withPHIDs($file_phids)
199200
->execute();
200201
$files = mpull($files, null, 'getPHID');

src/applications/paste/query/PhabricatorPasteQuery.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ protected function loadPage() {
8787
return $pastes;
8888
}
8989

90-
protected function willFilterPage(array $pastes) {
90+
protected function didFilterPage(array $pastes) {
9191
if ($this->needRawContent) {
9292
$pastes = $this->loadRawContent($pastes);
9393
}
@@ -163,6 +163,7 @@ private function getContentCacheKey(PhabricatorPaste $paste) {
163163
private function loadRawContent(array $pastes) {
164164
$file_phids = mpull($pastes, 'getFilePHID');
165165
$files = id(new PhabricatorFileQuery())
166+
->setParentQuery($this)
166167
->setViewer($this->getViewer())
167168
->withPHIDs($file_phids)
168169
->execute();

src/applications/people/query/PhabricatorPeopleQuery.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,10 @@ public function loadPage() {
113113
$table->putInSet(new LiskDAOSet());
114114
}
115115

116-
$users = $table->loadAllFromArray($data);
116+
return $table->loadAllFromArray($data);
117+
}
117118

119+
protected function didFilterPage(array $users) {
118120
if ($this->needProfile) {
119121
$user_list = mpull($users, null, 'getPHID');
120122
$profiles = new PhabricatorUserProfile();
@@ -138,6 +140,7 @@ public function loadPage() {
138140
$user_profile_file_phids = array_filter($user_profile_file_phids);
139141
if ($user_profile_file_phids) {
140142
$files = id(new PhabricatorFileQuery())
143+
->setParentQuery($this)
141144
->setViewer($this->getViewer())
142145
->withPHIDs($user_profile_file_phids)
143146
->execute();

src/applications/phid/query/PhabricatorObjectQuery.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,27 @@ private function loadObjectsByName(array $types, array $names) {
104104
}
105105

106106
private function loadObjectsByPHID(array $types, array $phids) {
107+
$results = array();
108+
109+
$workspace = $this->getObjectsFromWorkspace($phids);
110+
111+
foreach ($phids as $key => $phid) {
112+
if (isset($workspace[$phid])) {
113+
$results[$phid] = $workspace[$phid];
114+
unset($phids[$key]);
115+
}
116+
}
117+
118+
if (!$phids) {
119+
return $results;
120+
}
121+
107122
$groups = array();
108123
foreach ($phids as $phid) {
109124
$type = phid_get_type($phid);
110125
$groups[$type][] = $phid;
111126
}
112127

113-
$results = array();
114128
foreach ($groups as $type => $group) {
115129
if (isset($types[$type])) {
116130
$objects = $types[$type]->loadObjects($this, $group);

src/applications/pholio/query/PholioImageQuery.php

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,37 @@ private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
103103
protected function willFilterPage(array $images) {
104104
assert_instances_of($images, 'PholioImage');
105105

106+
if ($this->getMockCache()) {
107+
$mocks = $this->getMockCache();
108+
} else {
109+
$mock_ids = mpull($images, 'getMockID');
110+
// DO NOT set needImages to true; recursion results!
111+
$mocks = id(new PholioMockQuery())
112+
->setViewer($this->getViewer())
113+
->withIDs($mock_ids)
114+
->execute();
115+
$mocks = mpull($mocks, null, 'getID');
116+
}
117+
foreach ($images as $index => $image) {
118+
$mock = idx($mocks, $image->getMockID());
119+
if ($mock) {
120+
$image->attachMock($mock);
121+
} else {
122+
// mock is missing or we can't see it
123+
unset($images[$index]);
124+
}
125+
}
126+
127+
return $images;
128+
}
129+
130+
protected function didFilterPage(array $images) {
131+
assert_instances_of($images, 'PholioImage');
132+
106133
$file_phids = mpull($images, 'getFilePHID');
107134

108135
$all_files = id(new PhabricatorFileQuery())
136+
->setParentQuery($this)
109137
->setViewer($this->getViewer())
110138
->withPHIDs($file_phids)
111139
->execute();
@@ -130,27 +158,6 @@ protected function willFilterPage(array $images) {
130158
}
131159
}
132160

133-
if ($this->getMockCache()) {
134-
$mocks = $this->getMockCache();
135-
} else {
136-
$mock_ids = mpull($images, 'getMockID');
137-
// DO NOT set needImages to true; recursion results!
138-
$mocks = id(new PholioMockQuery())
139-
->setViewer($this->getViewer())
140-
->withIDs($mock_ids)
141-
->execute();
142-
$mocks = mpull($mocks, null, 'getID');
143-
}
144-
foreach ($images as $index => $image) {
145-
$mock = idx($mocks, $image->getMockID());
146-
if ($mock) {
147-
$image->attachMock($mock);
148-
} else {
149-
// mock is missing or we can't see it
150-
unset($images[$index]);
151-
}
152-
}
153-
154161
return $images;
155162
}
156163

src/applications/project/controller/PhabricatorProjectProfileController.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ final class PhabricatorProjectProfileController
66
private $id;
77
private $page;
88

9+
public function shouldAllowPublic() {
10+
return true;
11+
}
12+
913
public function willProcessRequest(array $data) {
1014
$this->id = idx($data, 'id');
1115
$this->page = idx($data, 'page');

src/applications/project/query/PhabricatorProjectQuery.php

Lines changed: 40 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -114,50 +114,55 @@ protected function loadPage() {
114114
($row['viewerIsMember'] !== null));
115115
}
116116
}
117+
}
117118

118-
if ($this->needProfiles) {
119-
$profiles = id(new PhabricatorProjectProfile())->loadAllWhere(
120-
'projectPHID IN (%Ls)',
121-
mpull($projects, 'getPHID'));
122-
$profiles = mpull($profiles, null, 'getProjectPHID');
123-
124-
$default = null;
125-
126-
if ($profiles) {
127-
$file_phids = mpull($profiles, 'getProfileImagePHID');
128-
$files = id(new PhabricatorFileQuery())
129-
->setViewer($this->getViewer())
130-
->withPHIDs($file_phids)
131-
->execute();
132-
$files = mpull($files, null, 'getPHID');
133-
foreach ($profiles as $profile) {
134-
$file = idx($files, $profile->getProfileImagePHID());
135-
if (!$file) {
136-
if (!$default) {
137-
$default = PhabricatorFile::loadBuiltin(
138-
$this->getViewer(),
139-
'profile.png');
140-
}
141-
$file = $default;
142-
}
143-
$profile->attachProfileImageFile($file);
144-
}
145-
}
119+
return $projects;
120+
}
146121

147-
foreach ($projects as $project) {
148-
$profile = idx($profiles, $project->getPHID());
149-
if (!$profile) {
122+
protected function didFilterPage(array $projects) {
123+
if ($this->needProfiles) {
124+
$profiles = id(new PhabricatorProjectProfile())->loadAllWhere(
125+
'projectPHID IN (%Ls)',
126+
mpull($projects, 'getPHID'));
127+
$profiles = mpull($profiles, null, 'getProjectPHID');
128+
129+
$default = null;
130+
131+
if ($profiles) {
132+
$file_phids = mpull($profiles, 'getProfileImagePHID');
133+
$files = id(new PhabricatorFileQuery())
134+
->setParentQuery($this)
135+
->setViewer($this->getViewer())
136+
->withPHIDs($file_phids)
137+
->execute();
138+
$files = mpull($files, null, 'getPHID');
139+
foreach ($profiles as $profile) {
140+
$file = idx($files, $profile->getProfileImagePHID());
141+
if (!$file) {
150142
if (!$default) {
151143
$default = PhabricatorFile::loadBuiltin(
152144
$this->getViewer(),
153145
'profile.png');
154146
}
155-
$profile = id(new PhabricatorProjectProfile())
156-
->setProjectPHID($project->getPHID())
157-
->attachProfileImageFile($default);
147+
$file = $default;
148+
}
149+
$profile->attachProfileImageFile($file);
150+
}
151+
}
152+
153+
foreach ($projects as $project) {
154+
$profile = idx($profiles, $project->getPHID());
155+
if (!$profile) {
156+
if (!$default) {
157+
$default = PhabricatorFile::loadBuiltin(
158+
$this->getViewer(),
159+
'profile.png');
158160
}
159-
$project->attachProfile($profile);
161+
$profile = id(new PhabricatorProjectProfile())
162+
->setProjectPHID($project->getPHID())
163+
->attachProfileImageFile($default);
160164
}
165+
$project->attachProfile($profile);
161166
}
162167
}
163168

0 commit comments

Comments
 (0)