From acf63436aa82b3f7729ef9e8b8cb6e53742ca4ec Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Sat, 3 Sep 2022 16:20:16 -0400 Subject: [PATCH] Load default recipes for new user --- Makefile | 2 +- kitchen/sqlx-data.json | 20 ++++++++++++++++++ kitchen/src/main.rs | 3 +++ kitchen/src/web/mod.rs | 33 ++++++++++++++++++++++++++++-- kitchen/src/web/storage/mod.rs | 37 ++++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 36fda75..466014d 100644 --- a/Makefile +++ b/Makefile @@ -38,4 +38,4 @@ clean: cargo clean sqlx-prepare: - cd kitchen; cargo sqlx prepare + cd kitchen; cargo sqlx prepare --database-url sqlite://\$(pwd)/../.session_store/store.db diff --git a/kitchen/sqlx-data.json b/kitchen/sqlx-data.json index 62df1b6..1cf8d4f 100644 --- a/kitchen/sqlx-data.json +++ b/kitchen/sqlx-data.json @@ -18,6 +18,26 @@ }, "query": "select password_hashed from users where id = ?" }, + "2519fa6cd665764d0c9a0152e5c8ce20152fc4853c5cd9c34259cec27d8bf47e": { + "describe": { + "columns": [], + "nullable": [], + "parameters": { + "Right": 2 + } + }, + "query": "insert into categories (user_id, category_text) values (?, ?)" + }, + "3311b1ceb15128dca0a3554f1e0f50c03e6c531919a6be1e7f9f940544236143": { + "describe": { + "columns": [], + "nullable": [], + "parameters": { + "Right": 3 + } + }, + "query": "insert into recipes (user_id, recipe_id, recipe_text) values (?, ?, ?)" + }, "5d743897fb0d8fd54c3708f1b1c6e416346201faa9e28823c1ba5a421472b1fa": { "describe": { "columns": [], diff --git a/kitchen/src/main.rs b/kitchen/src/main.rs index 5582ee0..465b61a 100644 --- a/kitchen/src/main.rs +++ b/kitchen/src/main.rs @@ -50,6 +50,7 @@ fn create_app<'a>() -> clap::App<'a> { ) (@subcommand add_user => (about: "add users to to the interface") + (@arg recipe_dir: -d --dir +takes_value "Directory containing recipe files to load for user") (@arg user: -u --user +takes_value +required "username to add") (@arg pass: -p --pass +takes_value +required "password to add for this user") (@arg session_dir: --session_dir +takes_value "Session store directory to use") @@ -138,12 +139,14 @@ fn main() { web::ui_main(recipe_dir_path, session_store_path, listen_socket).await }); } else if let Some(matches) = matches.subcommand_matches("add_user") { + let recipe_dir_path = matches.value_of("recipe_dir").map(|dir| PathBuf::from(dir)); let session_store_path: PathBuf = get_session_store_path(matches); async_std::task::block_on(async { web::add_user( session_store_path, matches.value_of("user").unwrap().to_owned(), matches.value_of("pass").unwrap().to_owned(), + recipe_dir_path, ) .await; }); diff --git a/kitchen/src/web/mod.rs b/kitchen/src/web/mod.rs index 10222de..dd516f8 100644 --- a/kitchen/src/web/mod.rs +++ b/kitchen/src/web/mod.rs @@ -128,18 +128,47 @@ async fn api_categories( result } -pub async fn add_user(store_path: PathBuf, username: String, password: String) { +pub async fn add_user( + store_path: PathBuf, + username: String, + password: String, + recipe_dir_path: Option, +) { let app_store = storage::SqliteStore::new(store_path) .await .expect("Unable to create app_store"); let user_creds = storage::UserCreds { - id: storage::UserId(username), + id: storage::UserId(username.clone()), pass: secrecy::Secret::from(password), }; app_store .store_user_creds(user_creds) .await .expect("Failed to store user creds"); + if let Some(path) = recipe_dir_path { + let store = recipe_store::AsyncFileStore::new(path); + if let Some(recipes) = store + .get_recipes() + .await + .expect("Unable to get recipes to load for user") + { + app_store + .store_recipes_for_user(&username, &recipes) + .await + .expect("Failed to load user recipes"); + } + if let Some(categories) = store + .get_categories() + .await + .expect("Unable to get categories to fetch for user") + { + app_store + .store_categories_for_user(&username, &categories) + .await + .expect("Failed to load user categories"); + } + // TODO(jwall): Load all the recipes into our sqlite database + } } #[instrument(fields(recipe_dir=?recipe_dir_path,listen=?listen_socket), skip_all)] diff --git a/kitchen/src/web/storage/mod.rs b/kitchen/src/web/storage/mod.rs index bfd940c..dd3b3f6 100644 --- a/kitchen/src/web/storage/mod.rs +++ b/kitchen/src/web/storage/mod.rs @@ -88,6 +88,11 @@ pub trait APIStore { async fn get_categories_for_user(&self, user_id: &str) -> Result>; async fn get_recipes_for_user(&self, user_id: &str) -> Result>>; + + async fn store_recipes_for_user(&self, user_id: &str, recipes: &Vec) + -> Result<()>; + + async fn store_categories_for_user(&self, user_id: &str, categories: &str) -> Result<()>; } #[async_trait] @@ -156,6 +161,7 @@ impl SqliteStore { pub async fn new>(path: P) -> sqlx::Result { let url = format!("sqlite://{}/store.db", path.as_ref().to_string_lossy()); let options = SqliteConnectOptions::from_str(&url)?.journal_mode(SqliteJournalMode::Wal); + info!(?options, "Connecting to sqlite db"); let pool = Arc::new(sqlx::SqlitePool::connect_with(options).await?); Ok(Self { pool, url }) } @@ -291,4 +297,35 @@ impl APIStore for SqliteStore { .collect(); Ok(Some(rows)) } + + async fn store_recipes_for_user( + &self, + user_id: &str, + recipes: &Vec, + ) -> Result<()> { + for entry in recipes { + let recipe_id = entry.recipe_id().to_owned(); + let recipe_text = entry.recipe_text().to_owned(); + sqlx::query!( + "insert into recipes (user_id, recipe_id, recipe_text) values (?, ?, ?)", + user_id, + recipe_id, + recipe_text, + ) + .execute(self.pool.as_ref()) + .await?; + } + Ok(()) + } + + async fn store_categories_for_user(&self, user_id: &str, categories: &str) -> Result<()> { + sqlx::query!( + "insert into categories (user_id, category_text) values (?, ?)", + user_id, + categories, + ) + .execute(self.pool.as_ref()) + .await?; + Ok(()) + } }