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

Apply application visibility checks during normal object filtering

Summary:
Fixes T9058. Normally, "Query" classes apply an application check and just don't load anything if it fails.

However, in some cases (like email recipient filtering) we run policy checks without having run a Query check first. In that case, one user (the actor) loads the object, then we filter it against other users (the recipeints).

Explicitly apply the application check during normal filtering.

Test Plan: Added a failing test case and made it pass.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9058

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

+93 -2
+2 -2
src/applications/base/PhabricatorApplication.php
··· 429 429 } 430 430 431 431 $cache = PhabricatorCaches::getRequestCache(); 432 - $viewer_phid = $viewer->getPHID(); 433 - $key = 'app.'.$class.'.installed.'.$viewer_phid; 432 + $viewer_fragment = $viewer->getCacheFragment(); 433 + $key = 'app.'.$class.'.installed.'.$viewer_fragment; 434 434 435 435 $result = $cache->getKey($key); 436 436 if ($result === null) {
+51
src/applications/policy/filter/PhabricatorPolicyFilter.php
··· 123 123 return $objects; 124 124 } 125 125 126 + // Before doing any actual object checks, make sure the viewer can see 127 + // the applications that these objects belong to. This is normally enforced 128 + // in the Query layer before we reach object filtering, but execution 129 + // sometimes reaches policy filtering without running application checks. 130 + $objects = $this->applyApplicationChecks($objects); 131 + 126 132 $filtered = array(); 127 133 $viewer_phid = $viewer->getPHID(); 128 134 ··· 862 868 ->setCapability(PhabricatorPolicyCapability::CAN_VIEW); 863 869 864 870 throw $exception; 871 + } 872 + 873 + private function applyApplicationChecks(array $objects) { 874 + $viewer = $this->viewer; 875 + 876 + foreach ($objects as $key => $object) { 877 + $phid = $object->getPHID(); 878 + if (!$phid) { 879 + continue; 880 + } 881 + 882 + $application_class = $this->getApplicationForPHID($phid); 883 + if ($application_class === null) { 884 + continue; 885 + } 886 + 887 + $can_see = PhabricatorApplication::isClassInstalledForViewer( 888 + $application_class, 889 + $viewer); 890 + if ($can_see) { 891 + continue; 892 + } 893 + 894 + unset($objects[$key]); 895 + 896 + $application = newv($application_class, array()); 897 + $this->rejectObject( 898 + $application, 899 + $application->getPolicy(PhabricatorPolicyCapability::CAN_VIEW), 900 + PhabricatorPolicyCapability::CAN_VIEW); 901 + } 902 + 903 + return $objects; 904 + } 905 + 906 + private function getApplicationForPHID($phid) { 907 + $phid_type = phid_get_type($phid); 908 + 909 + $type_objects = PhabricatorPHIDType::getTypes(array($phid_type)); 910 + $type_object = idx($type_objects, $phid_type); 911 + if (!$type_object) { 912 + return null; 913 + } 914 + 915 + return $type_object->getPHIDTypeApplicationClass(); 865 916 } 866 917 867 918 }
+40
src/applications/project/__tests__/PhabricatorProjectCoreTestCase.php
··· 39 39 $this->assertFalse((bool)$this->refreshProject($proj, $user2)); 40 40 } 41 41 42 + public function testApplicationPolicy() { 43 + $user = $this->createUser() 44 + ->save(); 45 + 46 + $proj = $this->createProject($user); 47 + 48 + $this->assertTrue( 49 + PhabricatorPolicyFilter::hasCapability( 50 + $user, 51 + $proj, 52 + PhabricatorPolicyCapability::CAN_VIEW)); 53 + 54 + // Change the "Can Use Application" policy for Projecs to "No One". This 55 + // should cause filtering checks to fail even when they are executed 56 + // directly rather than via a Query. 57 + $env = PhabricatorEnv::beginScopedEnv(); 58 + $env->overrideEnvConfig( 59 + 'phabricator.application-settings', 60 + array( 61 + 'PHID-APPS-PhabricatorProjectApplication' => array( 62 + 'policy' => array( 63 + 'view' => PhabricatorPolicies::POLICY_NOONE, 64 + ), 65 + ), 66 + )); 67 + 68 + // Application visibility is cached because it does not normally change 69 + // over the course of a single request. Drop the cache so the next filter 70 + // test uses the new visibility. 71 + PhabricatorCaches::destroyRequestCache(); 72 + 73 + $this->assertFalse( 74 + PhabricatorPolicyFilter::hasCapability( 75 + $user, 76 + $proj, 77 + PhabricatorPolicyCapability::CAN_VIEW)); 78 + 79 + unset($env); 80 + } 81 + 42 82 public function testIsViewerMemberOrWatcher() { 43 83 $user1 = $this->createUser() 44 84 ->save();