2025-01-24 11:48:15 -05:00

76 lines
2.1 KiB
Rust

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<ExitCode> {
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<ExitCode> {
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<ExitCode> {
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<ExitCode>
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)
}