use std::io::{self, BufRead, Write};
use anyhow::{bail, Result};
use crossterm::style::Stylize;
use crate::cli::args::AuthCommands;
use crate::config::manager::ConfigManager;
pub fn run(config_mgr: &ConfigManager, cmd: AuthCommands) -> Result<()> {
match cmd {
AuthCommands::Status => auth_status(config_mgr),
AuthCommands::Switch { org_id } => auth_switch(config_mgr, org_id),
}
}
fn mask_api_key(key: &str) -> String {
if key.len() >= 16 {
format!("{}****{}", &key[..4], &key[key.len() - 4..])
} else {
"****".to_string()
}
}
fn auth_status(config_mgr: &ConfigManager) -> Result<()> {
if let Some(user) = config_mgr.get_user_info() {
println!("Authenticated via browser login");
println!(" User: {} ({})", user.name, user.email);
let current_org = config_mgr.get_current_org();
if let Some(ref org) = current_org {
println!(" Organization: {} ({})", org.name, org.org_id);
if let Some(ref key) = org.api_key {
println!(" API Key: {}", mask_api_key(key));
}
}
let orgs = config_mgr.get_all_orgs();
if !orgs.is_empty() {
println!();
println!("Available organizations ({}):", orgs.len());
let current_id = current_org.as_ref().map(|o| o.org_id.as_str());
for org in &orgs {
let line = format!(" {} ({})", org.name, org.org_id);
if current_id == Some(org.org_id.as_str()) {
println!("{}", line.green());
} else {
println!("{}", line);
}
}
}
return Ok(());
}
if let Some(api_key) = config_mgr.get_credential("api_key") {
println!("Authenticated via API key");
println!(" API Key: {}", mask_api_key(&api_key));
return Ok(());
}
println!("Not authenticated. Run `zilliz login` to authenticate.");
Ok(())
}
fn auth_switch(config_mgr: &ConfigManager, org_id: Option<String>) -> Result<()> {
let orgs = config_mgr.get_all_orgs();
if orgs.is_empty() {
bail!("No organization data available. Log in with browser auth first: zilliz login");
}
if orgs.len() == 1 {
println!("Only one organization available. No switch needed.");
return Ok(());
}
let current_org = config_mgr.get_current_org();
let current_id = current_org.as_ref().map(|o| o.org_id.as_str());
let target_org_id = match org_id {
Some(id) => id,
None => {
println!("Available organizations:");
for (i, org) in orgs.iter().enumerate() {
let line = format!(" [{}] {} ({})", i + 1, org.name, org.org_id);
if current_id == Some(org.org_id.as_str()) {
println!("{}", line.green());
} else {
println!("{}", line);
}
}
print!("Select organization [1-{}]: ", orgs.len());
io::stdout().flush()?;
let mut input = String::new();
io::stdin().lock().read_line(&mut input)?;
let idx: usize = input
.trim()
.parse()
.map_err(|_| anyhow::anyhow!("Invalid selection"))?;
if idx < 1 || idx > orgs.len() {
bail!("Selection out of range");
}
orgs[idx - 1].org_id.clone()
}
};
let org = orgs
.iter()
.find(|o| o.org_id == target_org_id)
.ok_or_else(|| anyhow::anyhow!("Organization '{}' not found", target_org_id))?;
if let Some(ref api_key) = org.api_key {
config_mgr.set_credential("api_key", api_key)?;
config_mgr.set_credential("org_id", &org.org_id)?;
config_mgr.set_credential("org_name", &org.name)?;
config_mgr.clear_context()?;
println!("Switched to organization: {} ({})", org.name, org.org_id);
} else {
bail!(
"Organization '{}' has no API key. Try logging in again.",
org.name
);
}
Ok(())
}