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

Lock policy queries to their applications

Summary:
While we mostly have reasonable effective object accessibility when you lock a user out of an application, it's primarily enforced at the controller level. Users can still, e.g., load the handles of objects they can't actually see. Instead, lock the queries to the applications so that you can, e.g., never load a revision if you don't have access to Differential.

This has several parts:

- For PolicyAware queries, provide an application class name method.
- If the query specifies a class name and the user doesn't have permission to use it, fail the entire query unconditionally.
- For handles, simplify query construction and count all the PHIDs as "restricted" so we get a UI full of "restricted" instead of "unknown" handles.

Test Plan:
- Added a unit test to verify I got all the class names right.
- Browsed around, logged in/out as a normal user with public policies on and off.
- Browsed around, logged in/out as a restricted user with public policies on and off. With restrictions, saw all traces of restricted apps removed or restricted.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Differential Revision: https://secure.phabricator.com/D7367

+473 -186
+4
src/applications/auth/query/PhabricatorAuthProviderConfigQuery.php
··· 96 96 return $this->formatWhereClause($where); 97 97 } 98 98 99 + public function getQueryApplicationClass() { 100 + return 'PhabricatorApplicationAuth'; 101 + } 102 + 99 103 }
+4
src/applications/auth/query/PhabricatorExternalAccountQuery.php
··· 163 163 return $this->formatWhereClause($where); 164 164 } 165 165 166 + public function getQueryApplicationClass() { 167 + return 'PhabricatorApplicationPeople'; 168 + } 169 + 166 170 }
+5
src/applications/chatlog/PhabricatorChatLogChannelQuery.php
··· 55 55 56 56 return $this->formatWhereClause($where); 57 57 } 58 + 59 + public function getQueryApplicationClass() { 60 + return 'PhabricatorApplicationChatlog'; 61 + } 62 + 58 63 }
+5
src/applications/chatlog/PhabricatorChatLogQuery.php
··· 54 54 55 55 return $this->formatWhereClause($where); 56 56 } 57 + 58 + public function getQueryApplicationClass() { 59 + return 'PhabricatorApplicationChatlog'; 60 + } 61 + 57 62 }
+4
src/applications/conduit/query/PhabricatorConduitLogQuery.php
··· 40 40 return $this->formatWhereClause($where); 41 41 } 42 42 43 + public function getQueryApplicationClass() { 44 + return 'PhabricatorApplicationConduit'; 45 + } 46 + 43 47 }
+4
src/applications/conduit/query/PhabricatorConduitMethodQuery.php
··· 121 121 return $methods; 122 122 } 123 123 124 + public function getQueryApplicationClass() { 125 + return 'PhabricatorApplicationConduit'; 126 + } 127 + 124 128 }
+2 -5
src/applications/config/phid/PhabricatorConfigPHIDTypeConfig.php
··· 16 16 return new PhabricatorConfigEntry(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PhabricatorConfigEntryQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+4
src/applications/config/query/PhabricatorConfigEntryQuery.php
··· 53 53 return $this->formatWhereClause($where); 54 54 } 55 55 56 + public function getQueryApplicationClass() { 57 + return 'PhabricatorApplicationConfig'; 58 + } 59 + 56 60 }
+2 -5
src/applications/conpherence/phid/PhabricatorConpherencePHIDTypeThread.php
··· 19 19 return new ConpherenceThread(); 20 20 } 21 21 22 - public function loadObjects( 22 + protected function buildQueryForObjects( 23 23 PhabricatorObjectQuery $query, 24 24 array $phids) { 25 25 26 26 return id(new ConpherenceThreadQuery()) 27 - ->setViewer($query->getViewer()) 28 - ->setParentQuery($query) 29 - ->withPHIDs($phids) 30 - ->execute(); 27 + ->withPHIDs($phids); 31 28 } 32 29 33 30 public function loadHandles(
+4
src/applications/conpherence/query/ConpherenceThreadQuery.php
··· 282 282 return $this; 283 283 } 284 284 285 + public function getQueryApplicationClass() { 286 + return 'PhabricatorApplicationConpherence'; 287 + } 288 + 285 289 }
+2 -5
src/applications/countdown/phid/PhabricatorCountdownPHIDTypeCountdown.php
··· 16 16 return new PhabricatorCountdown(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PhabricatorCountdownQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+4
src/applications/countdown/query/PhabricatorCountdownQuery.php
··· 85 85 return $this->formatWhereClause($where); 86 86 } 87 87 88 + public function getQueryApplicationClass() { 89 + return 'PhabricatorApplicationCountdown'; 90 + } 91 + 88 92 }
+4
src/applications/daemon/query/PhabricatorDaemonLogQuery.php
··· 142 142 } 143 143 } 144 144 145 + public function getQueryApplicationClass() { 146 + return 'PhabricatorApplicationDaemons'; 147 + } 148 + 145 149 }
+2 -5
src/applications/differential/phid/DifferentialPHIDTypeRevision.php
··· 16 16 return new DifferentialRevision(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new DifferentialRevisionQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+4
src/applications/differential/query/DifferentialDiffQuery.php
··· 137 137 return $this->formatWhereClause($where); 138 138 } 139 139 140 + public function getQueryApplicationClass() { 141 + return 'PhabricatorApplicationDifferential'; 142 + } 143 + 140 144 }
+3 -2
src/applications/differential/query/DifferentialRevisionQuery.php
··· 1189 1189 ) + array_fuse($project_authority); 1190 1190 } 1191 1191 1192 - 1193 - 1192 + public function getQueryApplicationClass() { 1193 + return 'PhabricatorApplicationDifferential'; 1194 + } 1194 1195 1195 1196 }
+4
src/applications/diffusion/query/DiffusionCommitQuery.php
··· 250 250 } 251 251 } 252 252 253 + public function getQueryApplicationClass() { 254 + return 'PhabricatorApplicationDiffusion'; 255 + } 256 + 253 257 }
+2 -5
src/applications/diviner/phid/DivinerPHIDTypeAtom.php
··· 16 16 return new DivinerLiveSymbol(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new DivinerAtomQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+2 -5
src/applications/diviner/phid/DivinerPHIDTypeBook.php
··· 16 16 return new DivinerLiveBook(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new DivinerBookQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+4
src/applications/diviner/query/DivinerAtomQuery.php
··· 405 405 } 406 406 } 407 407 408 + public function getQueryApplicationClass() { 409 + return 'PhabricatorApplicationDiviner'; 410 + } 411 + 408 412 }
+5
src/applications/diviner/query/DivinerBookQuery.php
··· 66 66 return $this->formatWhereClause($where); 67 67 } 68 68 69 + 70 + public function getQueryApplicationClass() { 71 + return 'PhabricatorApplicationDiviner'; 72 + } 73 + 69 74 }
+4
src/applications/doorkeeper/query/DoorkeeperExternalObjectQuery.php
··· 52 52 return $this->formatWhereClause($where); 53 53 } 54 54 55 + public function getQueryApplicationClass() { 56 + return 'PhabricatorApplicationDoorkeeper'; 57 + } 58 + 55 59 }
+5
src/applications/feed/query/PhabricatorFeedQuery.php
··· 104 104 return $item['chronologicalKey']; 105 105 } 106 106 107 + 108 + public function getQueryApplicationClass() { 109 + return 'PhabricatorApplicationFeed'; 110 + } 111 + 107 112 }
+2 -5
src/applications/files/phid/PhabricatorFilePHIDTypeFile.php
··· 16 16 return new PhabricatorFile(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PhabricatorFileQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+5
src/applications/files/query/PhabricatorFileQuery.php
··· 235 235 return 'f.id'; 236 236 } 237 237 238 + 239 + public function getQueryApplicationClass() { 240 + return 'PhabricatorApplicationFiles'; 241 + } 242 + 238 243 }
+5
src/applications/flag/query/PhabricatorFlagQuery.php
··· 160 160 return $this->formatWhereClause($where); 161 161 } 162 162 163 + 164 + public function getQueryApplicationClass() { 165 + return 'PhabricatorApplicationFlags'; 166 + } 167 + 163 168 }
+2 -5
src/applications/herald/phid/HeraldPHIDTypeRule.php
··· 16 16 return new HeraldRule(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new HeraldRuleQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+5
src/applications/herald/query/HeraldRuleQuery.php
··· 229 229 } 230 230 } 231 231 232 + 233 + public function getQueryApplicationClass() { 234 + return 'PhabricatorApplicationHerald'; 235 + } 236 + 232 237 }
+3
src/applications/herald/query/HeraldTranscriptQuery.php
··· 94 94 return $this->formatWhereClause($where); 95 95 } 96 96 97 + public function getQueryApplicationClass() { 98 + return 'PhabricatorApplicationHerald'; 99 + } 97 100 98 101 }
+2 -5
src/applications/legalpad/phid/PhabricatorLegalpadPHIDTypeDocument.php
··· 19 19 return new LegalpadDocument(); 20 20 } 21 21 22 - public function loadObjects( 22 + protected function buildQueryForObjects( 23 23 PhabricatorObjectQuery $query, 24 24 array $phids) { 25 25 26 26 return id(new LegalpadDocumentQuery()) 27 - ->setViewer($query->getViewer()) 28 - ->setParentQuery($query) 29 27 ->withPHIDs($phids) 30 - ->needDocumentBodies(true) 31 - ->execute(); 28 + ->needDocumentBodies(true); 32 29 } 33 30 34 31 public function loadHandles(
+3
src/applications/legalpad/query/LegalpadDocumentQuery.php
··· 181 181 return $documents; 182 182 } 183 183 184 + public function getQueryApplicationClass() { 185 + return 'PhabricatorApplicationLegalpad'; 186 + } 184 187 185 188 }
+2 -5
src/applications/macro/phid/PhabricatorMacroPHIDTypeMacro.php
··· 16 16 return new PhabricatorFileImageMacro(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PhabricatorMacroQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+4
src/applications/macro/query/PhabricatorMacroQuery.php
··· 216 216 return 'm.id'; 217 217 } 218 218 219 + public function getQueryApplicationClass() { 220 + return 'PhabricatorApplicationMacro'; 221 + } 222 + 219 223 }
+2 -5
src/applications/mailinglists/phid/PhabricatorMailingListPHIDTypeList.php
··· 16 16 return new PhabricatorMetaMTAMailingList(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PhabricatorMailingListQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+4
src/applications/mailinglists/query/PhabricatorMailingListQuery.php
··· 53 53 return $this->formatWhereClause($where); 54 54 } 55 55 56 + public function getQueryApplicationClass() { 57 + return 'PhabricatorApplicationMailingLists'; 58 + } 59 + 56 60 }
+2 -5
src/applications/maniphest/phid/ManiphestPHIDTypeTask.php
··· 16 16 return new ManiphestTask(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new ManiphestTaskQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+5
src/applications/maniphest/query/ManiphestTaskQuery.php
··· 886 886 return 'task.phid'; 887 887 } 888 888 889 + 890 + public function getQueryApplicationClass() { 891 + return 'PhabricatorApplicationManiphest'; 892 + } 893 + 889 894 }
+2 -5
src/applications/meta/phid/PhabricatorApplicationPHIDTypeApplication.php
··· 17 17 return null; 18 18 } 19 19 20 - public function loadObjects( 20 + protected function buildQueryForObjects( 21 21 PhabricatorObjectQuery $query, 22 22 array $phids) { 23 23 24 24 return id(new PhabricatorApplicationQuery()) 25 - ->setViewer($query->getViewer()) 26 - ->setParentQuery($query) 27 - ->withPHIDs($phids) 28 - ->execute(); 25 + ->withPHIDs($phids); 29 26 } 30 27 31 28 public function loadHandles(
+9
src/applications/meta/query/PhabricatorApplicationQuery.php
··· 132 132 return $apps; 133 133 } 134 134 135 + 136 + public function getQueryApplicationClass() { 137 + // NOTE: Although this belongs to the "Applications" application, trying 138 + // to filter its results just leaves us recursing indefinitely. Users 139 + // always have access to applications regardless of other policy settings 140 + // anyway. 141 + return null; 142 + } 143 + 135 144 }
+6
src/applications/notification/PhabricatorNotificationQuery.php
··· 111 111 return $item->getChronologicalKey(); 112 112 } 113 113 114 + 115 + public function getQueryApplicationClass() { 116 + // TODO: No actual "Notification" app yet, but there probably should be. 117 + return null; 118 + } 119 + 114 120 }
+2 -5
src/applications/owners/phid/PhabricatorOwnersPHIDTypePackage.php
··· 16 16 return new PhabricatorOwnersPackage(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PhabricatorOwnersPackageQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+5
src/applications/owners/query/PhabricatorOwnersPackageQuery.php
··· 79 79 return $this->formatWhereClause($where); 80 80 } 81 81 82 + 83 + public function getQueryApplicationClass() { 84 + return 'PhabricatorApplicationOwners'; 85 + } 86 + 82 87 }
+2 -5
src/applications/paste/phid/PhabricatorPastePHIDTypePaste.php
··· 16 16 return new PhabricatorPaste(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PhabricatorPasteQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+5
src/applications/paste/query/PhabricatorPasteQuery.php
··· 249 249 } 250 250 } 251 251 252 + 253 + public function getQueryApplicationClass() { 254 + return 'PhabricatorApplicationPaste'; 255 + } 256 + 252 257 }
+2 -5
src/applications/people/phid/PhabricatorPeoplePHIDTypeExternal.php
··· 16 16 return new PhabricatorExternalAccount(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PhabricatorExternalAccountQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+2 -5
src/applications/people/phid/PhabricatorPeoplePHIDTypeUser.php
··· 16 16 return new PhabricatorUser(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PhabricatorPeopleQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 24 ->withPHIDs($phids) 27 25 ->needProfileImage(true) 28 - ->needStatus(true) 29 - ->execute(); 26 + ->needStatus(true); 30 27 } 31 28 32 29 public function loadHandles(
+4
src/applications/people/query/PhabricatorPeopleQuery.php
··· 282 282 return 'user.phid'; 283 283 } 284 284 285 + public function getQueryApplicationClass() { 286 + return 'PhabricatorApplicationPeople'; 287 + } 288 + 285 289 }
+2 -5
src/applications/phame/phid/PhabricatorPhamePHIDTypeBlog.php
··· 19 19 return new PhameBlog(); 20 20 } 21 21 22 - public function loadObjects( 22 + protected function buildQueryForObjects( 23 23 PhabricatorObjectQuery $query, 24 24 array $phids) { 25 25 26 26 return id(new PhameBlogQuery()) 27 - ->setViewer($query->getViewer()) 28 - ->setParentQuery($query) 29 - ->withPHIDs($phids) 30 - ->execute(); 27 + ->withPHIDs($phids); 31 28 } 32 29 33 30 public function loadHandles(
+2 -5
src/applications/phame/phid/PhabricatorPhamePHIDTypePost.php
··· 19 19 return new PhamePost(); 20 20 } 21 21 22 - public function loadObjects( 22 + protected function buildQueryForObjects( 23 23 PhabricatorObjectQuery $query, 24 24 array $phids) { 25 25 26 26 return id(new PhamePostQuery()) 27 - ->setViewer($query->getViewer()) 28 - ->setParentQuery($query) 29 - ->withPHIDs($phids) 30 - ->execute(); 27 + ->withPHIDs($phids); 31 28 } 32 29 33 30 public function loadHandles(
+5
src/applications/phame/query/PhameBlogQuery.php
··· 75 75 return $this->formatWhereClause($where); 76 76 } 77 77 78 + public function getQueryApplicationClass() { 79 + // TODO: Can we set this without breaking public blogs? 80 + return null; 81 + } 82 + 78 83 }
+5
src/applications/phame/query/PhamePostQuery.php
··· 141 141 return $this->formatWhereClause($where); 142 142 } 143 143 144 + public function getQueryApplicationClass() { 145 + // TODO: Does setting this break public blogs? 146 + return null; 147 + } 148 + 144 149 }
+4
src/applications/phid/query/PhabricatorHandleQuery.php
··· 67 67 return $results; 68 68 } 69 69 70 + public function getQueryApplicationClass() { 71 + return null; 72 + } 73 + 70 74 }
+4
src/applications/phid/query/PhabricatorObjectQuery.php
··· 152 152 return true; 153 153 } 154 154 155 + public function getQueryApplicationClass() { 156 + return null; 157 + } 158 + 155 159 }
+45 -2
src/applications/phid/type/PhabricatorPHIDType.php
··· 9 9 return null; 10 10 } 11 11 12 - abstract public function loadObjects( 12 + /** 13 + * Build a @{class:PhabricatorPolicyAwareQuery} to load objects of this type 14 + * by PHID. 15 + * 16 + * If you can not build a single query which satisfies this requirement, you 17 + * can provide a dummy implementation for this method and overload 18 + * @{method:loadObjects} instead. 19 + * 20 + * @param PhabricatorObjectQuery Query being executed. 21 + * @param list<phid> PHIDs to load. 22 + * @return PhabricatorPolicyAwareQuery Query object which loads the 23 + * specified PHIDs when executed. 24 + */ 25 + abstract protected function buildQueryForObjects( 13 26 PhabricatorObjectQuery $query, 14 27 array $phids); 15 28 16 29 17 30 /** 31 + * Load objects of this type, by PHID. For most PHID types, it is only 32 + * necessary to implement @{method:buildQueryForObjects} to get object 33 + * loading to work. 34 + * 35 + * @param PhabricatorObjectQuery Query being executed. 36 + * @param list<phid> PHIDs to load. 37 + * @return list<wild> Corresponding objects. 38 + */ 39 + public function loadObjects( 40 + PhabricatorObjectQuery $query, 41 + array $phids) { 42 + 43 + $object_query = $this->buildQueryForObjects($query, $phids) 44 + ->setViewer($query->getViewer()) 45 + ->setParentQuery($query); 46 + 47 + // If the user doesn't have permission to use the application at all, 48 + // just mark all the PHIDs as filtered. This primarily makes these 49 + // objects show up as "Restricted" instead of "Unknown" when loaded as 50 + // handles, which is technically true. 51 + if (!$object_query->canViewerUseQueryApplication()) { 52 + $object_query->addPolicyFilteredPHIDs(array_fuse($phids)); 53 + return array(); 54 + } 55 + 56 + return $object_query->execute(); 57 + } 58 + 59 + 60 + /** 18 61 * Populate provided handles with application-specific data, like titles and 19 62 * URIs. 20 63 * ··· 38 81 * @param PhabricatorHandleQuery Issuing query object. 39 82 * @param list<PhabricatorObjectHandle> Handles to populate with data. 40 83 * @param list<Object> Objects for these PHIDs loaded by 41 - * @{method:loadObjects()}. 84 + * @{method:buildQueryForObjects()}. 42 85 * @return void 43 86 */ 44 87 abstract public function loadHandles(
+2 -5
src/applications/phlux/phid/PhluxPHIDTypeVariable.php
··· 16 16 return new PhluxVariable(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PhluxVariableQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+4
src/applications/phlux/query/PhluxVariableQuery.php
··· 65 65 return true; 66 66 } 67 67 68 + public function getQueryApplicationClass() { 69 + return 'PhabricatorApplicationPhlux'; 70 + } 71 + 68 72 }
+2 -5
src/applications/pholio/phid/PholioPHIDTypeImage.php
··· 16 16 return new PholioImage(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PholioImageQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+2 -5
src/applications/pholio/phid/PholioPHIDTypeMock.php
··· 16 16 return new PholioMock(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PholioMockQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+4
src/applications/pholio/query/PholioImageQuery.php
··· 161 161 return $images; 162 162 } 163 163 164 + public function getQueryApplicationClass() { 165 + return 'PhabricatorApplicationPholio'; 166 + } 167 + 164 168 }
+4
src/applications/pholio/query/PholioMockQuery.php
··· 161 161 } 162 162 } 163 163 164 + public function getQueryApplicationClass() { 165 + return 'PhabricatorApplicationPholio'; 166 + } 167 + 164 168 }
+5
src/applications/phortune/query/PhortuneAccountQuery.php
··· 95 95 return implode(' ', $joins); 96 96 } 97 97 98 + 99 + public function getQueryApplicationClass() { 100 + return 'PhabricatorApplicationPhortune'; 101 + } 102 + 98 103 }
+5
src/applications/phortune/query/PhortunePaymentMethodQuery.php
··· 110 110 return $this->formatWhereClause($where); 111 111 } 112 112 113 + 114 + public function getQueryApplicationClass() { 115 + return 'PhabricatorApplicationPhortune'; 116 + } 117 + 113 118 }
+4
src/applications/phortune/query/PhortuneProductQuery.php
··· 53 53 return $this->formatWhereClause($where); 54 54 } 55 55 56 + public function getQueryApplicationClass() { 57 + return 'PhabricatorApplicationPhortune'; 58 + } 59 + 56 60 }
+5
src/applications/phrequent/query/PhrequentUserTimeQuery.php
··· 302 302 return $sum_ended['N'] + $sum_not_ended['N']; 303 303 } 304 304 305 + 306 + public function getQueryApplicationClass() { 307 + return 'PhabricatorApplicationPhrequent'; 308 + } 309 + 305 310 }
+2 -5
src/applications/phriction/phid/PhrictionPHIDTypeDocument.php
··· 16 16 return new PhrictionDocument(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PhrictionDocumentQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+5
src/applications/phriction/query/PhrictionDocumentQuery.php
··· 185 185 } 186 186 } 187 187 188 + 189 + public function getQueryApplicationClass() { 190 + return 'PhabricatorApplicationPhriction'; 191 + } 192 + 188 193 }
+4
src/applications/policy/__tests__/PhabricatorPolicyAwareTestQuery.php
··· 33 33 $this->offset += count($page); 34 34 } 35 35 36 + public function getQueryApplicationClass() { 37 + return null; 38 + } 39 + 36 40 }
+16
src/applications/policy/__tests__/PhabricatorPolicyTestCase.php
··· 210 210 count($query->execute())); 211 211 } 212 212 213 + public function testAllQueriesBelongToActualApplications() { 214 + $queries = id(new PhutilSymbolLoader()) 215 + ->setAncestorClass('PhabricatorPolicyAwareQuery') 216 + ->loadObjects(); 217 + 218 + foreach ($queries as $qclass => $query) { 219 + $class = $query->getQueryApplicationClass(); 220 + if (!$class) { 221 + continue; 222 + } 223 + $this->assertEqual( 224 + true, 225 + class_exists($class), 226 + "Application class '{$class}' for query '{$qclass}'"); 227 + } 228 + } 213 229 214 230 /** 215 231 * Test an object for visibility across multiple user specifications.
+2 -5
src/applications/policy/phid/PhabricatorPolicyPHIDTypePolicy.php
··· 17 17 return new PhabricatorPolicy(); 18 18 } 19 19 20 - public function loadObjects( 20 + protected function buildQueryForObjects( 21 21 PhabricatorObjectQuery $query, 22 22 array $phids) { 23 23 24 24 return id(new PhabricatorPolicyQuery()) 25 - ->setViewer($query->getViewer()) 26 - ->setParentQuery($query) 27 - ->withPHIDs($phids) 28 - ->execute(); 25 + ->withPHIDs($phids); 29 26 } 30 27 31 28 public function loadHandles(
+5
src/applications/policy/query/PhabricatorPolicyQuery.php
··· 223 223 return true; 224 224 } 225 225 226 + 227 + public function getQueryApplicationClass() { 228 + return 'PhabricatorApplicationPolicy'; 229 + } 230 + 226 231 } 227 232
+2 -5
src/applications/ponder/phid/PonderPHIDTypeAnswer.php
··· 16 16 return new PonderAnswer(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PonderAnswerQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+2 -5
src/applications/ponder/phid/PonderPHIDTypeQuestion.php
··· 16 16 return new PonderQuestion(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PonderQuestionQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+5
src/applications/ponder/query/PonderAnswerQuery.php
··· 123 123 return true; 124 124 } 125 125 126 + 127 + public function getQueryApplicationClass() { 128 + return 'PhabricatorApplicationPonder'; 129 + } 130 + 126 131 }
+5
src/applications/ponder/query/PonderQuestionQuery.php
··· 194 194 return implode(' ', $joins); 195 195 } 196 196 197 + 198 + public function getQueryApplicationClass() { 199 + return 'PhabricatorApplicationPonder'; 200 + } 201 + 197 202 }
+2 -5
src/applications/project/phid/PhabricatorProjectPHIDTypeProject.php
··· 16 16 return new PhabricatorProject(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PhabricatorProjectQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+5
src/applications/project/query/PhabricatorProjectQuery.php
··· 260 260 return implode(' ', $joins); 261 261 } 262 262 263 + 264 + public function getQueryApplicationClass() { 265 + return 'PhabricatorApplicationProject'; 266 + } 267 + 263 268 }
+2 -5
src/applications/releeph/phid/ReleephPHIDTypeBranch.php
··· 16 16 return new ReleephBranch(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new ReleephBranchQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+2 -5
src/applications/releeph/phid/ReleephPHIDTypeProject.php
··· 16 16 return new ReleephProject(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new ReleephProjectQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+2 -5
src/applications/releeph/phid/ReleephPHIDTypeRequest.php
··· 16 16 return new ReleephRequest(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new ReleephRequestQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+5
src/applications/releeph/query/ReleephBranchQuery.php
··· 129 129 return $this->formatWhereClause($where); 130 130 } 131 131 132 + 133 + public function getQueryApplicationClass() { 134 + return 'PhabricatorApplicationReleeph'; 135 + } 136 + 132 137 }
+4
src/applications/releeph/query/ReleephProjectQuery.php
··· 127 127 } 128 128 } 129 129 130 + public function getQueryApplicationClass() { 131 + return 'PhabricatorApplicationReleeph'; 132 + } 133 + 130 134 }
+5
src/applications/releeph/query/ReleephRequestQuery.php
··· 232 232 } 233 233 } 234 234 235 + 236 + public function getQueryApplicationClass() { 237 + return 'PhabricatorApplicationReleeph'; 238 + } 239 + 235 240 }
+2 -5
src/applications/repository/phid/PhabricatorRepositoryPHIDTypeArcanistProject.php
··· 20 20 return new PhabricatorRepositoryArcanistProject(); 21 21 } 22 22 23 - public function loadObjects( 23 + protected function buildQueryForObjects( 24 24 PhabricatorObjectQuery $query, 25 25 array $phids) { 26 26 27 27 return id(new PhabricatorRepositoryArcanistProjectQuery()) 28 - ->setViewer($query->getViewer()) 29 - ->setParentQuery($query) 30 - ->withPHIDs($phids) 31 - ->execute(); 28 + ->withPHIDs($phids); 32 29 } 33 30 34 31 public function loadHandles(
+2 -5
src/applications/repository/phid/PhabricatorRepositoryPHIDTypeCommit.php
··· 16 16 return new PhabricatorRepositoryCommit(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new DiffusionCommitQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+2 -5
src/applications/repository/phid/PhabricatorRepositoryPHIDTypeRepository.php
··· 17 17 return new PhabricatorRepository(); 18 18 } 19 19 20 - public function loadObjects( 20 + protected function buildQueryForObjects( 21 21 PhabricatorObjectQuery $query, 22 22 array $phids) { 23 23 24 24 return id(new PhabricatorRepositoryQuery()) 25 - ->setViewer($query->getViewer()) 26 - ->setParentQuery($query) 27 - ->withPHIDs($phids) 28 - ->execute(); 25 + ->withPHIDs($phids); 29 26 } 30 27 31 28 public function loadHandles(
+6
src/applications/repository/query/PhabricatorRepositoryArcanistProjectQuery.php
··· 81 81 return $this->formatWhereClause($where); 82 82 } 83 83 84 + 85 + public function getQueryApplicationClass() { 86 + // TODO: Diffusion? Differential? 87 + return null; 88 + } 89 + 84 90 }
+5
src/applications/repository/query/PhabricatorRepositoryQuery.php
··· 317 317 return $this->formatWhereClause($where); 318 318 } 319 319 320 + 321 + public function getQueryApplicationClass() { 322 + return 'PhabricatorApplicationDiffusion'; 323 + } 324 + 320 325 }
+6
src/applications/search/query/PhabricatorNamedQueryQuery.php
··· 81 81 82 82 return $this->formatWhereClause($where); 83 83 } 84 + 85 + 86 + public function getQueryApplicationClass() { 87 + return 'PhabricatorApplicationSearch'; 88 + } 89 + 84 90 }
+6
src/applications/search/query/PhabricatorSavedQueryQuery.php
··· 65 65 66 66 return $this->formatWhereClause($where); 67 67 } 68 + 69 + 70 + public function getQueryApplicationClass() { 71 + return 'PhabricatorApplicationSearch'; 72 + } 73 + 68 74 }
+2 -5
src/applications/slowvote/phid/PhabricatorSlowvotePHIDTypePoll.php
··· 16 16 return new PhabricatorSlowvotePoll(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PhabricatorSlowvoteQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+5
src/applications/slowvote/query/PhabricatorSlowvoteQuery.php
··· 168 168 return 'p.id'; 169 169 } 170 170 171 + 172 + public function getQueryApplicationClass() { 173 + return 'PhabricatorApplicationSlowvote'; 174 + } 175 + 171 176 }
+2 -5
src/applications/tokens/phid/PhabricatorTokenPHIDTypeToken.php
··· 16 16 return new PhabricatorToken(); 17 17 } 18 18 19 - public function loadObjects( 19 + protected function buildQueryForObjects( 20 20 PhabricatorObjectQuery $query, 21 21 array $phids) { 22 22 23 23 return id(new PhabricatorTokenQuery()) 24 - ->setViewer($query->getViewer()) 25 - ->setParentQuery($query) 26 - ->withPHIDs($phids) 27 - ->execute(); 24 + ->withPHIDs($phids); 28 25 } 29 26 30 27 public function loadHandles(
+4
src/applications/tokens/query/PhabricatorTokenGivenQuery.php
··· 89 89 return $results; 90 90 } 91 91 92 + public function getQueryApplicationClass() { 93 + return 'PhabricatorApplicationTokens'; 94 + } 95 + 92 96 }
+5
src/applications/tokens/query/PhabricatorTokenQuery.php
··· 61 61 return $tokens; 62 62 } 63 63 64 + 65 + public function getQueryApplicationClass() { 66 + return 'PhabricatorApplicationTokens'; 67 + } 68 + 64 69 }
+4
src/applications/tokens/query/PhabricatorTokenReceiverQuery.php
··· 34 34 return $this->tokenCounts; 35 35 } 36 36 37 + public function getQueryApplicationClass() { 38 + return 'PhabricatorApplicationTokens'; 39 + } 40 + 37 41 }
+15 -3
src/applications/transactions/phid/PhabricatorApplicationTransactionPHIDTypeTransaction.php
··· 20 20 return null; 21 21 } 22 22 23 + protected function buildQueryForObjects( 24 + PhabricatorObjectQuery $object_query, 25 + array $phids) { 26 + throw new Exception(); 27 + } 28 + 23 29 public function loadObjects( 24 30 PhabricatorObjectQuery $object_query, 25 31 array $phids) { ··· 55 61 continue; 56 62 } 57 63 58 - $xactions = id(clone $query) 64 + $xaction_query = id(clone $query) 59 65 ->setViewer($object_query->getViewer()) 60 66 ->setParentQuery($object_query) 61 - ->withPHIDs($subtype_phids) 62 - ->execute(); 67 + ->withPHIDs($subtype_phids); 68 + 69 + if (!$xaction_query->canViewerUseQueryApplication()) { 70 + $object_query->addPolicyFilteredPHIDs(array_fuse($subtype_phids)); 71 + continue; 72 + } 73 + 74 + $xactions = $xaction_query->execute(); 63 75 64 76 $results += mpull($xactions, null, 'getPHID'); 65 77 }
+6
src/applications/transactions/query/PhabricatorApplicationTransactionCommentQuery.php
··· 59 59 return $this->formatWhereClause($where); 60 60 } 61 61 62 + public function getQueryApplicationClass() { 63 + // TODO: Figure out the app via the template? 64 + return null; 65 + } 66 + 67 + 62 68 }
+6
src/applications/transactions/query/PhabricatorApplicationTransactionQuery.php
··· 160 160 return $this->formatWhereClause($where); 161 161 } 162 162 163 + 164 + public function getQueryApplicationClass() { 165 + // TODO: Sort this out? 166 + return null; 167 + } 168 + 163 169 }
+48 -4
src/infrastructure/query/policy/PhabricatorPolicyAwareQuery.php
··· 35 35 private $capabilities; 36 36 private $workspace = array(); 37 37 private $policyFilteredPHIDs = array(); 38 + private $canUseApplication; 38 39 39 40 40 41 /* -( Query Configuration )------------------------------------------------ */ ··· 213 214 $this->rawResultLimit = 0; 214 215 } 215 216 216 - try { 217 - $page = $this->loadPage(); 218 - } catch (PhabricatorEmptyQueryException $ex) { 217 + if ($this->canViewerUseQueryApplication()) { 218 + try { 219 + $page = $this->loadPage(); 220 + } catch (PhabricatorEmptyQueryException $ex) { 221 + $page = array(); 222 + } 223 + } else { 219 224 $page = array(); 220 225 } 221 226 ··· 317 322 PhabricatorPolicyCapability::CAN_VIEW); 318 323 } 319 324 320 - protected function addPolicyFilteredPHIDs(array $phids) { 325 + public function addPolicyFilteredPHIDs(array $phids) { 321 326 $this->policyFilteredPHIDs += $phids; 322 327 if ($this->getParentQuery()) { 323 328 $this->getParentQuery()->addPolicyFilteredPHIDs($phids); ··· 579 584 */ 580 585 protected function shouldDisablePolicyFiltering() { 581 586 return false; 587 + } 588 + 589 + 590 + /** 591 + * If this query belongs to an application, return the application class name 592 + * here. This will prevent the query from returning results if the viewer can 593 + * not access the application. 594 + * 595 + * If this query does not belong to an application, return `null`. 596 + * 597 + * @return string|null Application class name. 598 + */ 599 + abstract public function getQueryApplicationClass(); 600 + 601 + 602 + /** 603 + * Determine if the viewer has permission to use this query's application. 604 + * For queries which aren't part of an application, this method always returns 605 + * true. 606 + * 607 + * @return bool True if the viewer has application-level permission to 608 + * execute the query. 609 + */ 610 + public function canViewerUseQueryApplication() { 611 + if ($this->canUseApplication === null) { 612 + $class = $this->getQueryApplicationClass(); 613 + if (!$class) { 614 + $this->canUseApplication = true; 615 + } else { 616 + $result = id(new PhabricatorApplicationQuery()) 617 + ->setViewer($this->getViewer()) 618 + ->withClasses(array($class)) 619 + ->execute(); 620 + 621 + $this->canUseApplication = (bool)$result; 622 + } 623 + } 624 + 625 + return $this->canUseApplication; 582 626 } 583 627 584 628 }