1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 00:42:41 +01:00

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
This commit is contained in:
epriestley 2013-10-21 17:20:27 -07:00
parent 32dd8af9e5
commit 2a5c987c71
99 changed files with 473 additions and 186 deletions

View file

@ -96,4 +96,8 @@ final class PhabricatorAuthProviderConfigQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationAuth';
}
}

View file

@ -163,4 +163,8 @@ final class PhabricatorExternalAccountQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationPeople';
}
}

View file

@ -55,4 +55,9 @@ final class PhabricatorChatLogChannelQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationChatlog';
}
}

View file

@ -54,4 +54,9 @@ final class PhabricatorChatLogQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationChatlog';
}
}

View file

@ -40,4 +40,8 @@ final class PhabricatorConduitLogQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationConduit';
}
}

View file

@ -121,4 +121,8 @@ final class PhabricatorConduitMethodQuery
return $methods;
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationConduit';
}
}

View file

@ -16,15 +16,12 @@ final class PhabricatorConfigPHIDTypeConfig extends PhabricatorPHIDType {
return new PhabricatorConfigEntry();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorConfigEntryQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -53,4 +53,8 @@ final class PhabricatorConfigEntryQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationConfig';
}
}

View file

@ -19,15 +19,12 @@ final class PhabricatorConpherencePHIDTypeThread extends PhabricatorPHIDType {
return new ConpherenceThread();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new ConpherenceThreadQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -282,4 +282,8 @@ final class ConpherenceThreadQuery
return $this;
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationConpherence';
}
}

View file

@ -16,15 +16,12 @@ final class PhabricatorCountdownPHIDTypeCountdown extends PhabricatorPHIDType {
return new PhabricatorCountdown();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorCountdownQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -85,4 +85,8 @@ final class PhabricatorCountdownQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationCountdown';
}
}

View file

@ -142,4 +142,8 @@ final class PhabricatorDaemonLogQuery
}
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationDaemons';
}
}

View file

@ -16,15 +16,12 @@ final class DifferentialPHIDTypeRevision extends PhabricatorPHIDType {
return new DifferentialRevision();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new DifferentialRevisionQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -137,4 +137,8 @@ final class DifferentialDiffQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationDifferential';
}
}

View file

@ -1189,7 +1189,8 @@ final class DifferentialRevisionQuery
) + array_fuse($project_authority);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationDifferential';
}
}

View file

@ -250,4 +250,8 @@ final class DiffusionCommitQuery
}
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationDiffusion';
}
}

View file

@ -16,15 +16,12 @@ final class DivinerPHIDTypeAtom extends PhabricatorPHIDType {
return new DivinerLiveSymbol();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new DivinerAtomQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -16,15 +16,12 @@ final class DivinerPHIDTypeBook extends PhabricatorPHIDType {
return new DivinerLiveBook();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new DivinerBookQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -405,4 +405,8 @@ final class DivinerAtomQuery
}
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationDiviner';
}
}

View file

@ -66,4 +66,9 @@ final class DivinerBookQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationDiviner';
}
}

View file

@ -52,4 +52,8 @@ final class DoorkeeperExternalObjectQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationDoorkeeper';
}
}

View file

@ -104,4 +104,9 @@ final class PhabricatorFeedQuery
return $item['chronologicalKey'];
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationFeed';
}
}

View file

@ -16,15 +16,12 @@ final class PhabricatorFilePHIDTypeFile extends PhabricatorPHIDType {
return new PhabricatorFile();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorFileQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -235,4 +235,9 @@ final class PhabricatorFileQuery
return 'f.id';
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationFiles';
}
}

View file

@ -160,4 +160,9 @@ final class PhabricatorFlagQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationFlags';
}
}

View file

@ -16,15 +16,12 @@ final class HeraldPHIDTypeRule extends PhabricatorPHIDType {
return new HeraldRule();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new HeraldRuleQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -229,4 +229,9 @@ final class HeraldRuleQuery
}
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationHerald';
}
}

View file

@ -94,5 +94,8 @@ final class HeraldTranscriptQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationHerald';
}
}

View file

@ -19,16 +19,13 @@ final class PhabricatorLegalpadPHIDTypeDocument extends PhabricatorPHIDType {
return new LegalpadDocument();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new LegalpadDocumentQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->needDocumentBodies(true)
->execute();
->needDocumentBodies(true);
}
public function loadHandles(

View file

@ -181,5 +181,8 @@ final class LegalpadDocumentQuery
return $documents;
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationLegalpad';
}
}

View file

@ -16,15 +16,12 @@ final class PhabricatorMacroPHIDTypeMacro extends PhabricatorPHIDType {
return new PhabricatorFileImageMacro();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorMacroQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -216,4 +216,8 @@ final class PhabricatorMacroQuery
return 'm.id';
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationMacro';
}
}

View file

@ -16,15 +16,12 @@ final class PhabricatorMailingListPHIDTypeList extends PhabricatorPHIDType {
return new PhabricatorMetaMTAMailingList();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorMailingListQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -53,4 +53,8 @@ final class PhabricatorMailingListQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationMailingLists';
}
}

View file

@ -16,15 +16,12 @@ final class ManiphestPHIDTypeTask extends PhabricatorPHIDType {
return new ManiphestTask();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new ManiphestTaskQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -886,4 +886,9 @@ final class ManiphestTaskQuery
return 'task.phid';
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationManiphest';
}
}

View file

@ -17,15 +17,12 @@ final class PhabricatorApplicationPHIDTypeApplication
return null;
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorApplicationQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -132,4 +132,13 @@ final class PhabricatorApplicationQuery
return $apps;
}
public function getQueryApplicationClass() {
// NOTE: Although this belongs to the "Applications" application, trying
// to filter its results just leaves us recursing indefinitely. Users
// always have access to applications regardless of other policy settings
// anyway.
return null;
}
}

View file

@ -111,4 +111,10 @@ final class PhabricatorNotificationQuery
return $item->getChronologicalKey();
}
public function getQueryApplicationClass() {
// TODO: No actual "Notification" app yet, but there probably should be.
return null;
}
}

View file

@ -16,15 +16,12 @@ final class PhabricatorOwnersPHIDTypePackage extends PhabricatorPHIDType {
return new PhabricatorOwnersPackage();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorOwnersPackageQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -79,4 +79,9 @@ final class PhabricatorOwnersPackageQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationOwners';
}
}

View file

@ -16,15 +16,12 @@ final class PhabricatorPastePHIDTypePaste extends PhabricatorPHIDType {
return new PhabricatorPaste();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorPasteQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -249,4 +249,9 @@ final class PhabricatorPasteQuery
}
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationPaste';
}
}

View file

@ -16,15 +16,12 @@ final class PhabricatorPeoplePHIDTypeExternal extends PhabricatorPHIDType {
return new PhabricatorExternalAccount();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorExternalAccountQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -16,17 +16,14 @@ final class PhabricatorPeoplePHIDTypeUser extends PhabricatorPHIDType {
return new PhabricatorUser();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorPeopleQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->needProfileImage(true)
->needStatus(true)
->execute();
->needStatus(true);
}
public function loadHandles(

View file

@ -282,4 +282,8 @@ final class PhabricatorPeopleQuery
return 'user.phid';
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationPeople';
}
}

View file

@ -19,15 +19,12 @@ final class PhabricatorPhamePHIDTypeBlog extends PhabricatorPHIDType {
return new PhameBlog();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhameBlogQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -19,15 +19,12 @@ final class PhabricatorPhamePHIDTypePost extends PhabricatorPHIDType {
return new PhamePost();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhamePostQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -75,4 +75,9 @@ final class PhameBlogQuery extends PhabricatorCursorPagedPolicyAwareQuery {
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
// TODO: Can we set this without breaking public blogs?
return null;
}
}

View file

@ -141,4 +141,9 @@ final class PhamePostQuery extends PhabricatorCursorPagedPolicyAwareQuery {
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
// TODO: Does setting this break public blogs?
return null;
}
}

View file

@ -67,4 +67,8 @@ final class PhabricatorHandleQuery
return $results;
}
public function getQueryApplicationClass() {
return null;
}
}

View file

@ -152,4 +152,8 @@ final class PhabricatorObjectQuery
return true;
}
public function getQueryApplicationClass() {
return null;
}
}

View file

@ -9,11 +9,54 @@ abstract class PhabricatorPHIDType {
return null;
}
abstract public function loadObjects(
/**
* Build a @{class:PhabricatorPolicyAwareQuery} to load objects of this type
* by PHID.
*
* If you can not build a single query which satisfies this requirement, you
* can provide a dummy implementation for this method and overload
* @{method:loadObjects} instead.
*
* @param PhabricatorObjectQuery Query being executed.
* @param list<phid> PHIDs to load.
* @return PhabricatorPolicyAwareQuery Query object which loads the
* specified PHIDs when executed.
*/
abstract protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids);
/**
* Load objects of this type, by PHID. For most PHID types, it is only
* necessary to implement @{method:buildQueryForObjects} to get object
* loading to work.
*
* @param PhabricatorObjectQuery Query being executed.
* @param list<phid> PHIDs to load.
* @return list<wild> Corresponding objects.
*/
public function loadObjects(
PhabricatorObjectQuery $query,
array $phids) {
$object_query = $this->buildQueryForObjects($query, $phids)
->setViewer($query->getViewer())
->setParentQuery($query);
// If the user doesn't have permission to use the application at all,
// just mark all the PHIDs as filtered. This primarily makes these
// objects show up as "Restricted" instead of "Unknown" when loaded as
// handles, which is technically true.
if (!$object_query->canViewerUseQueryApplication()) {
$object_query->addPolicyFilteredPHIDs(array_fuse($phids));
return array();
}
return $object_query->execute();
}
/**
* Populate provided handles with application-specific data, like titles and
* URIs.
@ -38,7 +81,7 @@ abstract class PhabricatorPHIDType {
* @param PhabricatorHandleQuery Issuing query object.
* @param list<PhabricatorObjectHandle> Handles to populate with data.
* @param list<Object> Objects for these PHIDs loaded by
* @{method:loadObjects()}.
* @{method:buildQueryForObjects()}.
* @return void
*/
abstract public function loadHandles(

View file

@ -16,15 +16,12 @@ final class PhluxPHIDTypeVariable extends PhabricatorPHIDType {
return new PhluxVariable();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhluxVariableQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -65,4 +65,8 @@ final class PhluxVariableQuery
return true;
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationPhlux';
}
}

View file

@ -16,15 +16,12 @@ final class PholioPHIDTypeImage extends PhabricatorPHIDType {
return new PholioImage();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PholioImageQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -16,15 +16,12 @@ final class PholioPHIDTypeMock extends PhabricatorPHIDType {
return new PholioMock();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PholioMockQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -161,4 +161,8 @@ final class PholioImageQuery
return $images;
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationPholio';
}
}

View file

@ -161,4 +161,8 @@ final class PholioMockQuery
}
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationPholio';
}
}

View file

@ -95,4 +95,9 @@ final class PhortuneAccountQuery
return implode(' ', $joins);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationPhortune';
}
}

View file

@ -110,4 +110,9 @@ final class PhortunePaymentMethodQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationPhortune';
}
}

View file

@ -53,4 +53,8 @@ final class PhortuneProductQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationPhortune';
}
}

View file

@ -302,4 +302,9 @@ final class PhrequentUserTimeQuery
return $sum_ended['N'] + $sum_not_ended['N'];
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationPhrequent';
}
}

View file

@ -16,15 +16,12 @@ final class PhrictionPHIDTypeDocument extends PhabricatorPHIDType {
return new PhrictionDocument();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhrictionDocumentQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -185,4 +185,9 @@ final class PhrictionDocumentQuery
}
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationPhriction';
}
}

View file

@ -33,4 +33,8 @@ final class PhabricatorPolicyAwareTestQuery
$this->offset += count($page);
}
public function getQueryApplicationClass() {
return null;
}
}

View file

