Load default recipes for new user

This commit is contained in:
Jeremy Wall 2022-09-03 16:20:16 -04:00
parent 5750b33673
commit acf63436aa
5 changed files with 92 additions and 3 deletions

View File

@ -38,4 +38,4 @@ clean:
cargo clean cargo clean
sqlx-prepare: sqlx-prepare:
cd kitchen; cargo sqlx prepare cd kitchen; cargo sqlx prepare --database-url sqlite://\$(pwd)/../.session_store/store.db

View File

@ -18,6 +18,26 @@
}, },
"query": "select password_hashed from users where id = ?" "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": { "5d743897fb0d8fd54c3708f1b1c6e416346201faa9e28823c1ba5a421472b1fa": {
"describe": { "describe": {
"columns": [], "columns": [],

View File

@ -50,6 +50,7 @@ fn create_app<'a>() -> clap::App<'a> {
) )
(@subcommand add_user => (@subcommand add_user =>
(about: "add users to to the interface") (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 user: -u --user +takes_value +required "username to add")
(@arg pass: -p --pass +takes_value +required "password to add for this user") (@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") (@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 web::ui_main(recipe_dir_path, session_store_path, listen_socket).await
}); });
} else if let Some(matches) = matches.subcommand_matches("add_user") { } 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); let session_store_path: PathBuf = get_session_store_path(matches);
async_std::task::block_on(async { async_std::task::block_on(async {
web::add_user( web::add_user(
session_store_path, session_store_path,
matches.value_of("user").unwrap().to_owned(), matches.value_of("user").unwrap().to_owned(),
matches.value_of("pass").unwrap().to_owned(), matches.value_of("pass").unwrap().to_owned(),
recipe_dir_path,
) )
.await; .await;
}); });

View File

@ -128,18 +128,47 @@ async fn api_categories(
result 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<PathBuf>,
) {
let app_store = storage::SqliteStore::new(store_path) let app_store = storage::SqliteStore::new(store_path)
.await .await
.expect("Unable to create app_store"); .expect("Unable to create app_store");
let user_creds = storage::UserCreds { let user_creds = storage::UserCreds {
id: storage::UserId(username), id: storage::UserId(username.clone()),
pass: secrecy::Secret::from(password), pass: secrecy::Secret::from(password),
}; };
app_store app_store
.store_user_creds(user_creds) .store_user_creds(user_creds)
.await .await
.expect("Failed to store user creds"); .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)] #[instrument(fields(recipe_dir=?recipe_dir_path,listen=?listen_socket), skip_all)]

View File

@ -88,6 +88,11 @@ pub trait APIStore {
async fn get_categories_for_user(&self, user_id: &str) -> Result<Option<String>>; async fn get_categories_for_user(&self, user_id: &str) -> Result<Option<String>>;
async fn get_recipes_for_user(&self, user_id: &str) -> Result<Option<Vec<RecipeEntry>>>; async fn get_recipes_for_user(&self, user_id: &str) -> Result<Option<Vec<RecipeEntry>>>;
async fn store_recipes_for_user(&self, user_id: &str, recipes: &Vec<RecipeEntry>)
-> Result<()>;
async fn store_categories_for_user(&self, user_id: &str, categories: &str) -> Result<()>;
} }
#[async_trait] #[async_trait]
@ -156,6 +161,7 @@ impl SqliteStore {
pub async fn new<P: AsRef<Path>>(path: P) -> sqlx::Result<Self> { pub async fn new<P: AsRef<Path>>(path: P) -> sqlx::Result<Self> {
let url = format!("sqlite://{}/store.db", path.as_ref().to_string_lossy()); let url = format!("sqlite://{}/store.db", path.as_ref().to_string_lossy());
let options = SqliteConnectOptions::from_str(&url)?.journal_mode(SqliteJournalMode::Wal); 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?); let pool = Arc::new(sqlx::SqlitePool::connect_with(options).await?);
Ok(Self { pool, url }) Ok(Self { pool, url })
} }
@ -291,4 +297,35 @@ impl APIStore for SqliteStore {
.collect(); .collect();
Ok(Some(rows)) Ok(Some(rows))
} }
async fn store_recipes_for_user(
&self,
user_id: &str,
recipes: &Vec<RecipeEntry>,
) -> 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(())
}
} }