use crate::constants::StaticConstraints; use crate::controllers::HttpResult; use crate::services::login_token_service::LoginToken; use crate::services::rate_limiter_service::RatedAction; use crate::services::{families_service, rate_limiter_service}; use actix_remote_ip::RemoteIP; use actix_web::{web, HttpResponse}; #[derive(Debug, serde::Deserialize)] pub struct CreateFamilyReq { name: String, } /// Create a new family pub async fn create(req: web::Json, token: LoginToken) -> HttpResult { if !StaticConstraints::default() .family_name_len .validate(&req.name) { return Ok(HttpResponse::BadRequest().body("Invalid family name!")); } let family = families_service::create(&req.name, token.user_id).await?; Ok(HttpResponse::Created().json(family)) } #[derive(Debug, serde::Deserialize)] pub struct JoinFamilyReq { code: String, } /// Join a family pub async fn join( remote_ip: RemoteIP, req: web::Json, token: LoginToken, ) -> HttpResult { // Rate limiting if rate_limiter_service::should_block_action(remote_ip.0, RatedAction::JoinFamily).await? { return Ok(HttpResponse::TooManyRequests().finish()); } rate_limiter_service::record_action(remote_ip.0, RatedAction::JoinFamily).await?; let family = match families_service::get_by_invitation_code(&req.code).await { Ok(f) => f, Err(e) => { log::error!("Could not find family by invitation code! {e}"); return Ok(HttpResponse::NotFound().finish()); } }; if families_service::is_member(family.id(), token.user_id).await? { log::error!( "Could not add {:?} to family {:?} because it is already a member of the family!", token.user_id, family.id() ); return Ok(HttpResponse::Conflict().finish()); } families_service::add_member(family.id(), token.user_id, false).await?; Ok(HttpResponse::Accepted().finish()) }