GeneIT/geneit_backend/src/controllers/accommodations_list_controller.rs
Pierre HUBERT 48a43bf190
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
Fix build issue on newer Rust versions
2024-08-22 07:05:42 +00:00

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())
}