use axum::Json;
use axum::extract::State;
use serde::Deserialize;
use serde_json::{Value, json};
use std::time::Duration;
use crate::admin;
use crate::sqlite::nonce::Nonce;
use crate::webadmin::AdminState;
use crate::webadmin::error::AdminError;
use crate::webadmin::session::{Authenticated, AuthenticatedWrite};
#[derive(Debug, Deserialize, Default)]
pub struct CleanupRequest {
#[serde(rename = "ttlSeconds")]
pub ttl_seconds: Option<u64>,
}
pub async fn get_nonces(
State(state): State<AdminState>,
_auth: Authenticated,
) -> Result<Json<Value>, AdminError> {
let count = Nonce::count(&state.database).await?;
Ok(Json(admin::render_nonce_stats_json(
count,
state.config.nonce.ttl_seconds,
)))
}
pub async fn cleanup_nonces(
State(state): State<AdminState>,
AuthenticatedWrite(auth): AuthenticatedWrite,
request_context: crate::audit::RequestContext,
body: Option<Json<CleanupRequest>>,
) -> Result<Json<Value>, AdminError> {
let seconds = body
.and_then(|Json(body)| body.ttl_seconds)
.unwrap_or(state.config.nonce.ttl_seconds);
let removed =
admin::cleanup_nonces(Duration::from_secs(seconds), state.database.clone()).await?;
if removed > 0 {
state
.record_admin_action(&request_context, &auth.user.username, |actor, client| {
crate::audit::admin::nonce_cleanup_completed(actor, client, removed)
})
.await;
}
tracing::info!(event = "admin_nonces_cleaned",
outcome = "success",
surface = "api",
rows_removed = removed,
ttl_seconds = seconds,
username = %auth.user.username);
Ok(Json(json!({ "removed": removed })))
}
pub async fn list_profiles(State(state): State<AdminState>, _auth: Authenticated) -> Json<Value> {
Json(Value::Array(profile_rows(&state)))
}
pub(crate) fn profile_rows(state: &AdminState) -> Vec<Value> {
let mut names: Vec<&String> = state.profiles.keys().collect();
names.sort();
names
.into_iter()
.filter_map(|name| state.profiles.get(name))
.map(|profile| profile_row(profile))
.collect()
}
pub(crate) fn profile_row(profile: &crate::Profile) -> Value {
admin::render_profile_json(&admin::ProfileSummary::mounted(profile))
}