1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-26 07:20:57 +01:00

Require "Can Edit" on a build plan to abort or pause associated builds

Summary: Fixes T9614. This is kind of silly, but stop users from fighting turf wars over build resources or showing up on an install and just aborting a bunch of builds for the heck of it.

Test Plan:
  - Restarted / paused / aborted / etc builds.
  - Tried to do the same for builds I didn't have edit permission on the build plan for, got errors.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9614

Differential Revision: https://secure.phabricator.com/D15353
This commit is contained in:
epriestley 2016-02-26 11:24:03 -08:00
parent c64b822bee
commit 93b8f803a0
6 changed files with 166 additions and 31 deletions

View file

@ -39,6 +39,8 @@ final class HarbormasterBuildActionController
return new Aphront400Response(); return new Aphront400Response();
} }
$build->assertCanIssueCommand($viewer, $action);
switch ($via) { switch ($via) {
case 'buildable': case 'buildable':
$return_uri = '/'.$build->getBuildable()->getMonogram(); $return_uri = '/'.$build->getBuildable()->getMonogram();

View file

@ -441,10 +441,29 @@ final class HarbormasterBuildViewController
->setUser($viewer) ->setUser($viewer)
->setObject($build); ->setObject($build);
$can_restart = $build->canRestartBuild(); $can_restart =
$can_pause = $build->canPauseBuild(); $build->canRestartBuild() &&
$can_resume = $build->canResumeBuild(); $build->canIssueCommand(
$can_abort = $build->canAbortBuild(); $viewer,
HarbormasterBuildCommand::COMMAND_RESTART);
$can_pause =
$build->canPauseBuild() &&
$build->canIssueCommand(
$viewer,
HarbormasterBuildCommand::COMMAND_PAUSE);
$can_resume =
$build->canResumeBuild() &&
$build->canIssueCommand(
$viewer,
HarbormasterBuildCommand::COMMAND_RESUME);
$can_abort =
$build->canAbortBuild() &&
$build->canIssueCommand(
$viewer,
HarbormasterBuildCommand::COMMAND_ABORT);
$list->addAction( $list->addAction(
id(new PhabricatorActionView()) id(new PhabricatorActionView())

View file

@ -51,6 +51,14 @@ final class HarbormasterBuildableActionController
} }
} }
$restricted = false;
foreach ($issuable as $key => $build) {
if (!$build->canIssueCommand($viewer, $action)) {
$restricted = true;
unset($issuable[$key]);
}
}
$return_uri = '/'.$buildable->getMonogram(); $return_uri = '/'.$buildable->getMonogram();
if ($request->isDialogFormPost() && $issuable) { if ($request->isDialogFormPost() && $issuable) {
$editor = id(new HarbormasterBuildableTransactionEditor()) $editor = id(new HarbormasterBuildableTransactionEditor())
@ -84,49 +92,101 @@ final class HarbormasterBuildableActionController
switch ($action) { switch ($action) {
case HarbormasterBuildCommand::COMMAND_RESTART: case HarbormasterBuildCommand::COMMAND_RESTART:
if ($issuable) { if ($issuable) {
$title = pht('Really restart all builds?'); $title = pht('Really restart builds?');
$body = pht(
'Progress on all builds will be discarded, and all builds will '. if ($restricted) {
'restart. Side effects of the builds will occur again. Really '. $body = pht(
'restart all builds?'); 'You only have permission to restart some builds. Progress '.
$submit = pht('Restart All Builds'); 'on builds you have permission to restart will be discarded '.
'and they will restart. Side effects of these builds will '.
'occur again. Really restart all builds?');
} else {
$body = pht(
'Progress on all builds will be discarded, and all builds will '.
'restart. Side effects of the builds will occur again. Really '.
'restart all builds?');
}
$submit = pht('Restart Builds');
} else { } else {
$title = pht('Unable to Restart Builds'); $title = pht('Unable to Restart Builds');
$body = pht('No builds can be restarted.');
if ($restricted) {
$body = pht('You do not have permission to restart any builds.');
} else {
$body = pht('No builds can be restarted.');
}
} }
break; break;
case HarbormasterBuildCommand::COMMAND_PAUSE: case HarbormasterBuildCommand::COMMAND_PAUSE:
if ($issuable) { if ($issuable) {
$title = pht('Really pause all builds?'); $title = pht('Really pause builds?');
$body = pht(
'If you pause all builds, work will halt once the current steps '. if ($restricted) {
'complete. You can resume the builds later.'); $body = pht(
$submit = pht('Pause All Builds'); 'You only have permission to pause some builds. Once the '.
'current steps complete, work will halt on builds you have '.
'permission to pause. You can resume the builds later.');
} else {
$body = pht(
'If you pause all builds, work will halt once the current steps '.
'complete. You can resume the builds later.');
}
$submit = pht('Pause Builds');
} else { } else {
$title = pht('Unable to Pause Builds'); $title = pht('Unable to Pause Builds');
$body = pht('No builds can be paused.');
if ($restricted) {
$body = pht('You do not have permission to pause any builds.');
} else {
$body = pht('No builds can be paused.');
}
} }
break; break;
case HarbormasterBuildCommand::COMMAND_ABORT: case HarbormasterBuildCommand::COMMAND_ABORT:
if ($issuable) { if ($issuable) {
$title = pht('Really abort all builds?'); $title = pht('Really abort builds?');
$body = pht( if ($restricted) {
'If you abort all builds, work will halt immediately. Work '. $body = pht(
'will be discarded, and builds must be completely restarted.'); 'You only have permission to abort some builds. Work will '.
$submit = pht('Abort All Builds'); 'halt immediately on builds you have permission to abort. '.
'Progress will be discarded, and builds must be completely '.
'restarted if you want them to complete.');
} else {
$body = pht(
'If you abort all builds, work will halt immediately. Work '.
'will be discarded, and builds must be completely restarted.');
}
$submit = pht('Abort Builds');
} else { } else {
$title = pht('Unable to Abort Builds'); $title = pht('Unable to Abort Builds');
$body = pht('No builds can be aborted.');
if ($restricted) {
$body = pht('You do not have permission to abort any builds.');
} else {
$body = pht('No builds can be aborted.');
}
} }
break; break;
case HarbormasterBuildCommand::COMMAND_RESUME: case HarbormasterBuildCommand::COMMAND_RESUME:
if ($issuable) { if ($issuable) {
$title = pht('Really resume all builds?'); $title = pht('Really resume builds?');
$body = pht('Work will continue on all builds. Really resume?'); if ($restricted) {
$submit = pht('Resume All Builds'); $body = pht(
'You only have permission to resume some builds. Work will '.
'continue on builds you have permission to resume.');
} else {
$body = pht('Work will continue on all builds. Really resume?');
}
$submit = pht('Resume Builds');
} else { } else {
$title = pht('Unable to Resume Builds'); $title = pht('Unable to Resume Builds');
$body = pht('No builds can be resumed.'); if ($restricted) {
$body = pht('You do not have permission to resume any builds.');
} else {
$body = pht('No builds can be resumed.');
}
} }
break; break;
} }

View file

@ -86,18 +86,31 @@ final class HarbormasterBuildableViewController
$can_pause = false; $can_pause = false;
$can_abort = false; $can_abort = false;
$command_restart = HarbormasterBuildCommand::COMMAND_RESTART;
$command_resume = HarbormasterBuildCommand::COMMAND_RESUME;
$command_pause = HarbormasterBuildCommand::COMMAND_PAUSE;
$command_abort = HarbormasterBuildCommand::COMMAND_ABORT;
foreach ($buildable->getBuilds() as $build) { foreach ($buildable->getBuilds() as $build) {
if ($build->canRestartBuild()) { if ($build->canRestartBuild()) {
$can_restart = true; if ($build->canIssueCommand($viewer, $command_restart)) {
$can_restart = true;
}
} }
if ($build->canResumeBuild()) { if ($build->canResumeBuild()) {
$can_resume = true; if ($build->canIssueCommand($viewer, $command_resume)) {
$can_resume = true;
}
} }
if ($build->canPauseBuild()) { if ($build->canPauseBuild()) {
$can_pause = true; if ($build->canIssueCommand($viewer, $command_pause)) {
$can_pause = true;
}
} }
if ($build->canAbortBuild()) { if ($build->canAbortBuild()) {
$can_abort = true; if ($build->canIssueCommand($viewer, $command_abort)) {
$can_abort = true;
}
} }
} }

View file

@ -88,6 +88,11 @@ final class HarbormasterBuildTransactionEditor
return; return;
} }
$actor = $this->getActor();
if (!$build->canIssueCommand($actor, $command)) {
return;
}
id(new HarbormasterBuildCommand()) id(new HarbormasterBuildCommand())
->setAuthorPHID($xaction->getAuthorPHID()) ->setAuthorPHID($xaction->getAuthorPHID())
->setTargetPHID($build->getPHID()) ->setTargetPHID($build->getPHID())

View file

@ -450,6 +450,42 @@ final class HarbormasterBuild extends HarbormasterDAO
return $this; return $this;
} }
public function canIssueCommand(PhabricatorUser $viewer, $command) {
try {
$this->assertCanIssueCommand($viewer, $command);
return true;
} catch (Exception $ex) {
return false;
}
}
public function assertCanIssueCommand(PhabricatorUser $viewer, $command) {
$need_edit = false;
switch ($command) {
case HarbormasterBuildCommand::COMMAND_RESTART:
break;
case HarbormasterBuildCommand::COMMAND_PAUSE:
case HarbormasterBuildCommand::COMMAND_RESUME:
case HarbormasterBuildCommand::COMMAND_ABORT:
$need_edit = true;
break;
default:
throw new Exception(
pht(
'Invalid Harbormaster build command "%s".',
$command));
}
// Issuing these commands requires that you be able to edit the build, to
// prevent enemy engineers from sabotaging your builds. See T9614.
if ($need_edit) {
PhabricatorPolicyFilter::requireCapability(
$viewer,
$this->getBuildPlan(),
PhabricatorPolicyCapability::CAN_EDIT);
}
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */ /* -( PhabricatorApplicationTransactionInterface )------------------------- */