mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-25 08:12:40 +01:00
"arc install-certificate", client side changes
Summary: Provide an "install-certificate" workflow to simplify ~/.arcrc edits. See also D460. Test Plan: Installed certificates via "arc install-certificate". Reviewed By: aran Reviewers: aran, jungejason, tuomaspelkonen CC: aran, epriestley Differential Revision: 465
This commit is contained in:
parent
36de84eeee
commit
d73179ea99
6 changed files with 212 additions and 11 deletions
|
@ -61,6 +61,7 @@ if (function_exists('posix_isatty') && !posix_isatty(STDOUT)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
$args = array_values($args);
|
$args = array_values($args);
|
||||||
|
$working_directory = $_SERVER['PWD'];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ try {
|
||||||
throw new ArcanistUsageException("No command provided. Try 'arc help'.");
|
throw new ArcanistUsageException("No command provided. Try 'arc help'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
$working_copy = ArcanistWorkingCopyIdentity::newFromPath($_SERVER['PWD']);
|
$working_copy = ArcanistWorkingCopyIdentity::newFromPath($working_directory);
|
||||||
if ($load) {
|
if ($load) {
|
||||||
$libs = $load;
|
$libs = $load;
|
||||||
} else {
|
} else {
|
||||||
|
@ -118,16 +119,7 @@ try {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$user_config = array();
|
$user_config = ArcanistBaseWorkflow::readUserConfigurationFile();
|
||||||
$user_config_path = getenv('HOME').'/.arcrc';
|
|
||||||
if (Filesystem::pathExists($user_config_path)) {
|
|
||||||
$user_config_data = Filesystem::readFile($user_config_path);
|
|
||||||
$user_config = json_decode($user_config_data, true);
|
|
||||||
if (!is_array($user_config)) {
|
|
||||||
throw new ArcanistUsageException(
|
|
||||||
"Your '~/.arcrc' file is not a valid JSON file.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$config = $working_copy->getConfig('arcanist_configuration');
|
$config = $working_copy->getConfig('arcanist_configuration');
|
||||||
if ($config) {
|
if ($config) {
|
||||||
|
@ -145,6 +137,7 @@ try {
|
||||||
}
|
}
|
||||||
$workflow->setArcanistConfiguration($config);
|
$workflow->setArcanistConfiguration($config);
|
||||||
$workflow->setCommand($command);
|
$workflow->setCommand($command);
|
||||||
|
$workflow->setWorkingDirectory($working_directory);
|
||||||
$workflow->parseArguments(array_slice($args, 1));
|
$workflow->parseArguments(array_slice($args, 1));
|
||||||
|
|
||||||
$need_working_copy = $workflow->requiresWorkingCopy();
|
$need_working_copy = $workflow->requiresWorkingCopy();
|
||||||
|
|
|
@ -36,6 +36,7 @@ phutil_register_library_map(array(
|
||||||
'ArcanistGitAPI' => 'repository/api/git',
|
'ArcanistGitAPI' => 'repository/api/git',
|
||||||
'ArcanistGitHookPreReceiveWorkflow' => 'workflow/git-hook-pre-receive',
|
'ArcanistGitHookPreReceiveWorkflow' => 'workflow/git-hook-pre-receive',
|
||||||
'ArcanistHelpWorkflow' => 'workflow/help',
|
'ArcanistHelpWorkflow' => 'workflow/help',
|
||||||
|
'ArcanistInstallCertificateWorkflow' => 'workflow/install-certificate',
|
||||||
'ArcanistLiberateLintEngine' => 'lint/engine/liberate',
|
'ArcanistLiberateLintEngine' => 'lint/engine/liberate',
|
||||||
'ArcanistLiberateWorkflow' => 'workflow/liberate',
|
'ArcanistLiberateWorkflow' => 'workflow/liberate',
|
||||||
'ArcanistLicenseLinter' => 'lint/linter/license',
|
'ArcanistLicenseLinter' => 'lint/linter/license',
|
||||||
|
@ -101,6 +102,7 @@ phutil_register_library_map(array(
|
||||||
'ArcanistGitAPI' => 'ArcanistRepositoryAPI',
|
'ArcanistGitAPI' => 'ArcanistRepositoryAPI',
|
||||||
'ArcanistGitHookPreReceiveWorkflow' => 'ArcanistBaseWorkflow',
|
'ArcanistGitHookPreReceiveWorkflow' => 'ArcanistBaseWorkflow',
|
||||||
'ArcanistHelpWorkflow' => 'ArcanistBaseWorkflow',
|
'ArcanistHelpWorkflow' => 'ArcanistBaseWorkflow',
|
||||||
|
'ArcanistInstallCertificateWorkflow' => 'ArcanistBaseWorkflow',
|
||||||
'ArcanistLiberateLintEngine' => 'ArcanistLintEngine',
|
'ArcanistLiberateLintEngine' => 'ArcanistLintEngine',
|
||||||
'ArcanistLiberateWorkflow' => 'ArcanistBaseWorkflow',
|
'ArcanistLiberateWorkflow' => 'ArcanistBaseWorkflow',
|
||||||
'ArcanistLicenseLinter' => 'ArcanistLinter',
|
'ArcanistLicenseLinter' => 'ArcanistLinter',
|
||||||
|
|
|
@ -33,6 +33,7 @@ class ArcanistBaseWorkflow {
|
||||||
|
|
||||||
private $arcanistConfiguration;
|
private $arcanistConfiguration;
|
||||||
private $parentWorkflow;
|
private $parentWorkflow;
|
||||||
|
private $workingDirectory;
|
||||||
|
|
||||||
private $changeCache = array();
|
private $changeCache = array();
|
||||||
|
|
||||||
|
@ -91,6 +92,15 @@ class ArcanistBaseWorkflow {
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setWorkingDirectory($working_directory) {
|
||||||
|
$this->workingDirectory = $working_directory;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getWorkingDirectory() {
|
||||||
|
return $this->workingDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
private function setParentWorkflow($parent_workflow) {
|
private function setParentWorkflow($parent_workflow) {
|
||||||
$this->parentWorkflow = $parent_workflow;
|
$this->parentWorkflow = $parent_workflow;
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -627,4 +637,22 @@ class ArcanistBaseWorkflow {
|
||||||
return $argv;
|
return $argv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function getUserConfigurationFileLocation() {
|
||||||
|
return getenv('HOME').'/.arcrc';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function readUserConfigurationFile() {
|
||||||
|
$user_config = array();
|
||||||
|
$user_config_path = self::getUserConfigurationFileLocation();
|
||||||
|
if (Filesystem::pathExists($user_config_path)) {
|
||||||
|
$user_config_data = Filesystem::readFile($user_config_path);
|
||||||
|
$user_config = json_decode($user_config_data, true);
|
||||||
|
if (!is_array($user_config)) {
|
||||||
|
throw new ArcanistUsageException(
|
||||||
|
"Your '~/.arcrc' file is not a valid JSON file.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $user_config;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ phutil_require_module('arcanist', 'parser/diff/change');
|
||||||
phutil_require_module('arcanist', 'repository/api/git');
|
phutil_require_module('arcanist', 'repository/api/git');
|
||||||
|
|
||||||
phutil_require_module('phutil', 'console');
|
phutil_require_module('phutil', 'console');
|
||||||
|
phutil_require_module('phutil', 'filesystem');
|
||||||
phutil_require_module('phutil', 'future/exec');
|
phutil_require_module('phutil', 'future/exec');
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright 2011 Facebook, Inc.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs arcanist certificates.
|
||||||
|
*
|
||||||
|
* @group workflow
|
||||||
|
*/
|
||||||
|
class ArcanistInstallCertificateWorkflow extends ArcanistBaseWorkflow {
|
||||||
|
|
||||||
|
public function getCommandHelp() {
|
||||||
|
return phutil_console_format(<<<EOTEXT
|
||||||
|
**install-certificate** [uri]
|
||||||
|
Supports: http, https
|
||||||
|
Installs Conduit credentials into your ~/.arcrc for the given install
|
||||||
|
of Phabricator. You need to do this before you can use 'arc', as it
|
||||||
|
enables 'arc' to link your command-line activity with your account on
|
||||||
|
the web. Run this command from within a project directory to install
|
||||||
|
that project's certificate, or specify an explicit URI (like
|
||||||
|
"https://phabricator.example.com/").
|
||||||
|
EOTEXT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getArguments() {
|
||||||
|
return array(
|
||||||
|
'*' => 'uri',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shouldShellComplete() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function requiresConduit() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function requiresWorkingCopy() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run() {
|
||||||
|
|
||||||
|
$uri = $this->determineConduitURI();
|
||||||
|
|
||||||
|
echo "Installing certificate for '{$uri}'...\n";
|
||||||
|
|
||||||
|
$config = self::readUserConfigurationFile();
|
||||||
|
|
||||||
|
echo "Trying to connect to server...\n";
|
||||||
|
$conduit = new ConduitClient($uri);
|
||||||
|
$conduit->setTimeout(5);
|
||||||
|
try {
|
||||||
|
$conduit->callMethodSynchronous('conduit.ping', array());
|
||||||
|
} catch (Exception $ex) {
|
||||||
|
throw new ArcanistUsageException(
|
||||||
|
"Failed to connect to server: ".$ex->getMessage());
|
||||||
|
}
|
||||||
|
echo "Connection OK!\n";
|
||||||
|
|
||||||
|
$token_uri = new PhutilURI($uri);
|
||||||
|
$token_uri->setPath('/conduit/token/');
|
||||||
|
|
||||||
|
echo "\n";
|
||||||
|
echo phutil_console_format("**LOGIN TO PHABRICATOR**\n");
|
||||||
|
echo "Open this page in your browser and login to Phabricator if ".
|
||||||
|
"necessary:\n";
|
||||||
|
echo "\n";
|
||||||
|
echo " {$token_uri}\n";
|
||||||
|
echo "\n";
|
||||||
|
echo "Then paste the token on that page below.";
|
||||||
|
|
||||||
|
|
||||||
|
do {
|
||||||
|
$token = phutil_console_prompt('Paste token from that page:');
|
||||||
|
$token = trim($token);
|
||||||
|
if (strlen($token)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
echo "\n";
|
||||||
|
echo "Downloading authentication certificate...\n";
|
||||||
|
$info = $conduit->callMethodSynchronous(
|
||||||
|
'conduit.getcertificate',
|
||||||
|
array(
|
||||||
|
'token' => $token,
|
||||||
|
));
|
||||||
|
|
||||||
|
$user = $info['username'];
|
||||||
|
echo "Installing certificate for '{$user}'...\n";
|
||||||
|
$config['hosts'][$uri] = array(
|
||||||
|
'user' => $user,
|
||||||
|
'cert' => $info['certificate'],
|
||||||
|
);
|
||||||
|
|
||||||
|
$json_encoder = new PhutilJSON();
|
||||||
|
$json = $json_encoder->encodeFormatted($config);
|
||||||
|
|
||||||
|
echo "Writing ~/.arcconfig...\n";
|
||||||
|
|
||||||
|
$path = self::getUserConfigurationFileLocation();
|
||||||
|
Filesystem::writeFile($path, $json);
|
||||||
|
execx('chmod 600 %s', $path);
|
||||||
|
|
||||||
|
echo phutil_console_format(
|
||||||
|
"<bg:green>** SUCCESS! **</bg> Certificate installed.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function determineConduitURI() {
|
||||||
|
$uri = $this->getArgument('uri');
|
||||||
|
if (count($uri) > 1) {
|
||||||
|
throw new ArcanistUsageException("Specify at most one URI.");
|
||||||
|
} else if (count($uri) == 1) {
|
||||||
|
$uri = reset($uri);
|
||||||
|
} else {
|
||||||
|
$working_copy = ArcanistWorkingCopyIdentity::newFromPath(
|
||||||
|
$this->getWorkingDirectory());
|
||||||
|
if (!$working_copy->getProjectRoot()) {
|
||||||
|
throw new ArcanistUsageException(
|
||||||
|
"Specify an explicit URI or run this command from within a project ".
|
||||||
|
"which is configured with a .arcconfig.");
|
||||||
|
}
|
||||||
|
$conduit_uri = $working_copy->getConduitURI();
|
||||||
|
if (!$conduit_uri) {
|
||||||
|
throw new ArcanistUsageException(
|
||||||
|
"This project's .arcconfig does not specify a Conduit URI.");
|
||||||
|
}
|
||||||
|
$uri = $conduit_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
$uri = new PhutilURI($uri);
|
||||||
|
$uri->setPath('/api/');
|
||||||
|
|
||||||
|
return (string)$uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
21
src/workflow/install-certificate/__init__.php
Normal file
21
src/workflow/install-certificate/__init__.php
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is automatically generated. Lint this module to rebuild it.
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_module('arcanist', 'exception/usage');
|
||||||
|
phutil_require_module('arcanist', 'workflow/base');
|
||||||
|
phutil_require_module('arcanist', 'workingcopyidentity');
|
||||||
|
|
||||||
|
phutil_require_module('phutil', 'conduit/client');
|
||||||
|
phutil_require_module('phutil', 'console');
|
||||||
|
phutil_require_module('phutil', 'filesystem');
|
||||||
|
phutil_require_module('phutil', 'future/exec');
|
||||||
|
phutil_require_module('phutil', 'parser/json');
|
||||||
|
phutil_require_module('phutil', 'parser/uri');
|
||||||
|
|
||||||
|
|
||||||
|
phutil_require_source('ArcanistInstallCertificateWorkflow.php');
|
Loading…
Reference in a new issue