server: Add routes to manage ingredients
This commit is contained in:
parent
14fbde812f
commit
c23da789a1
3 changed files with 146 additions and 1 deletions
|
|
@ -48,3 +48,33 @@ pub struct UserInfo {
|
|||
pub name: String,
|
||||
pub id: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct CreateIngredientRequest {
|
||||
pub name: String,
|
||||
pub unit: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct CreateIngredientResponse {
|
||||
pub id: i64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct IngredientInfo {
|
||||
pub name: String,
|
||||
pub unit: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct IngredientList {
|
||||
pub ingredients: HashMap<i64, IngredientInfo>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct EditIngredientRequest {
|
||||
pub name: Option<String>,
|
||||
pub unit: Option<String>,
|
||||
#[serde(default)]
|
||||
pub has_unit: bool,
|
||||
}
|
||||
|
|
|
|||
99
src/routes/ingredients.rs
Normal file
99
src/routes/ingredients.rs
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
use axum::{
|
||||
extract::{Path, State},
|
||||
Json,
|
||||
};
|
||||
|
||||
use api::{
|
||||
CreateIngredientRequest, CreateIngredientResponse, EditIngredientRequest, EmptyResponse,
|
||||
IngredientInfo, IngredientList,
|
||||
};
|
||||
use sea_orm::{prelude::*, ActiveValue};
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::{household::AuthorizedHousehold, AppState, JsonResult};
|
||||
use crate::entity::{ingredient, prelude::*};
|
||||
|
||||
pub(super) async fn create_ingredient(
|
||||
AuthorizedHousehold(household): AuthorizedHousehold,
|
||||
State(state): State<AppState>,
|
||||
Json(request): Json<CreateIngredientRequest>,
|
||||
) -> JsonResult<CreateIngredientResponse> {
|
||||
let model = ingredient::ActiveModel {
|
||||
household: ActiveValue::Set(household.id),
|
||||
name: ActiveValue::Set(request.name),
|
||||
unit: ActiveValue::Set(request.unit),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let ingredient = model.insert(&state.db).await?;
|
||||
|
||||
Ok(Json(CreateIngredientResponse { id: ingredient.id }))
|
||||
}
|
||||
|
||||
pub(super) async fn list_ingredients(
|
||||
AuthorizedHousehold(household): AuthorizedHousehold,
|
||||
State(state): State<AppState>,
|
||||
) -> JsonResult<IngredientList> {
|
||||
let ingredients = household.find_related(Ingredient).all(&state.db).await?;
|
||||
|
||||
Ok(Json(IngredientList {
|
||||
ingredients: ingredients
|
||||
.into_iter()
|
||||
.map(|m| {
|
||||
(
|
||||
m.id,
|
||||
IngredientInfo {
|
||||
name: m.name,
|
||||
unit: m.unit,
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
}))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct IngredientId {
|
||||
iid: i64,
|
||||
}
|
||||
|
||||
pub(super) async fn remove_ingredient(
|
||||
AuthorizedHousehold(household): AuthorizedHousehold,
|
||||
State(state): State<AppState>,
|
||||
Path(IngredientId { iid }): Path<IngredientId>,
|
||||
) -> JsonResult<EmptyResponse> {
|
||||
Ingredient::delete_by_id(iid)
|
||||
.filter(ingredient::Column::Household.eq(household.id))
|
||||
.exec(&state.db)
|
||||
.await?;
|
||||
|
||||
Ok(Json(EmptyResponse {}))
|
||||
}
|
||||
|
||||
pub(super) async fn edit_ingredient(
|
||||
AuthorizedHousehold(household): AuthorizedHousehold,
|
||||
State(state): State<AppState>,
|
||||
Path(IngredientId { iid }): Path<IngredientId>,
|
||||
Json(request): Json<EditIngredientRequest>,
|
||||
) -> JsonResult<EmptyResponse> {
|
||||
let Some(ingredient) = Ingredient::find_by_id(iid)
|
||||
.filter(ingredient::Column::Household.eq(household.id))
|
||||
.one(&state.db)
|
||||
.await? else {
|
||||
return Err(super::RouteError::RessourceNotFound);
|
||||
};
|
||||
|
||||
let mut ingredient: ingredient::ActiveModel = ingredient.into();
|
||||
|
||||
if let Some(name) = request.name {
|
||||
ingredient.name = ActiveValue::Set(name);
|
||||
}
|
||||
|
||||
if request.has_unit || request.unit.is_some() {
|
||||
ingredient.unit = ActiveValue::Set(request.unit);
|
||||
}
|
||||
|
||||
ingredient.update(&state.db).await?;
|
||||
|
||||
Ok(Json(EmptyResponse {}))
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ use axum::{
|
|||
HeaderValue, Method, StatusCode,
|
||||
},
|
||||
response::IntoResponse,
|
||||
routing::{get, post, put},
|
||||
routing::{delete, get, post, put},
|
||||
Json, Router, TypedHeader,
|
||||
};
|
||||
use jwt_simple::prelude::*;
|
||||
|
|
@ -22,6 +22,7 @@ use tower_http::cors::{self, AllowOrigin, CorsLayer};
|
|||
use crate::entity::{prelude::*, user};
|
||||
|
||||
mod household;
|
||||
mod ingredients;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
enum RouteError {
|
||||
|
|
@ -39,6 +40,8 @@ enum RouteError {
|
|||
Unauthorized,
|
||||
#[error("Could not fetch required value from path")]
|
||||
PathRejection(#[from] axum::extract::rejection::PathRejection),
|
||||
#[error("The supplied ressource does not exist")]
|
||||
RessourceNotFound,
|
||||
}
|
||||
|
||||
impl IntoResponse for RouteError {
|
||||
|
|
@ -60,6 +63,7 @@ impl IntoResponse for RouteError {
|
|||
"Unauthorized to access this ressource",
|
||||
)
|
||||
.into_response(),
|
||||
RouteError::RessourceNotFound => StatusCode::NOT_FOUND.into_response(),
|
||||
e => {
|
||||
tracing::error!("Internal error: {e:?}");
|
||||
StatusCode::INTERNAL_SERVER_ERROR.into_response()
|
||||
|
|
@ -186,4 +190,16 @@ pub(crate) fn router(api_allowed: Option<HeaderValue>) -> Router<AppState> {
|
|||
.delete(household::leave)
|
||||
.layer(mk_service(vec![Method::PUT, Method::DELETE])),
|
||||
)
|
||||
.route(
|
||||
"/household/:house_id/ingredients/:iid",
|
||||
delete(ingredients::remove_ingredient)
|
||||
.patch(ingredients::edit_ingredient)
|
||||
.layer(mk_service(vec![Method::DELETE, Method::PATCH])),
|
||||
)
|
||||
.route(
|
||||
"/household/:house_id/ingredients",
|
||||
post(ingredients::create_ingredient)
|
||||
.get(ingredients::list_ingredients)
|
||||
.layer(mk_service(vec![Method::GET, Method::POST])),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue