Can get couple information
This commit is contained in:
		| @@ -1,7 +1,8 @@ | ||||
| use crate::controllers::members_controller::RequestDate; | ||||
| use crate::controllers::HttpResult; | ||||
| use crate::extractors::couple_extractor::FamilyAndCoupleInPath; | ||||
| use crate::extractors::family_extractor::FamilyInPath; | ||||
| use crate::models::{Couple, CoupleState, MemberID}; | ||||
| use crate::models::{Couple, CoupleState, MemberID, PhotoID}; | ||||
| use crate::services::{couples_service, members_service}; | ||||
| use actix_web::{web, HttpResponse}; | ||||
|  | ||||
| @@ -79,6 +80,22 @@ impl CoupleRequest { | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(serde::Serialize)] | ||||
| struct CoupleAPI { | ||||
|     #[serde(flatten)] | ||||
|     member: Couple, | ||||
|     signed_photo_id: Option<String>, | ||||
| } | ||||
|  | ||||
| impl CoupleAPI { | ||||
|     pub fn new(member: Couple) -> Self { | ||||
|         Self { | ||||
|             signed_photo_id: member.photo_id().as_ref().map(PhotoID::to_signed_hash), | ||||
|             member, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// Create a new couple | ||||
| pub async fn create(m: FamilyInPath, req: web::Json<CoupleRequest>) -> HttpResult { | ||||
|     let mut couple = couples_service::create(m.family_id()).await?; | ||||
| @@ -97,3 +114,19 @@ pub async fn create(m: FamilyInPath, req: web::Json<CoupleRequest>) -> HttpResul | ||||
|  | ||||
|     Ok(HttpResponse::Ok().json(couple)) | ||||
| } | ||||
|  | ||||
| /// Get the entire list of couples | ||||
| pub async fn get_all(m: FamilyInPath) -> HttpResult { | ||||
|     let couples = couples_service::get_all_of_family(m.family_id()) | ||||
|         .await? | ||||
|         .into_iter() | ||||
|         .map(CoupleAPI::new) | ||||
|         .collect::<Vec<_>>(); | ||||
|  | ||||
|     Ok(HttpResponse::Ok().json(couples)) | ||||
| } | ||||
|  | ||||
| /// Get a single couple entry | ||||
| pub async fn get_single(m: FamilyAndCoupleInPath) -> HttpResult { | ||||
|     Ok(HttpResponse::Ok().json(CoupleAPI::new(m.to_couple()))) | ||||
| } | ||||
|   | ||||
							
								
								
									
										79
									
								
								geneit_backend/src/extractors/couple_extractor.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								geneit_backend/src/extractors/couple_extractor.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| use crate::extractors::family_extractor::FamilyInPath; | ||||
| use crate::models::{Couple, CoupleID, FamilyID, Membership}; | ||||
| use crate::services::couples_service; | ||||
| use actix_web::dev::Payload; | ||||
| use actix_web::{FromRequest, HttpRequest}; | ||||
| use serde::Deserialize; | ||||
| use std::ops::Deref; | ||||
|  | ||||
| #[derive(thiserror::Error, Debug)] | ||||
| enum CoupleExtractorErr { | ||||
|     #[error("Couple {0:?} does not belong to family {1:?}!")] | ||||
|     CoupleNotInFamily(CoupleID, FamilyID), | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub struct FamilyAndCoupleInPath(Membership, Couple); | ||||
|  | ||||
| impl FamilyAndCoupleInPath { | ||||
|     async fn load_couple_from_path( | ||||
|         family: FamilyInPath, | ||||
|         couple_id: CoupleID, | ||||
|     ) -> anyhow::Result<Self> { | ||||
|         let couple = couples_service::get_by_id(couple_id).await?; | ||||
|         if couple.family_id() != family.family_id() { | ||||
|             return Err( | ||||
|                 CoupleExtractorErr::CoupleNotInFamily(couple.id(), family.family_id()).into(), | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         Ok(Self(family.into(), couple)) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl Deref for FamilyAndCoupleInPath { | ||||
|     type Target = Couple; | ||||
|  | ||||
|     fn deref(&self) -> &Self::Target { | ||||
|         &self.1 | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl FamilyAndCoupleInPath { | ||||
|     pub fn membership(&self) -> &Membership { | ||||
|         &self.0 | ||||
|     } | ||||
|  | ||||
|     pub fn to_couple(self) -> Couple { | ||||
|         self.1 | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[derive(Deserialize)] | ||||
| struct CoupleIDInPath { | ||||
|     couple_id: CoupleID, | ||||
| } | ||||
|  | ||||
| impl FromRequest for FamilyAndCoupleInPath { | ||||
|     type Error = actix_web::Error; | ||||
|     type Future = futures_util::future::LocalBoxFuture<'static, Result<Self, Self::Error>>; | ||||
|  | ||||
|     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 couple_id = | ||||
|                 actix_web::web::Path::<CoupleIDInPath>::from_request(&req, &mut Payload::None) | ||||
|                     .await? | ||||
|                     .couple_id; | ||||
|  | ||||
|             FamilyAndCoupleInPath::load_couple_from_path(family, couple_id) | ||||
|                 .await | ||||
|                 .map_err(|e| { | ||||
|                     log::error!("Failed to extract couple ID from URL! {}", e); | ||||
|                     actix_web::error::ErrorNotFound("Could not fetch couple information!") | ||||
|                 }) | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| @@ -1,2 +1,3 @@ | ||||
| pub mod couple_extractor; | ||||
| pub mod family_extractor; | ||||
| pub mod member_extractor; | ||||
|   | ||||
| @@ -167,6 +167,14 @@ async fn main() -> std::io::Result<()> { | ||||
|                 "/family/{id}/couple/create", | ||||
|                 web::post().to(couples_controller::create), | ||||
|             ) | ||||
|             .route( | ||||
|                 "/family/{id}/couples", | ||||
|                 web::get().to(couples_controller::get_all), | ||||
|             ) | ||||
|             .route( | ||||
|                 "/family/{id}/couple/{couple_id}", | ||||
|                 web::get().to(couples_controller::get_single), | ||||
|             ) | ||||
|             // Photos controller | ||||
|             .route( | ||||
|                 "/photo/{id}", | ||||
|   | ||||
		Reference in New Issue
	
	Block a user