diff --git a/geneit_backend/src/controllers/accommodations_list_controller.rs b/geneit_backend/src/controllers/accommodations_list_controller.rs index 06cabc7..44ffe8b 100644 --- a/geneit_backend/src/controllers/accommodations_list_controller.rs +++ b/geneit_backend/src/controllers/accommodations_list_controller.rs @@ -1,9 +1,9 @@ use crate::constants::StaticConstraints; use crate::controllers::HttpResult; +use crate::extractors::accommodation_extractor::FamilyAndAccommodationInPath; use crate::extractors::family_extractor::FamilyInPathWithAdminMembership; -use crate::models::{Accommodation, FamilyID}; +use crate::models::Accommodation; use crate::services::accommodations_list_service; -use crate::services::couples_service::{delete, get_all_of_family}; use actix_web::{web, HttpResponse}; #[derive(thiserror::Error, Debug)] @@ -66,10 +66,8 @@ pub async fn create( Ok(HttpResponse::Ok().json(accommodation)) } -/// Delete all the accommodations of a family -pub async fn delete_all_family(family_id: FamilyID) -> anyhow::Result<()> { - for mut m in get_all_of_family(family_id).await? { - delete(&mut m).await?; - } - Ok(()) +/// Delete an accommodation +pub async fn delete(m: FamilyAndAccommodationInPath) -> HttpResult { + accommodations_list_service::delete(&mut m.to_accommodation()).await?; + Ok(HttpResponse::Ok().finish()) } diff --git a/geneit_backend/src/extractors/accommodation_extractor.rs b/geneit_backend/src/extractors/accommodation_extractor.rs new file mode 100644 index 0000000..76bfca7 --- /dev/null +++ b/geneit_backend/src/extractors/accommodation_extractor.rs @@ -0,0 +1,83 @@ +use crate::extractors::family_extractor::FamilyInPath; +use crate::models::{Accommodation, AccommodationID, FamilyID, Membership}; +use crate::services::accommodations_list_service; +use actix_web::dev::Payload; +use actix_web::{FromRequest, HttpRequest}; +use serde::Deserialize; +use std::ops::Deref; + +#[derive(thiserror::Error, Debug)] +enum AccommodationExtractorErr { + #[error("Accommodation {0:?} does not belong to family {1:?}!")] + AccommodationNotInFamily(AccommodationID, FamilyID), +} + +#[derive(Debug)] +pub struct FamilyAndAccommodationInPath(Membership, Accommodation); + +impl FamilyAndAccommodationInPath { + async fn load_accommodation_from_path( + family: FamilyInPath, + accommodation_id: AccommodationID, + ) -> anyhow::Result { + let accommodation = accommodations_list_service::get_by_id(accommodation_id).await?; + if accommodation.family_id() != family.family_id() { + return Err(AccommodationExtractorErr::AccommodationNotInFamily( + accommodation.id(), + family.family_id(), + ) + .into()); + } + + Ok(Self(family.into(), accommodation)) + } +} + +impl Deref for FamilyAndAccommodationInPath { + type Target = Accommodation; + + fn deref(&self) -> &Self::Target { + &self.1 + } +} + +impl FamilyAndAccommodationInPath { + pub fn membership(&self) -> &Membership { + &self.0 + } + + pub fn to_accommodation(self) -> Accommodation { + self.1 + } +} + +#[derive(Deserialize)] +struct AccommodationIDInPath { + accommodation_id: AccommodationID, +} + +impl FromRequest for FamilyAndAccommodationInPath { + type Error = actix_web::Error; + type Future = futures_util::future::LocalBoxFuture<'static, Result>; + + fn from_request(req: &HttpRequest, _payload: &mut Payload) -> Self::Future { + let req = req.clone(); + Box::pin(async move { + let family = FamilyInPath::extract(&req).await?; + + let accommodation_id = actix_web::web::Path::::from_request( + &req, + &mut Payload::None, + ) + .await? + .accommodation_id; + + FamilyAndAccommodationInPath::load_accommodation_from_path(family, accommodation_id) + .await + .map_err(|e| { + log::error!("Failed to extract accommodation ID from URL! {}", e); + actix_web::error::ErrorNotFound("Could not fetch accommodation information!") + }) + }) + } +} diff --git a/geneit_backend/src/extractors/mod.rs b/geneit_backend/src/extractors/mod.rs index 0cafc82..8859615 100644 --- a/geneit_backend/src/extractors/mod.rs +++ b/geneit_backend/src/extractors/mod.rs @@ -1,3 +1,4 @@ +pub mod accommodation_extractor; pub mod couple_extractor; pub mod family_extractor; pub mod member_extractor; diff --git a/geneit_backend/src/main.rs b/geneit_backend/src/main.rs index e44f561..002334d 100644 --- a/geneit_backend/src/main.rs +++ b/geneit_backend/src/main.rs @@ -211,8 +211,12 @@ async fn main() -> std::io::Result<()> { web::post().to(accommodations_list_controller::create), ) // TODO : update - // TODO : delete + .route( + "/family/{id}/accommodations/list/{accommodation_id}", + web::delete().to(accommodations_list_controller::delete), + ) // TODO : list + // TODO : get single // [ACCOMODATIONS] Reservations controller // TODO : create // TODO : update diff --git a/geneit_backend/src/models.rs b/geneit_backend/src/models.rs index 7055c4f..498a10d 100644 --- a/geneit_backend/src/models.rs +++ b/geneit_backend/src/models.rs @@ -463,6 +463,10 @@ impl Accommodation { pub fn id(&self) -> AccommodationID { AccommodationID(self.id) } + + pub fn family_id(&self) -> FamilyID { + FamilyID(self.family_id) + } } #[derive(Insertable)]