feat: add username/password flags to create-token command
This commit is contained in:
parent
65e1e141ea
commit
02824a90f1
4 changed files with 53 additions and 38 deletions
|
|
@ -48,6 +48,10 @@ First, create an API token:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
brewlog create-token --name "my-cli-token"
|
brewlog create-token --name "my-cli-token"
|
||||||
|
# You will be prompted for username and password.
|
||||||
|
# Alternatively, you can provide them via flags:
|
||||||
|
# brewlog create-token --name "my-cli-token" --username admin --password secret
|
||||||
|
|
||||||
# Username: admin
|
# Username: admin
|
||||||
# Password: ********
|
# Password: ********
|
||||||
#
|
#
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,14 @@ pub struct CreateTokenCommand {
|
||||||
/// A descriptive name for this token
|
/// A descriptive name for this token
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
||||||
|
/// The username to authenticate with
|
||||||
|
#[arg(long)]
|
||||||
|
pub username: Option<String>,
|
||||||
|
|
||||||
|
/// The password to authenticate with
|
||||||
|
#[arg(long)]
|
||||||
|
pub password: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Args)]
|
#[derive(Debug, Args)]
|
||||||
|
|
@ -21,20 +29,28 @@ pub struct RevokeTokenCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_token(client: &BrewlogClient, cmd: CreateTokenCommand) -> Result<()> {
|
pub async fn create_token(client: &BrewlogClient, cmd: CreateTokenCommand) -> Result<()> {
|
||||||
// Prompt for username
|
let username = if let Some(u) = cmd.username {
|
||||||
print!("Username: ");
|
u
|
||||||
io::stdout().flush()?;
|
} else {
|
||||||
let mut username = String::new();
|
// Prompt for username
|
||||||
io::stdin().read_line(&mut username)?;
|
print!("Username: ");
|
||||||
let username = username.trim();
|
io::stdout().flush()?;
|
||||||
|
let mut username = String::new();
|
||||||
|
io::stdin().read_line(&mut username)?;
|
||||||
|
username.trim().to_string()
|
||||||
|
};
|
||||||
|
|
||||||
// Prompt for password (without echo)
|
let password = if let Some(p) = cmd.password {
|
||||||
let password = rpassword::prompt_password("Password: ").context("failed to read password")?;
|
p
|
||||||
|
} else {
|
||||||
|
// Prompt for password (without echo)
|
||||||
|
rpassword::prompt_password("Password: ").context("failed to read password")?
|
||||||
|
};
|
||||||
|
|
||||||
// Create the token
|
// Create the token
|
||||||
let token_response = client
|
let token_response = client
|
||||||
.tokens()
|
.tokens()
|
||||||
.create(username, &password, &cmd.name)
|
.create(&username, &password, &cmd.name)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
println!("\nToken created successfully!");
|
println!("\nToken created successfully!");
|
||||||
|
|
|
||||||
|
|
@ -113,40 +113,38 @@ pub fn server_info() -> (String, String) {
|
||||||
ensure_server_started().expect("Failed to start test server")
|
ensure_server_started().expect("Failed to start test server")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a token for testing using the API directly
|
/// Create a token for testing using the CLI
|
||||||
pub fn create_token(name: &str) -> String {
|
pub fn create_token(name: &str) -> String {
|
||||||
let (address, password) = ensure_server_started().expect("Failed to start test server");
|
let (_, password) = ensure_server_started().expect("Failed to start test server");
|
||||||
|
|
||||||
let client = reqwest::blocking::Client::builder()
|
let output = run_brewlog(
|
||||||
.timeout(Duration::from_secs(5))
|
&[
|
||||||
.build()
|
"create-token",
|
||||||
.expect("Failed to create HTTP client");
|
"--name",
|
||||||
|
name,
|
||||||
|
"--username",
|
||||||
|
"admin",
|
||||||
|
"--password",
|
||||||
|
&password,
|
||||||
|
],
|
||||||
|
&[],
|
||||||
|
);
|
||||||
|
|
||||||
let response = client
|
if !output.status.success() {
|
||||||
.post(format!("{}/api/v1/tokens", address))
|
|
||||||
.json(&serde_json::json!({
|
|
||||||
"username": "admin",
|
|
||||||
"password": password,
|
|
||||||
"name": name
|
|
||||||
}))
|
|
||||||
.send()
|
|
||||||
.expect("Failed to send token creation request");
|
|
||||||
|
|
||||||
if !response.status().is_success() {
|
|
||||||
panic!(
|
panic!(
|
||||||
"Failed to create token: status={} body={}",
|
"Failed to create token: {}",
|
||||||
response.status(),
|
String::from_utf8_lossy(&output.stderr)
|
||||||
response.text().unwrap_or_default()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let token_response: serde_json::Value =
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
response.json().expect("Failed to parse token response");
|
for line in stdout.lines() {
|
||||||
|
if let Some(token) = line.trim().strip_prefix("export BREWLOG_TOKEN=") {
|
||||||
|
return token.to_string();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
token_response["token"]
|
panic!("Could not find token in output: {}", stdout);
|
||||||
.as_str()
|
|
||||||
.expect("Token not found in response")
|
|
||||||
.to_string()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run a brewlog CLI command and return the output
|
/// Run a brewlog CLI command and return the output
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
use crate::helpers::{create_token, run_brewlog, server_info};
|
use crate::helpers::{create_token, run_brewlog, server_info};
|
||||||
|
|
||||||
// Note: create-token CLI command tests are omitted due to stdin handling complexity.
|
|
||||||
// Token creation for testing is done via API in the create_token() helper.
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_list_tokens_requires_authentication() {
|
fn test_list_tokens_requires_authentication() {
|
||||||
let _ = server_info();
|
let _ = server_info();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue