Files
phabricator/src/applications/harbormaster/controller/HarbormasterStepAddController.php
epriestley 5ee4a1a306 Give Harbormaster Build Plans real policies
Summary:
Ref T9614. Currently, a lot of Build Plan behavior is covered by a global "can manage" policy.

One install in particular is experiencing difficulty with warring factions within engineering aborting one another's builds.

As a first step to remedy this, and also generally make Harbormaster more flexible and bring it in line with other applications in terms of policy power:

  - Give Build Plans normal view/edit policies.
  - Require "Can Edit" to run a plan manually.

Having "Can View" on plans may be a little weird in some cases (the status of a Buildable might be bad because of a build you can't see) but we can cross that bridge when we come to it.

Next change here will require "Can Edit" to abort a build. This will reasonably allow installs to reserve pause/abort for administrators/adults. (I might let anyone restart a plan, though?)

Test Plan:
  - Created a new build plan.
  - Verified defaults were inherited from application defaults (swapped them around, too).
  - Saved build plan.
  - Edited policies.
  - Verified autoplans get the right policies.
  - Verified old plans got migrated properly.
  - Tried to run a plan I couldn't edit (denied).
  - Ran a plan from CLI with `bin/harbormaster`.
  - Tried to create a plan with an unprivileged user.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9614

Differential Revision: https://secure.phabricator.com/D14321
2015-10-26 12:38:21 -07:00

103 lines
2.7 KiB
PHP

<?php
final class HarbormasterStepAddController extends HarbormasterController {
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$plan = id(new HarbormasterBuildPlanQuery())
->setViewer($viewer)
->withIDs(array($request->getURIData('id')))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
if (!$plan) {
return new Aphront404Response();
}
$plan_id = $plan->getID();
$cancel_uri = $this->getApplicationURI("plan/{$plan_id}/");
$plan_title = pht('Plan %d', $plan_id);
$all = HarbormasterBuildStepImplementation::getImplementations();
$all = msort($all, 'getName');
$all_groups = HarbormasterBuildStepGroup::getAllGroups();
foreach ($all as $impl) {
$group_key = $impl->getBuildStepGroupKey();
if (empty($all_groups[$group_key])) {
throw new Exception(
pht(
'Build step "%s" has step group key "%s", but no step group '.
'with that key exists.',
get_class($impl),
$group_key));
}
}
$groups = mgroup($all, 'getBuildStepGroupKey');
$lists = array();
$enabled_groups = HarbormasterBuildStepGroup::getAllEnabledGroups();
foreach ($enabled_groups as $group) {
$list = id(new PHUIObjectItemListView())
->setHeader($group->getGroupName())
->setNoDataString(
pht(
'This group has no available build steps.'));
$steps = idx($groups, $group->getGroupKey(), array());
foreach ($steps as $key => $impl) {
if ($impl->shouldRequireAutotargeting()) {
unset($steps[$key]);
continue;
}
}
if (!$steps && !$group->shouldShowIfEmpty()) {
continue;
}
foreach ($steps as $key => $impl) {
$class = get_class($impl);
$new_uri = $this->getApplicationURI("step/new/{$plan_id}/{$class}/");
$item = id(new PHUIObjectItemView())
->setHeader($impl->getName())
->setHref($new_uri)
->addAttribute($impl->getGenericDescription());
$list->addItem($item);
}
$lists[] = $list;
}
$crumbs = $this->buildApplicationCrumbs()
->addTextCrumb($plan_title, $cancel_uri)
->addTextCrumb(pht('Add Build Step'));
$box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Add Build Step'))
->appendChild($lists);
return $this->buildApplicationPage(
array(
$crumbs,
$box,
),
array(
'title' => array(
$plan_title,
pht('Add Build Step'),
),
));
}
}