diff --git a/src/applications/policy/filter/PhabricatorPolicyFilter.php b/src/applications/policy/filter/PhabricatorPolicyFilter.php --- a/src/applications/policy/filter/PhabricatorPolicyFilter.php +++ b/src/applications/policy/filter/PhabricatorPolicyFilter.php @@ -874,6 +874,19 @@ $viewer = $this->viewer; foreach ($objects as $key => $object) { + // Don't filter handles: users are allowed to see handles from an + // application they can't see even if they can not see objects from + // that application. Note that the application policies still apply to + // the underlying object, so these will be "Restricted Object" handles. + + // If we don't let these through, PhabricatorHandleQuery will completely + // fail to load results for PHIDs that are part of applications which + // the viewer can not see, but a fundamental property of handles is that + // we always load something and they can safely be assumed to load. + if ($object instanceof PhabricatorObjectHandle) { + continue; + } + $phid = $object->getPHID(); if (!$phid) { continue; diff --git a/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php b/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php --- a/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php +++ b/src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php @@ -51,6 +51,13 @@ $proj, PhabricatorPolicyCapability::CAN_VIEW)); + // This object is visible so its handle should load normally. + $handle = id(new PhabricatorHandleQuery()) + ->setViewer($user) + ->withPHIDs(array($proj->getPHID())) + ->executeOne(); + $this->assertEqual($proj->getPHID(), $handle->getPHID()); + // Change the "Can Use Application" policy for Projecs to "No One". This // should cause filtering checks to fail even when they are executed // directly rather than via a Query. @@ -76,6 +83,19 @@ $proj, PhabricatorPolicyCapability::CAN_VIEW)); + // We should still be able to load a handle for the project, even if we + // can not see the application. + $handle = id(new PhabricatorHandleQuery()) + ->setViewer($user) + ->withPHIDs(array($proj->getPHID())) + ->executeOne(); + + // The handle should load... + $this->assertEqual($proj->getPHID(), $handle->getPHID()); + + // ...but be policy filtered. + $this->assertTrue($handle->getPolicyFiltered()); + unset($env); }