use crate::cli::args::{AuthArgs, ConfigAction, ProviderKind};
use crate::cli::output::{AppEmoji, print_header};
use crate::config::cli_config::CliConfig;
use console::style;
use miette::Result;
pub fn handle(action: ConfigAction, config: &mut CliConfig, profile_name: &str) -> Result<()> {
match action {
ConfigAction::Set { auth } => handle_set(config, profile_name, auth),
ConfigAction::Show => handle_show(config, profile_name),
ConfigAction::List => handle_list(config, profile_name),
}
}
fn handle_set(config: &mut CliConfig, profile_name: &str, auth: AuthArgs) -> Result<()> {
let profile = config.profiles.entry(profile_name.to_string()).or_default();
if let Some(p) = auth.provider {
profile.provider = Some(p);
}
if let Some(t) = auth.tenant_id {
profile.tenant_id = Some(t);
}
if let Some(d) = auth.domain {
profile.domain = Some(d);
}
if let Some(a) = auth.audience {
profile.audience = Some(a);
}
if let Some(c) = auth.client_id {
profile.client_id = Some(c);
}
if let Some(s) = auth.scopes {
profile.default_scopes = Some(s);
}
config.save()?;
let path = CliConfig::get_path()?;
println!(
"{} Configuration saved to {}",
AppEmoji::Floppy.as_emoji(),
style(path.to_string_lossy()).dim()
);
println!("Updated profile: {}", style(profile_name).bold().cyan());
Ok(())
}
fn handle_show(config: &CliConfig, profile_name: &str) -> Result<()> {
let profile = config
.profiles
.get(profile_name)
.cloned()
.unwrap_or_default();
print_header(&format!("Profile: [{}]", profile_name));
let display = |label: &str, value: &Option<String>| {
let v = value.as_deref().unwrap_or("not set");
println!("{} {}", label, style(v).cyan());
};
let provider_str = profile.provider.as_ref().map(|p| match p {
ProviderKind::Microsoft => "Microsoft Entra ID",
ProviderKind::Auth0 => "Auth0",
});
println!(
"Provider: {}",
style(provider_str.unwrap_or("not set")).cyan()
);
match profile.provider {
Some(ProviderKind::Microsoft) | None => {
display("Tenant ID:", &profile.tenant_id);
}
Some(ProviderKind::Auth0) => {
display("Domain: ", &profile.domain);
display("Audience: ", &profile.audience);
}
}
display("Client ID:", &profile.client_id);
display("Scopes: ", &profile.default_scopes);
if let Ok(path) = CliConfig::get_path() {
println!("\nLocation: {}", style(path.to_string_lossy()).dim());
}
Ok(())
}
fn handle_list(config: &CliConfig, profile_name: &str) -> Result<()> {
print_header("Available Profiles:");
for name in config.profiles.keys() {
if name == profile_name {
println!("* {}", style(name).green().bold());
} else {
println!(" {}", name);
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::config::cli_config::Profile;
#[test]
fn test_handle_set_creates_new_profile_works() {
let mut config = CliConfig::default();
let args = AuthArgs {
provider: Some(ProviderKind::Auth0),
domain: Some("test.auth0.com".to_string()),
..Default::default()
};
let result = handle_set(&mut config, "test-env", args);
assert!(result.is_ok());
let profile = config
.profiles
.get("test-env")
.expect("Profile should be created");
assert_eq!(profile.provider, Some(ProviderKind::Auth0));
assert_eq!(profile.domain.as_deref(), Some("test.auth0.com"));
assert!(profile.tenant_id.is_none());
assert!(profile.client_id.is_none());
}
#[test]
fn test_handle_set_update_works() {
let mut config = CliConfig::default();
let mut existing_profile = Profile::default();
existing_profile.client_id = Some("old-client".to_string());
existing_profile.tenant_id = Some("old-tenant".to_string());
config.profiles.insert("prod".to_string(), existing_profile);
let args = AuthArgs {
client_id: Some("new-client".to_string()),
..Default::default()
};
let result = handle_set(&mut config, "prod", args);
assert!(result.is_ok());
let profile = config.profiles.get("prod").unwrap();
assert_eq!(profile.client_id.as_deref(), Some("new-client"));
assert_eq!(profile.tenant_id.as_deref(), Some("old-tenant"));
}
}