mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-30 17:30:59 +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:
parent
819f899013
commit
51fb1ca16d
13 changed files with 296 additions and 231 deletions
2
resources/sql/patches/20131121.repocredentials.1.col.sql
Normal file
2
resources/sql/patches/20131121.repocredentials.1.col.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE {$NAMESPACE}_repository.repository
|
||||||
|
ADD credentialPHID VARCHAR(64) COLLATE utf8_bin;
|
104
resources/sql/patches/20131121.repocredentials.2.mig.php
Normal file
104
resources/sql/patches/20131121.repocredentials.2.mig.php
Normal 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";
|
|
@ -12,8 +12,10 @@ if (!$target_name) {
|
||||||
throw new Exception(pht("No 'PHABRICATOR_SSH_TARGET' in environment!"));
|
throw new Exception(pht("No 'PHABRICATOR_SSH_TARGET' in environment!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$viewer = PhabricatorUser::getOmnipotentUser();
|
||||||
|
|
||||||
$repository = id(new PhabricatorRepositoryQuery())
|
$repository = id(new PhabricatorRepositoryQuery())
|
||||||
->setViewer(PhabricatorUser::getOmnipotentUser())
|
->setViewer($viewer)
|
||||||
->withCallsigns(array($target_name))
|
->withCallsigns(array($target_name))
|
||||||
->executeOne();
|
->executeOne();
|
||||||
if (!$repository) {
|
if (!$repository) {
|
||||||
|
@ -28,30 +30,14 @@ $pattern[] = 'ssh';
|
||||||
$pattern[] = '-o';
|
$pattern[] = '-o';
|
||||||
$pattern[] = 'StrictHostKeyChecking=no';
|
$pattern[] = 'StrictHostKeyChecking=no';
|
||||||
|
|
||||||
$login = $repository->getSSHLogin();
|
$credential_phid = $repository->getCredentialPHID();
|
||||||
if (strlen($login)) {
|
if ($credential_phid) {
|
||||||
$pattern[] = '-l';
|
$key = PassphraseSSHKey::loadFromPHID($credential_phid, $viewer);
|
||||||
$pattern[] = '%P';
|
|
||||||
$arguments[] = new PhutilOpaqueEnvelope($login);
|
|
||||||
}
|
|
||||||
|
|
||||||
$ssh_identity = null;
|
$pattern[] = '-l %P';
|
||||||
|
$arguments[] = $key->getUsernameEnvelope();
|
||||||
$key = $repository->getDetail('ssh-key');
|
$pattern[] = '-i %P';
|
||||||
$keyfile = $repository->getDetail('ssh-keyfile');
|
$arguments[] = $key->getKeyfileEnvelope();
|
||||||
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[] = '--';
|
$pattern[] = '--';
|
||||||
|
|
|
@ -94,12 +94,8 @@ final class DiffusionRepositoryCreateController
|
||||||
$type_activate = PhabricatorRepositoryTransaction::TYPE_ACTIVATE;
|
$type_activate = PhabricatorRepositoryTransaction::TYPE_ACTIVATE;
|
||||||
$type_local_path = PhabricatorRepositoryTransaction::TYPE_LOCAL_PATH;
|
$type_local_path = PhabricatorRepositoryTransaction::TYPE_LOCAL_PATH;
|
||||||
$type_remote_uri = PhabricatorRepositoryTransaction::TYPE_REMOTE_URI;
|
$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_hosting = PhabricatorRepositoryTransaction::TYPE_HOSTING;
|
||||||
|
$type_credential = PhabricatorRepositoryTransaction::TYPE_CREDENTIAL;
|
||||||
|
|
||||||
$xactions = array();
|
$xactions = array();
|
||||||
|
|
||||||
|
@ -159,29 +155,9 @@ final class DiffusionRepositoryCreateController
|
||||||
->getValue());
|
->getValue());
|
||||||
|
|
||||||
$xactions[] = id(clone $template)
|
$xactions[] = id(clone $template)
|
||||||
->setTransactionType($type_ssh_login)
|
->setTransactionType($type_credential)
|
||||||
->setNewValue(
|
->setNewValue(
|
||||||
$form->getPage('auth')->getControl('ssh-login')->getValue());
|
$form->getPage('auth')->getControl('credential')->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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
id(new PhabricatorRepositoryEditor())
|
id(new PhabricatorRepositoryEditor())
|
||||||
|
@ -198,11 +174,7 @@ final class DiffusionRepositoryCreateController
|
||||||
if ($repository) {
|
if ($repository) {
|
||||||
$dict = array(
|
$dict = array(
|
||||||
'remoteURI' => $repository->getRemoteURI(),
|
'remoteURI' => $repository->getRemoteURI(),
|
||||||
'ssh-login' => $repository->getDetail('ssh-login'),
|
'credential' => $repository->getCredentialPHID(),
|
||||||
'ssh-key' => $repository->getDetail('ssh-key'),
|
|
||||||
'ssh-keyfile' => $repository->getDetail('ssh-keyfile'),
|
|
||||||
'http-login' => $repository->getDetail('http-login'),
|
|
||||||
'http-pass' => $repository->getDetail('http-pass'),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
$form->readFromObject($dict);
|
$form->readFromObject($dict);
|
||||||
|
@ -550,105 +522,86 @@ final class DiffusionRepositoryCreateController
|
||||||
->setUser($this->getRequest()->getUser())
|
->setUser($this->getRequest()->getUser())
|
||||||
->setAdjustFormPageCallback(array($this, 'adjustAuthPage'))
|
->setAdjustFormPageCallback(array($this, 'adjustAuthPage'))
|
||||||
->addControl(
|
->addControl(
|
||||||
id(new AphrontFormTextControl())
|
id(new PassphraseCredentialControl())
|
||||||
->setName('ssh-login')
|
->setName('credential'));
|
||||||
->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'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function adjustAuthPage($page) {
|
public function adjustAuthPage($page) {
|
||||||
$form = $page->getForm();
|
$form = $page->getForm();
|
||||||
|
|
||||||
$remote_uri = $form->getPage('remote-uri')
|
|
||||||
->getControl('remoteURI')
|
|
||||||
->getValue();
|
|
||||||
|
|
||||||
if ($this->getRepository()) {
|
if ($this->getRepository()) {
|
||||||
$vcs = $this->getRepository()->getVersionControlSystem();
|
$vcs = $this->getRepository()->getVersionControlSystem();
|
||||||
} else {
|
} else {
|
||||||
$vcs = $form->getPage('vcs')->getControl('vcs')->getValue();
|
$vcs = $form->getPage('vcs')->getControl('vcs')->getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$remote_uri = $form->getPage('remote-uri')
|
||||||
|
->getControl('remoteURI')
|
||||||
|
->getValue();
|
||||||
$proto = $this->getRemoteURIProtocol($remote_uri);
|
$proto = $this->getRemoteURIProtocol($remote_uri);
|
||||||
$remote_user = $this->getRemoteURIUser($remote_uri);
|
$remote_user = $this->getRemoteURIUser($remote_uri);
|
||||||
|
|
||||||
$page->getControl('ssh-login')->setHidden(true);
|
$c_credential = $page->getControl('credential');
|
||||||
$page->getControl('ssh-key')->setHidden(true);
|
$c_credential->setDefaultUsername($remote_user);
|
||||||
$page->getControl('ssh-keyfile')->setHidden(true);
|
|
||||||
$page->getControl('http-login')->setHidden(true);
|
|
||||||
$page->getControl('http-pass')->setHidden(true);
|
|
||||||
|
|
||||||
if ($this->isSSHProtocol($proto)) {
|
if ($this->isSSHProtocol($proto)) {
|
||||||
$page->getControl('ssh-login')->setHidden(false);
|
$c_credential->setLabel(pht('SSH Key'));
|
||||||
$page->getControl('ssh-key')->setHidden(false);
|
$c_credential->setCredentialType(
|
||||||
$page->getControl('ssh-keyfile')->setHidden(false);
|
PassphraseCredentialTypeSSHPrivateKeyText::CREDENTIAL_TYPE);
|
||||||
|
$provides_type = PassphraseCredentialTypeSSHPrivateKey::PROVIDES_TYPE;
|
||||||
$c_login = $page->getControl('ssh-login');
|
|
||||||
if (!strlen($c_login->getValue())) {
|
|
||||||
$c_login->setValue($remote_user);
|
|
||||||
}
|
|
||||||
|
|
||||||
$page->addRemarkupInstructions(
|
$page->addRemarkupInstructions(
|
||||||
pht(
|
pht(
|
||||||
'Enter the username and private key to use to connect to the '.
|
'Choose or add the SSH credentials to use to connect to the the '.
|
||||||
'the repository hosted at:'.
|
'repository hosted at:'.
|
||||||
"\n\n".
|
"\n\n".
|
||||||
" lang=text\n".
|
" lang=text\n".
|
||||||
" %s".
|
" %s",
|
||||||
"\n\n".
|
|
||||||
'You can either copy/paste the entire private key, or put it '.
|
|
||||||
'somewhere on disk and provide the path to it.',
|
|
||||||
$remote_uri),
|
$remote_uri),
|
||||||
'ssh-login');
|
'credential');
|
||||||
|
|
||||||
} else if ($this->isUsernamePasswordProtocol($proto)) {
|
} else if ($this->isUsernamePasswordProtocol($proto)) {
|
||||||
$page->getControl('http-login')->setHidden(false);
|
$c_credential->setLabel(pht('Password'));
|
||||||
$page->getControl('http-pass')->setHidden(false);
|
$c_credential->setAllowNull(true);
|
||||||
|
$c_credential->setCredentialType(
|
||||||
|
PassphraseCredentialTypePassword::CREDENTIAL_TYPE);
|
||||||
|
$provides_type = PassphraseCredentialTypePassword::PROVIDES_TYPE;
|
||||||
|
|
||||||
$page->addRemarkupInstructions(
|
$page->addRemarkupInstructions(
|
||||||
pht(
|
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:'.
|
'repository hosted at:'.
|
||||||
"\n\n".
|
"\n\n".
|
||||||
" lang=text\n".
|
" lang=text\n".
|
||||||
" %s".
|
" %s".
|
||||||
"\n\n".
|
"\n\n".
|
||||||
"If this repository does not require a username or password, ".
|
"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),
|
$remote_uri),
|
||||||
'http-login');
|
'credential');
|
||||||
} else if ($proto == 'file') {
|
} else if ($proto == 'file') {
|
||||||
|
$c_credential->setHidden(true);
|
||||||
$page->addRemarkupInstructions(
|
$page->addRemarkupInstructions(
|
||||||
pht(
|
pht(
|
||||||
'You do not need to configure any authentication options for '.
|
'You do not need to configure any credentials for repositories '.
|
||||||
'repositories accessed over the `file://` protocol. Continue '.
|
'accessed over the `file://` protocol. Continue to the next step.'),
|
||||||
'to the next step.'),
|
'credential');
|
||||||
'ssh-login');
|
|
||||||
} else {
|
} else {
|
||||||
throw new Exception("Unknown URI protocol!");
|
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) {
|
public function validateAuthPage(PHUIFormPageView $page) {
|
||||||
|
@ -656,49 +609,46 @@ final class DiffusionRepositoryCreateController
|
||||||
$remote_uri = $form->getPage('remote')->getControl('remoteURI')->getValue();
|
$remote_uri = $form->getPage('remote')->getControl('remoteURI')->getValue();
|
||||||
$proto = $this->getRemoteURIProtocol($remote_uri);
|
$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)) {
|
if ($this->isSSHProtocol($proto)) {
|
||||||
$c_user = $page->getControl('ssh-login');
|
if (!$credential) {
|
||||||
$c_key = $page->getControl('ssh-key');
|
$c_credential->setError(pht('Required'));
|
||||||
$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'));
|
|
||||||
$page->addPageError(
|
$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)) {
|
$ssh_type = PassphraseCredentialTypeSSHPrivateKey::PROVIDES_TYPE;
|
||||||
$c_key->setError(pht('No Key'));
|
if ($credential->getProvidesType() !== $ssh_type) {
|
||||||
$c_file->setError(pht('No Key'));
|
$c_credential->setError(pht('Invalid'));
|
||||||
$page->addPageError(
|
$page->addPageError(
|
||||||
pht(
|
pht(
|
||||||
'You must provide either a private key or the path to a private '.
|
'You must choose an SSH credential, not some other type '.
|
||||||
'key to connect over SSH.'));
|
'of credential.'));
|
||||||
} 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?)'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $c_user->isValid() &&
|
|
||||||
$c_key->isValid() &&
|
|
||||||
$c_file->isValid();
|
|
||||||
} else if ($this->isUsernamePasswordProtocol($proto)) {
|
} 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 {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -481,6 +481,14 @@ final class DiffusionRepositoryEditMainController
|
||||||
pht('Remote URI'),
|
pht('Remote URI'),
|
||||||
$repository->getHumanReadableDetail('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;
|
return $view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,8 @@ final class PhabricatorApplicationPassphrase extends PhabricatorApplication {
|
||||||
return self::GROUP_UTILITIES;
|
return self::GROUP_UTILITIES;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isBeta() {
|
public function canUninstall() {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRoutes() {
|
public function getRoutes() {
|
||||||
|
|
|
@ -32,16 +32,24 @@ abstract class PassphraseAbstractKey extends Phobject {
|
||||||
PassphraseCredential $credential,
|
PassphraseCredential $credential,
|
||||||
$provides_type) {
|
$provides_type) {
|
||||||
|
|
||||||
$type = $credential->getCredentialType();
|
$type = $credential->getCredentialTypeImplementation();
|
||||||
if ($type->getProvides() !== $provides_type) {
|
|
||||||
|
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(
|
throw new Exception(
|
||||||
pht(
|
pht(
|
||||||
'Credential "%s" must provide "%s", but provides "%s"!',
|
'Credential "%s" must provide "%s", but provides "%s"!',
|
||||||
'K'.$credential->getID(),
|
'K'.$credential->getID(),
|
||||||
$provides_type,
|
$provides_type,
|
||||||
$type->getProvides()));
|
$type->getProvidesType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function loadAndValidateFromPHID(
|
protected function loadAndValidateFromPHID(
|
||||||
|
|
|
@ -45,6 +45,11 @@ final class PassphraseCredential extends PassphraseDAO
|
||||||
return $this->assertAttached($this->secret);
|
return $this->assertAttached($this->secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getCredentialTypeImplementation() {
|
||||||
|
$type = $this->getCredentialType();
|
||||||
|
return PassphraseCredentialType::getTypeByConstant($type);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
|
|
@ -27,11 +27,7 @@ final class ConduitAPI_repository_create_Method
|
||||||
'encoding' => 'optional string',
|
'encoding' => 'optional string',
|
||||||
'tracking' => 'optional bool',
|
'tracking' => 'optional bool',
|
||||||
'uri' => 'optional string',
|
'uri' => 'optional string',
|
||||||
'sshUser' => 'optional string',
|
'credentialPHID' => 'optional string',
|
||||||
'sshKey' => 'optional string',
|
|
||||||
'sshKeyFile' => 'optional string',
|
|
||||||
'httpUser' => 'optional string',
|
|
||||||
'httpPassword' => 'optional string',
|
|
||||||
'localPath' => 'optional string',
|
'localPath' => 'optional string',
|
||||||
'svnSubpath' => 'optional string',
|
'svnSubpath' => 'optional string',
|
||||||
'branchFilter' => 'optional list<string>',
|
'branchFilter' => 'optional list<string>',
|
||||||
|
@ -100,6 +96,8 @@ final class ConduitAPI_repository_create_Method
|
||||||
}
|
}
|
||||||
$repository->setVersionControlSystem($map[$vcs]);
|
$repository->setVersionControlSystem($map[$vcs]);
|
||||||
|
|
||||||
|
$repository->setCredentialPHID($request->getValue('credentialPHID'));
|
||||||
|
|
||||||
$details = array(
|
$details = array(
|
||||||
'encoding' => $request->getValue('encoding'),
|
'encoding' => $request->getValue('encoding'),
|
||||||
'description' => $request->getValue('description'),
|
'description' => $request->getValue('description'),
|
||||||
|
@ -114,9 +112,6 @@ final class ConduitAPI_repository_create_Method
|
||||||
true),
|
true),
|
||||||
'pull-frequency' => $request->getValue('pullFrequency'),
|
'pull-frequency' => $request->getValue('pullFrequency'),
|
||||||
'default-branch' => $request->getValue('defaultBranch'),
|
'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),
|
'herald-disabled' => !$request->getValue('heraldEnabled', true),
|
||||||
'svn-subpath' => $request->getValue('svnSubpath'),
|
'svn-subpath' => $request->getValue('svnSubpath'),
|
||||||
'disable-autoclose' => !$request->getValue('autocloseEnabled', true),
|
'disable-autoclose' => !$request->getValue('autocloseEnabled', true),
|
||||||
|
|
|
@ -29,6 +29,7 @@ final class PhabricatorRepositoryEditor
|
||||||
$types[] = PhabricatorRepositoryTransaction::TYPE_PROTOCOL_HTTP;
|
$types[] = PhabricatorRepositoryTransaction::TYPE_PROTOCOL_HTTP;
|
||||||
$types[] = PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH;
|
$types[] = PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH;
|
||||||
$types[] = PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY;
|
$types[] = PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY;
|
||||||
|
$types[] = PhabricatorRepositoryTransaction::TYPE_CREDENTIAL;
|
||||||
|
|
||||||
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
||||||
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
|
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
|
||||||
|
@ -67,16 +68,6 @@ final class PhabricatorRepositoryEditor
|
||||||
return (int)!$object->getDetail('disable-autoclose');
|
return (int)!$object->getDetail('disable-autoclose');
|
||||||
case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI:
|
case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI:
|
||||||
return $object->getDetail('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:
|
case PhabricatorRepositoryTransaction::TYPE_LOCAL_PATH:
|
||||||
return $object->getDetail('local-path');
|
return $object->getDetail('local-path');
|
||||||
case PhabricatorRepositoryTransaction::TYPE_HOSTING:
|
case PhabricatorRepositoryTransaction::TYPE_HOSTING:
|
||||||
|
@ -87,6 +78,8 @@ final class PhabricatorRepositoryEditor
|
||||||
return $object->getServeOverSSH();
|
return $object->getServeOverSSH();
|
||||||
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
|
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
|
||||||
return $object->getPushPolicy();
|
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_HTTP:
|
||||||
case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH:
|
case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH:
|
||||||
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
|
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
|
||||||
|
case PhabricatorRepositoryTransaction::TYPE_CREDENTIAL:
|
||||||
return $xaction->getNewValue();
|
return $xaction->getNewValue();
|
||||||
case PhabricatorRepositoryTransaction::TYPE_NOTIFY:
|
case PhabricatorRepositoryTransaction::TYPE_NOTIFY:
|
||||||
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE:
|
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE:
|
||||||
|
@ -168,21 +162,6 @@ final class PhabricatorRepositoryEditor
|
||||||
case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI:
|
case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI:
|
||||||
$object->setDetail('remote-uri', $xaction->getNewValue());
|
$object->setDetail('remote-uri', $xaction->getNewValue());
|
||||||
break;
|
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:
|
case PhabricatorRepositoryTransaction::TYPE_LOCAL_PATH:
|
||||||
$object->setDetail('local-path', $xaction->getNewValue());
|
$object->setDetail('local-path', $xaction->getNewValue());
|
||||||
break;
|
break;
|
||||||
|
@ -194,6 +173,8 @@ final class PhabricatorRepositoryEditor
|
||||||
return $object->setServeOverSSH($xaction->getNewValue());
|
return $object->setServeOverSSH($xaction->getNewValue());
|
||||||
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
|
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
|
||||||
return $object->setPushPolicy($xaction->getNewValue());
|
return $object->setPushPolicy($xaction->getNewValue());
|
||||||
|
case PhabricatorRepositoryTransaction::TYPE_CREDENTIAL:
|
||||||
|
return $object->setCredentialPHID($xaction->getNewValue());
|
||||||
case PhabricatorRepositoryTransaction::TYPE_ENCODING:
|
case PhabricatorRepositoryTransaction::TYPE_ENCODING:
|
||||||
// Make sure the encoding is valid by converting to UTF-8. This tests
|
// 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
|
// that the user has mbstring installed, and also that they didn't type
|
||||||
|
@ -221,7 +202,32 @@ final class PhabricatorRepositoryEditor
|
||||||
protected function applyCustomExternalTransaction(
|
protected function applyCustomExternalTransaction(
|
||||||
PhabricatorLiskDAO $object,
|
PhabricatorLiskDAO $object,
|
||||||
PhabricatorApplicationTransaction $xaction) {
|
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(
|
protected function mergeTransactions(
|
||||||
|
@ -278,6 +284,7 @@ final class PhabricatorRepositoryEditor
|
||||||
case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_HTTP:
|
case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_HTTP:
|
||||||
case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH:
|
case PhabricatorRepositoryTransaction::TYPE_PROTOCOL_SSH:
|
||||||
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
|
case PhabricatorRepositoryTransaction::TYPE_PUSH_POLICY:
|
||||||
|
case PhabricatorRepositoryTransaction::TYPE_CREDENTIAL:
|
||||||
PhabricatorPolicyFilter::requireCapability(
|
PhabricatorPolicyFilter::requireCapability(
|
||||||
$this->requireActor(),
|
$this->requireActor(),
|
||||||
$object,
|
$object,
|
||||||
|
|
|
@ -39,8 +39,7 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
||||||
|
|
||||||
protected $versionControlSystem;
|
protected $versionControlSystem;
|
||||||
protected $details = array();
|
protected $details = array();
|
||||||
|
protected $credentialPHID;
|
||||||
private $sshKeyfile;
|
|
||||||
|
|
||||||
private $commitCount = self::ATTACHABLE;
|
private $commitCount = self::ATTACHABLE;
|
||||||
private $mostRecentCommit = self::ATTACHABLE;
|
private $mostRecentCommit = self::ATTACHABLE;
|
||||||
|
@ -366,31 +365,29 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
||||||
|
|
||||||
switch ($this->getVersionControlSystem()) {
|
switch ($this->getVersionControlSystem()) {
|
||||||
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
|
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
|
||||||
|
if ($this->shouldUseHTTP() || $this->shouldUseSVNProtocol()) {
|
||||||
|
$flags = array();
|
||||||
|
$flag_args = array();
|
||||||
|
$flags[] = '--non-interactive';
|
||||||
|
$flags[] = '--no-auth-cache';
|
||||||
if ($this->shouldUseHTTP()) {
|
if ($this->shouldUseHTTP()) {
|
||||||
$pattern =
|
$flags[] = '--trust-server-cert';
|
||||||
"svn ".
|
}
|
||||||
"--non-interactive ".
|
|
||||||
"--no-auth-cache ".
|
$credential_phid = $this->getCredentialPHID();
|
||||||
"--trust-server-cert ".
|
if ($credential_phid) {
|
||||||
"--username %P ".
|
$key = PassphrasePasswordKey::loadFromPHID(
|
||||||
"--password %P ".
|
$credential_phid,
|
||||||
$pattern;
|
PhabricatorUser::getOmnipotentUser());
|
||||||
array_unshift(
|
$flags[] = '--username %P';
|
||||||
$args,
|
$flags[] = '--password %P';
|
||||||
new PhutilOpaqueEnvelope($this->getDetail('http-login')),
|
$flag_args[] = $key->getUsernameEnvelope();
|
||||||
new PhutilOpaqueEnvelope($this->getDetail('http-pass')));
|
$flag_args[] = $key->getPasswordEnvelope();
|
||||||
} else if ($this->shouldUseSVNProtocol()) {
|
}
|
||||||
$pattern =
|
|
||||||
"svn ".
|
$flags = implode(' ', $flags);
|
||||||
"--non-interactive ".
|
$pattern = "svn {$flags} {$pattern}";
|
||||||
"--no-auth-cache ".
|
$args = array_mergev(array($flag_args, $args));
|
||||||
"--username %P ".
|
|
||||||
"--password %P ".
|
|
||||||
$pattern;
|
|
||||||
array_unshift(
|
|
||||||
$args,
|
|
||||||
new PhutilOpaqueEnvelope($this->getDetail('http-login')),
|
|
||||||
new PhutilOpaqueEnvelope($this->getDetail('http-pass')));
|
|
||||||
} else {
|
} else {
|
||||||
$pattern = "svn --non-interactive {$pattern}";
|
$pattern = "svn --non-interactive {$pattern}";
|
||||||
}
|
}
|
||||||
|
@ -687,11 +684,7 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
$protocol = $this->getRemoteProtocol();
|
$protocol = $this->getRemoteProtocol();
|
||||||
if ($protocol == 'http' || $protocol == 'https') {
|
return ($protocol == 'http' || $protocol == 'https');
|
||||||
return (bool)$this->getDetail('http-login');
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -708,11 +701,7 @@ final class PhabricatorRepository extends PhabricatorRepositoryDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
$protocol = $this->getRemoteProtocol();
|
$protocol = $this->getRemoteProtocol();
|
||||||
if ($protocol == 'svn') {
|
return ($protocol == 'svn');
|
||||||
return (bool)$this->getDetail('http-login');
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,16 +16,19 @@ final class PhabricatorRepositoryTransaction
|
||||||
const TYPE_NOTIFY = 'repo:notify';
|
const TYPE_NOTIFY = 'repo:notify';
|
||||||
const TYPE_AUTOCLOSE = 'repo:autoclose';
|
const TYPE_AUTOCLOSE = 'repo:autoclose';
|
||||||
const TYPE_REMOTE_URI = 'repo:remote-uri';
|
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_LOCAL_PATH = 'repo:local-path';
|
||||||
const TYPE_HOSTING = 'repo:hosting';
|
const TYPE_HOSTING = 'repo:hosting';
|
||||||
const TYPE_PROTOCOL_HTTP = 'repo:serve-http';
|
const TYPE_PROTOCOL_HTTP = 'repo:serve-http';
|
||||||
const TYPE_PROTOCOL_SSH = 'repo:serve-ssh';
|
const TYPE_PROTOCOL_SSH = 'repo:serve-ssh';
|
||||||
const TYPE_PUSH_POLICY = 'repo:push-policy';
|
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() {
|
public function getApplicationName() {
|
||||||
return 'repository';
|
return 'repository';
|
||||||
|
|
|
@ -1776,6 +1776,14 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
||||||
'type' => 'sql',
|
'type' => 'sql',
|
||||||
'name' => $this->getPatchPath('20131121.passphraseedge.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'),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue