use futures::{stream::BoxStream, Stream, TryStreamExt}; use serde::Serialize; use uuid::Uuid; use crate::Pool; /// Creates user and returns its id pub async fn create_user( user_name: &str, user_email: &str, hashed_password: &[u8], pool: &Pool, ) -> sqlx::Result { let id = sqlx::query!( "INSERT INTO users(username, email, hashed_password) VALUES ($1, $2, $3) RETURNING user_id", user_name, user_email, hashed_password ) .fetch_one(pool) .await? .user_id; sqlx::query!( "INSERT INTO folders(owner_id, folder_name) VALUES ($1, $2)", id, "ROOT" ) .execute(pool) .await?; Ok(id) } /// Deletes the user and returns the files that must be deleted pub fn delete_user(user_id: i32, pool: &Pool) -> impl Stream> + '_ { sqlx::query_file!("sql/delete_user.sql", user_id) .fetch(pool) .map_ok(|record| record.file_id) } #[derive(Serialize, Debug)] pub struct UserInfo { user_id: i32, username: String, email: String, } pub async fn update( user_id: i32, username: &str, email: &str, pool: &Pool, ) -> sqlx::Result { sqlx::query_as!( UserInfo, "UPDATE users SET username = $2, email = $3 WHERE user_id = $1 RETURNING user_id, username, email", user_id, username, email ) .fetch_one(pool) .await } pub async fn get(user_id: i32, pool: &Pool) -> sqlx::Result { sqlx::query_as!( UserInfo, "SELECT user_id, username, email FROM users WHERE user_id = $1", user_id ) .fetch_one(pool) .await } /// Gets the hashed password field by either the email or th username pub async fn get_hash(search_string: &str, pool: &Pool) -> sqlx::Result)>> { let record = sqlx::query!( "SELECT user_id, hashed_password FROM users WHERE username = $1 OR email = $1", search_string ) .fetch_optional(pool) .await?; Ok(record.map(|record| (record.user_id, record.hashed_password))) } pub fn search_for_user<'a>( search_string: &str, pool: &'a Pool, ) -> BoxStream<'a, sqlx::Result> { sqlx::query_file_as!(UserInfo, "sql/search_for_user.sql", search_string).fetch(pool) }