use axum::Json;
use axum::extract::{Path, Query, State};
use serde::Deserialize;
use serde_json::Value;
use crate::admin;
use crate::webadmin::AdminState;
use crate::webadmin::error::AdminError;
use crate::webadmin::handlers::paging::{PageParams, page_envelope};
use crate::webadmin::handlers::params::{bad_status, empty_is_absent};
use crate::webadmin::session::Authenticated;
use acme_proxy_store::status::UnknownStatus;
use acme_proxy_store::status::UpstreamOrderStatus;
use acme_proxy_store::upstream_order::UpstreamOrder;
use acme_proxy_store::upstream_order::UpstreamOrderQuery;
#[derive(Debug, Deserialize, Default)]
pub struct UpstreamOrderListParams {
#[serde(default, deserialize_with = "empty_is_absent")]
pub profile: Option<String>,
#[serde(default, deserialize_with = "empty_is_absent")]
pub status: Option<String>,
pub limit: Option<i64>,
pub offset: Option<i64>,
}
impl UpstreamOrderListParams {
pub fn parsed_status(&self) -> Result<Option<UpstreamOrderStatus>, UnknownStatus> {
self.status.as_deref().map(str::parse).transpose()
}
}
pub(crate) fn upstream_order_query(
params: &UpstreamOrderListParams,
page: crate::webadmin::handlers::paging::Page,
) -> Result<UpstreamOrderQuery, AdminError> {
Ok(UpstreamOrderQuery {
profile: params.profile.clone(),
status: params.parsed_status().map_err(bad_status)?,
limit: page.limit,
offset: page.offset,
})
}
pub async fn list_upstream_orders(
State(state): State<AdminState>,
Query(params): Query<UpstreamOrderListParams>,
_auth: Authenticated,
) -> Result<Json<Value>, AdminError> {
let page = PageParams::from(params.limit, params.offset).resolve(&state.config);
let query = upstream_order_query(¶ms, page)?;
let (rows, total) = UpstreamOrder::search(&query, &state.database).await?;
let items = rows.iter().map(admin::render_upstream_order_json).collect();
Ok(Json(page_envelope(items, total, page)))
}
pub async fn get_upstream_order(
State(state): State<AdminState>,
Path(id): Path<String>,
_auth: Authenticated,
) -> Result<Json<Value>, AdminError> {
let detail = admin::load_upstream_order_detail(&id, state.database.clone())
.await?
.ok_or_else(|| AdminError::not_found(format!("no upstream order for local order {id}")))?;
Ok(Json(admin::render_upstream_order_detail_json(&detail)))
}