use crate::{ api::{CliError, Config, ConfigProfile}, CONFIG_DIR_NAME, CONFIG_PROFILE_FILE, ISSUE_TRACKER_LOC, }; use anyhow::{anyhow, Context}; use colored::Colorize; use home::home_dir; use secd::Secd; use std::{ env::var, error::Error, fs::{self, File}, io::{self, Read}, path::PathBuf, result, str::FromStr, }; use thiserror; pub type Result = anyhow::Result; macro_rules! err { ($($tt:tt)*) => { Err(Box::::from(format!($($tt)*))) } } pub(crate) use err; #[derive(Debug, thiserror::Error)] pub enum InternalError { #[error( "Cannot read {0} profile from {1}. Initialize a default iam store with `iam admin init`" )] CannotReadProfile(String, String), } pub fn get_config_dir() -> PathBuf { let xdg_dir = var("XDG_CONFIG_HOME").map(|s| PathBuf::from_str(&s).unwrap()); let mut home_dir = home_dir().expect(&format!( "Could not find home directory. This should not be possible, please file a bug at {}", ISSUE_TRACKER_LOC )); match xdg_dir { Ok(mut d) => { d.push(format!(".{}", CONFIG_DIR_NAME)); d } Err(_) => { home_dir.push(".config"); home_dir.push(CONFIG_DIR_NAME); home_dir } } } pub fn get_config_profile() -> PathBuf { let mut config_dir = get_config_dir(); config_dir.push(CONFIG_PROFILE_FILE); config_dir } pub fn read_config(profile_name: Option) -> Result { let profile_path = get_config_profile(); let profile_name = profile_name.unwrap_or("default".into()); let bytes = fs::read(profile_path.clone())?; let config: Config = toml::from_slice(&bytes)?; let mut cfg = config .profile .into_iter() .filter(|p| p.name == profile_name) .last() .ok_or(anyhow!( "cannot read configuration file when calling read_config" ))?; if let Some(path) = cfg.email_template_login { let buf = fs::read_to_string(path)?; cfg.email_template_login = Some(buf); } if let Some(path) = cfg.email_template_signup { let buf = fs::read_to_string(path)?; cfg.email_template_signup = Some(buf); } Ok(cfg) } pub fn error_detail(id: &str, d: &str) -> String { format!("[debug info {}] {}", id, d) }