mirror of
https://github.com/rust-lang/cargo
synced 2024-10-14 03:32:39 +00:00
96f8d6ced8
Use registry.default for login/logout This changes `cargo login` and `cargo logout` to use the registry configured at `registry.default` as the registry instead of crates.io. For `cargo login`, this was an unintentional regression from #6466. The documentation has always stated that it will use the default registry. This makes the command more in line with other registry-involving commands. There are still some inconsistencies. These commands use the default if not specified: * `cargo init` * `cargo new` * `cargo owner` * `cargo search` * `cargo yank` * `cargo publish` uses the default, but will also look at the `publish` field `Cargo.toml` and use that if the registry is not specified. These commands would always use crates.io if `--registry` is not specified: * `cargo login` * `cargo logout` * `cargo install` I'm a bit uncertain how to proceed, since this is technically a breaking change particularly if someone has scripted it. I suspect that the number of users that use `registry.default` is very small, and those that script `cargo login` are even smaller, and thus the intersection is probably small or nonexistent. However, there is some risk here.
405 lines
14 KiB
Rust
405 lines
14 KiB
Rust
//! Tests for the `cargo login` command.
|
|
|
|
use cargo_test_support::cargo_process;
|
|
use cargo_test_support::paths::{self, CargoPathExt};
|
|
use cargo_test_support::registry::{self, RegistryBuilder};
|
|
use cargo_test_support::t;
|
|
use std::fs;
|
|
use std::path::PathBuf;
|
|
|
|
const TOKEN: &str = "test-token";
|
|
const TOKEN2: &str = "test-token2";
|
|
const ORIGINAL_TOKEN: &str = "api-token";
|
|
|
|
fn credentials_toml() -> PathBuf {
|
|
paths::home().join(".cargo/credentials.toml")
|
|
}
|
|
|
|
fn setup_new_credentials() {
|
|
setup_new_credentials_at(credentials_toml());
|
|
}
|
|
|
|
fn setup_new_credentials_at(config: PathBuf) {
|
|
t!(fs::create_dir_all(config.parent().unwrap()));
|
|
t!(fs::write(
|
|
&config,
|
|
format!(r#"token = "{token}""#, token = ORIGINAL_TOKEN)
|
|
));
|
|
}
|
|
|
|
/// Asserts whether or not the token is set to the given value for the given registry.
|
|
pub fn check_token(expected_token: Option<&str>, registry: Option<&str>) {
|
|
let credentials = credentials_toml();
|
|
assert!(credentials.is_file());
|
|
|
|
let contents = fs::read_to_string(&credentials).unwrap();
|
|
let toml: toml::Table = contents.parse().unwrap();
|
|
|
|
let actual_token = match registry {
|
|
// A registry has been provided, so check that the token exists in a
|
|
// table for the registry.
|
|
Some(registry) => toml
|
|
.get("registries")
|
|
.and_then(|registries_table| registries_table.get(registry))
|
|
.and_then(|registry_table| match registry_table.get("token") {
|
|
Some(&toml::Value::String(ref token)) => Some(token.as_str().to_string()),
|
|
_ => None,
|
|
}),
|
|
// There is no registry provided, so check the global token instead.
|
|
None => toml
|
|
.get("registry")
|
|
.and_then(|registry_table| registry_table.get("token"))
|
|
.and_then(|v| match v {
|
|
toml::Value::String(ref token) => Some(token.as_str().to_string()),
|
|
_ => None,
|
|
}),
|
|
};
|
|
|
|
match (actual_token, expected_token) {
|
|
(None, None) => {}
|
|
(Some(actual), Some(expected)) => assert_eq!(actual, expected),
|
|
(None, Some(expected)) => {
|
|
panic!("expected `{registry:?}` to be `{expected}`, but was not set")
|
|
}
|
|
(Some(actual), None) => {
|
|
panic!("expected `{registry:?}` to be unset, but was set to `{actual}`")
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn registry_credentials() {
|
|
let _alternative = RegistryBuilder::new().alternative().build();
|
|
let _alternative2 = RegistryBuilder::new()
|
|
.alternative_named("alternative2")
|
|
.build();
|
|
|
|
setup_new_credentials();
|
|
|
|
let reg = "alternative";
|
|
|
|
cargo_process("login --registry").arg(reg).arg(TOKEN).run();
|
|
|
|
// Ensure that we have not updated the default token
|
|
check_token(Some(ORIGINAL_TOKEN), None);
|
|
|
|
// Also ensure that we get the new token for the registry
|
|
check_token(Some(TOKEN), Some(reg));
|
|
|
|
let reg2 = "alternative2";
|
|
cargo_process("login --registry")
|
|
.arg(reg2)
|
|
.arg(TOKEN2)
|
|
.run();
|
|
|
|
// Ensure not overwriting 1st alternate registry token with
|
|
// 2nd alternate registry token (see rust-lang/cargo#7701).
|
|
check_token(Some(ORIGINAL_TOKEN), None);
|
|
check_token(Some(TOKEN), Some(reg));
|
|
check_token(Some(TOKEN2), Some(reg2));
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn empty_login_token() {
|
|
let registry = RegistryBuilder::new()
|
|
.no_configure_registry()
|
|
.no_configure_token()
|
|
.build();
|
|
setup_new_credentials();
|
|
|
|
cargo_process("login")
|
|
.replace_crates_io(registry.index_url())
|
|
.with_stdout("please paste the token found on [..]/me below")
|
|
.with_stdin("\t\n")
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] crates.io index
|
|
[ERROR] please provide a non-empty token
|
|
",
|
|
)
|
|
.with_status(101)
|
|
.run();
|
|
|
|
cargo_process("login")
|
|
.replace_crates_io(registry.index_url())
|
|
.arg("")
|
|
.with_stderr(
|
|
"\
|
|
[ERROR] please provide a non-empty token
|
|
",
|
|
)
|
|
.with_status(101)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn invalid_login_token() {
|
|
let registry = RegistryBuilder::new()
|
|
.no_configure_registry()
|
|
.no_configure_token()
|
|
.build();
|
|
setup_new_credentials();
|
|
|
|
let check = |stdin: &str, stderr: &str, status: i32| {
|
|
cargo_process("login")
|
|
.replace_crates_io(registry.index_url())
|
|
.with_stdout("please paste the token found on [..]/me below")
|
|
.with_stdin(stdin)
|
|
.with_stderr(stderr)
|
|
.with_status(status)
|
|
.run();
|
|
};
|
|
|
|
let invalid = |stdin: &str| {
|
|
check(
|
|
stdin,
|
|
"[ERROR] token contains invalid characters.
|
|
Only printable ISO-8859-1 characters are allowed as it is sent in a HTTPS header.",
|
|
101,
|
|
)
|
|
};
|
|
let valid = |stdin: &str| check(stdin, "[LOGIN] token for `crates.io` saved", 0);
|
|
|
|
// Update config.json so that the rest of the tests don't need to care
|
|
// whether or not `Updating` is printed.
|
|
check(
|
|
"test",
|
|
"\
|
|
[UPDATING] crates.io index
|
|
[LOGIN] token for `crates.io` saved
|
|
",
|
|
0,
|
|
);
|
|
|
|
invalid("😄");
|
|
invalid("\u{0016}");
|
|
invalid("\u{0000}");
|
|
invalid("你好");
|
|
valid("foo\tbar");
|
|
valid("foo bar");
|
|
valid(
|
|
r##"!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"##,
|
|
);
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn bad_asymmetric_token_args() {
|
|
// These cases are kept brief as the implementation is covered by clap, so this is only smoke testing that we have clap configured correctly.
|
|
cargo_process("login --key-subject=foo tok")
|
|
.with_stderr_contains(
|
|
"error: the argument '--key-subject <SUBJECT>' cannot be used with '[token]'",
|
|
)
|
|
.with_status(1)
|
|
.run();
|
|
|
|
cargo_process("login --generate-keypair tok")
|
|
.with_stderr_contains(
|
|
"error: the argument '--generate-keypair' cannot be used with '[token]'",
|
|
)
|
|
.with_status(1)
|
|
.run();
|
|
|
|
cargo_process("login --secret-key tok")
|
|
.with_stderr_contains("error: the argument '--secret-key' cannot be used with '[token]'")
|
|
.with_status(1)
|
|
.run();
|
|
|
|
cargo_process("login --generate-keypair --secret-key")
|
|
.with_stderr_contains(
|
|
"error: the argument '--generate-keypair' cannot be used with '--secret-key'",
|
|
)
|
|
.with_status(1)
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn asymmetric_requires_nightly() {
|
|
let registry = registry::init();
|
|
cargo_process("login --key-subject=foo")
|
|
.replace_crates_io(registry.index_url())
|
|
.with_status(101)
|
|
.with_stderr_contains("[ERROR] the `key-subject` flag is unstable, pass `-Z registry-auth` to enable it\n\
|
|
See https://github.com/rust-lang/cargo/issues/10519 for more information about the `key-subject` flag.")
|
|
.run();
|
|
cargo_process("login --generate-keypair")
|
|
.replace_crates_io(registry.index_url())
|
|
.with_status(101)
|
|
.with_stderr_contains("[ERROR] the `generate-keypair` flag is unstable, pass `-Z registry-auth` to enable it\n\
|
|
See https://github.com/rust-lang/cargo/issues/10519 for more information about the `generate-keypair` flag.")
|
|
.run();
|
|
cargo_process("login --secret-key")
|
|
.replace_crates_io(registry.index_url())
|
|
.with_status(101)
|
|
.with_stderr_contains("[ERROR] the `secret-key` flag is unstable, pass `-Z registry-auth` to enable it\n\
|
|
See https://github.com/rust-lang/cargo/issues/10519 for more information about the `secret-key` flag.")
|
|
.run();
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn login_with_no_cargo_dir() {
|
|
// Create a config in the root directory because `login` requires the
|
|
// index to be updated, and we don't want to hit crates.io.
|
|
let registry = registry::init();
|
|
fs::rename(paths::home().join(".cargo"), paths::root().join(".cargo")).unwrap();
|
|
paths::home().rm_rf();
|
|
cargo_process("login foo -v")
|
|
.replace_crates_io(registry.index_url())
|
|
.run();
|
|
let credentials = fs::read_to_string(credentials_toml()).unwrap();
|
|
assert_eq!(credentials, "[registry]\ntoken = \"foo\"\n");
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn login_with_differently_sized_token() {
|
|
// Verify that the configuration file gets properly truncated.
|
|
let registry = registry::init();
|
|
let credentials = credentials_toml();
|
|
fs::remove_file(&credentials).unwrap();
|
|
cargo_process("login lmaolmaolmao -v")
|
|
.replace_crates_io(registry.index_url())
|
|
.run();
|
|
cargo_process("login lmao -v")
|
|
.replace_crates_io(registry.index_url())
|
|
.run();
|
|
cargo_process("login lmaolmaolmao -v")
|
|
.replace_crates_io(registry.index_url())
|
|
.run();
|
|
let credentials = fs::read_to_string(&credentials).unwrap();
|
|
assert_eq!(credentials, "[registry]\ntoken = \"lmaolmaolmao\"\n");
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn login_with_token_on_stdin() {
|
|
let registry = registry::init();
|
|
let credentials = credentials_toml();
|
|
fs::remove_file(&credentials).unwrap();
|
|
cargo_process("login lmao -v")
|
|
.replace_crates_io(registry.index_url())
|
|
.run();
|
|
cargo_process("login")
|
|
.replace_crates_io(registry.index_url())
|
|
.with_stdout("please paste the token found on [..]/me below")
|
|
.with_stdin("some token")
|
|
.run();
|
|
let credentials = fs::read_to_string(&credentials).unwrap();
|
|
assert_eq!(credentials, "[registry]\ntoken = \"some token\"\n");
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn login_with_asymmetric_token_and_subject_on_stdin() {
|
|
let registry = registry::init();
|
|
let credentials = credentials_toml();
|
|
fs::remove_file(&credentials).unwrap();
|
|
cargo_process("login --key-subject=foo --secret-key -v -Z registry-auth")
|
|
.masquerade_as_nightly_cargo(&["registry-auth"])
|
|
.replace_crates_io(registry.index_url())
|
|
.with_stdout(
|
|
"\
|
|
please paste the API secret key below
|
|
k3.public.AmDwjlyf8jAV3gm5Z7Kz9xAOcsKslt_Vwp5v-emjFzBHLCtcANzTaVEghTNEMj9PkQ",
|
|
)
|
|
.with_stdin("k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36")
|
|
.run();
|
|
let credentials = fs::read_to_string(&credentials).unwrap();
|
|
assert!(credentials.starts_with("[registry]\n"));
|
|
assert!(credentials.contains("secret-key-subject = \"foo\"\n"));
|
|
assert!(credentials.contains("secret-key = \"k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36\"\n"));
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn login_with_asymmetric_token_on_stdin() {
|
|
let registry = registry::init();
|
|
let credentials = credentials_toml();
|
|
fs::remove_file(&credentials).unwrap();
|
|
cargo_process("login --secret-key -v -Z registry-auth")
|
|
.masquerade_as_nightly_cargo(&["registry-auth"])
|
|
.replace_crates_io(registry.index_url())
|
|
.with_stdout(
|
|
"\
|
|
please paste the API secret key below
|
|
k3.public.AmDwjlyf8jAV3gm5Z7Kz9xAOcsKslt_Vwp5v-emjFzBHLCtcANzTaVEghTNEMj9PkQ",
|
|
)
|
|
.with_stdin("k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36")
|
|
.run();
|
|
let credentials = fs::read_to_string(&credentials).unwrap();
|
|
assert_eq!(credentials, "[registry]\nsecret-key = \"k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36\"\n");
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn login_with_asymmetric_key_subject_without_key() {
|
|
let registry = registry::init();
|
|
let credentials = credentials_toml();
|
|
fs::remove_file(&credentials).unwrap();
|
|
cargo_process("login --key-subject=foo -Z registry-auth")
|
|
.masquerade_as_nightly_cargo(&["registry-auth"])
|
|
.replace_crates_io(registry.index_url())
|
|
.with_stderr_contains("error: need a secret_key to set a key_subject")
|
|
.with_status(101)
|
|
.run();
|
|
|
|
// ok so add a secret_key to the credentials
|
|
cargo_process("login --secret-key -v -Z registry-auth")
|
|
.masquerade_as_nightly_cargo(&["registry-auth"])
|
|
.replace_crates_io(registry.index_url())
|
|
.with_stdout(
|
|
"please paste the API secret key below
|
|
k3.public.AmDwjlyf8jAV3gm5Z7Kz9xAOcsKslt_Vwp5v-emjFzBHLCtcANzTaVEghTNEMj9PkQ",
|
|
)
|
|
.with_stdin("k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36")
|
|
.run();
|
|
|
|
// and then it should work
|
|
cargo_process("login --key-subject=foo -Z registry-auth")
|
|
.masquerade_as_nightly_cargo(&["registry-auth"])
|
|
.replace_crates_io(registry.index_url())
|
|
.run();
|
|
|
|
let credentials = fs::read_to_string(&credentials).unwrap();
|
|
assert!(credentials.starts_with("[registry]\n"));
|
|
assert!(credentials.contains("secret-key-subject = \"foo\"\n"));
|
|
assert!(credentials.contains("secret-key = \"k3.secret.fNYVuMvBgOlljt9TDohnaYLblghqaHoQquVZwgR6X12cBFHZLFsaU3q7X3k1Zn36\"\n"));
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn login_with_generate_asymmetric_token() {
|
|
let registry = registry::init();
|
|
let credentials = credentials_toml();
|
|
fs::remove_file(&credentials).unwrap();
|
|
cargo_process("login --generate-keypair -Z registry-auth")
|
|
.masquerade_as_nightly_cargo(&["registry-auth"])
|
|
.replace_crates_io(registry.index_url())
|
|
.with_stdout("k3.public.[..]")
|
|
.run();
|
|
let credentials = fs::read_to_string(&credentials).unwrap();
|
|
assert!(credentials.contains("secret-key = \"k3.secret."));
|
|
}
|
|
|
|
#[cargo_test]
|
|
fn default_registry_configured() {
|
|
// When registry.default is set, login should use that one when
|
|
// --registry is not used.
|
|
let _alternative = RegistryBuilder::new().alternative().build();
|
|
let cargo_home = paths::home().join(".cargo");
|
|
cargo_util::paths::append(
|
|
&cargo_home.join("config"),
|
|
br#"
|
|
[registry]
|
|
default = "alternative"
|
|
"#,
|
|
)
|
|
.unwrap();
|
|
|
|
cargo_process("login")
|
|
.arg("a-new-token")
|
|
.with_stderr(
|
|
"\
|
|
[UPDATING] `alternative` index
|
|
[LOGIN] token for `alternative` saved
|
|
",
|
|
)
|
|
.run();
|
|
|
|
check_token(None, None);
|
|
check_token(Some("a-new-token"), Some("alternative"));
|
|
}
|