1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-28 08:20:57 +01:00

Migrate repositories to use Passphrase for credential management

Summary: Fixes T4122. Ref T2230. Instead of storing credentials on each repository, store them in Passphrase. This allows easy creation/management of many repositories which share credentials.

Test Plan:
  - Upgraded repositories.
  - Created and edited repositories.
  - Pulled HTTP and SSH repositories.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2230, T4122

Differential Revision: https://secure.phabricator.com/D7629
This commit is contained in:
epriestley 2013-11-22 15:23:33 -08:00
parent 819f899013
commit 51fb1ca16d
13 changed files with 296 additions and 231 deletions

View file

@ -0,0 +1,2 @@
ALTER TABLE {$NAMESPACE}_repository.repository
ADD credentialPHID VARCHAR(64) COLLATE utf8_bin;

View file

@ -0,0 +1,104 @@
<?php
$table = new PhabricatorRepository();
$conn_w = $table->establishConnection('w');
$viewer = PhabricatorUser::getOmnipotentUser();
$map = array();
foreach (new LiskMigrationIterator($table) as $repository) {
$callsign = $repository->getCallsign();
echo "Examining repository {$callsign}...\n";
if ($repository->getCredentialPHID()) {
echo "...already has a Credential.\n";
continue;
}
$uri = $repository->getRemoteURI();
if (!$uri) {
echo "...no remote URI.\n";
continue;
}
$uri = new PhutilURI($uri);
$proto = strtolower($uri->getProtocol());
if ($proto == 'http' || $proto == 'https' || $proto == 'svn') {
$username = $repository->getDetail('http-login');
$secret = $repository->getDetail('http-pass');
$type = PassphraseCredentialTypePassword::CREDENTIAL_TYPE;
} else {
$username = $repository->getDetail('ssh-login');
$file = $repository->getDetail('ssh-keyfile');
if ($file) {
$secret = $file;
$type = PassphraseCredentialTypeSSHPrivateKeyFile::CREDENTIAL_TYPE;
} else {
$secret = $repository->getDetail('ssh-key');
$type = PassphraseCredentialTypeSSHPrivateKeyText::CREDENTIAL_TYPE;
}
}
if (!$username || !$secret) {
echo "...no credentials set.\n";
continue;
}
$map[$type][$username][$secret][] = $repository;
echo "...will migrate.\n";
}
$passphrase = new PassphraseSecret();
$passphrase->openTransaction();
$table->openTransaction();
foreach ($map as $credential_type => $credential_usernames) {
$type = PassphraseCredentialType::getTypeByConstant($credential_type);
foreach ($credential_usernames as $username => $credential_secrets) {
foreach ($credential_secrets as $secret_plaintext => $repositories) {
$callsigns = mpull($repositories, 'getCallsign');
$name = pht(
'Migrated Repository Credential (%s)',
implode(', ', $callsigns));
echo "Creating: {$name}...\n";
$secret = id(new PassphraseSecret())
->setSecretData($secret_plaintext)
->save();
$secret_id = $secret->getID();
$credential = PassphraseCredential::initializeNewCredential($viewer)
->setCredentialType($type->getCredentialType())
->setProvidesType($type->getProvidesType())
->setViewPolicy(PhabricatorPolicies::POLICY_ADMIN)
->setEditPolicy(PhabricatorPolicies::POLICY_ADMIN)
->setName($name)
->setUsername($username)
->setSecretID($secret_id)
->save();
foreach ($repositories as $repository) {
queryfx(
$conn_w,
'UPDATE %T SET credentialPHID = %s WHERE id = %d',
$table->getTableName(),
$credential->getPHID(),
$repository->getID());
$edge_type = PhabricatorEdgeConfig::TYPE_OBJECT_USES_CREDENTIAL;
id(new PhabricatorEdgeEditor())
->setActor($viewer)
->addEdge($repository->getPHID(), $edge_type, $credential->getPHID())
->save();
}
}
}
}
$table->saveTransaction();
$passphrase->saveTransaction();
echo "Done.\n";

