mirror of
https://we.phorge.it/source/phorge.git
synced 2025-02-01 01:18:22 +01:00
Implement a "credential" standard custom field
Summary: Ref T4590. Ref T1049. This is primarily intended to support HTTP auth in Harbormaster. Test Plan: Added a field, edited it, etc. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T4590, T1049 Differential Revision: https://secure.phabricator.com/D8607
This commit is contained in:
parent
acfc3c3e5d
commit
e8e12910a7
7 changed files with 245 additions and 1 deletions
|
@ -2091,6 +2091,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorSourceCodeView' => 'view/layout/PhabricatorSourceCodeView.php',
|
||||
'PhabricatorStandardCustomField' => 'infrastructure/customfield/standard/PhabricatorStandardCustomField.php',
|
||||
'PhabricatorStandardCustomFieldBool' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldBool.php',
|
||||
'PhabricatorStandardCustomFieldCredential' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldCredential.php',
|
||||
'PhabricatorStandardCustomFieldDate' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldDate.php',
|
||||
'PhabricatorStandardCustomFieldHeader' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldHeader.php',
|
||||
'PhabricatorStandardCustomFieldInt' => 'infrastructure/customfield/standard/PhabricatorStandardCustomFieldInt.php',
|
||||
|
@ -4937,6 +4938,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorSourceCodeView' => 'AphrontView',
|
||||
'PhabricatorStandardCustomField' => 'PhabricatorCustomField',
|
||||
'PhabricatorStandardCustomFieldBool' => 'PhabricatorStandardCustomField',
|
||||
'PhabricatorStandardCustomFieldCredential' => 'PhabricatorStandardCustomField',
|
||||
'PhabricatorStandardCustomFieldDate' => 'PhabricatorStandardCustomField',
|
||||
'PhabricatorStandardCustomFieldHeader' => 'PhabricatorStandardCustomField',
|
||||
'PhabricatorStandardCustomFieldInt' => 'PhabricatorStandardCustomField',
|
||||
|
|
|
@ -33,6 +33,14 @@ abstract class PassphraseCredentialType extends Phobject {
|
|||
return $types;
|
||||
}
|
||||
|
||||
public static function getAllProvidesTypes() {
|
||||
$types = array();
|
||||
foreach (self::getAllTypes() as $type) {
|
||||
$types[] = $type->getProvidesType();
|
||||
}
|
||||
return array_unique($types);
|
||||
}
|
||||
|
||||
public static function getTypeByConstant($constant) {
|
||||
$all = self::getAllTypes();
|
||||
$all = mpull($all, null, 'getCredentialType');
|
||||
|
|
|
@ -98,4 +98,63 @@ final class PassphraseCredentialControl extends AphrontFormControl {
|
|||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that a given actor has permission to use all of the credentials
|
||||
* in a list of credential transactions.
|
||||
*
|
||||
* In general, the rule here is:
|
||||
*
|
||||
* - If you're editing an object and it uses a credential you can't use,
|
||||
* that's fine as long as you don't change the credential.
|
||||
* - If you do change the credential, the new credential must be one you
|
||||
* can use.
|
||||
*
|
||||
* @param PhabricatorUser The acting user.
|
||||
* @param list<PhabricatorApplicationTransaction> List of credential altering
|
||||
* transactions.
|
||||
* @return bool True if the transactions are valid.
|
||||
*/
|
||||
public static function validateTransactions(
|
||||
PhabricatorUser $actor,
|
||||
array $xactions) {
|
||||
|
||||
$new_phids = array();
|
||||
foreach ($xactions as $xaction) {
|
||||
$new = $xaction->getNewValue();
|
||||
if (!$new) {
|
||||
// Removing a credential, so this is OK.
|
||||
continue;
|
||||
}
|
||||
|
||||
$old = $xaction->getOldValue();
|
||||
if ($old == $new) {
|
||||
// This is a no-op transaction, so this is also OK.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, we need to check this credential.
|
||||
$new_phids[] = $new;
|
||||
}
|
||||
|
||||
if (!$new_phids) {
|
||||
// No new credentials being set, so this is fine.
|
||||
return true;
|
||||
}
|
||||
|
||||
$usable_credentials = id(new PassphraseCredentialQuery())
|
||||
->setViewer($actor)
|
||||
->withPHIDs($new_phids)
|
||||
->execute();
|
||||
$usable_credentials = mpull($usable_credentials, null, 'getPHID');
|
||||
|
||||
foreach ($new_phids as $phid) {
|
||||
if (empty($usable_credentials[$phid])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -310,4 +310,33 @@ final class PhabricatorRepositoryEditor
|
|||
}
|
||||
}
|
||||
|
||||
protected function validateTransaction(
|
||||
PhabricatorLiskDAO $object,
|
||||
$type,
|
||||
array $xactions) {
|
||||
|
||||
$errors = parent::validateTransaction($object, $type, $xactions);
|
||||
|
||||
switch ($type) {
|
||||
case self::TYPE_CREDENTIAL:
|
||||
$ok = PassphraseCredentialControl::validateTransactions(
|
||||
$this->getActor(),
|
||||
$xactions);
|
||||
if (!$ok) {
|
||||
foreach ($xactions as $xaction) {
|
||||
$errors[] = new PhabricatorApplicationTransactionValidationError(
|
||||
$type,
|
||||
pht('Invalid'),
|
||||
pht(
|
||||
'The selected credential does not exist, or you do not have '.
|
||||
'permission to use it.'),
|
||||
$xaction);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -121,6 +121,14 @@ In **Maniphest**:
|
|||
into the new task, while others are not; by default, fields are not copied.
|
||||
If you want this field to be copied, specify `true` for the `copy` property.
|
||||
|
||||
Internally, Phabricator implements some additional custom field types and
|
||||
options. These are not intended for general use and are subject to abrupt
|
||||
change, but are documented here for completeness:
|
||||
|
||||
- **Credentials**: Controls with type `credential` allow selection of a
|
||||
Passphrase credential which provides `credential.provides`, and creation
|
||||
of credentials of `credential.type`.
|
||||
|
||||
= Advanced Custom Fields =
|
||||
|
||||
If you want custom fields to have advanced behaviors (sophisticated rendering,
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorStandardCustomFieldCredential
|
||||
extends PhabricatorStandardCustomField {
|
||||
|
||||
public function getFieldType() {
|
||||
return 'credential';
|
||||
}
|
||||
|
||||
public function buildFieldIndexes() {
|
||||
$indexes = array();
|
||||
|
||||
$value = $this->getFieldValue();
|
||||
if (strlen($value)) {
|
||||
$indexes[] = $this->newStringIndex($value);
|
||||
}
|
||||
|
||||
return $indexes;
|
||||
}
|
||||
|
||||
public function renderEditControl(array $handles) {
|
||||
$provides_type = $this->getFieldConfigValue('credential.provides');
|
||||
$credential_type = $this->getFieldConfigValue('credential.type');
|
||||
|
||||
$all_types = PassphraseCredentialType::getAllProvidesTypes();
|
||||
if (!in_array($provides_type, $all_types)) {
|
||||
$provides_type = PassphraseCredentialTypePassword::PROVIDES_TYPE;
|
||||
}
|
||||
|
||||
$credentials = id(new PassphraseCredentialQuery())
|
||||
->setViewer($this->getViewer())
|
||||
->withIsDestroyed(false)
|
||||
->withProvidesTypes(array($provides_type))
|
||||
->execute();
|
||||
|
||||
return id(new PassphraseCredentialControl())
|
||||
->setLabel($this->getFieldName())
|
||||
->setName($this->getFieldKey())
|
||||
->setCaption($this->getCaption())
|
||||
->setAllowNull(!$this->getRequired())
|
||||
->setCredentialType($credential_type)
|
||||
->setValue($this->getFieldValue())
|
||||
->setError($this->getFieldError())
|
||||
->setOptions($credentials);
|
||||
}
|
||||
|
||||
public function getRequiredHandlePHIDsForPropertyView() {
|
||||
$value = $this->getFieldValue();
|
||||
if ($value) {
|
||||
return array($value);
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
public function renderPropertyViewValue(array $handles) {
|
||||
$value = $this->getFieldValue();
|
||||
if ($value) {
|
||||
return $handles[$value]->renderLink();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function validateApplicationTransactions(
|
||||
PhabricatorApplicationTransactionEditor $editor,
|
||||
$type,
|
||||
array $xactions) {
|
||||
|
||||
$errors = parent::validateApplicationTransactions(
|
||||
$editor,
|
||||
$type,
|
||||
$xactions);
|
||||
|
||||
$ok = PassphraseCredentialControl::validateTransactions(
|
||||
$this->getViewer(),
|
||||
$xactions);
|
||||
|
||||
if (!$ok) {
|
||||
foreach ($xactions as $xaction) {
|
||||
$errors[] = new PhabricatorApplicationTransactionValidationError(
|
||||
$type,
|
||||
pht('Invalid'),
|
||||
pht(
|
||||
'The selected credential does not exist, or you do not have '.
|
||||
'permission to use it.'),
|
||||
$xaction);
|
||||
$this->setFieldError(pht('Invalid'));
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
public function getApplicationTransactionRequiredHandlePHIDs(
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
$phids = array();
|
||||
$old = $xaction->getOldValue();
|
||||
$new = $xaction->getNewValue();
|
||||
if ($old) {
|
||||
$phids[] = $old;
|
||||
}
|
||||
if ($new) {
|
||||
$phids[] = $new;
|
||||
}
|
||||
return $phids;
|
||||
}
|
||||
|
||||
|
||||
public function getApplicationTransactionTitle(
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
$author_phid = $xaction->getAuthorPHID();
|
||||
|
||||
$old = $xaction->getOldValue();
|
||||
$new = $xaction->getNewValue();
|
||||
|
||||
if ($old && !$new) {
|
||||
return pht(
|
||||
'%s removed %s as %s.',
|
||||
$xaction->renderHandleLink($author_phid),
|
||||
$xaction->renderHandleLink($old),
|
||||
$this->getFieldName());
|
||||
} else if ($new && !$old) {
|
||||
return pht(
|
||||
'%s set %s to %s.',
|
||||
$xaction->renderHandleLink($author_phid),
|
||||
$this->getFieldName(),
|
||||
$xaction->renderHandleLink($new));
|
||||
} else {
|
||||
return pht(
|
||||
'%s changed %s from %s to %s.',
|
||||
$xaction->renderHandleLink($author_phid),
|
||||
$this->getFieldName(),
|
||||
$xaction->renderHandleLink($old),
|
||||
$xaction->renderHandleLink($new));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -68,7 +68,7 @@ abstract class PhabricatorStandardCustomFieldPHIDs
|
|||
return array();
|
||||
}
|
||||
|
||||
public function getRequiredHandlePHIDsForProperyView() {
|
||||
public function getRequiredHandlePHIDsForPropertyView() {
|
||||
$value = $this->getFieldValue();
|
||||
if ($value) {
|
||||
return $value;
|
||||
|
|
Loading…
Add table
Reference in a new issue