From d63789e4b2a03bc47d1083d48665b290b060e3fe Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 23 Sep 2013 12:53:41 -0700 Subject: [PATCH] Allow repository policies to be edited Summary: Ref T603. Allows permitted users to set view and edit policies for repositories. So far the repository list, repository detail, repository edit, and browse interfaces respect these settings. Most other interfaces will respect stricter settings, but "Public" won't work. Lots of rough edges in the integration still. None of this makes policies any looser than they were already without explicit user intervention, so I just put a warning about it in the UI. Test Plan: Set a repository to public and browsed it. Verified I could not access non-public repositories. Reviewers: btrahan Reviewed By: btrahan CC: aran, davidressman Maniphest Tasks: T603 Differential Revision: https://secure.phabricator.com/D7061 --- src/__phutil_library_map__.php | 2 + .../PhabricatorApplicationDiffusion.php | 1 + .../controller/DiffusionBrowseController.php | 4 + .../DiffusionRepositoryController.php | 4 + .../DiffusionRepositoryEditController.php | 51 ++++++++ ...iffusionRepositoryEditPolicyController.php | 113 ++++++++++++++++++ .../editor/PhabricatorRepositoryEditor.php | 2 + .../storage/PhabricatorRepository.php | 4 +- 8 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 src/applications/diffusion/controller/DiffusionRepositoryEditPolicyController.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 160a6ff000..fe7c78300e 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -498,6 +498,7 @@ phutil_register_library_map(array( 'DiffusionRepositoryEditBasicController' => 'applications/diffusion/controller/DiffusionRepositoryEditBasicController.php', 'DiffusionRepositoryEditController' => 'applications/diffusion/controller/DiffusionRepositoryEditController.php', 'DiffusionRepositoryEditEncodingController' => 'applications/diffusion/controller/DiffusionRepositoryEditEncodingController.php', + 'DiffusionRepositoryEditPolicyController' => 'applications/diffusion/controller/DiffusionRepositoryEditPolicyController.php', 'DiffusionRepositoryListController' => 'applications/diffusion/controller/DiffusionRepositoryListController.php', 'DiffusionRepositoryPath' => 'applications/diffusion/data/DiffusionRepositoryPath.php', 'DiffusionRepositoryTag' => 'applications/diffusion/data/DiffusionRepositoryTag.php', @@ -2559,6 +2560,7 @@ phutil_register_library_map(array( 'DiffusionRepositoryEditBasicController' => 'DiffusionController', 'DiffusionRepositoryEditController' => 'DiffusionController', 'DiffusionRepositoryEditEncodingController' => 'DiffusionController', + 'DiffusionRepositoryEditPolicyController' => 'DiffusionController', 'DiffusionRepositoryListController' => array( 0 => 'DiffusionController', diff --git a/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php b/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php index 595f47da07..5ef260b9cf 100644 --- a/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php +++ b/src/applications/diffusion/application/PhabricatorApplicationDiffusion.php @@ -68,6 +68,7 @@ final class PhabricatorApplicationDiffusion extends PhabricatorApplication { 'basic/' => 'DiffusionRepositoryEditBasicController', 'encoding/' => 'DiffusionRepositoryEditEncodingController', 'activate/' => 'DiffusionRepositoryEditActivateController', + 'policy/' => 'DiffusionRepositoryEditPolicyController', ), ), 'inline/' => array( diff --git a/src/applications/diffusion/controller/DiffusionBrowseController.php b/src/applications/diffusion/controller/DiffusionBrowseController.php index 63f68b0fe9..92ad12efad 100644 --- a/src/applications/diffusion/controller/DiffusionBrowseController.php +++ b/src/applications/diffusion/controller/DiffusionBrowseController.php @@ -2,6 +2,10 @@ abstract class DiffusionBrowseController extends DiffusionController { + public function shouldAllowPublic() { + return true; + } + protected function renderSearchForm($collapsed) { $drequest = $this->getDiffusionRequest(); $form = id(new AphrontFormView()) diff --git a/src/applications/diffusion/controller/DiffusionRepositoryController.php b/src/applications/diffusion/controller/DiffusionRepositoryController.php index 8d0c3faf7f..bbcd5d38b2 100644 --- a/src/applications/diffusion/controller/DiffusionRepositoryController.php +++ b/src/applications/diffusion/controller/DiffusionRepositoryController.php @@ -2,6 +2,10 @@ final class DiffusionRepositoryController extends DiffusionController { + public function shouldAllowPublic() { + return true; + } + public function processRequest() { $drequest = $this->diffusionRequest; diff --git a/src/applications/diffusion/controller/DiffusionRepositoryEditController.php b/src/applications/diffusion/controller/DiffusionRepositoryEditController.php index af2d96c8ae..2475872037 100644 --- a/src/applications/diffusion/controller/DiffusionRepositoryEditController.php +++ b/src/applications/diffusion/controller/DiffusionRepositoryEditController.php @@ -33,6 +33,12 @@ final class DiffusionRepositoryEditController extends DiffusionController { $content[] = $this->buildBasicActions($repository); $content[] = $this->buildBasicProperties($repository); + $content[] = id(new PHUIHeaderView()) + ->setHeader(pht('Policies')); + + $content[] = $this->buildPolicyActions($repository); + $content[] = $this->buildPolicyProperties($repository); + $content[] = id(new PHUIHeaderView()) ->setHeader(pht('Text Encoding')); @@ -164,6 +170,7 @@ final class DiffusionRepositoryEditController extends DiffusionController { ->setName(pht('Edit Text Encoding')) ->setHref( $this->getRepositoryControllerURI($repository, 'edit/encoding/')) + ->setWorkflow(!$can_edit) ->setDisabled(!$can_edit); $view->addAction($edit); @@ -186,6 +193,50 @@ final class DiffusionRepositoryEditController extends DiffusionController { return $view; } + private function buildPolicyActions(PhabricatorRepository $repository) { + $viewer = $this->getRequest()->getUser(); + $view = id(new PhabricatorActionListView()) + ->setObjectURI($this->getRequest()->getRequestURI()) + ->setUser($viewer); + + $can_edit = PhabricatorPolicyFilter::hasCapability( + $viewer, + $repository, + PhabricatorPolicyCapability::CAN_EDIT); + + $edit = id(new PhabricatorActionView()) + ->setIcon('edit') + ->setName(pht('Edit Policies')) + ->setHref( + $this->getRepositoryControllerURI($repository, 'edit/policy/')) + ->setWorkflow(!$can_edit) + ->setDisabled(!$can_edit); + $view->addAction($edit); + + return $view; + } + + private function buildPolicyProperties(PhabricatorRepository $repository) { + $viewer = $this->getRequest()->getUser(); + + $view = id(new PhabricatorPropertyListView()) + ->setUser($viewer); + + $descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions( + $viewer, + $repository); + + $view->addProperty( + pht('Visible To'), + $descriptions[PhabricatorPolicyCapability::CAN_VIEW]); + + $view->addProperty( + pht('Editable By'), + $descriptions[PhabricatorPolicyCapability::CAN_EDIT]); + + + return $view; + } } diff --git a/src/applications/diffusion/controller/DiffusionRepositoryEditPolicyController.php b/src/applications/diffusion/controller/DiffusionRepositoryEditPolicyController.php new file mode 100644 index 0000000000..bb5f3463b8 --- /dev/null +++ b/src/applications/diffusion/controller/DiffusionRepositoryEditPolicyController.php @@ -0,0 +1,113 @@ +getRequest(); + $viewer = $request->getUser(); + $drequest = $this->diffusionRequest; + $repository = $drequest->getRepository(); + + $repository = id(new PhabricatorRepositoryQuery()) + ->setViewer($viewer) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->withIDs(array($repository->getID())) + ->executeOne(); + + if (!$repository) { + return new Aphront404Response(); + } + + $edit_uri = $this->getRepositoryControllerURI($repository, 'edit/'); + + $v_view = $repository->getViewPolicy(); + $v_edit = $repository->getEditPolicy(); + + if ($request->isFormPost()) { + $v_view = $request->getStr('viewPolicy'); + $v_edit = $request->getStr('editPolicy'); + + $xactions = array(); + $template = id(new PhabricatorRepositoryTransaction()); + + $type_view = PhabricatorTransactions::TYPE_VIEW_POLICY; + $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY; + + $xactions[] = id(clone $template) + ->setTransactionType($type_view) + ->setNewValue($v_view); + + $xactions[] = id(clone $template) + ->setTransactionType($type_edit) + ->setNewValue($v_edit); + + id(new PhabricatorRepositoryEditor()) + ->setContinueOnNoEffect(true) + ->setContentSourceFromRequest($request) + ->setActor($viewer) + ->applyTransactions($repository, $xactions); + + return id(new AphrontRedirectResponse())->setURI($edit_uri); + } + + $content = array(); + + $crumbs = $this->buildCrumbs(); + $crumbs->addCrumb( + id(new PhabricatorCrumbView()) + ->setName(pht('Edit Policies'))); + + $title = pht('Edit %s', $repository->getName()); + + $policies = id(new PhabricatorPolicyQuery()) + ->setViewer($viewer) + ->setObject($repository) + ->execute(); + + $form = id(new AphrontFormView()) + ->setUser($viewer) + ->appendRemarkupInstructions( + pht( + 'NOTE: The "Visible To" control is not yet fully functional. It '. + 'applies to some interfaces, but some interfaces will bypass this '. + 'setting and act as though it were set to "all users" for now.')) + ->appendChild( + id(new AphrontFormPolicyControl()) + ->setUser($viewer) + ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) + ->setPolicyObject($repository) + ->setPolicies($policies) + ->setName('viewPolicy')) + ->appendChild( + id(new AphrontFormPolicyControl()) + ->setUser($viewer) + ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) + ->setPolicyObject($repository) + ->setPolicies($policies) + ->setName('editPolicy')) + ->appendChild( + id(new AphrontFormSubmitControl()) + ->setValue(pht('Save Policies')) + ->addCancelButton($edit_uri)); + + $form_box = id(new PHUIFormBoxView()) + ->setHeaderText($title) + ->setForm($form); + + return $this->buildApplicationPage( + array( + $crumbs, + $form_box, + ), + array( + 'title' => $title, + 'device' => true, + )); + } + +} diff --git a/src/applications/repository/editor/PhabricatorRepositoryEditor.php b/src/applications/repository/editor/PhabricatorRepositoryEditor.php index c1e30e6aed..bd0561d43c 100644 --- a/src/applications/repository/editor/PhabricatorRepositoryEditor.php +++ b/src/applications/repository/editor/PhabricatorRepositoryEditor.php @@ -10,6 +10,8 @@ final class PhabricatorRepositoryEditor $types[] = PhabricatorRepositoryTransaction::TYPE_NAME; $types[] = PhabricatorRepositoryTransaction::TYPE_DESCRIPTION; $types[] = PhabricatorRepositoryTransaction::TYPE_ENCODING; + $types[] = PhabricatorTransactions::TYPE_VIEW_POLICY; + $types[] = PhabricatorTransactions::TYPE_EDIT_POLICY; return $types; } diff --git a/src/applications/repository/storage/PhabricatorRepository.php b/src/applications/repository/storage/PhabricatorRepository.php index 67137188fa..4c6877bbda 100644 --- a/src/applications/repository/storage/PhabricatorRepository.php +++ b/src/applications/repository/storage/PhabricatorRepository.php @@ -707,9 +707,9 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO public function getPolicy($capability) { switch ($capability) { case PhabricatorPolicyCapability::CAN_VIEW: - return PhabricatorPolicies::POLICY_USER; + return $this->getViewPolicy(); case PhabricatorPolicyCapability::CAN_EDIT: - return PhabricatorPolicies::POLICY_ADMIN; + return $this->getEditPolicy(); } }