#![allow(clippy::unused_async)]
use axum::extract::State;
use axum::http::{HeaderMap, StatusCode};
use axum::response::IntoResponse;
use crate::proxy::{AppState, error_response, is_admin_authorised};
pub async fn issue_token(
State(state): State<AppState>,
headers: HeaderMap,
axum::Json(req): axum::Json<IssueTokenRequest>,
) -> impl IntoResponse {
if !is_admin_authorised(&state, &headers) {
return error_response(
StatusCode::UNAUTHORIZED,
"authentication_error",
"missing or invalid admin Bearer key",
);
}
let ttl = req.ttl_hours.unwrap_or(24);
let label = req.label.unwrap_or_default();
match state.token_manager.issue_token_full(
ttl,
&label,
req.account.as_deref(),
req.max_requests,
) {
Ok(token) => {
state.metrics.record_token_issued();
(
StatusCode::OK,
axum::Json(serde_json::json!({
"token": token,
"ttl_hours": ttl,
"label": label,
"account": req.account,
"max_requests": req.max_requests,
})),
)
.into_response()
}
Err(e) => error_response(
StatusCode::INTERNAL_SERVER_ERROR,
"api_error",
&format!("Failed to issue token: {e}"),
),
}
}
pub async fn list_tokens(State(state): State<AppState>, headers: HeaderMap) -> impl IntoResponse {
if !is_admin_authorised(&state, &headers) {
return error_response(
StatusCode::UNAUTHORIZED,
"authentication_error",
"admin Bearer key required",
);
}
match state.token_manager.list_tokens() {
Ok(records) => (
StatusCode::OK,
axum::Json(serde_json::json!({"data": records})),
)
.into_response(),
Err(e) => error_response(
StatusCode::INTERNAL_SERVER_ERROR,
"api_error",
&format!("{e}"),
),
}
}
pub async fn revoke_token(
State(state): State<AppState>,
headers: HeaderMap,
axum::Json(req): axum::Json<RevokeTokenRequest>,
) -> impl IntoResponse {
if !is_admin_authorised(&state, &headers) {
return error_response(
StatusCode::UNAUTHORIZED,
"authentication_error",
"admin Bearer key required",
);
}
match state.token_manager.revoke_token(&req.id) {
Ok(()) => {
state.metrics.record_token_revoked();
(
StatusCode::OK,
axum::Json(serde_json::json!({"revoked": req.id})),
)
.into_response()
}
Err(e) => error_response(
StatusCode::INTERNAL_SERVER_ERROR,
"api_error",
&format!("{e}"),
),
}
}
#[derive(serde::Deserialize)]
pub struct IssueTokenRequest {
pub ttl_hours: Option<i64>,
pub label: Option<String>,
pub account: Option<String>,
pub max_requests: Option<u64>,
}
#[derive(serde::Deserialize)]
pub struct RevokeTokenRequest {
pub id: String,
}