use axum::extract::State;
use axum::response::Json;
use axum::Extension;
use serde::Deserialize;
use crate::ai::{ValidationConfig, ValidationPipeline, ValidationResult};
use crate::error::DbError;
use crate::server::auth::Claims;
use crate::server::authorization::PermissionAction;
use crate::server::handlers::AppState;
fn require_validation_enabled(claims: &Claims, state: &AppState) -> Result<(), DbError> {
let enabled = std::env::var("SOLIDB_ENABLE_AI_VALIDATION")
.map(|v| v == "1" || v.eq_ignore_ascii_case("true"))
.unwrap_or(false);
if !enabled {
return Err(DbError::Forbidden(
"The AI validation endpoints are disabled; set \
SOLIDB_ENABLE_AI_VALIDATION=1 to enable them on a development host"
.to_string(),
));
}
let roles = claims.roles.clone().unwrap_or_default();
if !roles.iter().any(|r| r.eq_ignore_ascii_case("admin")) {
return Err(DbError::Forbidden(format!(
"{:?} requires global admin",
PermissionAction::Admin
)));
}
let _ = state;
Ok(())
}
#[derive(Debug, Deserialize)]
pub struct RunValidationRequest {
#[serde(default)]
pub project_root: Option<String>,
#[serde(default = "default_true")]
pub run_tests: bool,
#[serde(default = "default_true")]
pub run_clippy: bool,
#[serde(default = "default_true")]
pub run_rustfmt: bool,
#[serde(default)]
pub quick: bool,
}
fn default_true() -> bool {
true
}
pub async fn run_validation_handler(
State(state): State<AppState>,
Extension(claims): Extension<Claims>,
Json(request): Json<RunValidationRequest>,
) -> Result<Json<ValidationResult>, DbError> {
require_validation_enabled(&claims, &state)?;
let project_root = ".".to_string();
let config = ValidationConfig {
project_root,
run_tests: request.run_tests && !request.quick,
run_clippy: request.run_clippy,
run_rustfmt: request.run_rustfmt,
test_timeout_secs: 300,
test_filter: None,
};
let pipeline = ValidationPipeline::new(config);
let result = if request.quick {
pipeline.run_quick()
} else {
pipeline.run()
};
Ok(Json(result))
}
pub async fn run_quick_validation_handler(
State(state): State<AppState>,
Extension(claims): Extension<Claims>,
) -> Result<Json<ValidationResult>, DbError> {
require_validation_enabled(&claims, &state)?;
let pipeline = ValidationPipeline::for_project(".");
let result = pipeline.run_quick();
Ok(Json(result))
}