View file

@ -12,8 +12,10 @@ if (!$target_name) {
throw new Exception(pht("No 'PHABRICATOR_SSH_TARGET' in environment!"));
}
$viewer = PhabricatorUser::getOmnipotentUser();
$repository = id(new PhabricatorRepositoryQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->setViewer($viewer)
->withCallsigns(array($target_name))
->executeOne();
if (!$repository) {
@ -28,30 +30,14 @@ $pattern[] = 'ssh';
$pattern[] = '-o';
$pattern[] = 'StrictHostKeyChecking=no';
$login = $repository->getSSHLogin();
if (strlen($login)) {
$pattern[] = '-l';
$pattern[] = '%P';
$arguments[] = new PhutilOpaqueEnvelope($login);
}
$credential_phid = $repository->getCredentialPHID();
if ($credential_phid) {
$key = PassphraseSSHKey::loadFromPHID($credential_phid, $viewer);
$ssh_identity = null;
$key = $repository->getDetail('ssh-key');
$keyfile = $repository->getDetail('ssh-keyfile');
if ($keyfile) {
$ssh_identity = $keyfile;
} else if ($key) {
$tmpfile = new TempFile('phabricator-repository-ssh-key');
chmod($tmpfile, 0600);
Filesystem::writeFile($tmpfile, $key);
$ssh_identity = (string)$tmpfile;
}
if ($ssh_identity) {
$pattern[] = '-i';
$pattern[] = '%P';
$arguments[] = new PhutilOpaqueEnvelope($keyfile);
$pattern[] = '-l %P';
$arguments[] = $key->getUsernameEnvelope();
$pattern[] = '-i %P';
$arguments[] = $key->getKeyfileEnvelope();
}
$pattern[] = '--';

View file

@ -94,12 +94,8 @@ final class DiffusionRepositoryCreateController
$type_activate = PhabricatorRepositoryTransaction::TYPE_ACTIVATE;
$type_local_path = PhabricatorRepositoryTransaction::TYPE_LOCAL_PATH;
$type_remote_uri = PhabricatorRepositoryTransaction::TYPE_REMOTE_URI;
$type_ssh_login = PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN;
$type_ssh_key = PhabricatorRepositoryTransaction::TYPE_SSH_KEY;
$type_ssh_keyfile = PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE;
$type_http_login = PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN;
$type_http_pass = PhabricatorRepositoryTransaction::TYPE_HTTP_PASS;
$type_hosting = PhabricatorRepositoryTransaction::TYPE_HOSTING;
$type_credential = PhabricatorRepositoryTransaction::TYPE_CREDENTIAL;
$xactions = array();
@ -159,29 +155,9 @@ final class DiffusionRepositoryCreateController
->getValue());
$xactions[] = id(clone $template)
->setTransactionType($type_ssh_login)
->setTransactionType($type_credential)
->setNewValue(
$form->getPage('auth')->getControl('ssh-login')->getValue());
$xactions[] = id(clone $template)
->setTransactionType($type_ssh_key)
->setNewValue(
$form->getPage('auth')->getControl('ssh-key')->getValue());
$xactions[] = id(clone $template)
->setTransactionType($type_ssh_keyfile)
->setNewValue(
$form->getPage('auth')->getControl('ssh-keyfile')->getValue());
$xactions[] = id(clone $template)
->setTransactionType($type_http_login)
->setNewValue(
$form->getPage('auth')->getControl('http-login')->getValue());
$xactions[] = id(clone $template)
->setTransactionType($type_http_pass)
->setNewValue(
$form->getPage('auth')->getControl('http-pass')->getValue());
$form->getPage('auth')->getControl('credential')->getValue());
}
id(new PhabricatorRepositoryEditor())
@ -198,11 +174,7 @@ final class DiffusionRepositoryCreateController
if ($repository) {
$dict = array(
'remoteURI' => $repository->getRemoteURI(),
'ssh-login' => $repository->getDetail('ssh-login'),
'ssh-key' => $repository->getDetail('ssh-key'),
'ssh-keyfile' => $repository->getDetail('ssh-keyfile'),
'http-login' => $repository->getDetail('http-login'),
'http-pass' => $repository->getDetail('http-pass'),
'credential' => $repository->getCredentialPHID(),
);
}
$form->readFromObject($dict);
@ -550,105 +522,86 @@ final class DiffusionRepositoryCreateController
->setUser($this->getRequest()->getUser())
->setAdjustFormPageCallback(array($this, 'adjustAuthPage'))
->addControl(
id(new AphrontFormTextControl())
->setName('ssh-login')
->setLabel('SSH User'))
->addControl(
id(new AphrontFormTextAreaControl())
->setName('ssh-key')
->setLabel('SSH Private Key')
->setHeight(AphrontFormTextAreaControl::HEIGHT_SHORT)
->setCaption(
hsprintf('Specify the entire private key, <em>or</em>...')))
->addControl(
id(new AphrontFormTextControl())
->setName('ssh-keyfile')
->setLabel('SSH Private Key Path')
->setCaption(
'...specify a path on disk where the daemon should '.
'look for a private key.'))
->addControl(
id(new AphrontFormTextControl())
->setName('http-login')
->setLabel('Username'))
->addControl(
id(new AphrontFormPasswordControl())
->setName('http-pass')
->setLabel('Password'));
id(new PassphraseCredentialControl())
->setName('credential'));
}
public function adjustAuthPage($page) {
$form = $page->getForm();
$remote_uri = $form->getPage('remote-uri')
->getControl('remoteURI')
->getValue();
if ($this->getRepository()) {
$vcs = $this->getRepository()->getVersionControlSystem();
} else {
$vcs = $form->getPage('vcs')->getControl('vcs')->getValue();
}
$remote_uri = $form->getPage('remote-uri')
->getControl('remoteURI')
->getValue();
$proto = $this->getRemoteURIProtocol($remote_uri);
$remote_user = $this->getRemoteURIUser($remote_uri);
$page->getControl('ssh-login')->setHidden(true);
$page->getControl('ssh-key')->setHidden(true);
$page->getControl('ssh-keyfile')->setHidden(true);
$page->getControl('http-login')->setHidden(true);
$page->getControl('http-pass')->setHidden(true);
$c_credential = $page->getControl('credential');
$c_credential->setDefaultUsername($remote_user);
if ($this->isSSHProtocol($proto)) {
$page->getControl('ssh-login')->setHidden(false);
$page->getControl('ssh-key')->setHidden(false);
$page->getControl('ssh-keyfile')->setHidden(false);
$c_login = $page->getControl('ssh-login');
if (!strlen($c_login->getValue())) {
$c_login->setValue($remote_user);
}
$c_credential->setLabel(pht('SSH Key'));
$c_credential->setCredentialType(
PassphraseCredentialTypeSSHPrivateKeyText::CREDENTIAL_TYPE);
$provides_type = PassphraseCredentialTypeSSHPrivateKey::PROVIDES_TYPE;
$page->addRemarkupInstructions(
pht(
'Enter the username and private key to use to connect to the '.
'the repository hosted at:'.
'Choose or add the SSH credentials to use to connect to the the '.
'repository hosted at:'.
"\n\n".
" lang=text\n".
" %s".
"\n\n".
'You can either copy/paste the entire private key, or put it '.
'somewhere on disk and provide the path to it.',
" %s",
$remote_uri),
'ssh-login');
'credential');
} else if ($this->isUsernamePasswordProtocol($proto)) {
$page->getControl('http-login')->setHidden(false);
$page->getControl('http-pass')->setHidden(false);
$c_credential->setLabel(pht('Password'));
$c_credential->setAllowNull(true);
$c_credential->setCredentialType(
PassphraseCredentialTypePassword::CREDENTIAL_TYPE);
$provides_type = PassphraseCredentialTypePassword::PROVIDES_TYPE;
$page->addRemarkupInstructions(
pht(
'Enter the a username and pasword used to connect to the '.
'Choose the a username and pasword used to connect to the '.
'repository hosted at:'.
"\n\n".
" lang=text\n".
" %s".
"\n\n".
"If this repository does not require a username or password, ".
"you can leave these fields blank.",
"you can continue to the next step.",
$remote_uri),
'http-login');
'credential');
} else if ($proto == 'file') {
$c_credential->setHidden(true);
$page->addRemarkupInstructions(
pht(
'You do not need to configure any authentication options for '.
'repositories accessed over the `file://` protocol. Continue '.
'to the next step.'),
'ssh-login');
'You do not need to configure any credentials for repositories '.
'accessed over the `file://` protocol. Continue to the next step.'),
'credential');
} else {
throw new Exception("Unknown URI protocol!");
}
if ($provides_type) {
$viewer = $this->getRequest()->getUser();
$options = id(new PassphraseCredentialQuery())
->setViewer($viewer)
->withIsDestroyed(false)
->withProvidesTypes(array($provides_type))
->execute();
$c_credential->setOptions($options);
}
}
public function validateAuthPage(PHUIFormPageView $page) {
@ -656,49 +609,46 @@ final class DiffusionRepositoryCreateController
$remote_uri = $form->getPage('remote')->getControl('remoteURI')->getValue();
$proto = $this->getRemoteURIProtocol($remote_uri);
$c_credential = $page->getControl('credential');
$v_credential = $c_credential->getValue();
// NOTE: We're using the omnipotent user here because the viewer might be
// editing a repository they're allowed to edit which uses a credential they
// are not allowed to see. This is fine, as long as they don't change it.
$credential = id(new PassphraseCredentialQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->withPHIDs(array($v_credential))
->executeOne();
if ($this->isSSHProtocol($proto)) {
$c_user = $page->getControl('ssh-login');
$c_key = $page->getControl('ssh-key');
$c_file = $page->getControl('ssh-keyfile');
$v_user = $c_user->getValue();
$v_key = $c_key->getValue();
$v_file = $c_file->getValue();
if (!strlen($v_user)) {
$c_user->setError(pht('Required'));
if (!$credential) {
$c_credential->setError(pht('Required'));
$page->addPageError(
pht('You must provide an SSH login username to connect over SSH.'));
pht('You must choose an SSH credential to connect over SSH.'));
}
if (!strlen($v_key) && !strlen($v_file)) {
$c_key->setError(pht('No Key'));
$c_file->setError(pht('No Key'));
$ssh_type = PassphraseCredentialTypeSSHPrivateKey::PROVIDES_TYPE;
if ($credential->getProvidesType() !== $ssh_type) {
$c_credential->setError(pht('Invalid'));
$page->addPageError(
pht(
'You must provide either a private key or the path to a private '.
'key to connect over SSH.'));
} else if (strlen($v_key) && strlen($v_file)) {
$c_key->setError(pht('Ambiguous'));
$c_file->setError(pht('Ambiguous'));
$page->addPageError(
pht(
'Provide either a private key or the path to a private key, not '.
'both.'));
} else if (!preg_match('/PRIVATE KEY/', $v_key)) {
$c_key->setError(pht('Invalid'));
$page->addPageError(
pht(
'The private key you provided is missing the PRIVATE KEY header. '.
'You should include the header and footer. (Did you provide a '.
'public key by mistake?)'));
'You must choose an SSH credential, not some other type '.
'of credential.'));
}
return $c_user->isValid() &&
$c_key->isValid() &&
$c_file->isValid();
} else if ($this->isUsernamePasswordProtocol($proto)) {
return true;
if ($credential) {
$password_type = PassphraseCredentialTypePassword::PROVIDES_TYPE;
if ($credential->getProvidesType() !== $password_type) {
$c_credential->setError(pht('Invalid'));
$page->addPageError(
pht(
'You must choose a username/password credential, not some other '.
'type of credential.'));
}
}
return $c_credential->isValid();
} else {
return true;
}

View file

@ -481,6 +481,14 @@ final class DiffusionRepositoryEditMainController
pht('Remote URI'),
$repository->getHumanReadableDetail('remote-uri'));
$credential_phid = $repository->getCredentialPHID();
if ($credential_phid) {
$this->loadHandles(array($credential_phid));
$view->addProperty(
pht('Credential'),
$this->getHandle($credential_phid)->renderLink());
}
return $view;
}

