use std::sync::Arc; use axum::{ Json, extract::{Path, State}, http::StatusCode, response::IntoResponse, }; use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::routes::api::{ApiRouter, AppError}; use crate::service::proxy::limit_zone::{ CreateLimitZoneParams, LimitZoneService, UpdateLimitZoneParams, }; use crate::service::proxy::types::LimitZoneConfig; #[derive(Serialize)] pub(crate) struct LimitZoneResponse { pub id: Uuid, pub name: String, pub key: String, pub rate: String, pub override_of_id: Option, } impl From for LimitZoneResponse { fn from(c: LimitZoneConfig) -> Self { Self { id: c.id, name: c.name, key: c.key, rate: c.rate, override_of_id: c.override_of_id, } } } #[derive(Deserialize)] pub(crate) struct CreateLimitZoneRequest { pub name: String, pub key: String, pub rate: String, pub override_of_id: Option, } impl From for CreateLimitZoneParams { fn from(r: CreateLimitZoneRequest) -> Self { Self { name: r.name, key: r.key, rate: r.rate, override_of_id: r.override_of_id, } } } #[derive(Deserialize)] pub(crate) struct UpdateLimitZoneRequest { pub name: Option, pub key: Option, pub rate: Option, pub override_of_id: Option>, } impl From for UpdateLimitZoneParams { fn from(r: UpdateLimitZoneRequest) -> Self { Self { name: r.name, key: r.key, rate: r.rate, override_of_id: r.override_of_id, } } } async fn list_limit_zones( State(svc): State>, ) -> Result>, AppError> { let zones = svc.list().await?; Ok(Json(zones.into_iter().map(Into::into).collect())) } async fn create_limit_zone( State(svc): State>, Json(body): Json, ) -> Result { let zone = svc.create(body.into()).await?; Ok((StatusCode::CREATED, Json(LimitZoneResponse::from(zone)))) } async fn get_limit_zone( State(svc): State>, Path(id): Path, ) -> Result, AppError> { let zone = svc.get(id).await?; Ok(Json(zone.into())) } async fn update_limit_zone( State(svc): State>, Path(id): Path, Json(body): Json, ) -> Result, AppError> { let zone = svc.update(id, body.into()).await?; Ok(Json(zone.into())) } async fn delete_limit_zone( State(svc): State>, Path(id): Path, ) -> Result { let deleted = svc.delete(id).await?; if deleted { Ok((StatusCode::NO_CONTENT,)) } else { Err(AppError::NotFound) } } pub(super) fn routes() -> ApiRouter { ApiRouter::new() .route( "/limit-zones", axum::routing::get(list_limit_zones).post(create_limit_zone), ) .route( "/limit-zones/{id}", axum::routing::get(get_limit_zone) .put(update_limit_zone) .delete(delete_limit_zone), ) }