Clean up some EditEngine policy issues
Summary: Ref T9908. - You should not need edit permission on a task in order to comment on it. - At least for now, ignore any customization in Conduit and Stacked Actions. These UIs always use the full edit form as it's written in the application. Test Plan: - Verified a non-editor can now comment on tasks they can see. - Verified a user still can't use an edit form they can't see. Reviewers: chad Reviewed By: chad Maniphest Tasks: T9908 Differential Revision: https://secure.phabricator.com/D14691
This commit is contained in:
		@@ -190,22 +190,51 @@ abstract class PhabricatorEditEngine
 | 
				
			|||||||
    return $this->editEngineConfiguration;
 | 
					    return $this->editEngineConfiguration;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private function loadEditEngineConfiguration($key) {
 | 
					 | 
				
			||||||
    $viewer = $this->getViewer();
 | 
					 | 
				
			||||||
    if ($key === null) {
 | 
					 | 
				
			||||||
      $key = self::EDITENGINECONFIG_DEFAULT;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // TODO: At least for now, we need to load the default configuration
 | 
					  /**
 | 
				
			||||||
      // in some cases (editing, comment actions) even if the viewer can not
 | 
					   * Load the default configuration, ignoring customization in the database
 | 
				
			||||||
      // otherwise see it. This should be cleaned up eventually, but we can
 | 
					   * (which means we implicitly ignore policies).
 | 
				
			||||||
      // safely use the omnipotent user for now without policy violations.
 | 
					   *
 | 
				
			||||||
      $viewer = PhabricatorUser::getOmnipotentUser();
 | 
					   * This is used from places like Conduit, where the fields available in the
 | 
				
			||||||
 | 
					   * API should not be affected by configuration changes.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @return PhabricatorEditEngineConfiguration Default configuration, ignoring
 | 
				
			||||||
 | 
					   *   customization.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  private function loadDefaultEditEngineConfiguration() {
 | 
				
			||||||
 | 
					    return $this->loadEditEngineConfigurationWithOptions(
 | 
				
			||||||
 | 
					      self::EDITENGINECONFIG_DEFAULT,
 | 
				
			||||||
 | 
					      true);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * Load a named configuration, respecting database customization and policies.
 | 
				
			||||||
 | 
					   *
 | 
				
			||||||
 | 
					   * @param string Configuration key, or null to load the default.
 | 
				
			||||||
 | 
					   * @return PhabricatorEditEngineConfiguration Default configuration,
 | 
				
			||||||
 | 
					   *   respecting customization.
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  private function loadEditEngineConfiguration($key) {
 | 
				
			||||||
 | 
					    if (!strlen($key)) {
 | 
				
			||||||
 | 
					      $key = self::EDITENGINECONFIG_DEFAULT;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return $this->loadEditEngineConfigurationWithOptions(
 | 
				
			||||||
 | 
					      $key,
 | 
				
			||||||
 | 
					      false);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private function loadEditEngineConfigurationWithOptions(
 | 
				
			||||||
 | 
					    $key,
 | 
				
			||||||
 | 
					    $ignore_database) {
 | 
				
			||||||
 | 
					    $viewer = $this->getViewer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $config = id(new PhabricatorEditEngineConfigurationQuery())
 | 
					    $config = id(new PhabricatorEditEngineConfigurationQuery())
 | 
				
			||||||
      ->setViewer($viewer)
 | 
					      ->setViewer($viewer)
 | 
				
			||||||
      ->withEngineKeys(array($this->getEngineKey()))
 | 
					      ->withEngineKeys(array($this->getEngineKey()))
 | 
				
			||||||
      ->withIdentifiers(array($key))
 | 
					      ->withIdentifiers(array($key))
 | 
				
			||||||
 | 
					      ->withIgnoreDatabaseConfigurations($ignore_database)
 | 
				
			||||||
      ->executeOne();
 | 
					      ->executeOne();
 | 
				
			||||||
    if (!$config) {
 | 
					    if (!$config) {
 | 
				
			||||||
      return null;
 | 
					      return null;
 | 
				
			||||||
@@ -482,14 +511,16 @@ abstract class PhabricatorEditEngine
 | 
				
			|||||||
   * Load an object by ID.
 | 
					   * Load an object by ID.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @param int Object ID.
 | 
					   * @param int Object ID.
 | 
				
			||||||
 | 
					   * @param list<const> List of required capability constants, or omit for
 | 
				
			||||||
 | 
					   *   defaults.
 | 
				
			||||||
   * @return object|null Object, or null if no such object exists.
 | 
					   * @return object|null Object, or null if no such object exists.
 | 
				
			||||||
   * @task load
 | 
					   * @task load
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  private function newObjectFromID($id) {
 | 
					  private function newObjectFromID($id, array $capabilities = array()) {
 | 
				
			||||||
    $query = $this->newObjectQuery()
 | 
					    $query = $this->newObjectQuery()
 | 
				
			||||||
      ->withIDs(array($id));
 | 
					      ->withIDs(array($id));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return $this->newObjectFromQuery($query);
 | 
					    return $this->newObjectFromQuery($query, $capabilities);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -512,19 +543,27 @@ abstract class PhabricatorEditEngine
 | 
				
			|||||||
   * Load an object given a configured query.
 | 
					   * Load an object given a configured query.
 | 
				
			||||||
   *
 | 
					   *
 | 
				
			||||||
   * @param PhabricatorPolicyAwareQuery Configured query.
 | 
					   * @param PhabricatorPolicyAwareQuery Configured query.
 | 
				
			||||||
 | 
					   * @param list<const> List of required capabilitiy constants, or omit for
 | 
				
			||||||
 | 
					   *  defaults.
 | 
				
			||||||
   * @return object|null Object, or null if no such object exists.
 | 
					   * @return object|null Object, or null if no such object exists.
 | 
				
			||||||
   * @task load
 | 
					   * @task load
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  private function newObjectFromQuery(PhabricatorPolicyAwareQuery $query) {
 | 
					  private function newObjectFromQuery(
 | 
				
			||||||
 | 
					    PhabricatorPolicyAwareQuery $query,
 | 
				
			||||||
 | 
					    array $capabilities = array()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $viewer = $this->getViewer();
 | 
					    $viewer = $this->getViewer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!$capabilities) {
 | 
				
			||||||
 | 
					      $capabilities = array(
 | 
				
			||||||
 | 
					        PhabricatorPolicyCapability::CAN_VIEW,
 | 
				
			||||||
 | 
					        PhabricatorPolicyCapability::CAN_EDIT,
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $object = $query
 | 
					    $object = $query
 | 
				
			||||||
      ->setViewer($viewer)
 | 
					      ->setViewer($viewer)
 | 
				
			||||||
      ->requireCapabilities(
 | 
					      ->requireCapabilities($capabilities)
 | 
				
			||||||
        array(
 | 
					 | 
				
			||||||
          PhabricatorPolicyCapability::CAN_VIEW,
 | 
					 | 
				
			||||||
          PhabricatorPolicyCapability::CAN_EDIT,
 | 
					 | 
				
			||||||
        ))
 | 
					 | 
				
			||||||
      ->executeOne();
 | 
					      ->executeOne();
 | 
				
			||||||
    if (!$object) {
 | 
					    if (!$object) {
 | 
				
			||||||
      return null;
 | 
					      return null;
 | 
				
			||||||
@@ -571,8 +610,28 @@ abstract class PhabricatorEditEngine
 | 
				
			|||||||
    $controller = $this->getController();
 | 
					    $controller = $this->getController();
 | 
				
			||||||
    $request = $controller->getRequest();
 | 
					    $request = $controller->getRequest();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $form_key = $request->getURIData('formKey');
 | 
					    $action = $request->getURIData('editAction');
 | 
				
			||||||
    $config = $this->loadEditEngineConfiguration($form_key);
 | 
					
 | 
				
			||||||
 | 
					    $capabilities = array();
 | 
				
			||||||
 | 
					    $use_default = false;
 | 
				
			||||||
 | 
					    switch ($action) {
 | 
				
			||||||
 | 
					      case 'comment':
 | 
				
			||||||
 | 
					        $capabilities = array(
 | 
				
			||||||
 | 
					          PhabricatorPolicyCapability::CAN_VIEW,
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        $use_default = true;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ($use_default) {
 | 
				
			||||||
 | 
					      $config = $this->loadDefaultEditEngineConfiguration();
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      $form_key = $request->getURIData('formKey');
 | 
				
			||||||
 | 
					      $config = $this->loadEditEngineConfiguration($form_key);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!$config) {
 | 
					    if (!$config) {
 | 
				
			||||||
      return new Aphront404Response();
 | 
					      return new Aphront404Response();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -580,7 +639,7 @@ abstract class PhabricatorEditEngine
 | 
				
			|||||||
    $id = $request->getURIData('id');
 | 
					    $id = $request->getURIData('id');
 | 
				
			||||||
    if ($id) {
 | 
					    if ($id) {
 | 
				
			||||||
      $this->setIsCreate(false);
 | 
					      $this->setIsCreate(false);
 | 
				
			||||||
      $object = $this->newObjectFromID($id);
 | 
					      $object = $this->newObjectFromID($id, $capabilities);
 | 
				
			||||||
      if (!$object) {
 | 
					      if (!$object) {
 | 
				
			||||||
        return new Aphront404Response();
 | 
					        return new Aphront404Response();
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -591,7 +650,6 @@ abstract class PhabricatorEditEngine
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    $this->validateObject($object);
 | 
					    $this->validateObject($object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $action = $request->getURIData('editAction');
 | 
					 | 
				
			||||||
    switch ($action) {
 | 
					    switch ($action) {
 | 
				
			||||||
      case 'parameters':
 | 
					      case 'parameters':
 | 
				
			||||||
        return $this->buildParametersResponse($object);
 | 
					        return $this->buildParametersResponse($object);
 | 
				
			||||||
@@ -880,7 +938,7 @@ abstract class PhabricatorEditEngine
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  final public function buildEditEngineCommentView($object) {
 | 
					  final public function buildEditEngineCommentView($object) {
 | 
				
			||||||
    $config = $this->loadEditEngineConfiguration(null);
 | 
					    $config = $this->loadDefaultEditEngineConfiguration();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $viewer = $this->getViewer();
 | 
					    $viewer = $this->getViewer();
 | 
				
			||||||
    $object_phid = $object->getPHID();
 | 
					    $object_phid = $object->getPHID();
 | 
				
			||||||
@@ -1021,7 +1079,7 @@ abstract class PhabricatorEditEngine
 | 
				
			|||||||
      return new Aphront400Response();
 | 
					      return new Aphront400Response();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $config = $this->loadEditEngineConfiguration(null);
 | 
					    $config = $this->loadDefaultEditEngineConfiguration();
 | 
				
			||||||
    $fields = $this->buildEditFields($object);
 | 
					    $fields = $this->buildEditFields($object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $is_preview = $request->isPreviewRequest();
 | 
					    $is_preview = $request->isPreviewRequest();
 | 
				
			||||||
@@ -1151,7 +1209,7 @@ abstract class PhabricatorEditEngine
 | 
				
			|||||||
  final public function buildConduitResponse(ConduitAPIRequest $request) {
 | 
					  final public function buildConduitResponse(ConduitAPIRequest $request) {
 | 
				
			||||||
    $viewer = $this->getViewer();
 | 
					    $viewer = $this->getViewer();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $config = $this->loadEditEngineConfiguration(null);
 | 
					    $config = $this->loadDefaultEditEngineConfiguration();
 | 
				
			||||||
    if (!$config) {
 | 
					    if (!$config) {
 | 
				
			||||||
      throw new Exception(
 | 
					      throw new Exception(
 | 
				
			||||||
        pht(
 | 
					        pht(
 | 
				
			||||||
@@ -1297,7 +1355,7 @@ abstract class PhabricatorEditEngine
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function getConduitEditTypes() {
 | 
					  public function getConduitEditTypes() {
 | 
				
			||||||
    $config = $this->loadEditEngineConfiguration(null);
 | 
					    $config = $this->loadDefaultEditEngineConfiguration();
 | 
				
			||||||
    if (!$config) {
 | 
					    if (!$config) {
 | 
				
			||||||
      return array();
 | 
					      return array();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,7 @@ final class PhabricatorEditEngineConfigurationQuery
 | 
				
			|||||||
  private $identifiers;
 | 
					  private $identifiers;
 | 
				
			||||||
  private $default;
 | 
					  private $default;
 | 
				
			||||||
  private $disabled;
 | 
					  private $disabled;
 | 
				
			||||||
 | 
					  private $ignoreDatabaseConfigurations;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function withIDs(array $ids) {
 | 
					  public function withIDs(array $ids) {
 | 
				
			||||||
    $this->ids = $ids;
 | 
					    $this->ids = $ids;
 | 
				
			||||||
@@ -46,6 +47,11 @@ final class PhabricatorEditEngineConfigurationQuery
 | 
				
			|||||||
    return $this;
 | 
					    return $this;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public function withIgnoreDatabaseConfigurations($ignore) {
 | 
				
			||||||
 | 
					    $this->ignoreDatabaseConfigurations = $ignore;
 | 
				
			||||||
 | 
					    return $this;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public function newResultObject() {
 | 
					  public function newResultObject() {
 | 
				
			||||||
    return new PhabricatorEditEngineConfiguration();
 | 
					    return new PhabricatorEditEngineConfiguration();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -57,7 +63,11 @@ final class PhabricatorEditEngineConfigurationQuery
 | 
				
			|||||||
    // number of edit forms for any particular engine for the lack of UI
 | 
					    // number of edit forms for any particular engine for the lack of UI
 | 
				
			||||||
    // pagination to become a problem.
 | 
					    // pagination to become a problem.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $page = $this->loadStandardPage($this->newResultObject());
 | 
					    if ($this->ignoreDatabaseConfigurations) {
 | 
				
			||||||
 | 
					      $page = array();
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      $page = $this->loadStandardPage($this->newResultObject());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Now that we've loaded the real results from the database, we're going
 | 
					    // Now that we've loaded the real results from the database, we're going
 | 
				
			||||||
    // to load builtins from the edit engines and add them to the list.
 | 
					    // to load builtins from the edit engines and add them to the list.
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user