use std::{ error::Error, io::{stdin, stdout, Write}, process::exit, }; use sqlx::{Pool, Postgres}; use crate::{ mail::Mailer, models::{Function, Role, User}, utils::auth::generate_salt_and_hash_plain_password, }; pub enum Command { Migrate, CreateAdmin, TestMail(String), } pub struct Args { pub command: Option, } pub fn parse_args() -> Result { let mut pargs = pico_args::Arguments::from_env(); let command = pargs.free_from_str::(); let argument = pargs.opt_free_from_str::()?; let mut args = Args { command: None }; if let Ok(parsed) = command { match parsed.trim() { "migrate" => args.command = Some(Command::Migrate), "createadmin" => args.command = Some(Command::CreateAdmin), "testmail" => { if let Some(to) = argument { args.command = Some(Command::TestMail(to)) } else { eprintln!("Testmail command requires an email. Use it like this 'brass testmail abc@example.com'"); exit(1) } } _ => (), } } Ok(args) } fn prompt(prompt: &str) -> anyhow::Result { print!("{}: ", prompt); stdout().flush()?; let mut input = String::new(); stdin().read_line(&mut input)?; Ok(input.trim().to_string()) } pub async fn handle_command( command: Option, pool: &Pool, mailer: &Mailer, ) -> anyhow::Result<()> { match command { Some(Command::Migrate) => { sqlx::migrate!("../migrations").run(pool).await?; exit(0); } Some(Command::CreateAdmin) => { let name = prompt("Full name of Admin")?; let email = prompt("E-Mail of Admin (for login)")?; let password = prompt("Password of Admin")?; let retyped_password = prompt("Retype Passsword of Admin")?; if password != retyped_password { eprintln!("Given passwords don't match!"); exit(1) } let (hash, salt) = generate_salt_and_hash_plain_password(&password)?; User::create_with_password( pool, &name, &email, &hash, &salt, Role::Admin, &[Function::Posten, Function::Wachhabender, Function::Fuehrungsassistent], 1, ) .await?; exit(0); } Some(Command::TestMail(to)) => { match mailer.send_test_mail(&to).await { Ok(_) => println!("Successfully sent mail to {to}."), Err(e) => { if let Some(source) = e.source() { eprintln!("Error sending mail with error source: {source}"); } else { eprintln!("Error sending mail with unkown error source."); } } } exit(0); } None => (), }; Ok(()) }