acme_proxy/webadmin/handlers/
misc.rs1use axum::Json;
4use axum::extract::State;
5use serde::Deserialize;
6use serde_json::{Value, json};
7use std::time::Duration;
8
9use crate::admin;
10use crate::sqlite::nonce::Nonce;
11use crate::webadmin::AdminState;
12use crate::webadmin::error::AdminError;
13use crate::webadmin::session::{Authenticated, AuthenticatedWrite};
14
15#[derive(Debug, Deserialize, Default)]
16pub struct CleanupRequest {
17 #[serde(rename = "ttlSeconds")]
19 pub ttl_seconds: Option<u64>,
20}
21
22pub async fn get_nonces(
27 State(state): State<AdminState>,
28 _auth: Authenticated,
29) -> Result<Json<Value>, AdminError> {
30 let count = Nonce::count(&state.database).await?;
31 Ok(Json(admin::render_nonce_stats_json(
32 count,
33 state.config.nonce.ttl_seconds,
34 )))
35}
36
37pub async fn cleanup_nonces(
39 State(state): State<AdminState>,
40 AuthenticatedWrite(auth): AuthenticatedWrite,
41 body: Option<Json<CleanupRequest>>,
42) -> Result<Json<Value>, AdminError> {
43 let seconds = body
44 .and_then(|Json(body)| body.ttl_seconds)
45 .unwrap_or(state.config.nonce.ttl_seconds);
46
47 let removed =
48 admin::cleanup_nonces(Duration::from_secs(seconds), state.database.clone()).await?;
49 tracing::info!(event = "admin_nonces_cleaned",
50 outcome = "success",
51 surface = "api",
52 rows_removed = removed,
53 ttl_seconds = seconds,
54 username = %auth.user.username);
55 Ok(Json(json!({ "removed": removed })))
56}
57
58pub async fn list_profiles(State(state): State<AdminState>, _auth: Authenticated) -> Json<Value> {
64 Json(Value::Array(profile_rows(&state)))
65}
66
67pub(crate) fn profile_rows(state: &AdminState) -> Vec<Value> {
73 let mut names: Vec<&String> = state.profiles.keys().collect();
74 names.sort();
75
76 names
77 .into_iter()
78 .filter_map(|name| state.profiles.get(name))
79 .map(|profile| profile_row(profile))
80 .collect()
81}
82
83pub(crate) fn profile_row(profile: &crate::Profile) -> Value {
95 admin::render_profile_json(&admin::ProfileSummary::mounted(profile))
96}