diff --git a/src/demo.rs b/src/demo.rs index cad30dc..e3cbb1b 100644 --- a/src/demo.rs +++ b/src/demo.rs @@ -1,48 +1,32 @@ -use uuid::Uuid; - use crate::feeds::Feed; +use crate::user::User; pub async fn setup_demo_data(pool: &sqlx::SqlitePool) { // Create admin user - let admin_id = Uuid::new_v4(); - let admin_id_str = admin_id.to_string(); - let admin_hash = bcrypt::hash("admin", bcrypt::DEFAULT_COST).unwrap(); - let now = chrono::Utc::now().to_rfc3339(); - - sqlx::query( - "INSERT INTO users (id, username, password_hash, email, display_name, created_at, admin) - VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)", - ) - .bind(&admin_id_str) - .bind("admin") - .bind(&admin_hash) - .bind(Option::::None) - .bind(Option::::None) - .bind(&now) - .bind(true) - .execute(pool) - .await - .expect("Failed to create admin user"); + let mut admin = User::new( + "admin".to_string(), + bcrypt::hash("admin", bcrypt::DEFAULT_COST).unwrap(), + None, + None, + ); + admin.admin = true; + admin + .write_to_database(pool) + .await + .expect("Failed to create admin user"); // Create demo user - let demo_id = Uuid::new_v4(); - let demo_id_str = demo_id.to_string(); - let demo_hash = bcrypt::hash("demo", bcrypt::DEFAULT_COST).unwrap(); + let demo = User::new( + "demo".to_string(), + bcrypt::hash("demo", bcrypt::DEFAULT_COST).unwrap(), + None, + None, + ); + demo.write_to_database(pool) + .await + .expect("Failed to create demo user"); - sqlx::query( - "INSERT INTO users (id, username, password_hash, email, display_name, created_at, admin) - VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)", - ) - .bind(&demo_id_str) - .bind("demo") - .bind(&demo_hash) - .bind(Option::::None) - .bind(Option::::None) - .bind(&now) - .bind(false) - .execute(pool) - .await - .expect("Failed to create demo user"); + let demo_id = demo.id; let mut bbc_news = Feed::new( "BBC News".to_string(), diff --git a/src/user.rs b/src/user.rs index 70a6dad..ef21d37 100644 --- a/src/user.rs +++ b/src/user.rs @@ -81,6 +81,29 @@ impl User { admin: false, } } + + pub async fn write_to_database<'a, E>(&self, executor: E) -> sqlx::Result<()> + where + E: sqlx::Executor<'a, Database = sqlx::Sqlite>, + { + sqlx::query( + r#" + INSERT INTO users (id, username, password_hash, email, display_name, created_at, admin) + VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7) + "#, + ) + .bind(self.id.to_string()) + .bind(self.username.clone()) + .bind(self.password_hash.clone()) + .bind(self.email.clone()) + .bind(self.display_name.clone()) + .bind(self.created_at.to_rfc3339()) + .bind(self.admin) + .execute(executor) + .await?; + + Ok(()) + } } #[derive(Debug, Deserialize)] @@ -130,19 +153,7 @@ pub async fn create_user( new_user.display_name, ); - let query = sqlx::query( - "INSERT INTO users (id, username, password_hash, email, display_name, created_at, admin) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)" - ) - .bind(user.id.to_string()) - .bind(user.username.as_str()) - .bind(user.password_hash.as_str()) - .bind(user.email.as_ref()) - .bind(user.display_name.as_ref()) - .bind(user.created_at.to_rfc3339()) - .bind(false) - .execute(&mut **db).await; - - match query { + match user.write_to_database(&mut **db).await { Ok(_) => Ok(Json(user)), Err(e) => { eprintln!("Database error: {}", e); @@ -350,6 +361,8 @@ pub async fn setup( mut db: Connection, new_user: Json, ) -> Result> { + let new_user = new_user.into_inner(); + // Check if any users exist let count = sqlx::query!("SELECT COUNT(*) as count FROM users") .fetch_one(&mut **db) @@ -368,34 +381,25 @@ pub async fn setup( })); } + let password = new_user.password.as_bytes(); + // Hash the password - let password_hash = - bcrypt::hash(new_user.password.as_bytes(), bcrypt::DEFAULT_COST).map_err(|e| { - eprintln!("Password hashing error: {}", e); - Json(SetupError { - error: "Failed to process password".to_string(), - }) - })?; + let password_hash = bcrypt::hash(password, bcrypt::DEFAULT_COST).map_err(|e| { + eprintln!("Password hashing error: {}", e); + Json(SetupError { + error: "Failed to process password".to_string(), + }) + })?; - // Create admin user - let user_id = Uuid::new_v4().to_string(); - let now = chrono::Utc::now().to_rfc3339(); + let mut user = User::new( + new_user.username, + password_hash, + new_user.email, + new_user.display_name, + ); + user.admin = true; // This is an admin user - let result = sqlx::query( - "INSERT INTO users (id, username, password_hash, email, display_name, created_at, admin) - VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)", - ) - .bind(&user_id) - .bind(&new_user.username) - .bind(&password_hash) - .bind(&new_user.email) - .bind(&new_user.display_name) - .bind(&now) - .bind(true) // This is an admin user - .execute(&mut **db) - .await; - - match result { + match user.write_to_database(&mut **db).await { Ok(_) => Ok(Status::Created), Err(e) => { eprintln!("Database error: {}", e);