use axum::Json;
use axum::extract::State;
use serde_json::Value;
use vti_common::auth::extractor::{ManageAuth, SuperAdminAuth};
use vti_common::error::AppError;
use crate::operations::step_up_policy::{
SetPolicyError, effective_response, policy_from_value, set_step_up_policy,
};
use crate::server::AppState;
#[utoipa::path(
get, path = "/step-up/policy", tag = "step-up",
security(("bearer_jwt" = [])),
responses(
(status = 200, description = "Current effective step-up policy", body = serde_json::Value),
(status = 401, description = "Missing or invalid bearer token"),
(status = 403, description = "Caller lacks manage-level access"),
),
)]
pub async fn get_step_up_policy(
_auth: ManageAuth,
State(state): State<AppState>,
) -> Result<Json<Value>, AppError> {
let policy = state.config.read().await.auth.step_up.clone();
Ok(Json(effective_response(&policy)))
}
#[utoipa::path(
put, path = "/step-up/policy", tag = "step-up",
security(("bearer_jwt" = [])),
request_body = serde_json::Value,
responses(
(status = 200, description = "Updated effective step-up policy", body = serde_json::Value),
(status = 401, description = "Missing or invalid bearer token"),
(status = 403, description = "Caller is not a super-admin"),
),
)]
pub async fn put_step_up_policy(
_auth: SuperAdminAuth,
State(state): State<AppState>,
Json(body): Json<Value>,
) -> Result<Json<Value>, AppError> {
let requested = policy_from_value(&body).map_err(AppError::Validation)?;
let effective = set_step_up_policy(&state.config, &state.acl_ks, requested)
.await
.map_err(set_policy_error_to_app)?;
Ok(Json(effective_response(&effective)))
}
fn set_policy_error_to_app(e: SetPolicyError) -> AppError {
match e {
SetPolicyError::UnknownOperation(op) => AppError::Validation(format!(
"unknown operation-class '{op}' (not a gated op or '*')"
)),
SetPolicyError::LockoutRefused(msg) => AppError::Conflict(msg),
SetPolicyError::Store(m) | SetPolicyError::Persistence(m) => AppError::Config(m),
}
}