Page MenuHomePhabricator

D8607.id20397.diff
No OneTemporary

D8607.id20397.diff

diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2088,6 +2088,7 @@
'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',
@@ -4931,6 +4932,7 @@
'PhabricatorSourceCodeView' => 'AphrontView',
'PhabricatorStandardCustomField' => 'PhabricatorCustomField',
'PhabricatorStandardCustomFieldBool' => 'PhabricatorStandardCustomField',
+ 'PhabricatorStandardCustomFieldCredential' => 'PhabricatorStandardCustomField',
'PhabricatorStandardCustomFieldDate' => 'PhabricatorStandardCustomField',
'PhabricatorStandardCustomFieldHeader' => 'PhabricatorStandardCustomField',
'PhabricatorStandardCustomFieldInt' => 'PhabricatorStandardCustomField',
diff --git a/src/applications/passphrase/credentialtype/PassphraseCredentialType.php b/src/applications/passphrase/credentialtype/PassphraseCredentialType.php
--- a/src/applications/passphrase/credentialtype/PassphraseCredentialType.php
+++ b/src/applications/passphrase/credentialtype/PassphraseCredentialType.php
@@ -33,6 +33,14 @@
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');
diff --git a/src/applications/passphrase/view/PassphraseCredentialControl.php b/src/applications/passphrase/view/PassphraseCredentialControl.php
--- a/src/applications/passphrase/view/PassphraseCredentialControl.php
+++ b/src/applications/passphrase/view/PassphraseCredentialControl.php
@@ -98,4 +98,63 @@
));
}
+ /**
+ * 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;
+ }
+
+
}
diff --git a/src/applications/repository/editor/PhabricatorRepositoryEditor.php b/src/applications/repository/editor/PhabricatorRepositoryEditor.php
--- a/src/applications/repository/editor/PhabricatorRepositoryEditor.php
+++ b/src/applications/repository/editor/PhabricatorRepositoryEditor.php
@@ -310,4 +310,33 @@
}
}
+ 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;
+ }
+
}
diff --git a/src/docs/user/configuration/custom_fields.diviner b/src/docs/user/configuration/custom_fields.diviner
--- a/src/docs/user/configuration/custom_fields.diviner
+++ b/src/docs/user/configuration/custom_fields.diviner
@@ -121,6 +121,14 @@
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,
diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldCredential.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldCredential.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldCredential.php
@@ -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));
+ }
+ }
+
+
+}
diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php
--- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php
+++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php
@@ -68,7 +68,7 @@
return array();
}
- public function getRequiredHandlePHIDsForProperyView() {
+ public function getRequiredHandlePHIDsForPropertyView() {
$value = $this->getFieldValue();
if ($value) {
return $value;

File Metadata

Mime Type
text/plain
Expires
Sun, Apr 13, 6:56 PM (1 w, 2 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7715618
Default Alt Text
D8607.id20397.diff (10 KB)

Event Timeline