116 lines
4.0 KiB
Rust
116 lines
4.0 KiB
Rust
use crate::constants::StaticConstraints;
|
|
use crate::controllers::HttpResult;
|
|
use crate::extractors::accommodation_extractor::FamilyAndAccommodationInPath;
|
|
use crate::extractors::family_extractor::{FamilyInPath, FamilyInPathWithAdminMembership};
|
|
use crate::models::Accommodation;
|
|
use crate::services::accommodations_list_service;
|
|
use actix_web::{web, HttpResponse};
|
|
|
|
#[derive(thiserror::Error, Debug)]
|
|
enum AccommodationListControllerErr {
|
|
#[error("Invalid name length!")]
|
|
InvalidNameLength,
|
|
#[error("Invalid description length!")]
|
|
InvalidDescriptionLength,
|
|
#[error("Malformed color!")]
|
|
MalformedColor,
|
|
}
|
|
|
|
#[derive(serde::Deserialize, Clone)]
|
|
pub struct AccommodationRequest {
|
|
pub name: String,
|
|
pub need_validation: bool,
|
|
pub description: Option<String>,
|
|
pub color: Option<String>,
|
|
pub open_to_reservations: bool,
|
|
}
|
|
|
|
impl AccommodationRequest {
|
|
pub async fn to_accommodation(self, accommodation: &mut Accommodation) -> anyhow::Result<()> {
|
|
let c = StaticConstraints::default();
|
|
|
|
if !c.accommodation_name_len.validate(&self.name) {
|
|
return Err(AccommodationListControllerErr::InvalidNameLength.into());
|
|
}
|
|
accommodation.name = self.name;
|
|
|
|
if let Some(d) = &self.description {
|
|
if !c.accommodation_description_len.validate(d) {
|
|
return Err(AccommodationListControllerErr::InvalidDescriptionLength.into());
|
|
}
|
|
}
|
|
accommodation.description.clone_from(&self.description);
|
|
|
|
if let Some(c) = &self.color {
|
|
if !lazy_regex::regex!("[a-fA-F0-9]{6}").is_match(c) {
|
|
return Err(AccommodationListControllerErr::MalformedColor.into());
|
|
}
|
|
}
|
|
accommodation.color.clone_from(&self.color);
|
|
|
|
accommodation.need_validation = self.need_validation;
|
|
accommodation.open_to_reservations = self.open_to_reservations;
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
/// Create a new accommodation
|
|
pub async fn create(
|
|
m: FamilyInPathWithAdminMembership,
|
|
req: web::Json<AccommodationRequest>,
|
|
) -> HttpResult {
|
|
let mut accommodation = accommodations_list_service::create(m.family_id()).await?;
|
|
|
|
if let Err(e) = req.0.to_accommodation(&mut accommodation).await {
|
|
log::error!("Failed to apply accommodation information! {e}");
|
|
accommodations_list_service::delete(&mut accommodation).await?;
|
|
return Ok(HttpResponse::BadRequest().body(e.to_string()));
|
|
}
|
|
|
|
if let Err(e) = accommodations_list_service::update(&mut accommodation).await {
|
|
log::error!("Failed to update accommodation information! {e}");
|
|
accommodations_list_service::delete(&mut accommodation).await?;
|
|
return Ok(HttpResponse::InternalServerError().finish());
|
|
}
|
|
|
|
Ok(HttpResponse::Ok().json(accommodation))
|
|
}
|
|
|
|
/// Get the full list of accommodations
|
|
pub async fn get_full_list(m: FamilyInPath) -> HttpResult {
|
|
Ok(HttpResponse::Ok()
|
|
.json(accommodations_list_service::get_all_of_family(m.family_id()).await?))
|
|
}
|
|
|
|
/// Get the information of a single accommodation
|
|
pub async fn get_single(m: FamilyAndAccommodationInPath) -> HttpResult {
|
|
Ok(HttpResponse::Ok().json(m.to_accommodation()))
|
|
}
|
|
|
|
/// Update an accommodation
|
|
pub async fn update(
|
|
m: FamilyAndAccommodationInPath,
|
|
req: web::Json<AccommodationRequest>,
|
|
_admin: FamilyInPathWithAdminMembership,
|
|
) -> HttpResult {
|
|
let mut accommodation = m.to_accommodation();
|
|
|
|
if let Err(e) = req.0.to_accommodation(&mut accommodation).await {
|
|
log::error!("Failed to parse accommodation information! {e}");
|
|
return Ok(HttpResponse::BadRequest().body(e.to_string()));
|
|
}
|
|
|
|
accommodations_list_service::update(&mut accommodation).await?;
|
|
|
|
Ok(HttpResponse::Accepted().finish())
|
|
}
|
|
|
|
/// Delete an accommodation
|
|
pub async fn delete(
|
|
m: FamilyAndAccommodationInPath,
|
|
_admin: FamilyInPathWithAdminMembership,
|
|
) -> HttpResult {
|
|
accommodations_list_service::delete(&mut m.to_accommodation()).await?;
|
|
Ok(HttpResponse::Ok().finish())
|
|
}
|