diff --git a/src/app/household.rs b/src/app/household.rs index c44fbaf..d29e940 100644 --- a/src/app/household.rs +++ b/src/app/household.rs @@ -12,11 +12,14 @@ use serde::{Deserialize, Serialize}; use tower_sessions::Session; use uuid::Uuid; -use crate::entity::{household, household_members, prelude::*}; +use crate::entity::{household, household_members, prelude::*, user}; use super::{base_page_with_head, AppState, AuthenticatedUser, RedirectOrError, RouteError}; -pub(super) struct CurrentHousehold(pub household::Model); +pub(super) struct CurrentHousehold { + pub(super) user: user::Model, + pub(super) household: household::Model, +} pub(super) fn routes() -> Router { Router::new() @@ -44,19 +47,30 @@ where .await .map_err(|_| RouteError::SessionExtract)?; - let id: Uuid = session + let user_id: Uuid = session + .get("id") + .await + .map_err(RouteError::from)? + .ok_or_else(|| Redirect::to("/login"))?; + + let household_id: Uuid = session .get("household") .await .map_err(RouteError::from)? .ok_or_else(|| Redirect::to("/household/select"))?; - Ok(Self( - Household::find_by_id(id) - .one(&app_state.db) - .await - .map_err(RouteError::from)? - .unwrap(), - )) + let (household, user) = Household::find_by_id(household_id) + .find_also_related(user::Entity) + .filter(user::Column::Id.eq(user_id)) + .one(&app_state.db) + .await + .map_err(RouteError::from)? + .ok_or_else(|| RouteError::RessourceNotFound)?; + + Ok(CurrentHousehold { + household, + user: user.ok_or_else(|| RouteError::RessourceNotFound)?, + }) } } @@ -147,11 +161,11 @@ struct HouseholdName { } async fn rename( - household: CurrentHousehold, + current: CurrentHousehold, state: State, Form(form): Form, ) -> Result { - let mut household: household::ActiveModel = household.0.into(); + let mut household: household::ActiveModel = current.household.into(); household.name = ActiveValue::Set(form.name); @@ -218,8 +232,7 @@ async fn delete_household( } async fn leave( - household: CurrentHousehold, - user: AuthenticatedUser, + current: CurrentHousehold, session: Session, state: State, ) -> Result { @@ -227,14 +240,13 @@ async fn leave( .db .transaction(|txn| { Box::pin(async move { - HouseholdMembers::delete_by_id((household.0.id, user.model.id)) + HouseholdMembers::delete_by_id((current.household.id, current.user.id)) .exec(txn) .await?; - let Some(household) = Household::find_by_id(household.0.id) - .one(txn) - .await? else { - return Err(RouteError::InvalidRequest("No such household".into())); + let Some(household) = Household::find_by_id(current.household.id).one(txn).await? + else { + return Err(RouteError::InvalidRequest("No such household".into())); }; let member_count = household.find_related(User).count(txn).await?; diff --git a/src/app/ingredients.rs b/src/app/ingredients.rs index 0978997..5b3e512 100644 --- a/src/app/ingredients.rs +++ b/src/app/ingredients.rs @@ -14,7 +14,7 @@ use super::{ confirm_danger_modal, error_alert, household::CurrentHousehold, sidebar::{sidebar, SidebarLocation}, - AppState, AuthenticatedUser, RouteError, + AppState, RouteError, }; pub(super) fn routes() -> Router { @@ -118,12 +118,11 @@ fn render_ingredients(error: Option, ingredient_list: &[ingredient::Mode async fn ingredients_view( error: Option, - household: &CurrentHousehold, - user: &AuthenticatedUser, + current: &CurrentHousehold, db: &DatabaseConnection, ) -> Result { - let list = household - .0 + let list = current + .household .find_related(Ingredient) .order_by_asc(ingredient::Column::Id) .all(db) @@ -131,27 +130,25 @@ async fn ingredients_view( Ok(sidebar( SidebarLocation::Ingredients, - household, - user, + current, render_ingredients(error, &list), )) } async fn ingredients( state: State, - user: AuthenticatedUser, - household: CurrentHousehold, + current: CurrentHousehold, ) -> Result { - ingredients_view(None, &household, &user, &state.db).await + ingredients_view(None, ¤t, &state.db).await } async fn do_ingredient_delete( - household: &CurrentHousehold, + current: &CurrentHousehold, db: &DatabaseConnection, id: i64, ) -> Result, RouteError> { - if household - .0 + if current + .household .find_related(Ingredient) .filter(ingredient::Column::Id.eq(id)) .count(db) @@ -182,14 +179,12 @@ async fn do_ingredient_delete( async fn delete_ingredient( state: State, - user: AuthenticatedUser, - household: CurrentHousehold, + current: CurrentHousehold, ig: Path, ) -> Result { ingredients_view( - do_ingredient_delete(&household, &state.db, ig.0).await?, - &household, - &user, + do_ingredient_delete(¤t, &state.db, ig.0).await?, + ¤t, &state.db, ) .await @@ -203,12 +198,12 @@ struct IngredientDesc { async fn edit_ingredient( state: State, - household: CurrentHousehold, + current: CurrentHousehold, ig: Path, form: Form, ) -> Result { - let ingredient = household - .0 + let ingredient = current + .household .find_related(Ingredient) .filter(ingredient::Column::Id.eq(ig.0)) .one(&state.db) @@ -228,7 +223,7 @@ async fn edit_ingredient( async fn add_ingredient( state: State, - household: CurrentHousehold, + current: CurrentHousehold, form: Form, ) -> Result { let mut ingredient = ingredient::ActiveModel::new(); @@ -237,7 +232,7 @@ async fn add_ingredient( true => None, false => Some(form.0.unit), }); - ingredient.household = ActiveValue::Set(household.0.id); + ingredient.household = ActiveValue::Set(current.household.id); ingredient.insert(&state.db).await?; diff --git a/src/app/mod.rs b/src/app/mod.rs index 87fac55..4948280 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -345,13 +345,12 @@ fn confirm_danger_modal(id: &str, inner: &str, action: &str, title: &str) -> Mar } } -async fn index(user: AuthenticatedUser, household: CurrentHousehold) -> Markup { +async fn index(current: CurrentHousehold) -> Markup { sidebar::sidebar( SidebarLocation::Home, - &household, - &user, + ¤t, html! { - "Hello world in " (household.0.name) "!" + "Hello world in " (current.household.name) "!" }, ) } diff --git a/src/app/recipe.rs b/src/app/recipe.rs index 48ec47e..1e866ec 100644 --- a/src/app/recipe.rs +++ b/src/app/recipe.rs @@ -17,7 +17,7 @@ use super::{ base_page, household::CurrentHousehold, sidebar::{sidebar, SidebarLocation}, - AppState, AuthenticatedUser, RouteError, + AppState, RouteError, }; pub(super) fn routes() -> Router { @@ -72,11 +72,10 @@ fn recipe_list(recipes: &[recipe::Model], household: Option) -> Markup { async fn list_recipes( state: State, - user: AuthenticatedUser, - household: CurrentHousehold, + current: CurrentHousehold, ) -> Result { - let recipes = household - .0 + let recipes = current + .household .find_related(Recipe) .order_by_asc(recipe::Column::Name) .all(&state.db) @@ -84,8 +83,7 @@ async fn list_recipes( Ok(sidebar( SidebarLocation::RecipeList, - &household, - &user, + ¤t, recipe_list(&recipes, None), )) } @@ -222,12 +220,11 @@ async fn recipe_view( async fn view_recipe( state: State, - user: AuthenticatedUser, - household: CurrentHousehold, + current: CurrentHousehold, id: Path, ) -> Result { - let recipe = household - .0 + let recipe = current + .household .find_related(Recipe) .filter(recipe::Column::Id.eq(id.0)) .one(&state.db) @@ -236,9 +233,8 @@ async fn view_recipe( Ok(sidebar( SidebarLocation::RecipeList, - &household, - &user, - recipe_view(&recipe, household.0.id, true, &state.db).await?, + ¤t, + recipe_view(&recipe, current.household.id, true, &state.db).await?, )) } @@ -290,12 +286,11 @@ struct CreateAddIngredient { async fn create_recipe_ingredient( state: State, - _user: AuthenticatedUser, - household: CurrentHousehold, + current: CurrentHousehold, Form(form): Form, ) -> Result { let ingredient = ingredient::ActiveModel { - household: sea_orm::ActiveValue::Set(household.0.id), + household: sea_orm::ActiveValue::Set(current.household.id), name: sea_orm::ActiveValue::Set(form.name), unit: sea_orm::ActiveValue::Set(form.unit), id: sea_orm::ActiveValue::NotSet, @@ -363,9 +358,13 @@ fn create_ingredient_modal() -> Markup { async fn ingredient_list( state: &State, - household: &CurrentHousehold, + current: &CurrentHousehold, ) -> Result { - let list = household.0.find_related(Ingredient).all(&state.db).await?; + let list = current + .household + .find_related(Ingredient) + .all(&state.db) + .await?; Ok(html! { @for ig in list { @@ -376,10 +375,10 @@ async fn ingredient_list( async fn select_ingredient( state: &State, - household: &CurrentHousehold, + current: &CurrentHousehold, extra_controls: Markup, ) -> Result { - let ingredients = ingredient_list(state, household).await?; + let ingredients = ingredient_list(state, current).await?; Ok(html! { .d-flex.flex-column.align-items-start { @@ -469,8 +468,7 @@ igAdd.addEventListener("click", function(event) { async fn do_create_recipe( state: State, - _user: AuthenticatedUser, - household: CurrentHousehold, + current: CurrentHousehold, Form(form): Form>, ) -> Result { let mut name = None; @@ -527,7 +525,7 @@ async fn do_create_recipe( person_count: extract("person_count", person_count)?, ranking: extract("rating", rating)?, steps: extract("steps", steps)?, - household: sea_orm::ActiveValue::Set(household.0.id), + household: sea_orm::ActiveValue::Set(current.household.id), } .insert(tx) .await?; @@ -552,8 +550,7 @@ async fn do_create_recipe( async fn create_recipe( state: State, - user: AuthenticatedUser, - household: CurrentHousehold, + current: CurrentHousehold, ) -> Result { let create_ig = html! { button .btn.btn-primary @@ -564,8 +561,7 @@ async fn create_recipe( Ok(sidebar( SidebarLocation::RecipeCreator, - &household, - &user, + ¤t, html! { script { (PreEscaped(r#" function removeIngredient (self) { @@ -603,7 +599,7 @@ function removeIngredient (self) { .d-flex.flex-column.justify-content-start { h2 { "Ingredients" } - (select_ingredient(&state, &household, create_ig).await?) + (select_ingredient(&state, ¤t, create_ig).await?) ul .list-group.list-group-flush.text-start #recipeIngredients {} } diff --git a/src/app/sidebar.rs b/src/app/sidebar.rs index e567f32..b696fb0 100644 --- a/src/app/sidebar.rs +++ b/src/app/sidebar.rs @@ -1,6 +1,6 @@ use maud::{html, Markup}; -use super::{base_page, confirm_danger_modal, household::CurrentHousehold, AuthenticatedUser}; +use super::{base_page, confirm_danger_modal, household::CurrentHousehold}; #[derive(Clone, Copy, PartialEq)] pub(super) enum SidebarLocation { @@ -80,9 +80,8 @@ fn rename_hs_modal(current: &str) -> Markup { } pub(super) fn sidebar( - current: SidebarLocation, - household: &CurrentHousehold, - user: &AuthenticatedUser, + current_page: SidebarLocation, + current: &CurrentHousehold, inner: Markup, ) -> Markup { let entries = &[ @@ -118,7 +117,7 @@ pub(super) fn sidebar( li .nav-item."w-100" { a href=(entry.location.to()) class={"nav-link text-white" ( - (entry.location == current).then_some(" active").unwrap_or("") + (entry.location == current_page).then_some(" active").unwrap_or("") )} { i class={"fs-4 " (entry.icon)} {} span ."ms-2".d-none.d-sm-inline { (entry.label) } @@ -129,17 +128,17 @@ pub(super) fn sidebar( hr ."w-100"; (confirm_danger_modal( "leaveModal", - &format!("Are you sure you want to leave the household {}", household.0.name), + &format!("Are you sure you want to leave the household {}", current.household.name), "/household/leave", "Leave Household", )) - (rename_hs_modal(&household.0.name)) + (rename_hs_modal(¤t.household.name)) .dropdown { a href="#" "data-bs-toggle"="dropdown" "aria-expanded"="false" .d-flex.align-items-center.text-white.text-decoration-none.dropdown-toggle { i ."fs-4".bi-house-door-fill {} strong ."ms-2".d-none.d-sm-inline { - (household.0.name) " (" (user.model.name) ")" + (current.household.name) " (" (current.user.name) ")" } } ul .dropdown-menu {