View file

@ -26,8 +26,8 @@ final class PhabricatorApplicationPassphrase extends PhabricatorApplication {
return self::GROUP_UTILITIES;
}
public function isBeta() {
return true;
public function canUninstall() {
return false;
}
public function getRoutes() {

View file

@ -32,16 +32,24 @@ abstract class PassphraseAbstractKey extends Phobject {
PassphraseCredential $credential,
$provides_type) {
$type = $credential->getCredentialType();
if ($type->getProvides() !== $provides_type) {
$type = $credential->getCredentialTypeImplementation();
if (!$type) {
throw new Exception(
pht(
'Credential "%s" is of unknown type "%s"!',
'K'.$credential->getID(),
$credential->getCredentialType()));
}
if ($type->getProvidesType() !== $provides_type) {
throw new Exception(
pht(
'Credential "%s" must provide "%s", but provides "%s"!',
'K'.$credential->getID(),
$provides_type,
$type->getProvides()));
$type->getProvidesType()));
}
}
protected function loadAndValidateFromPHID(

View file

@ -45,6 +45,11 @@ final class PassphraseCredential extends PassphraseDAO
return $this->assertAttached($this->secret);
}
public function getCredentialTypeImplementation() {
$type = $this->getCredentialType();
return PassphraseCredentialType::getTypeByConstant($type);
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */

View file

@ -27,11 +27,7 @@ final class ConduitAPI_repository_create_Method
'encoding' => 'optional string',
'tracking' => 'optional bool',
'uri' => 'optional string',
'sshUser' => 'optional string',
'sshKey' => 'optional string',
'sshKeyFile' => 'optional string',
'httpUser' => 'optional string',
'httpPassword' => 'optional string',
'credentialPHID' => 'optional string',
'localPath' => 'optional string',
'svnSubpath' => 'optional string',
'branchFilter' => 'optional list<string>',
@ -100,6 +96,8 @@ final class ConduitAPI_repository_create_Method
}
$repository->setVersionControlSystem($map[$vcs]);
$repository->setCredentialPHID($request->getValue('credentialPHID'));
$details = array(
'encoding' => $request->getValue('encoding'),
'description' => $request->getValue('description'),
@ -114,9 +112,6 @@ final class ConduitAPI_repository_create_Method
true),
'pull-frequency' => $request->getValue('pullFrequency'),
'default-branch' => $request->getValue('defaultBranch'),
'ssh-login' => $request->getValue('sshUser'),
'ssh-key' => $request->getValue('sshKey'),
'ssh-keyfile' => $request->getValue('sshKeyFile'),
'herald-disabled' => !$request->getValue('heraldEnabled', true),
'svn-subpath' => $request->getValue('svnSubpath'),
'disable-autoclose' => !$request->getValue('autocloseEnabled', true),

View file

@ -29,6 +29,7 @@ final class PhabricatorRepositoryEditor
$types[] = PhabricatorRepositoryTransaction::TYPE_PROTOCOL_HTTP;
$types[] = PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH;
$types[] = PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY;
$types[] = PhabricatorRepositoryTransaction::TYPE_CREDENTIAL;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
@ -67,16 +68,6 @@ final class PhabricatorRepositoryEditor
return (int)!$object->getDetail('disable-autoclose');
case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI:
return $object->getDetail('remote-uri');
case PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN:
return $object->getDetail('ssh-login');
case PhabricatorRepositoryTransaction::TYPE_SSH_KEY:
return $object->getDetail('ssh-key');
case PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE:
return $object->getDetail('ssh-keyfile');
case PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN:
return $object->getDetail('http-login');
case PhabricatorRepositoryTransaction::TYPE_HTTP_PASS:
return $object->getDetail('http-pass');
case PhabricatorRepositoryTransaction::TYPE_LOCAL_PATH:
return $object->getDetail('local-path');
case PhabricatorRepositoryTransaction::TYPE_HOSTING:
@ -87,6 +78,8 @@ final class PhabricatorRepositoryEditor
return $object->getServeOverSSH();
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
return $object->getPushPolicy();
case PhabricatorRepositoryTransaction::TYPE_CREDENTIAL:
return $object->getCredentialPHID();
}
}
@ -116,6 +109,7 @@ final class PhabricatorRepositoryEditor
case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_HTTP:
case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH:
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
case PhabricatorRepositoryTransaction::TYPE_CREDENTIAL:
return $xaction->getNewValue();
case PhabricatorRepositoryTransaction::TYPE_NOTIFY:
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE:
@ -168,21 +162,6 @@ final class PhabricatorRepositoryEditor
case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI:
$object->setDetail('remote-uri', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN:
$object->setDetail('ssh-login', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_SSH_KEY:
$object->setDetail('ssh-key', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE:
$object->setDetail('ssh-keyfile', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN:
$object->setDetail('http-login', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_HTTP_PASS:
$object->setDetail('http-pass', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_LOCAL_PATH:
$object->setDetail('local-path', $xaction->getNewValue());
break;
@ -194,6 +173,8 @@ final class PhabricatorRepositoryEditor
return $object->setServeOverSSH($xaction->getNewValue());
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
return $object->setPushPolicy($xaction->getNewValue());
case PhabricatorRepositoryTransaction::TYPE_CREDENTIAL:
return $object->setCredentialPHID($xaction->getNewValue());
case PhabricatorRepositoryTransaction::TYPE_ENCODING:
// Make sure the encoding is valid by converting to UTF-8. This tests
// that the user has mbstring installed, and also that they didn't type
@ -221,7 +202,32 @@ final class PhabricatorRepositoryEditor
protected function applyCustomExternalTransaction(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
return;
switch ($xaction->getTransactionType()) {
case PhabricatorRepositoryTransaction::TYPE_CREDENTIAL:
// Adjust the object <-> credential edge for this repository.
$old_phid = $xaction->getOldValue();
$new_phid = $xaction->getNewValue();
$editor = id(new PhabricatorEdgeEditor())
->setActor($this->requireActor());
$edge_type = PhabricatorEdgeConfig::TYPE_OBJECT_USES_CREDENTIAL;
$src_phid = $object->getPHID();
if ($old_phid) {
$editor->removeEdge($src_phid, $edge_type, $old_phid);
}
if ($new_phid) {
$editor->addEdge($src_phid, $edge_type, $new_phid);
}
$editor->save();
break;
}
}
protected function mergeTransactions(
@ -278,6 +284,7 @@ final class PhabricatorRepositoryEditor
case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_HTTP:
case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH:
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
case PhabricatorRepositoryTransaction::TYPE_CREDENTIAL:
PhabricatorPolicyFilter::requireCapability(
$this->requireActor(),
$object,

View file

@ -39,8 +39,7 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
protected $versionControlSystem;
protected $details = array();
private $sshKeyfile;
protected $credentialPHID;
private $commitCount = self::ATTACHABLE;
private $mostRecentCommit = self::ATTACHABLE;
@ -366,31 +365,29 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
switch ($this->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
if ($this->shouldUseHTTP()) {
$pattern =
"svn ".
"--non-interactive ".
"--no-auth-cache ".
"--trust-server-cert ".
"--username %P ".
"--password %P ".
$pattern;
array_unshift(
$args,
new PhutilOpaqueEnvelope($this->getDetail('http-login')),
new PhutilOpaqueEnvelope($this->getDetail('http-pass')));
} else if ($this->shouldUseSVNProtocol()) {
$pattern =
"svn ".
"--non-interactive ".
"--no-auth-cache ".
"--username %P ".
"--password %P ".
$pattern;
array_unshift(
$args,
new PhutilOpaqueEnvelope($this->getDetail('http-login')),
new PhutilOpaqueEnvelope($this->getDetail('http-pass')));
if ($this->shouldUseHTTP() || $this->shouldUseSVNProtocol()) {
$flags = array();
$flag_args = array();
$flags[] = '--non-interactive';
$flags[] = '--no-auth-cache';
if ($this->shouldUseHTTP()) {
$flags[] = '--trust-server-cert';
}
$credential_phid = $this->getCredentialPHID();
if ($credential_phid) {
$key = PassphrasePasswordKey::loadFromPHID(
$credential_phid,
PhabricatorUser::getOmnipotentUser());
$flags[] = '--username %P';
$flags[] = '--password %P';
$flag_args[] = $key->getUsernameEnvelope();
$flag_args[] = $key->getPasswordEnvelope();
}
$flags = implode(' ', $flags);
$pattern = "svn {$flags} {$pattern}";
$args = array_mergev(array($flag_args, $args));
} else {
$pattern = "svn --non-interactive {$pattern}";
}
@ -687,11 +684,7 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
}
$protocol = $this->getRemoteProtocol();
if ($protocol == 'http' || $protocol == 'https') {
return (bool)$this->getDetail('http-login');
} else {
return false;
}
return ($protocol == 'http' || $protocol == 'https');
}
@ -708,11 +701,7 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
}
$protocol = $this->getRemoteProtocol();
if ($protocol == 'svn') {
return (bool)$this->getDetail('http-login');
} else {
return false;
}
return ($protocol == 'svn');
}

View file

@ -16,16 +16,19 @@ final class PhabricatorRepositoryTransaction
const TYPE_NOTIFY = 'repo:notify';
const TYPE_AUTOCLOSE = 'repo:autoclose';
const TYPE_REMOTE_URI = 'repo:remote-uri';
const TYPE_SSH_LOGIN = 'repo:ssh-login';
const TYPE_SSH_KEY = 'repo:ssh-key';
const TYPE_SSH_KEYFILE = 'repo:ssh-keyfile';
const TYPE_HTTP_LOGIN = 'repo:http-login';
const TYPE_HTTP_PASS = 'repo:http-pass';
const TYPE_LOCAL_PATH = 'repo:local-path';
const TYPE_HOSTING = 'repo:hosting';
const TYPE_PROTOCOL_HTTP = 'repo:serve-http';
const TYPE_PROTOCOL_SSH = 'repo:serve-ssh';
const TYPE_PUSH_POLICY = 'repo:push-policy';
const TYPE_CREDENTIAL = 'repo:credential';
// TODO: Clean up these legacy transaction types.
const TYPE_SSH_LOGIN = 'repo:ssh-login';
const TYPE_SSH_KEY = 'repo:ssh-key';
const TYPE_SSH_KEYFILE = 'repo:ssh-keyfile';
const TYPE_HTTP_LOGIN = 'repo:http-login';
const TYPE_HTTP_PASS = 'repo:http-pass';
public function getApplicationName() {
return 'repository';

View file

@ -1776,6 +1776,14 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
'type' => 'sql',
'name' => $this->getPatchPath('20131121.passphraseedge.sql'),
),
'20131121.repocredentials.1.col.sql' => array(
'type' => 'sql',
'name' => $this->getPatchPath('20131121.repocredentials.1.col.sql'),
),
'20131121.repocredentials.2.mig.php' => array(
'type' => 'php',
'name' => $this->getPatchPath('20131121.repocredentials.2.mig.php'),
),
);
}
}