feat: add username/password flags to create-token command

This commit is contained in:
Jon Seager 2025-11-26 16:32:40 +00:00
parent 65e1e141ea
commit 02824a90f1
No known key found for this signature in database
4 changed files with 53 additions and 38 deletions

View file

@ -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: ********
# #

View file

@ -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!");

View file

@ -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

View file

@ -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();