use axum::{ debug_handler, extract::{Extension, State}, http::StatusCode, response::{IntoResponse, Result}, }; use axum_extra::extract::Query; use common::ron_api; // use tracing::{event, Level}; use crate::{ app::Context, data::db, data::model, ron_extractor::ExtractRon, ron_utils::ron_response_ok, }; use super::rights::*; /// Ask recipe titles associated with each given id. The returned titles are in the same order /// as the given ids. #[debug_handler] pub async fn get_titles( State(connection): State, recipe_ids: Query, ) -> Result { Ok(ron_response_ok(ron_api::Strings { strs: connection.get_recipe_titles(&recipe_ids.ids).await?, })) } #[debug_handler] pub async fn set_title( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &context.user, ron.recipe_id).await?; connection .set_recipe_title(ron.recipe_id, &ron.title) .await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_description( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &context.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(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &context.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(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &context.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 get_tags( State(connection): State, recipe_id: Query, ) -> Result { Ok(ron_response_ok(ron_api::Tags { recipe_id: recipe_id.id, tags: connection.get_recipes_tags(recipe_id.id).await?, })) } #[debug_handler] pub async fn add_tags( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &context.user, ron.recipe_id).await?; connection .add_recipe_tags( ron.recipe_id, &ron.tags .into_iter() .map(|tag| tag.to_lowercase()) .collect::>(), ) .await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn rm_tags( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &context.user, ron.recipe_id).await?; connection.rm_recipe_tags(ron.recipe_id, &ron.tags).await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_difficulty( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &context.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(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { if !crate::translation::available_codes() .iter() .any(|&l| l == ron.lang) { // TODO: log? return Ok(StatusCode::BAD_REQUEST); } check_user_rights_recipe(&connection, &context.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_public( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &context.user, ron.recipe_id).await?; connection .set_recipe_is_public(ron.recipe_id, ron.is_public) .await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn rm( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &context.user, ron.id).await?; connection.rm_recipe(ron.id).await?; Ok(StatusCode::OK) } impl From for 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(ron_api::Step::from).collect(), } } } impl From for ron_api::Step { fn from(step: model::Step) -> Self { Self { id: step.id, action: step.action, ingredients: step .ingredients .into_iter() .map(ron_api::Ingredient::from) .collect(), } } } impl From for 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, } } } #[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_ok( connection .get_groups(recipe_id.id) .await? .into_iter() .map(ron_api::Group::from) .collect::>(), )) } #[debug_handler] pub async fn add_group( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe(&connection, &context.user, ron.id).await?; let id = connection.add_recipe_group(ron.id).await?; Ok(ron_response_ok(ron_api::Id { id })) } #[debug_handler] pub async fn rm_group( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_group(&connection, &context.user, ron.id).await?; connection.rm_recipe_group(ron.id).await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_group_name( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_group(&connection, &context.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(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_group(&connection, &context.user, ron.group_id).await?; connection .set_group_comment(ron.group_id, &ron.comment) .await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_groups_order( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_groups(&connection, &context.user, &ron.ids).await?; connection.set_groups_order(&ron.ids).await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn add_step( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_group(&connection, &context.user, ron.id).await?; let id = connection.add_recipe_step(ron.id).await?; Ok(ron_response_ok(ron_api::Id { id })) } #[debug_handler] pub async fn rm_step( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_step(&connection, &context.user, ron.id).await?; connection.rm_recipe_step(ron.id).await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_step_action( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_step(&connection, &context.user, ron.step_id).await?; connection.set_step_action(ron.step_id, &ron.action).await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_steps_order( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_steps(&connection, &context.user, &ron.ids).await?; connection.set_steps_order(&ron.ids).await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn add_ingredient( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_step(&connection, &context.user, ron.id).await?; let id = connection.add_recipe_ingredient(ron.id).await?; Ok(ron_response_ok(ron_api::Id { id })) } #[debug_handler] pub async fn rm_ingredient( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_ingredient(&connection, &context.user, ron.id).await?; connection.rm_recipe_ingredient(ron.id).await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_ingredient_name( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_ingredient(&connection, &context.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(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_ingredient(&connection, &context.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(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_ingredient(&connection, &context.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(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_ingredient(&connection, &context.user, ron.ingredient_id).await?; connection .set_ingredient_unit(ron.ingredient_id, &ron.unit) .await?; Ok(StatusCode::OK) } #[debug_handler] pub async fn set_ingredients_order( State(connection): State, Extension(context): Extension, ExtractRon(ron): ExtractRon, ) -> Result { check_user_rights_recipe_ingredients(&connection, &context.user, &ron.ids).await?; connection.set_ingredients_order(&ron.ids).await?; Ok(StatusCode::OK) }