use crate::error::DbError;
use crate::server::auth::Claims;
use crate::server::authorization::PermissionAction;
use crate::server::handlers;
use axum::{
extract::{Path, State},
response::IntoResponse,
Extension, Json,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct EnvVarValue {
pub value: String,
}
async fn require_env_admin(
claims: &Claims,
state: &handlers::AppState,
db_name: &str,
) -> Result<(), DbError> {
crate::server::authz_middleware::enforce(claims, state, PermissionAction::Admin, Some(db_name))
.await
}
pub async fn list_env_vars_handler(
State(state): State<handlers::AppState>,
Extension(claims): Extension<Claims>,
Path(db_name): Path<String>,
) -> Result<impl IntoResponse, DbError> {
require_env_admin(&claims, &state, &db_name).await?;
let db = state.storage.get_database(&db_name)?;
if db.system_collection("_env").is_err() {
return Ok(Json(std::collections::HashMap::new()));
}
let collection = db.system_collection("_env")?;
let all_docs = collection.scan(None);
let mut env_map: std::collections::HashMap<String, String> = std::collections::HashMap::new();
for doc in all_docs {
if let Some(key) = doc
.get("_key")
.and_then(|v| v.as_str().map(|s| s.to_string()))
{
if let Some(val) = doc
.get("value")
.and_then(|v| v.as_str().map(|s| s.to_string()))
{
env_map.insert(key.to_string(), val.to_string());
}
}
}
Ok(Json(env_map))
}
pub async fn set_env_var_handler(
State(state): State<handlers::AppState>,
Extension(claims): Extension<Claims>,
Path((db_name, key)): Path<(String, String)>,
Json(payload): Json<EnvVarValue>,
) -> Result<impl IntoResponse, DbError> {
require_env_admin(&claims, &state, &db_name).await?;
let db = state.storage.get_database(&db_name)?;
if db.system_collection("_env").is_err() {
db.create_collection("_env".to_string(), None)?;
}
let collection = db.system_collection("_env")?;
let doc = serde_json::json!({
"_key": key,
"value": payload.value,
"updated_at": chrono::Utc::now().to_rfc3339()
});
collection.insert(doc)?;
Ok(Json(serde_json::json!({ "status": "ok", "key": key })))
}
pub async fn delete_env_var_handler(
State(state): State<handlers::AppState>,
Extension(claims): Extension<Claims>,
Path((db_name, key)): Path<(String, String)>,
) -> Result<impl IntoResponse, DbError> {
require_env_admin(&claims, &state, &db_name).await?;
let db = state.storage.get_database(&db_name)?;
if db.system_collection("_env").is_err() {
return Err(DbError::DocumentNotFound(format!(
"Environment variable {} not found",
key
)));
}
let collection = db.system_collection("_env")?;
match collection.delete(&key) {
Ok(_) => Ok(Json(serde_json::json!({ "status": "deleted", "key": key }))),
Err(_) => Err(DbError::DocumentNotFound(format!(
"Environment variable {} not found",
key
))),
}
}