use std::process::ExitCode; use futures_util::StreamExt; use sqlx::{Database, query, sqlite::SqlitePool}; use crate::cli::UserCommand as UC; pub async fn handle_user_command(user_command: UC, db: SqlitePool) -> anyhow::Result { match user_command { UC::List {} => list_users(db).await, UC::Create { user_name } => create_user(db, user_name).await, UC::ResetPassword { user_id } => reset_password(&db, user_id).await } } async fn list_users(db: SqlitePool) -> anyhow::Result { println!("\n\nListing users:"); let mut results = query!("SELECT user_id, user_name FROM users;").fetch(&db); while let Some(Ok(user)) = results.next().await { println!("\t{:?}: {}", user.user_id, user.user_name); } Ok(ExitCode::SUCCESS) } async fn create_user(db: SqlitePool, name: String) -> anyhow::Result { let mut tx = db.begin().await?; let previous_user_check = sqlx::query_scalar!( "SELECT COUNT(*) FROM users WHERE user_name = ?", name ) .fetch_one(&mut *tx) .await?; if previous_user_check > 0 { eprintln!("Error! User already exists!"); return Ok(ExitCode::FAILURE); } let new_id = query!( r#"INSERT INTO users (user_name, password_salt, password_hash) VALUES (?, "", "")"#, name ) .execute(&mut *tx) .await? .last_insert_rowid(); reset_password(&mut *tx, new_id as i16).await?; tx.commit().await?; println!("User successfully created!"); Ok(ExitCode::SUCCESS) } async fn reset_password<'a, E>(db: E, id: i16) -> anyhow::Result where E: sqlx::Executor<'a, Database = sqlx::Sqlite> { let password1 = rpassword::prompt_password("Enter new password: ")?; let password2 = rpassword::prompt_password("Enter password again: ")?; if password1 != password2 { Err(anyhow::anyhow!("Passwords do not match!"))? } crate::db::user::reset_password(db, id, password1).await?; println!("Password set successfully!"); Ok(ExitCode::SUCCESS) }