mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-18 19:40:55 +01:00
Implement passphrase.query
for querying credentials
Summary: Resolves T5868. This implements `passphrase.query` and a mechanism for allowing Conduit access to credentials. Test Plan: Tested locally. Reviewers: epriestley, #blessed_reviewers Reviewed By: epriestley, #blessed_reviewers Subscribers: talshiri, epriestley, Korvin Maniphest Tasks: T5868 Differential Revision: https://secure.phabricator.com/D10262
This commit is contained in:
parent
300910f462
commit
26f283fe21
11 changed files with 274 additions and 0 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE {$NAMESPACE}_passphrase.passphrase_credential
|
||||||
|
ADD COLUMN allowConduit BOOL NOT NULL DEFAULT 0;
|
|
@ -1034,8 +1034,10 @@ phutil_register_library_map(array(
|
||||||
'PackageMail' => 'applications/owners/mail/PackageMail.php',
|
'PackageMail' => 'applications/owners/mail/PackageMail.php',
|
||||||
'PackageModifyMail' => 'applications/owners/mail/PackageModifyMail.php',
|
'PackageModifyMail' => 'applications/owners/mail/PackageModifyMail.php',
|
||||||
'PassphraseAbstractKey' => 'applications/passphrase/keys/PassphraseAbstractKey.php',
|
'PassphraseAbstractKey' => 'applications/passphrase/keys/PassphraseAbstractKey.php',
|
||||||
|
'PassphraseConduitAPIMethod' => 'applications/passphrase/conduit/PassphraseConduitAPIMethod.php',
|
||||||
'PassphraseController' => 'applications/passphrase/controller/PassphraseController.php',
|
'PassphraseController' => 'applications/passphrase/controller/PassphraseController.php',
|
||||||
'PassphraseCredential' => 'applications/passphrase/storage/PassphraseCredential.php',
|
'PassphraseCredential' => 'applications/passphrase/storage/PassphraseCredential.php',
|
||||||
|
'PassphraseCredentialConduitController' => 'applications/passphrase/controller/PassphraseCredentialConduitController.php',
|
||||||
'PassphraseCredentialControl' => 'applications/passphrase/view/PassphraseCredentialControl.php',
|
'PassphraseCredentialControl' => 'applications/passphrase/view/PassphraseCredentialControl.php',
|
||||||
'PassphraseCredentialCreateController' => 'applications/passphrase/controller/PassphraseCredentialCreateController.php',
|
'PassphraseCredentialCreateController' => 'applications/passphrase/controller/PassphraseCredentialCreateController.php',
|
||||||
'PassphraseCredentialDestroyController' => 'applications/passphrase/controller/PassphraseCredentialDestroyController.php',
|
'PassphraseCredentialDestroyController' => 'applications/passphrase/controller/PassphraseCredentialDestroyController.php',
|
||||||
|
@ -1059,6 +1061,7 @@ phutil_register_library_map(array(
|
||||||
'PassphraseCredentialViewController' => 'applications/passphrase/controller/PassphraseCredentialViewController.php',
|
'PassphraseCredentialViewController' => 'applications/passphrase/controller/PassphraseCredentialViewController.php',
|
||||||
'PassphraseDAO' => 'applications/passphrase/storage/PassphraseDAO.php',
|
'PassphraseDAO' => 'applications/passphrase/storage/PassphraseDAO.php',
|
||||||
'PassphrasePasswordKey' => 'applications/passphrase/keys/PassphrasePasswordKey.php',
|
'PassphrasePasswordKey' => 'applications/passphrase/keys/PassphrasePasswordKey.php',
|
||||||
|
'PassphraseQueryConduitAPIMethod' => 'applications/passphrase/conduit/PassphraseQueryConduitAPIMethod.php',
|
||||||
'PassphraseRemarkupRule' => 'applications/passphrase/remarkup/PassphraseRemarkupRule.php',
|
'PassphraseRemarkupRule' => 'applications/passphrase/remarkup/PassphraseRemarkupRule.php',
|
||||||
'PassphraseSSHKey' => 'applications/passphrase/keys/PassphraseSSHKey.php',
|
'PassphraseSSHKey' => 'applications/passphrase/keys/PassphraseSSHKey.php',
|
||||||
'PassphraseSecret' => 'applications/passphrase/storage/PassphraseSecret.php',
|
'PassphraseSecret' => 'applications/passphrase/storage/PassphraseSecret.php',
|
||||||
|
@ -3839,12 +3842,14 @@ phutil_register_library_map(array(
|
||||||
'PackageMail' => 'PhabricatorMail',
|
'PackageMail' => 'PhabricatorMail',
|
||||||
'PackageModifyMail' => 'PackageMail',
|
'PackageModifyMail' => 'PackageMail',
|
||||||
'PassphraseAbstractKey' => 'Phobject',
|
'PassphraseAbstractKey' => 'Phobject',
|
||||||
|
'PassphraseConduitAPIMethod' => 'ConduitAPIMethod',
|
||||||
'PassphraseController' => 'PhabricatorController',
|
'PassphraseController' => 'PhabricatorController',
|
||||||
'PassphraseCredential' => array(
|
'PassphraseCredential' => array(
|
||||||
'PassphraseDAO',
|
'PassphraseDAO',
|
||||||
'PhabricatorPolicyInterface',
|
'PhabricatorPolicyInterface',
|
||||||
'PhabricatorDestructibleInterface',
|
'PhabricatorDestructibleInterface',
|
||||||
),
|
),
|
||||||
|
'PassphraseCredentialConduitController' => 'PassphraseController',
|
||||||
'PassphraseCredentialControl' => 'AphrontFormControl',
|
'PassphraseCredentialControl' => 'AphrontFormControl',
|
||||||
'PassphraseCredentialCreateController' => 'PassphraseController',
|
'PassphraseCredentialCreateController' => 'PassphraseController',
|
||||||
'PassphraseCredentialDestroyController' => 'PassphraseController',
|
'PassphraseCredentialDestroyController' => 'PassphraseController',
|
||||||
|
@ -3868,6 +3873,7 @@ phutil_register_library_map(array(
|
||||||
'PassphraseCredentialViewController' => 'PassphraseController',
|
'PassphraseCredentialViewController' => 'PassphraseController',
|
||||||
'PassphraseDAO' => 'PhabricatorLiskDAO',
|
'PassphraseDAO' => 'PhabricatorLiskDAO',
|
||||||
'PassphrasePasswordKey' => 'PassphraseAbstractKey',
|
'PassphrasePasswordKey' => 'PassphraseAbstractKey',
|
||||||
|
'PassphraseQueryConduitAPIMethod' => 'PassphraseConduitAPIMethod',
|
||||||
'PassphraseRemarkupRule' => 'PhabricatorObjectRemarkupRule',
|
'PassphraseRemarkupRule' => 'PhabricatorObjectRemarkupRule',
|
||||||
'PassphraseSSHKey' => 'PassphraseAbstractKey',
|
'PassphraseSSHKey' => 'PassphraseAbstractKey',
|
||||||
'PassphraseSecret' => 'PassphraseDAO',
|
'PassphraseSecret' => 'PassphraseDAO',
|
||||||
|
|
|
@ -46,6 +46,7 @@ final class PhabricatorPassphraseApplication extends PhabricatorApplication {
|
||||||
'reveal/(?P<id>\d+)/' => 'PassphraseCredentialRevealController',
|
'reveal/(?P<id>\d+)/' => 'PassphraseCredentialRevealController',
|
||||||
'public/(?P<id>\d+)/' => 'PassphraseCredentialPublicController',
|
'public/(?P<id>\d+)/' => 'PassphraseCredentialPublicController',
|
||||||
'lock/(?P<id>\d+)/' => 'PassphraseCredentialLockController',
|
'lock/(?P<id>\d+)/' => 'PassphraseCredentialLockController',
|
||||||
|
'conduit/(?P<id>\d+)/' => 'PassphraseCredentialConduitController',
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class PassphraseConduitAPIMethod extends ConduitAPIMethod {
|
||||||
|
|
||||||
|
final public function getApplication() {
|
||||||
|
return PhabricatorApplication::getByClass(
|
||||||
|
'PhabricatorPassphraseApplication');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PassphraseQueryConduitAPIMethod
|
||||||
|
extends PassphraseConduitAPIMethod {
|
||||||
|
|
||||||
|
public function getAPIMethodName() {
|
||||||
|
return 'passphrase.query';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMethodDescription() {
|
||||||
|
return pht('Query credentials.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function defineParamTypes() {
|
||||||
|
return array(
|
||||||
|
'ids' => 'optional list<int>',
|
||||||
|
'phids' => 'optional list<phid>',
|
||||||
|
'needSecrets' => 'optional bool',
|
||||||
|
'needPublicKeys' => 'optional bool',
|
||||||
|
) + $this->getPagerParamTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function defineReturnType() {
|
||||||
|
return 'list<dict>';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function defineErrorTypes() {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(ConduitAPIRequest $request) {
|
||||||
|
$query = id(new PassphraseCredentialQuery())
|
||||||
|
->setViewer($request->getUser());
|
||||||
|
|
||||||
|
if ($request->getValue('ids')) {
|
||||||
|
$query->withIDs($request->getValue('ids'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->getValue('phids')) {
|
||||||
|
$query->withPHIDs($request->getValue('phids'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->getValue('needSecrets')) {
|
||||||
|
$query->needSecrets(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pager = $this->newPager($request);
|
||||||
|
$credentials = $query->executeWithCursorPager($pager);
|
||||||
|
|
||||||
|
$results = array();
|
||||||
|
foreach ($credentials as $credential) {
|
||||||
|
$type = PassphraseCredentialType::getTypeByConstant(
|
||||||
|
$credential->getCredentialType());
|
||||||
|
if (!$type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$public_key = null;
|
||||||
|
if ($request->getValue('needPublicKeys') && $type->hasPublicKey()) {
|
||||||
|
$public_key = $type->getPublicKey(
|
||||||
|
$request->getUser(),
|
||||||
|
$credential);
|
||||||
|
}
|
||||||
|
|
||||||
|
$secret = null;
|
||||||
|
if ($request->getValue('needSecrets')) {
|
||||||
|
if ($credential->getAllowConduit()) {
|
||||||
|
$secret = $credential->getSecret()->openEnvelope();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$material = array();
|
||||||
|
switch ($credential->getCredentialType()) {
|
||||||
|
case PassphraseCredentialTypeSSHPrivateKeyFile::CREDENTIAL_TYPE:
|
||||||
|
if ($secret) {
|
||||||
|
$material['file'] = $secret;
|
||||||
|
}
|
||||||
|
if ($public_key) {
|
||||||
|
$material['publicKey'] = $public_key;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PassphraseCredentialTypeSSHPrivateKeyText::CREDENTIAL_TYPE:
|
||||||
|
if ($secret) {
|
||||||
|
$material['privateKey'] = $secret;
|
||||||
|
}
|
||||||
|
if ($public_key) {
|
||||||
|
$material['publicKey'] = $public_key;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PassphraseCredentialTypePassword::CREDENTIAL_TYPE:
|
||||||
|
if ($secret) {
|
||||||
|
$material['password'] = $secret;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$credential->getAllowConduit()) {
|
||||||
|
$material['noAPIAccess'] = pht(
|
||||||
|
'This credential\'s private material '.
|
||||||
|
'is not accessible via API calls.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$results[$credential->getPHID()] = array(
|
||||||
|
'id' => $credential->getID(),
|
||||||
|
'phid' => $credential->getPHID(),
|
||||||
|
'type' => $credential->getCredentialType(),
|
||||||
|
'name' => $credential->getName(),
|
||||||
|
'uri' =>
|
||||||
|
PhabricatorEnv::getProductionURI('/'.$credential->getMonogram()),
|
||||||
|
'monogram' => $credential->getMonogram(),
|
||||||
|
'username' => $credential->getUsername(),
|
||||||
|
'material' => $material,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = array(
|
||||||
|
'data' => $results,
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->addPagerResults($result, $pager);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PassphraseCredentialConduitController
|
||||||
|
extends PassphraseController {
|
||||||
|
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
public function willProcessRequest(array $data) {
|
||||||
|
$this->id = $data['id'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processRequest() {
|
||||||
|
$request = $this->getRequest();
|
||||||
|
$viewer = $request->getUser();
|
||||||
|
|
||||||
|
$credential = id(new PassphraseCredentialQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withIDs(array($this->id))
|
||||||
|
->requireCapabilities(
|
||||||
|
array(
|
||||||
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
|
PhabricatorPolicyCapability::CAN_EDIT,
|
||||||
|
))
|
||||||
|
->executeOne();
|
||||||
|
if (!$credential) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$view_uri = '/K'.$credential->getID();
|
||||||
|
|
||||||
|
$token = id(new PhabricatorAuthSessionEngine())->requireHighSecuritySession(
|
||||||
|
$viewer,
|
||||||
|
$request,
|
||||||
|
$view_uri);
|
||||||
|
|
||||||
|
$type = PassphraseCredentialType::getTypeByConstant(
|
||||||
|
$credential->getCredentialType());
|
||||||
|
if (!$type) {
|
||||||
|
throw new Exception(pht('Credential has invalid type "%s"!', $type));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->isFormPost()) {
|
||||||
|
$xactions = array();
|
||||||
|
$xactions[] = id(new PassphraseCredentialTransaction())
|
||||||
|
->setTransactionType(PassphraseCredentialTransaction::TYPE_CONDUIT)
|
||||||
|
->setNewValue(!$credential->getAllowConduit());
|
||||||
|
|
||||||
|
$editor = id(new PassphraseCredentialTransactionEditor())
|
||||||
|
->setActor($viewer)
|
||||||
|
->setContinueOnMissingFields(true)
|
||||||
|
->setContentSourceFromRequest($request)
|
||||||
|
->applyTransactions($credential, $xactions);
|
||||||
|
|
||||||
|
return id(new AphrontRedirectResponse())->setURI($view_uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($credential->getAllowConduit()) {
|
||||||
|
return $this->newDialog()
|
||||||
|
->setTitle(pht('Prevent Conduit access?'))
|
||||||
|
->appendChild(
|
||||||
|
pht(
|
||||||
|
'This credential and its secret will no longer be able '.
|
||||||
|
'to be retrieved using the `passphrase.query` method '.
|
||||||
|
'in Conduit.'))
|
||||||
|
->addSubmitButton(pht('Prevent Conduit Access'))
|
||||||
|
->addCancelButton($view_uri);
|
||||||
|
} else {
|
||||||
|
return $this->newDialog()
|
||||||
|
->setTitle(pht('Allow Conduit access?'))
|
||||||
|
->appendChild(
|
||||||
|
pht(
|
||||||
|
'This credential will be able to be retrieved via the Conduit '.
|
||||||
|
'API by users who have access to this credential. You should '.
|
||||||
|
'only enable this for credentials which need to be accessed '.
|
||||||
|
'programmatically (such as from build agents).'))
|
||||||
|
->addSubmitButton(pht('Allow Conduit Access'))
|
||||||
|
->addCancelButton($view_uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -93,6 +93,15 @@ final class PassphraseCredentialViewController extends PassphraseController {
|
||||||
$credential_lock_icon = 'fa-unlock';
|
$credential_lock_icon = 'fa-unlock';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$allow_conduit = $credential->getAllowConduit();
|
||||||
|
if ($allow_conduit) {
|
||||||
|
$credential_conduit_text = pht('Prevent Conduit Access');
|
||||||
|
$credential_conduit_icon = 'fa-ban';
|
||||||
|
} else {
|
||||||
|
$credential_conduit_text = pht('Allow Conduit Access');
|
||||||
|
$credential_conduit_icon = 'fa-wrench';
|
||||||
|
}
|
||||||
|
|
||||||
$actions = id(new PhabricatorActionListView())
|
$actions = id(new PhabricatorActionListView())
|
||||||
->setObjectURI('/K'.$id)
|
->setObjectURI('/K'.$id)
|
||||||
->setUser($viewer);
|
->setUser($viewer);
|
||||||
|
@ -136,6 +145,13 @@ final class PassphraseCredentialViewController extends PassphraseController {
|
||||||
->setWorkflow(true));
|
->setWorkflow(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$actions->addAction(
|
||||||
|
id(new PhabricatorActionView())
|
||||||
|
->setName($credential_conduit_text)
|
||||||
|
->setIcon($credential_conduit_icon)
|
||||||
|
->setHref($this->getApplicationURI("conduit/{$id}/"))
|
||||||
|
->setWorkflow(true));
|
||||||
|
|
||||||
$actions->addAction(
|
$actions->addAction(
|
||||||
id(new PhabricatorActionView())
|
id(new PhabricatorActionView())
|
||||||
->setName($credential_lock_text)
|
->setName($credential_lock_text)
|
||||||
|
|
|
@ -24,6 +24,7 @@ final class PassphraseCredentialTransactionEditor
|
||||||
$types[] = PassphraseCredentialTransaction::TYPE_DESTROY;
|
$types[] = PassphraseCredentialTransaction::TYPE_DESTROY;
|
||||||
$types[] = PassphraseCredentialTransaction::TYPE_LOOKEDATSECRET;
|
$types[] = PassphraseCredentialTransaction::TYPE_LOOKEDATSECRET;
|
||||||
$types[] = PassphraseCredentialTransaction::TYPE_LOCK;
|
$types[] = PassphraseCredentialTransaction::TYPE_LOCK;
|
||||||
|
$types[] = PassphraseCredentialTransaction::TYPE_CONDUIT;
|
||||||
|
|
||||||
return $types;
|
return $types;
|
||||||
}
|
}
|
||||||
|
@ -47,6 +48,8 @@ final class PassphraseCredentialTransactionEditor
|
||||||
return (int)$object->getIsDestroyed();
|
return (int)$object->getIsDestroyed();
|
||||||
case PassphraseCredentialTransaction::TYPE_LOCK:
|
case PassphraseCredentialTransaction::TYPE_LOCK:
|
||||||
return (int)$object->getIsLocked();
|
return (int)$object->getIsLocked();
|
||||||
|
case PassphraseCredentialTransaction::TYPE_CONDUIT:
|
||||||
|
return (int)$object->getAllowConduit();
|
||||||
case PassphraseCredentialTransaction::TYPE_LOOKEDATSECRET:
|
case PassphraseCredentialTransaction::TYPE_LOOKEDATSECRET:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -67,6 +70,8 @@ final class PassphraseCredentialTransactionEditor
|
||||||
case PassphraseCredentialTransaction::TYPE_DESTROY:
|
case PassphraseCredentialTransaction::TYPE_DESTROY:
|
||||||
case PassphraseCredentialTransaction::TYPE_LOCK:
|
case PassphraseCredentialTransaction::TYPE_LOCK:
|
||||||
return (int)$xaction->getNewValue();
|
return (int)$xaction->getNewValue();
|
||||||
|
case PassphraseCredentialTransaction::TYPE_CONDUIT:
|
||||||
|
return (int)$xaction->getNewValue();
|
||||||
}
|
}
|
||||||
return parent::getCustomTransactionNewValue($object, $xaction);
|
return parent::getCustomTransactionNewValue($object, $xaction);
|
||||||
}
|
}
|
||||||
|
@ -114,6 +119,9 @@ final class PassphraseCredentialTransactionEditor
|
||||||
case PassphraseCredentialTransaction::TYPE_LOCK:
|
case PassphraseCredentialTransaction::TYPE_LOCK:
|
||||||
$object->setIsLocked((int)$xaction->getNewValue());
|
$object->setIsLocked((int)$xaction->getNewValue());
|
||||||
return;
|
return;
|
||||||
|
case PassphraseCredentialTransaction::TYPE_CONDUIT:
|
||||||
|
$object->setAllowConduit((int)$xaction->getNewValue());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::applyCustomInternalTransaction($object, $xaction);
|
return parent::applyCustomInternalTransaction($object, $xaction);
|
||||||
|
@ -131,6 +139,7 @@ final class PassphraseCredentialTransactionEditor
|
||||||
case PassphraseCredentialTransaction::TYPE_DESTROY:
|
case PassphraseCredentialTransaction::TYPE_DESTROY:
|
||||||
case PassphraseCredentialTransaction::TYPE_LOOKEDATSECRET:
|
case PassphraseCredentialTransaction::TYPE_LOOKEDATSECRET:
|
||||||
case PassphraseCredentialTransaction::TYPE_LOCK:
|
case PassphraseCredentialTransaction::TYPE_LOCK:
|
||||||
|
case PassphraseCredentialTransaction::TYPE_CONDUIT:
|
||||||
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
case PhabricatorTransactions::TYPE_VIEW_POLICY:
|
||||||
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
case PhabricatorTransactions::TYPE_EDIT_POLICY:
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -8,6 +8,7 @@ final class PassphraseCredentialQuery
|
||||||
private $credentialTypes;
|
private $credentialTypes;
|
||||||
private $providesTypes;
|
private $providesTypes;
|
||||||
private $isDestroyed;
|
private $isDestroyed;
|
||||||
|
private $allowConduit;
|
||||||
|
|
||||||
private $needSecrets;
|
private $needSecrets;
|
||||||
|
|
||||||
|
@ -36,6 +37,11 @@ final class PassphraseCredentialQuery
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function withAllowConduit($allow_conduit) {
|
||||||
|
$this->allowConduit = $allow_conduit;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function needSecrets($need_secrets) {
|
public function needSecrets($need_secrets) {
|
||||||
$this->needSecrets = $need_secrets;
|
$this->needSecrets = $need_secrets;
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -127,6 +133,13 @@ final class PassphraseCredentialQuery
|
||||||
(int)$this->isDestroyed);
|
(int)$this->isDestroyed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->allowConduit !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn_r,
|
||||||
|
'allowConduit = %d',
|
||||||
|
(int)$this->allowConduit);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->formatWhereClause($where);
|
return $this->formatWhereClause($where);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ final class PassphraseCredential extends PassphraseDAO
|
||||||
protected $secretID;
|
protected $secretID;
|
||||||
protected $isDestroyed;
|
protected $isDestroyed;
|
||||||
protected $isLocked = 0;
|
protected $isLocked = 0;
|
||||||
|
protected $allowConduit = 0;
|
||||||
|
|
||||||
private $secret = self::ATTACHABLE;
|
private $secret = self::ATTACHABLE;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ final class PassphraseCredentialTransaction
|
||||||
const TYPE_DESTROY = 'passphrase:destroy';
|
const TYPE_DESTROY = 'passphrase:destroy';
|
||||||
const TYPE_LOOKEDATSECRET = 'passphrase:lookedAtSecret';
|
const TYPE_LOOKEDATSECRET = 'passphrase:lookedAtSecret';
|
||||||
const TYPE_LOCK = 'passphrase:lock';
|
const TYPE_LOCK = 'passphrase:lock';
|
||||||
|
const TYPE_CONDUIT = 'passphrase:conduit';
|
||||||
|
|
||||||
public function getApplicationName() {
|
public function getApplicationName() {
|
||||||
return 'passphrase';
|
return 'passphrase';
|
||||||
|
@ -91,6 +92,17 @@ final class PassphraseCredentialTransaction
|
||||||
return pht(
|
return pht(
|
||||||
'%s locked this credential.',
|
'%s locked this credential.',
|
||||||
$this->renderHandleLink($author_phid));
|
$this->renderHandleLink($author_phid));
|
||||||
|
case self::TYPE_CONDUIT:
|
||||||
|
if ($old) {
|
||||||
|
return pht(
|
||||||
|
'%s disallowed Conduit API access to this credential.',
|
||||||
|
$this->renderHandleLink($author_phid));
|
||||||
|
} else {
|
||||||
|
return pht(
|
||||||
|
'%s allowed Conduit API access to this credential.',
|
||||||
|
$this->renderHandleLink($author_phid));
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::getTitle();
|
return parent::getTitle();
|
||||||
|
|
Loading…
Reference in a new issue