use super::generate_random_alphanumeric; use crate::{auth::User, AppState}; use argon2::password_hash::rand_core::OsRng; use argon2::{password_hash::SaltString, Argon2, PasswordHasher}; use axum::Router; use sqlx::SqlitePool; mod web; impl User { pub(crate) async fn all(db: &SqlitePool) -> Vec { sqlx::query_as::<_, Self>( "SELECT id, name, pw, require_new_password_code FROM user ORDER BY name;", ) .fetch_all(db) .await .unwrap() } pub async fn find_by_id(db: &SqlitePool, id: i64) -> Option { sqlx::query_as!( Self, "SELECT id, name, pw, require_new_password_code FROM user WHERE id = ?", id ) .fetch_one(db) .await .ok() } async fn create(db: &SqlitePool, name: &str) -> Result { let code = generate_random_alphanumeric(8); let result = sqlx::query!( "INSERT INTO user(name, pw, require_new_password_code) VALUES (?, 'pw-to-be-defined', ?) RETURNING id", name, code ) .fetch_one(db) .await .map_err(|e| e.to_string())?; Ok(result.id) } async fn update_name(&self, db: &SqlitePool, name: &str) { sqlx::query!("UPDATE user SET name = ? WHERE id = ?", name, self.id) .execute(db) .await .unwrap(); } async fn new_pw(&self, db: &SqlitePool) { let code = generate_random_alphanumeric(8); sqlx::query!( "UPDATE user SET pw='pw-to-be-redefined', require_new_password_code=? WHERE id = ?", code, self.id ) .execute(db) .await .unwrap(); } pub(crate) async fn update_pw(&self, db: &SqlitePool, pw: &str) -> Result<(), String> { if self.require_new_password_code.is_some() { let argon2 = Argon2::default(); let salt = SaltString::generate(&mut OsRng); let password_hash = argon2 .hash_password(pw.as_bytes(), &salt) .unwrap() .to_string(); sqlx::query!( "UPDATE user SET pw = ?, require_new_password_code=NULL WHERE id = ?", password_hash, self.id ) .execute(db) .await .unwrap(); return Ok(()); } Err(t!("cant_update_pw_if_already_existing").into()) } async fn delete(&self, db: &SqlitePool) -> Result<(), String> { sqlx::query!("DELETE FROM user WHERE id = ?", self.id) .execute(db) .await .map_err(|e| e.to_string())?; Ok(()) } } pub(super) fn routes() -> Router { web::routes() }