From: Greg Burri Date: Tue, 21 Jan 2025 18:27:06 +0000 (+0100) Subject: Add tables for shopping list and planner X-Git-Url: https://git.euphorik.ch/?a=commitdiff_plain;h=d9449de02b4f7041515ddc080b9f909de8830531;p=recipes.git Add tables for shopping list and planner --- diff --git a/Cargo.lock b/Cargo.lock index 06c8034..5b745be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -149,11 +149,11 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d6fd624c75e18b3b4c6b9caf42b1afe24437daaee904069137d8bab077be8b8" +checksum = "efea76243612a2436fb4074ba0cf3ba9ea29efdeb72645d8fc63f116462be1de" dependencies = [ - "axum-core 0.5.0", + "axum-core", "axum-macros", "bytes", "form_urlencoded", @@ -184,32 +184,12 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 1.2.0", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum-core" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1362f362fd16024ae199c1970ce98f9661bf5ef94b9808fee734bc3698b733" +checksum = "eab1b0df7cded837c40dacaa2e1c33aa17c84fc3356ae67b5645f1e83190753e" dependencies = [ "bytes", - "futures-util", + "futures-core", "http 1.2.0", "http-body", "http-body-util", @@ -224,12 +204,12 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fc6f625a1f7705c6cf62d0d070794e94668988b1c38111baeec177c715f7b" +checksum = "543f0799d22486525744f06a3580b64f3e51d97aba73ea0e09040969c0034722" dependencies = [ "axum", - "axum-core 0.5.0", + "axum-core", "bytes", "cookie", "futures-util", @@ -392,9 +372,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.26" +version = "4.5.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" +checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796" dependencies = [ "clap_builder", "clap_derive", @@ -402,9 +382,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.26" +version = "4.5.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" +checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" dependencies = [ "anstream", "anstyle", @@ -1393,9 +1373,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -1919,7 +1899,6 @@ dependencies = [ "rand", "rand_core", "rinja", - "rinja_axum", "ron", "serde", "sqlx", @@ -2013,17 +1992,6 @@ dependencies = [ "rinja_derive", ] -[[package]] -name = "rinja_axum" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc64d77bb950f6498d0fc64b028d168fcb4e56ac31b66a8ae05f64d3b0c218b6" -dependencies = [ - "axum-core 0.4.5", - "http 1.2.0", - "rinja", -] - [[package]] name = "rinja_derive" version = "0.3.5" @@ -2202,9 +2170,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.136" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "336a0c23cf42a38d9eaa7cd22c7040d04e1228a19a933890805ffd00a16437d2" +checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b" dependencies = [ "itoa", "memchr", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index cf5db85..a55c0e1 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" common = { path = "../common" } axum = { version = "0.8", features = ["macros"] } -axum-extra = { version = "0.10", features = ["cookie"] } +axum-extra = { version = "0.11", features = ["cookie"] } tokio = { version = "1", features = ["full"] } tower = { version = "0.5", features = ["util"] } tower-http = { version = "0.6", features = ["fs", "trace"] } @@ -27,8 +27,7 @@ clap = { version = "4", features = ["derive"] } sqlx = { version = "0.8", features = ["sqlite", "runtime-tokio", "chrono"] } -rinja = { version = "0.3", features = ["with-axum"] } -rinja_axum = "0.3" +rinja = { version = "0.3" } argon2 = { version = "0.5", features = ["default", "std"] } rand_core = { version = "0.6", features = ["std"] } diff --git a/backend/sql/data_test.sql b/backend/sql/data_test.sql index c68174b..c2ec78c 100644 --- a/backend/sql/data_test.sql +++ b/backend/sql/data_test.sql @@ -1,8 +1,9 @@ -INSERT INTO [User] ([id], [email], [name], [creation_datetime], [password], [validation_token_datetime], [validation_token]) +INSERT INTO [User] ([id], [email], [name], [is_admin], [creation_datetime], [password], [validation_token_datetime], [validation_token]) VALUES ( 1, 'paul@atreides.com', 'Paul', + TRUE, '2025-01-07T10:41:05.697884837+00:00', '$argon2id$v=19$m=4096,t=4,p=2$l1fAMRc0VfkNzqpEfFEReg$/gsUsY2aML8EbKjPeCxucenxkxhiFSXDmizWZPLvNuo', 0, diff --git a/backend/sql/version_1.sql b/backend/sql/version_1.sql index 46cbd1d..0100ee3 100644 --- a/backend/sql/version_1.sql +++ b/backend/sql/version_1.sql @@ -151,19 +151,72 @@ CREATE TABLE [Ingredient] ( [step_id] INTEGER NOT NULL, [name] TEXT NOT NULL DEFAULT '', - [comment] TEXT NOT NULL DEFAULT '', [quantity_value] REAL, [quantity_unit] TEXT NOT NULL DEFAULT '', + [comment] TEXT NOT NULL DEFAULT '', + FOREIGN KEY([step_id]) REFERENCES [Step]([id]) ON DELETE CASCADE ) STRICT; CREATE INDEX [Ingredient_order_index] ON [Ingredient]([order]); --- Table not strict because [value] can story any type of data. +CREATE TABLE [RecipeScheduled] ( + [id] INTEGER PRIMARY KEY, + [user_id] INTEGER NOT NULL, + [recipe_id] INTEGER NOT NULL, + [date] TEXT NOT NULL, + [servings] INTEGER, -- If NULL use [recipe].[servings]. + + FOREIGN KEY([user_id]) REFERENCES [User]([id]) ON DELETE CASCADE, + FOREIGN KEY([recipe_id]) REFERENCES [Recipe]([id]) ON DELETE CASCADE +); + +CREATE TABLE [ShoppingEntry] ( + [id] INTEGER PRIMARY KEY, + [user_id] INTEGER NOT NULL, + -- The linkded ingredient can be deleted or a custom entry can be manually added. + -- In both cases [name], [quantity_value] and [quantity_unit] are used to display + -- the entry instead of [Ingredient] data. + [ingredient_id] INTEGER, + [is_checked] INTEGER NOT NULL DEFAULT FALSE, + + [name] TEXT NOT NULL DEFAULT '', + [quantity_value] REAL, + [quantity_unit] TEXT NOT NULL DEFAULT '', + [servings] INTEGER, + + FOREIGN KEY([user_id]) REFERENCES [User]([id]) ON DELETE CASCADE, + FOREIGN KEY([ingredient_id]) REFERENCES [Ingredient]([id]) ON DELETE SET NULL +); + +-- When an ingredient is deleted, its values are copied to any shopping entry +-- that referenced it. +CREATE TRIGGER [Ingredient_trigger_delete] +BEFORE DELETE +ON [Ingredient] +BEGIN + UPDATE [ShoppingEntry] + SET + [name] = OLD.[name], + [quantity_value] = OLD.[quantity_value], + [quantity_unit] = OLD.[quantity_unit], + [servings] = ( + SELECT [servings] + FROM [Recipe] + INNER JOIN [Group] ON [Group].[recipe_id] = [Recipe].[id] + INNER JOIN [Step] ON [Step].[group_id] = [Group].[id] + WHERE [Step].[id] = OLD.[step_id] + ) + WHERE [ingredient_id] = OLD.[id]; +END; + CREATE TABLE [Settings] ( [name] TEXT NOT NULL PRIMARY KEY, + + -- Value can by anything that can be read from a text by + -- implementing the trait 'std::str::FromStr'. [value] TEXT NOT NULL -); +) STRICT; -INSERT INTO [Settings] ([name], [value]) VALUES ('new_user_registration_enabled', TRUE); +INSERT INTO [Settings] ([name], [value]) VALUES ('new_user_registration_enabled', 'true'); diff --git a/backend/src/data/db/recipe.rs b/backend/src/data/db/recipe.rs index e59b064..d1e1a8f 100644 --- a/backend/src/data/db/recipe.rs +++ b/backend/src/data/db/recipe.rs @@ -64,8 +64,8 @@ ORDER BY [title] r#" SELECT COUNT(*) = 1 FROM [Recipe] -INNER JOIN [User] ON [User].id = [Recipe].user_id -WHERE [Recipe].[id] = $1 AND ([is_admin] OR [user_id] = $2) +INNER JOIN [User] ON [User].[id] = [Recipe].[user_id] +WHERE [Recipe].[id] = $1 AND ([user_id] = $2 OR (SELECT [is_admin] FROM [User] WHERE [id] = $2)) "#, ) .bind(recipe_id) @@ -80,9 +80,9 @@ WHERE [Recipe].[id] = $1 AND ([is_admin] OR [user_id] = $2) r#" SELECT COUNT(*) = 1 FROM [Recipe] -INNER JOIN [User] ON [User].id = [Recipe].user_id +INNER JOIN [User] ON [User].[id] = [Recipe].[user_id] INNER JOIN [Group] ON [Group].[recipe_id] = [Recipe].[id] -WHERE [Group].[id] = $1 AND ([is_admin] OR [user_id] = $2) +WHERE [Group].[id] = $1 AND ([user_id] = $2 OR (SELECT [is_admin] FROM [User] WHERE [id] = $2)) "#, ) .bind(group_id) @@ -104,9 +104,9 @@ WHERE [Group].[id] = $1 AND ([is_admin] OR [user_id] = $2) r#" SELECT COUNT(*) FROM [Recipe] -INNER JOIN [User] ON [User].id = [Recipe].user_id +INNER JOIN [User] ON [User].[id] = [Recipe].[user_id] INNER JOIN [Group] ON [Group].[recipe_id] = [Recipe].[id] -WHERE [Group].[id] IN ({}) AND ([is_admin] OR [user_id] = $2) +WHERE [Group].[id] IN ({}) AND ([user_id] = $2 OR (SELECT [is_admin] FROM [User] WHERE [id] = $2)) "#, params ); @@ -123,10 +123,10 @@ WHERE [Group].[id] IN ({}) AND ([is_admin] OR [user_id] = $2) r#" SELECT COUNT(*) = 1 FROM [Recipe] -INNER JOIN [User] ON [User].id = [Recipe].user_id +INNER JOIN [User] ON [User].[id] = [Recipe].[user_id] INNER JOIN [Group] ON [Group].[recipe_id] = [Recipe].[id] INNER JOIN [Step] ON [Step].[group_id] = [Group].[id] -WHERE [Step].[id] = $1 AND ([is_admin] OR [user_id] = $2) +WHERE [Step].[id] = $1 AND ([user_id] = $2 OR (SELECT [is_admin] FROM [User] WHERE [id] = $2)) "#, ) .bind(step_id) @@ -144,10 +144,10 @@ WHERE [Step].[id] = $1 AND ([is_admin] OR [user_id] = $2) r#" SELECT COUNT(*) FROM [Recipe] -INNER JOIN [User] ON [User].id = [Recipe].user_id +INNER JOIN [User] ON [User].[id] = [Recipe].[user_id] INNER JOIN [Group] ON [Group].[recipe_id] = [Recipe].[id] INNER JOIN [Step] ON [Step].[group_id] = [Group].[id] -WHERE [Step].[id] IN ({}) AND ([is_admin] OR [user_id] = $2) +WHERE [Step].[id] IN ({}) AND ([user_id] = $2 OR (SELECT [is_admin] FROM [User] WHERE [id] = $2)) "#, params ); @@ -168,11 +168,11 @@ WHERE [Step].[id] IN ({}) AND ([is_admin] OR [user_id] = $2) r#" SELECT COUNT(*) FROM [Recipe] -INNER JOIN [User] ON [User].id = [Recipe].user_id +INNER JOIN [User] ON [User].[id] = [Recipe].[user_id] INNER JOIN [Group] ON [Group].[recipe_id] = [Recipe].[id] INNER JOIN [Step] ON [Step].[group_id] = [Group].[id] INNER JOIN [Ingredient] ON [Ingredient].[step_id] = [Step].[id] -WHERE [Ingredient].[id] = $1 AND ([is_admin] OR [user_id] = $2) +WHERE [Ingredient].[id] = $1 AND ([user_id] = $2 OR (SELECT [is_admin] FROM [User] WHERE [id] = $2)) "#, ) .bind(ingredient_id) @@ -194,11 +194,12 @@ WHERE [Ingredient].[id] = $1 AND ([is_admin] OR [user_id] = $2) r#" SELECT COUNT(*) FROM [Recipe] -INNER JOIN [User] ON [User].id = [Recipe].user_id +INNER JOIN [User] ON [User].[id] = [Recipe].[user_id] INNER JOIN [Group] ON [Group].[recipe_id] = [Recipe].[id] INNER JOIN [Step] ON [Step].[group_id] = [Group].[id] INNER JOIN [Ingredient] ON [Ingredient].[step_id] = [Step].[id] -WHERE [Ingredient].[id] IN ({}) AND ([is_admin] OR [user_id] = $2) +WHERE [Ingredient].[id] IN ({}) AND + ([user_id] = $2 OR (SELECT [is_admin] FROM [User] WHERE [id] = $2)) "#, params ); @@ -681,6 +682,8 @@ VALUES ($1, $2) .execute(&mut *tx) .await?; + tx.commit().await?; + Ok(db_result.last_insert_rowid()) } diff --git a/backend/src/html_templates.rs b/backend/src/html_templates.rs index a1fb570..3ee4ff1 100644 --- a/backend/src/html_templates.rs +++ b/backend/src/html_templates.rs @@ -1,4 +1,4 @@ -use rinja_axum::Template; +use rinja::Template; use crate::{ data::model, diff --git a/backend/src/services/ron.rs b/backend/src/services/ron.rs index 900152b..a6c6238 100644 --- a/backend/src/services/ron.rs +++ b/backend/src/services/ron.rs @@ -522,7 +522,6 @@ pub async fn add_ingredient( ) -> Result { check_user_rights_recipe_step(&connection, &user, ron.id).await?; let id = connection.add_recipe_ingredient(ron.id).await?; - Ok(ron_response(StatusCode::OK, common::ron_api::Id { id })) } diff --git a/backend/translation.ron b/backend/translation.ron index cf79c8f..835f018 100644 --- a/backend/translation.ron +++ b/backend/translation.ron @@ -182,7 +182,7 @@ (RecipeDifficultyHard, "Difficile"), (RecipeTags, "Tags"), (RecipeLanguage, "Langue"), - (RecipeIsPublished, "Est publié"), + (RecipeIsPublished, "Est publiée"), (RecipeDelete, "Supprimer la recette"), (RecipeAddAGroup, "Ajouter un groupe"), (RecipeRemoveGroup, "Supprimer le groupe"),