From 4c9742af65d7921682b9b780eb53a79a1e2bc97d Mon Sep 17 00:00:00 2001 From: Greg Burri Date: Mon, 20 Jan 2025 01:25:19 +0100 Subject: [PATCH] Add an admin flag to user --- backend/src/data/db/recipe.rs | 25 ++++++++++++++++++------- backend/src/data/db/user.rs | 12 +++++++----- backend/src/data/model.rs | 5 +++++ backend/src/services/recipe.rs | 2 +- backend/templates/recipe_view.html | 2 +- 5 files changed, 32 insertions(+), 14 deletions(-) diff --git a/backend/src/data/db/recipe.rs b/backend/src/data/db/recipe.rs index 64ed972..e59b064 100644 --- a/backend/src/data/db/recipe.rs +++ b/backend/src/data/db/recipe.rs @@ -61,7 +61,12 @@ ORDER BY [title] pub async fn can_edit_recipe(&self, user_id: i64, recipe_id: i64) -> Result { sqlx::query_scalar( - r#"SELECT COUNT(*) = 1 FROM [Recipe] WHERE [id] = $1 AND [user_id] = $2"#, + 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) + "#, ) .bind(recipe_id) .bind(user_id) @@ -75,8 +80,9 @@ ORDER BY [title] r#" SELECT COUNT(*) = 1 FROM [Recipe] +INNER JOIN [User] ON [User].id = [Recipe].user_id INNER JOIN [Group] ON [Group].[recipe_id] = [Recipe].[id] -WHERE [Group].[id] = $1 AND [user_id] = $2 +WHERE [Group].[id] = $1 AND ([is_admin] OR [user_id] = $2) "#, ) .bind(group_id) @@ -98,8 +104,9 @@ WHERE [Group].[id] = $1 AND [user_id] = $2 r#" SELECT COUNT(*) FROM [Recipe] +INNER JOIN [User] ON [User].id = [Recipe].user_id INNER JOIN [Group] ON [Group].[recipe_id] = [Recipe].[id] -WHERE [Group].[id] IN ({}) AND [user_id] = $1 +WHERE [Group].[id] IN ({}) AND ([is_admin] OR [user_id] = $2) "#, params ); @@ -116,9 +123,10 @@ WHERE [Group].[id] IN ({}) AND [user_id] = $1 r#" SELECT COUNT(*) = 1 FROM [Recipe] +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 [user_id] = $2 +WHERE [Step].[id] = $1 AND ([is_admin] OR [user_id] = $2) "#, ) .bind(step_id) @@ -136,9 +144,10 @@ WHERE [Step].[id] = $1 AND [user_id] = $2 r#" SELECT COUNT(*) FROM [Recipe] +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 [user_id] = $1 +WHERE [Step].[id] IN ({}) AND ([is_admin] OR [user_id] = $2) "#, params ); @@ -159,10 +168,11 @@ WHERE [Step].[id] IN ({}) AND [user_id] = $1 r#" SELECT COUNT(*) FROM [Recipe] +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 [user_id] = $2 +WHERE [Ingredient].[id] = $1 AND ([is_admin] OR [user_id] = $2) "#, ) .bind(ingredient_id) @@ -184,10 +194,11 @@ WHERE [Ingredient].[id] = $1 AND [user_id] = $2 r#" SELECT COUNT(*) FROM [Recipe] +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 [user_id] = $1 +WHERE [Ingredient].[id] IN ({}) AND ([is_admin] OR [user_id] = $2) "#, params ); diff --git a/backend/src/data/db/user.rs b/backend/src/data/db/user.rs index e23fd38..4b7d2b4 100644 --- a/backend/src/data/db/user.rs +++ b/backend/src/data/db/user.rs @@ -76,11 +76,13 @@ FROM [UserLoginToken] WHERE [token] = $1 } pub async fn load_user(&self, user_id: i64) -> Result> { - sqlx::query_as("SELECT [id], [email], [name], [lang] FROM [User] WHERE [id] = $1") - .bind(user_id) - .fetch_optional(&self.pool) - .await - .map_err(DBError::from) + sqlx::query_as( + "SELECT [id], [email], [name], [lang], [is_admin] FROM [User] WHERE [id] = $1", + ) + .bind(user_id) + .fetch_optional(&self.pool) + .await + .map_err(DBError::from) } /// If a new email is given and it doesn't match the current one then it has to be diff --git a/backend/src/data/model.rs b/backend/src/data/model.rs index a0aff3b..ceb7128 100644 --- a/backend/src/data/model.rs +++ b/backend/src/data/model.rs @@ -8,6 +8,7 @@ pub struct User { pub name: String, pub email: String, pub lang: String, + pub is_admin: bool, } #[derive(Debug, FromRow)] @@ -39,6 +40,10 @@ pub struct Recipe { pub groups: Vec, } +pub fn can_user_edit_recipe(user: &User, recipe: &Recipe) -> bool { + user.is_admin || recipe.user_id == user.id +} + #[derive(Debug, FromRow)] pub struct Group { pub id: i64, diff --git a/backend/src/services/recipe.rs b/backend/src/services/recipe.rs index 160b6d1..09eb138 100644 --- a/backend/src/services/recipe.rs +++ b/backend/src/services/recipe.rs @@ -36,7 +36,7 @@ pub async fn edit_recipe( ) -> Result { if let Some(user) = user { if let Some(recipe) = connection.get_recipe(recipe_id, false).await? { - if recipe.user_id == user.id { + if model::can_user_edit_recipe(&user, &recipe) { let recipes = Recipes { published: connection .get_all_published_recipe_titles(tr.current_lang_code(), Some(user.id)) diff --git a/backend/templates/recipe_view.html b/backend/templates/recipe_view.html index 39aea85..989735e 100644 --- a/backend/templates/recipe_view.html +++ b/backend/templates/recipe_view.html @@ -5,7 +5,7 @@

{{ recipe.title }}

- {% if user.is_some() && recipe.user_id == user.as_ref().unwrap().id %} + {% if user.is_some() && crate::data::model::can_user_edit_recipe(&user.as_ref().unwrap(), &recipe) %} Edit {% endif %} -- 2.49.0