1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-03-29 04:28:12 +01:00
phorge-phorge/src/applications/subscriptions/controller/PhabricatorSubscriptionsEditController.php
epriestley d3c325c4fc Allow objects to be put in an "MFA required for all interactions" mode, and support "MFA required" statuses in Maniphest
Summary:
Depends on D19898. Ref T13222. See PHI873. Allow objects to opt into an "MFA is required for all edits" mode.

Put tasks in this mode if they're in a status that specifies it is an `mfa` status.

This is still a little rough for now:

  - There's no UI hint that you'll have to MFA. I'll likely add some hinting in a followup.
  - All edits currently require MFA, even subscribe/unsubscribe. We could maybe relax this if it's an issue.

Test Plan:
  - Edited an MFA-required object via comments, edit forms, and most/all of the extensions. These prompted for MFA, then worked correctly.
  - Tried to edit via Conduit, failed with a reasonably comprehensible error.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13222

Differential Revision: https://secure.phabricator.com/D19899
2018-12-28 00:10:54 -08:00

118 lines
3.3 KiB
PHP

<?php
final class PhabricatorSubscriptionsEditController
extends PhabricatorController {
public function handleRequest(AphrontRequest $request) {
$viewer = $request->getViewer();
$phid = $request->getURIData('phid');
$action = $request->getURIData('action');
if (!$request->isFormOrHisecPost()) {
return new Aphront400Response();
}
switch ($action) {
case 'add':
$is_add = true;
break;
case 'delete':
$is_add = false;
break;
default:
return new Aphront400Response();
}
$handle = id(new PhabricatorHandleQuery())
->setViewer($viewer)
->withPHIDs(array($phid))
->executeOne();
$object = id(new PhabricatorObjectQuery())
->setViewer($viewer)
->withPHIDs(array($phid))
->executeOne();
if (!($object instanceof PhabricatorSubscribableInterface)) {
return $this->buildErrorResponse(
pht('Bad Object'),
pht('This object is not subscribable.'),
$handle->getURI());
}
if ($object->isAutomaticallySubscribed($viewer->getPHID())) {
return $this->buildErrorResponse(
pht('Automatically Subscribed'),
pht('You are automatically subscribed to this object.'),
$handle->getURI());
}
if (!PhabricatorPolicyFilter::canInteract($viewer, $object)) {
$lock = PhabricatorEditEngineLock::newForObject($viewer, $object);
$dialog = $this->newDialog()
->addCancelButton($handle->getURI());
return $lock->willBlockUserInteractionWithDialog($dialog);
}
if ($object instanceof PhabricatorApplicationTransactionInterface) {
if ($is_add) {
$xaction_value = array(
'+' => array($viewer->getPHID()),
);
} else {
$xaction_value = array(
'-' => array($viewer->getPHID()),
);
}
$xaction = id($object->getApplicationTransactionTemplate())
->setTransactionType(PhabricatorTransactions::TYPE_SUBSCRIBERS)
->setNewValue($xaction_value);
$editor = id($object->getApplicationTransactionEditor())
->setActor($viewer)
->setCancelURI($handle->getURI())
->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true)
->setContentSourceFromRequest($request);
$editor->applyTransactions($object, array($xaction));
} else {
// TODO: Eventually, get rid of this once everything implements
// PhabricatorApplicationTransactionInterface.
$editor = id(new PhabricatorSubscriptionsEditor())
->setActor($viewer)
->setObject($object);
if ($is_add) {
$editor->subscribeExplicit(array($viewer->getPHID()), $explicit = true);
} else {
$editor->unsubscribe(array($viewer->getPHID()));
}
$editor->save();
}
// TODO: We should just render the "Unsubscribe" action and swap it out
// in the document for Ajax requests.
return id(new AphrontReloadResponse())->setURI($handle->getURI());
}
private function buildErrorResponse($title, $message, $uri) {
$request = $this->getRequest();
$viewer = $request->getUser();
$dialog = id(new AphrontDialogView())
->setUser($viewer)
->setTitle($title)
->appendChild($message)
->addCancelButton($uri);
return id(new AphrontDialogResponse())->setDialog($dialog);
}
}