diff options
| author | benj <benj@rse8.com> | 2022-12-01 10:30:34 -0800 |
|---|---|---|
| committer | benj <benj@rse8.com> | 2022-12-01 10:35:50 -0800 |
| commit | 2c4eb2d311919ad9fb70738199ecf99bf20c9fce (patch) | |
| tree | 8739dd9d1d0c07fc27df2ece3d21f3a03db7397b /crates/iam/src/command.rs | |
| parent | aa8c20d501b58001a5e1b24964c62363e2112ff8 (diff) | |
| download | secdiam-2c4eb2d311919ad9fb70738199ecf99bf20c9fce.tar secdiam-2c4eb2d311919ad9fb70738199ecf99bf20c9fce.tar.gz secdiam-2c4eb2d311919ad9fb70738199ecf99bf20c9fce.tar.bz2 secdiam-2c4eb2d311919ad9fb70738199ecf99bf20c9fce.tar.lz secdiam-2c4eb2d311919ad9fb70738199ecf99bf20c9fce.tar.xz secdiam-2c4eb2d311919ad9fb70738199ecf99bf20c9fce.tar.zst secdiam-2c4eb2d311919ad9fb70738199ecf99bf20c9fce.zip | |
- basic functionality with psql and sqlite
- cli helper tool
Diffstat (limited to '')
| -rw-r--r-- | crates/iam/src/command.rs | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/crates/iam/src/command.rs b/crates/iam/src/command.rs new file mode 100644 index 0000000..e9e0f23 --- /dev/null +++ b/crates/iam/src/command.rs @@ -0,0 +1,164 @@ +use crate::{ + api, + util::{self, get_config_profile, Result}, + CONFIG_LOGIN_TEMPLATE, CONFIG_SIGNUP_TEMPLATE, +}; +use async_std::fs; +use colored::*; +use rand::distributions::{Alphanumeric, DistString}; +use secd::{AuthEmail, AuthStore}; +use std::{ + fs::File, + io::{self, stdin, stdout, Write}, + str::FromStr, +}; +use strum::VariantNames; + +const DEFAULT_LOGIN_EMAIL: &str = "<!doctype html><html><body><p>You requested a login link for %secd_email_address%. Please click the following link<br/><br/>http://localhost:5500/myapp/iam/exchange/%secd_link%<br/><br/>or use code: %secd_code%</p></body></html>"; +const DEFAULT_SIGNUP_EMAIL: &str = "<!doctype html><html><body><h1>Welcome to SecD IAM</h1></h1><p>If you did not request this sign up, you can safely ignore this email. Otherwise, please click the following link to validate your account<br/><br/>http://localhost:5500/myapp/iam/exchange/%secd_link%<br/><br/>or use code: %secd_code%</p></body></html>"; + +pub async fn admin_init(is_interactive: bool) -> Result<()> { + let config_dir = util::get_config_dir(); + let config_profile = get_config_profile(); + fs::create_dir_all(config_dir.clone()).await?; + + if config_profile.try_exists()? { + writeln!( + io::stdout(), + "{} {}", + config_profile.clone().display(), + "already exists and there is nothing to initialize. To create a new IAM store use `iam admin create store` or modify the configuration profile directly" + .yellow() + )?; + } else { + writeln!(stdout(), "{}", "creating default profile".green())?; + + let mut login_template = config_dir.clone(); + login_template.push(CONFIG_LOGIN_TEMPLATE); + let mut f = File::create(login_template.clone())?; + f.write_all(DEFAULT_LOGIN_EMAIL.as_bytes())?; + + let mut signup_template = config_dir.clone(); + signup_template.push(CONFIG_SIGNUP_TEMPLATE); + f = File::create(signup_template.clone())?; + f.write_all(DEFAULT_SIGNUP_EMAIL.as_bytes())?; + + let mut cfg = api::Config { + profile: vec![api::ConfigProfile { + name: "default".to_string(), + store: AuthStore::Sqlite, + store_conn: format!( + "sqlite://{}/{}.sql?mode=rwc", + config_dir.clone().display().to_string(), + Alphanumeric.sample_string(&mut rand::thread_rng(), 5), + ), + emailer: secd::AuthEmail::LocalStub, + email_template_login: Some(login_template.display().to_string()), + email_template_signup: Some(signup_template.display().to_string()), + }], + }; + + let mut input: String = String::new(); + if is_interactive { + writeln!(stdout(), "{}", "For a complete overview of configuration options, cancel the initialization and explore `iam help`")?; + write!(stdout(), "Would you like to create a default local store with local stubs for external services?[(y)es/(n)o]: ")?; + stdout().flush()?; + 'outer: loop { + input.clear(); + stdin().read_line(&mut input)?; + match input.as_str().trim() { + "Y" | "y" | "Yes" | "yes" => break, + "N" | "n" | "No" | "no" => { + loop { + write!( + stdout(), + "Persistence store {:?}: ", + AuthStore::VARIANTS + .iter() + .map(|s| s.to_lowercase()) + .collect::<Vec<String>>() + )?; + stdout().flush()?; + input.clear(); + stdin().read_line(&mut input)?; + match AuthStore::from_str(&input.trim()) { + Ok(s) => { + cfg.profile[0].store = s; + break; + } + Err(_) => { + writeln!(stdout(), "{}", "Invalid store type".red())?; + } + } + } + + write!(stdout(), "Store connection string: ")?; + stdout().flush()?; + input.clear(); + stdin().read_line(&mut input)?; + cfg.profile[0].store_conn = input.trim().to_string().clone(); + + loop { + write!( + stdout(), + "Email provider {:?}: ", + AuthEmail::VARIANTS + .iter() + .map(|s| s.to_lowercase()) + .collect::<Vec<String>>() + )?; + stdout().flush()?; + input.clear(); + stdin().read_line(&mut input)?; + match AuthEmail::from_str(&input.trim()) { + Ok(s) => { + cfg.profile[0].emailer = s; + break; + } + Err(_) => { + writeln!(stdout(), "{}", "Invalid email provider".red())?; + } + } + } + + write!( + stdout(), + "Email template for login validation:[FilePath or Enter for default]: " + )?; + stdout().flush()?; + input.clear(); + stdin().read_line(&mut input)?; + cfg.profile[0].email_template_login = + Some(input.trim().to_string().clone()); + + write!( + stdout(), + "Email template for signup validation:[FilePath or Enter for default]: " + )?; + stdout().flush()?; + input.clear(); + stdin().read_line(&mut input)?; + cfg.profile[0].email_template_login = + Some(input.trim().to_string().clone()); + + break 'outer; + } + _ => {} + } + } + } + + let mut f = File::create(config_profile.clone())?; + f.write_all(toml::to_string(&cfg)?.as_bytes())?; + writeln!( + stdout(), + "{} {} {} {} {}", + "created iam config".green(), + "default", + "at".green(), + config_dir.display().to_string(), + "to hold secD iam configurations".green() + )?; + } + Ok(()) +} |
