1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-19 05:12:41 +01:00

Make "JIRA Issues" field work better with noncredentialed accounts

Summary:
Currently, users get an error when making any changes to this field if they don't have a linked JIRA account.

Instead:

  - We should only raise an error if they're trying to //add// issues, and only on the new issues. It's always fine to remove issues, and existing issues the author can't see are also fine.
  - When we can't add things because there's no account (vs because there's a permissions error or they don't exist), raise a more tailored exception.

Test Plan:
  - As JIRA and non-JIRA users, made various edits to this field.
  - Got appropriate exceptions, including better tailoring.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: mbishopim3, epriestley

Differential Revision: https://secure.phabricator.com/D8676
This commit is contained in:
epriestley 2014-04-02 12:03:59 -07:00
parent b50426a98f
commit 81fa847bc5
7 changed files with 68 additions and 11 deletions

View file

@ -622,6 +622,7 @@ phutil_register_library_map(array(
'DoorkeeperFeedWorkerAsana' => 'applications/doorkeeper/worker/DoorkeeperFeedWorkerAsana.php',
'DoorkeeperFeedWorkerJIRA' => 'applications/doorkeeper/worker/DoorkeeperFeedWorkerJIRA.php',
'DoorkeeperImportEngine' => 'applications/doorkeeper/engine/DoorkeeperImportEngine.php',
'DoorkeeperMissingLinkException' => 'applications/doorkeeper/exception/DoorkeeperMissingLinkException.php',
'DoorkeeperObjectRef' => 'applications/doorkeeper/engine/DoorkeeperObjectRef.php',
'DoorkeeperRemarkupRule' => 'applications/doorkeeper/remarkup/DoorkeeperRemarkupRule.php',
'DoorkeeperRemarkupRuleAsana' => 'applications/doorkeeper/remarkup/DoorkeeperRemarkupRuleAsana.php',
@ -3196,6 +3197,7 @@ phutil_register_library_map(array(
'DoorkeeperFeedWorkerAsana' => 'DoorkeeperFeedWorker',
'DoorkeeperFeedWorkerJIRA' => 'DoorkeeperFeedWorker',
'DoorkeeperImportEngine' => 'Phobject',
'DoorkeeperMissingLinkException' => 'Exception',
'DoorkeeperObjectRef' => 'Phobject',
'DoorkeeperRemarkupRule' => 'PhutilRemarkupRule',
'DoorkeeperRemarkupRuleAsana' => 'DoorkeeperRemarkupRule',

View file

@ -116,11 +116,11 @@ final class DifferentialJIRAIssuesField
}
public function getOldValueForApplicationTransactions() {
return nonempty($this->getValue(), array());
return array_unique(nonempty($this->getValue(), array()));
}
public function getNewValueForApplicationTransactions() {
return nonempty($this->getValue(), array());
return array_unique(nonempty($this->getValue(), array()));
}
public function validateApplicationTransactions(
@ -137,12 +137,36 @@ final class DifferentialJIRAIssuesField
$transaction = null;
foreach ($xactions as $xaction) {
$value = $xaction->getNewValue();
$old = $xaction->getOldValue();
$new = $xaction->getNewValue();
$refs = id(new DoorkeeperImportEngine())
->setViewer($this->getViewer())
->setRefs($this->buildDoorkeeperRefs($value))
->execute();
$add = array_diff($new, $old);
if (!$add) {
continue;
}
// Only check that the actor can see newly added JIRA refs. You're
// allowed to remove refs or make no-op changes even if you aren't
// linked to JIRA.
try {
$refs = id(new DoorkeeperImportEngine())
->setViewer($this->getViewer())
->setRefs($this->buildDoorkeeperRefs($add))
->setThrowOnMissingLink(true)
->execute();
} catch (DoorkeeperMissingLinkException $ex) {
$this->error = pht('Not Linked');
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Not Linked'),
pht(
'You can not add JIRA issues (%s) to this revision because your '.
'Phabricator account is not linked to a JIRA account.',
implode(', ', $add)),
$xaction);
continue;
}
$bad = array();
foreach ($refs as $ref) {
@ -155,7 +179,7 @@ final class DifferentialJIRAIssuesField
$bad = implode(', ', $bad);
$this->error = pht('Invalid');
$error = new PhabricatorApplicationTransactionValidationError(
$errors[] = new PhabricatorApplicationTransactionValidationError(
$type,
pht('Invalid'),
pht(
@ -163,7 +187,6 @@ final class DifferentialJIRAIssuesField
"you may not have permission to view them: %s",
$bad),
$xaction);
$errors[] = $error;
}
}

View file

@ -3,6 +3,12 @@
abstract class DoorkeeperBridge extends Phobject {
private $viewer;
private $throwOnMissingLink;
public function setThrowOnMissingLink($throw_on_missing_link) {
$this->throwOnMissingLink = $throw_on_missing_link;
return $this;
}
final public function setViewer($viewer) {
$this->viewer = $viewer;
@ -21,6 +27,15 @@ abstract class DoorkeeperBridge extends Phobject {
abstract public function pullRefs(array $refs);
public function fillObjectFromData(DoorkeeperExternalObject $obj, $result) {
return;
}
public function didFailOnMissingLink() {
if ($this->throwOnMissingLink) {
throw new DoorkeeperMissingLinkException();
}
return null;
}
}

View file

@ -40,7 +40,7 @@ final class DoorkeeperBridgeAsana extends DoorkeeperBridge {
->execute();
if (!$accounts) {
return;
return $this->didFailOnMissingLink();
}
// TODO: If the user has several linked Asana accounts, we just pick the

View file

@ -34,7 +34,7 @@ final class DoorkeeperBridgeJIRA extends DoorkeeperBridge {
->execute();
if (!$accounts) {
return;
return $this->didFailOnMissingLink();
}
// TODO: When we support multiple JIRA instances, we need to disambiguate

View file

@ -6,6 +6,7 @@ final class DoorkeeperImportEngine extends Phobject {
private $refs = array();
private $phids = array();
private $localOnly;
private $throwOnMissingLink;
public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
@ -36,6 +37,16 @@ final class DoorkeeperImportEngine extends Phobject {
return $this;
}
/**
* Configure behavior if remote refs can not be retrieved because an
* authentication link is missing.
*/
public function setThrowOnMissingLink($throw) {
$this->throwOnMissingLink = $throw;
return $this;
}
public function execute() {
$refs = $this->getRefs();
$viewer = $this->getViewer();
@ -86,6 +97,7 @@ final class DoorkeeperImportEngine extends Phobject {
unset($bridges[$key]);
}
$bridge->setViewer($viewer);
$bridge->setThrowOnMissingLink($this->throwOnMissingLink);
}
$working_set = $refs;

View file

@ -0,0 +1,5 @@
<?php
final class DoorkeeperMissingLinkException extends Exception {
}