Changeset View
Changeset View
Standalone View
Standalone View
src/applications/policy/filter/PhabricatorPolicyFilter.php
| Show First 20 Lines • Show All 447 Lines • ▼ Show 20 Lines | private function checkCapability( | ||||
| } | } | ||||
| $viewer = $this->viewer; | $viewer = $this->viewer; | ||||
| if ($viewer->isOmnipotent()) { | if ($viewer->isOmnipotent()) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| if ($object instanceof PhabricatorSpacesInterface) { | |||||
| $space_phid = $object->getSpacePHID(); | |||||
| if (!$this->canViewerSeeObjectsInSpace($viewer, $space_phid)) { | |||||
| $this->rejectObjectFromSpace($object, $space_phid); | |||||
| return false; | |||||
| } | |||||
| } | |||||
| if ($object->hasAutomaticCapability($capability, $viewer)) { | if ($object->hasAutomaticCapability($capability, $viewer)) { | ||||
| return true; | return true; | ||||
| } | } | ||||
epriestley: We can just swap the order here to make automatic capabilities stronger than spaces, but then… | |||||
| switch ($policy) { | switch ($policy) { | ||||
| case PhabricatorPolicies::POLICY_PUBLIC: | case PhabricatorPolicies::POLICY_PUBLIC: | ||||
| return true; | return true; | ||||
| case PhabricatorPolicies::POLICY_USER: | case PhabricatorPolicies::POLICY_USER: | ||||
| if ($viewer->getPHID()) { | if ($viewer->getPHID()) { | ||||
| return true; | return true; | ||||
| } else { | } else { | ||||
| ▲ Show 20 Lines • Show All 204 Lines • ▼ Show 20 Lines | if ($is_serious) { | ||||
| $access_denied = pht( | $access_denied = pht( | ||||
| 'You Shall Not Pass: %s', | 'You Shall Not Pass: %s', | ||||
| $object_name); | $object_name); | ||||
| } | } | ||||
| return $access_denied; | return $access_denied; | ||||
| } | } | ||||
| private function canViewerSeeObjectsInSpace( | |||||
| PhabricatorUser $viewer, | |||||
| $space_phid) { | |||||
| $spaces = PhabricatorSpacesNamespaceQuery::getAllSpaces(); | |||||
| // If there are no spaces, everything exists in an implicit default space | |||||
| // with no policy controls. This is the default state. | |||||
| if (!$spaces) { | |||||
| if ($space_phid !== null) { | |||||
| return false; | |||||
| } else { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| if ($space_phid === null) { | |||||
| $space = PhabricatorSpacesNamespaceQuery::getDefaultSpace(); | |||||
| } else { | |||||
| $space = idx($spaces, $space_phid); | |||||
| } | |||||
| if (!$space) { | |||||
| return false; | |||||
| } | |||||
| // This may be more involved later, but for now being able to see the | |||||
| // space is equivalent to being able to see everything in it. | |||||
| return self::hasCapability( | |||||
| $viewer, | |||||
| $space, | |||||
| PhabricatorPolicyCapability::CAN_VIEW); | |||||
| } | |||||
| private function rejectObjectFromSpace( | |||||
| PhabricatorPolicyInterface $object, | |||||
| $space_phid) { | |||||
| if (!$this->raisePolicyExceptions) { | |||||
| return; | |||||
| } | |||||
| if ($this->viewer->isOmnipotent()) { | |||||
| return; | |||||
| } | |||||
| $access_denied = $this->renderAccessDenied($object); | |||||
| $rejection = pht( | |||||
| 'This object is in a space you do not have permission to access.'); | |||||
| $full_message = pht('[%s] %s', $access_denied, $rejection); | |||||
| $exception = id(new PhabricatorPolicyException($full_message)) | |||||
| ->setTitle($access_denied) | |||||
| ->setRejection($rejection); | |||||
| throw $exception; | |||||
| } | |||||
| } | } | ||||
We can just swap the order here to make automatic capabilities stronger than spaces, but then we have to drop the automatic WHERE spacePHID IN (...) constraint in the query and potentially do a lot more filtering in-process, which might be slow.