@ -210,6 +210,22 @@ final class PhabricatorPolicyTestCase extends PhabricatorTestCase {
count($query->execute()));
}
public function testAllQueriesBelongToActualApplications() {
$queries = id(new PhutilSymbolLoader())
->setAncestorClass('PhabricatorPolicyAwareQuery')
->loadObjects();
foreach ($queries as $qclass => $query) {
$class = $query->getQueryApplicationClass();
if (!$class) {
continue;
}
$this->assertEqual(
true,
class_exists($class),
"Application class '{$class}' for query '{$qclass}'");
}
}
/**
* Test an object for visibility across multiple user specifications.

View file

@ -17,15 +17,12 @@ final class PhabricatorPolicyPHIDTypePolicy
return new PhabricatorPolicy();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorPolicyQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -223,5 +223,10 @@ final class PhabricatorPolicyQuery
return true;
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationPolicy';
}
}

View file

@ -16,15 +16,12 @@ final class PonderPHIDTypeAnswer extends PhabricatorPHIDType {
return new PonderAnswer();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PonderAnswerQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -16,15 +16,12 @@ final class PonderPHIDTypeQuestion extends PhabricatorPHIDType {
return new PonderQuestion();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PonderQuestionQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -123,4 +123,9 @@ final class PonderAnswerQuery
return true;
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationPonder';
}
}

View file

@ -194,4 +194,9 @@ final class PonderQuestionQuery
return implode(' ', $joins);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationPonder';
}
}

View file

@ -16,15 +16,12 @@ final class PhabricatorProjectPHIDTypeProject extends PhabricatorPHIDType {
return new PhabricatorProject();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorProjectQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -260,4 +260,9 @@ final class PhabricatorProjectQuery
return implode(' ', $joins);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationProject';
}
}

View file

@ -16,15 +16,12 @@ final class ReleephPHIDTypeBranch extends PhabricatorPHIDType {
return new ReleephBranch();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new ReleephBranchQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -16,15 +16,12 @@ final class ReleephPHIDTypeProject extends PhabricatorPHIDType {
return new ReleephProject();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new ReleephProjectQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -16,15 +16,12 @@ final class ReleephPHIDTypeRequest extends PhabricatorPHIDType {
return new ReleephRequest();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new ReleephRequestQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -129,4 +129,9 @@ final class ReleephBranchQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationReleeph';
}
}

View file

@ -127,4 +127,8 @@ final class ReleephProjectQuery
}
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationReleeph';
}
}

View file

@ -232,4 +232,9 @@ final class ReleephRequestQuery
}
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationReleeph';
}
}

View file

@ -20,15 +20,12 @@ final class PhabricatorRepositoryPHIDTypeArcanistProject
return new PhabricatorRepositoryArcanistProject();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorRepositoryArcanistProjectQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -16,15 +16,12 @@ final class PhabricatorRepositoryPHIDTypeCommit extends PhabricatorPHIDType {
return new PhabricatorRepositoryCommit();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new DiffusionCommitQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -17,15 +17,12 @@ final class PhabricatorRepositoryPHIDTypeRepository
return new PhabricatorRepository();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorRepositoryQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -81,4 +81,10 @@ final class PhabricatorRepositoryArcanistProjectQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
// TODO: Diffusion? Differential?
return null;
}
}

View file

@ -317,4 +317,9 @@ final class PhabricatorRepositoryQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationDiffusion';
}
}

View file

@ -81,4 +81,10 @@ final class PhabricatorNamedQueryQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationSearch';
}
}

View file

@ -65,4 +65,10 @@ final class PhabricatorSavedQueryQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationSearch';
}
}

View file

@ -16,15 +16,12 @@ final class PhabricatorSlowvotePHIDTypePoll extends PhabricatorPHIDType {
return new PhabricatorSlowvotePoll();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorSlowvoteQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -168,4 +168,9 @@ final class PhabricatorSlowvoteQuery
return 'p.id';
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationSlowvote';
}
}

View file

@ -16,15 +16,12 @@ final class PhabricatorTokenPHIDTypeToken extends PhabricatorPHIDType {
return new PhabricatorToken();
}
public function loadObjects(
protected function buildQueryForObjects(
PhabricatorObjectQuery $query,
array $phids) {
return id(new PhabricatorTokenQuery())
->setViewer($query->getViewer())
->setParentQuery($query)
->withPHIDs($phids)
->execute();
->withPHIDs($phids);
}
public function loadHandles(

View file

@ -89,4 +89,8 @@ final class PhabricatorTokenGivenQuery
return $results;
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationTokens';
}
}

View file

@ -61,4 +61,9 @@ final class PhabricatorTokenQuery
return $tokens;
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationTokens';
}
}

View file

@ -34,4 +34,8 @@ final class PhabricatorTokenReceiverQuery
return $this->tokenCounts;
}
public function getQueryApplicationClass() {
return 'PhabricatorApplicationTokens';
}
}

View file

@ -20,6 +20,12 @@ final class PhabricatorApplicationTransactionPHIDTypeTransaction
return null;
}
protected function buildQueryForObjects(
PhabricatorObjectQuery $object_query,
array $phids) {
throw new Exception();
}
public function loadObjects(
PhabricatorObjectQuery $object_query,
array $phids) {
@ -55,11 +61,17 @@ final class PhabricatorApplicationTransactionPHIDTypeTransaction
continue;
}
$xactions = id(clone $query)
$xaction_query = id(clone $query)
->setViewer($object_query->getViewer())
->setParentQuery($object_query)
->withPHIDs($subtype_phids)
->execute();
->withPHIDs($subtype_phids);
if (!$xaction_query->canViewerUseQueryApplication()) {
$object_query->addPolicyFilteredPHIDs(array_fuse($subtype_phids));
continue;
}
$xactions = $xaction_query->execute();
$results += mpull($xactions, null, 'getPHID');
}

View file

@ -59,4 +59,10 @@ final class PhabricatorApplicationTransactionCommentQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
// TODO: Figure out the app via the template?
return null;
}
}

View file

@ -160,4 +160,10 @@ abstract class PhabricatorApplicationTransactionQuery
return $this->formatWhereClause($where);
}
public function getQueryApplicationClass() {
// TODO: Sort this out?
return null;
}
}

View file

@ -35,6 +35,7 @@ abstract class PhabricatorPolicyAwareQuery extends PhabricatorOffsetPagedQuery {
private $capabilities;
private $workspace = array();
private $policyFilteredPHIDs = array();
private $canUseApplication;
/* -( Query Configuration )------------------------------------------------ */
@ -213,9 +214,13 @@ abstract class PhabricatorPolicyAwareQuery extends PhabricatorOffsetPagedQuery {
$this->rawResultLimit = 0;
}
try {
$page = $this->loadPage();
} catch (PhabricatorEmptyQueryException $ex) {
if ($this->canViewerUseQueryApplication()) {
try {
$page = $this->loadPage();
} catch (PhabricatorEmptyQueryException $ex) {
$page = array();
}
} else {
$page = array();
}
@ -317,7 +322,7 @@ abstract class PhabricatorPolicyAwareQuery extends PhabricatorOffsetPagedQuery {
PhabricatorPolicyCapability::CAN_VIEW);
}
protected function addPolicyFilteredPHIDs(array $phids) {
public function addPolicyFilteredPHIDs(array $phids) {
$this->policyFilteredPHIDs += $phids;
if ($this->getParentQuery()) {
$this->getParentQuery()->addPolicyFilteredPHIDs($phids);
@ -581,4 +586,43 @@ abstract class PhabricatorPolicyAwareQuery extends PhabricatorOffsetPagedQuery {
return false;
}
/**
* If this query belongs to an application, return the application class name
* here. This will prevent the query from returning results if the viewer can
* not access the application.
*
* If this query does not belong to an application, return `null`.
*
* @return string|null Application class name.
*/
abstract public function getQueryApplicationClass();
/**
* Determine if the viewer has permission to use this query's application.
* For queries which aren't part of an application, this method always returns
* true.
*
* @return bool True if the viewer has application-level permission to
* execute the query.
*/
public function canViewerUseQueryApplication() {
if ($this->canUseApplication === null) {
$class = $this->getQueryApplicationClass();
if (!$class) {
$this->canUseApplication = true;
} else {
$result = id(new PhabricatorApplicationQuery())
->setViewer($this->getViewer())
->withClasses(array($class))
->execute();
$this->canUseApplication = (bool)$result;
}
}
return $this->canUseApplication;
}
}