use axum::{ debug_handler, extract::{Extension, Query, State}, http::StatusCode, response::{ErrorResponse, IntoResponse, Result}, }; use serde::Deserialize; // use tracing::{event, Level}; use crate::{ data::db, model, ron_extractor::ExtractRon, ron_utils::{ron_error, ron_response}, }; const NOT_AUTHORIZED_MESSAGE: &str = "Action not authorized"; #[allow(dead_code)] #[debug_handler] pub async fn update_user( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { if let Some(user) = user { connection .update_user( user.id, ron.email.as_deref().map(str::trim), ron.name.as_deref(), ron.password.as_deref(), ) .await?; } else { return Err(ErrorResponse::from(ron_error( StatusCode::UNAUTHORIZED, NOT_AUTHORIZED_MESSAGE, ))); } Ok(StatusCode::OK) } async fn check_user_rights_recipe( connection: &db::Connection, user: &Option, recipe_id: i64, ) -> Result<()> { if user.is_none() || !connection .can_edit_recipe(user.as_ref().unwrap().id, recipe_id) .await? { Err(ErrorResponse::from(ron_error( StatusCode::UNAUTHORIZED, NOT_AUTHORIZED_MESSAGE, ))) } else { Ok(()) } } async fn check_user_rights_recipe_group( connection: &db::Connection, user: &Option, group_id: i64, ) -> Result<()> { if user.is_none() || !connection .can_edit_recipe_group(user.as_ref().unwrap().id, group_id) .await? { Err(ErrorResponse::from(ron_error( StatusCode::UNAUTHORIZED, NOT_AUTHORIZED_MESSAGE, ))) } else { Ok(()) } } async fn check_user_rights_recipe_step( connection: &db::Connection, user: &Option, step_id: i64, ) -> Result<()> { if user.is_none() || !connection .can_edit_recipe_step(user.as_ref().unwrap().id, step_id) .await? { Err(ErrorResponse::from(ron_error( StatusCode::UNAUTHORIZED, NOT_AUTHORIZED_MESSAGE, ))) } else { Ok(()) } } async fn check_user_rights_recipe_ingredient( connection: &db::Connection, user: &Option, ingredient_id: i64, ) -> Result<()> { if user.is_none() || !connection .can_edit_recipe_ingredient(user.as_ref().unwrap().id, ingredient_id) .await? { Err(ErrorResponse::from(ron_error( StatusCode::UNAUTHORIZED, NOT_AUTHORIZED_MESSAGE, ))) } else { Ok(()) } } #[debug_handler] pub async fn set_recipe_title( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &user, ron.recipe_id).await?; connection .set_recipe_title(ron.recipe_id, &ron.title) .await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_recipe_description( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &user, ron.recipe_id).await?; connection .set_recipe_description(ron.recipe_id, &ron.description) .await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_servings( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &user, ron.recipe_id).await?; connection .set_recipe_servings(ron.recipe_id, ron.servings) .await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_estimated_time( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &user, ron.recipe_id).await?; connection .set_recipe_estimated_time(ron.recipe_id, ron.estimated_time) .await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_difficulty( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &user, ron.recipe_id).await?; connection .set_recipe_difficulty(ron.recipe_id, ron.difficulty) .await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_language( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &user, ron.recipe_id).await?; connection .set_recipe_language(ron.recipe_id, &ron.lang) .await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_is_published( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &user, ron.recipe_id).await?; connection .set_recipe_is_published(ron.recipe_id, ron.is_published) .await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn rm( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &user, ron.recipe_id).await?; connection.rm_recipe(ron.recipe_id).await?; Ok(StatusCode::OK) } impl From for common::ron_api::Group { fn from(group: model::Group) -> Self { Self { id: group.id, name: group.name, comment: group.comment, steps: group .steps .into_iter() .map(common::ron_api::Step::from) .collect(), } } } impl From for common::ron_api::Step { fn from(step: model::Step) -> Self { Self { id: step.id, action: step.action, ingredients: step .ingredients .into_iter() .map(common::ron_api::Ingredient::from) .collect(), } } } impl From for common::ron_api::Ingredient { fn from(ingredient: model::Ingredient) -> Self { Self { id: ingredient.id, name: ingredient.name, comment: ingredient.comment, quantity_value: ingredient.quantity_value, quantity_unit: ingredient.quantity_unit, } } } #[derive(Deserialize)] pub struct RecipeId { #[serde(rename = "recipe_id")] id: i64, } #[debug_handler] pub async fn get_groups( State(connection): State, recipe_id: Query, ) -> Result { // Here we don't check user rights on purpose. Ok(ron_response( StatusCode::OK, connection .get_groups(recipe_id.id) .await? .into_iter() .map(common::ron_api::Group::from) .collect::>(), )) } #[debug_handler] pub async fn add_group( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &user, ron.recipe_id).await?; let group_id = connection.add_recipe_group(ron.recipe_id).await?; Ok(ron_response( StatusCode::OK, common::ron_api::AddRecipeGroupResult { group_id }, )) } #[debug_handler] pub async fn rm_group( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_group(&connection, &user, ron.group_id).await?; connection.rm_recipe_group(ron.group_id).await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_group_name( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_group(&connection, &user, ron.group_id).await?; connection.set_group_name(ron.group_id, &ron.name).await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_group_comment( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_group(&connection, &user, ron.group_id).await?; connection .set_group_comment(ron.group_id, &ron.comment) .await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn add_step( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_group(&connection, &user, ron.group_id).await?; let step_id = connection.add_recipe_step(ron.group_id).await?; Ok(ron_response( StatusCode::OK, common::ron_api::AddRecipeStepResult { step_id }, )) } #[debug_handler] pub async fn rm_step( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_step(&connection, &user, ron.step_id).await?; connection.rm_recipe_step(ron.step_id).await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_step_action( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_step(&connection, &user, ron.step_id).await?; connection.set_step_action(ron.step_id, &ron.action).await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn add_ingredient( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_step(&connection, &user, ron.step_id).await?; let ingredient_id = connection.add_recipe_ingredient(ron.step_id).await?; Ok(ron_response( StatusCode::OK, common::ron_api::AddRecipeIngredientResult { ingredient_id }, )) } #[debug_handler] pub async fn rm_ingredient( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_ingredient(&connection, &user, ron.ingredient_id).await?; connection.rm_recipe_ingredient(ron.ingredient_id).await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_ingredient_name( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_ingredient(&connection, &user, ron.ingredient_id).await?; connection .set_ingredient_name(ron.ingredient_id, &ron.name) .await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_ingredient_comment( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_ingredient(&connection, &user, ron.ingredient_id).await?; connection .set_ingredient_comment(ron.ingredient_id, &ron.comment) .await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_ingredient_quantity( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_ingredient(&connection, &user, ron.ingredient_id).await?; connection .set_ingredient_quantity(ron.ingredient_id, ron.quantity) .await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_ingredient_unit( State(connection): State, Extension(user): Extension>, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_ingredient(&connection, &user, ron.ingredient_id).await?; connection .set_ingredient_unit(ron.ingredient_id, &ron.unit) .await?; Ok(StatusCode::OK) } ///// 404 ///// #[debug_handler] pub async fn not_found(Extension(_user): Extension>) -> impl IntoResponse { ron_error(StatusCode::NOT_FOUND, "Not found") }