Files
Arkendro/server/src/routes/config.rs

114 lines
3.7 KiB
Rust

use crate::utils::{auth::*, config::ConfigManager, error::*, DbPool};
use axum::{extract::State, response::Json};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct ConfigRequest {
pub key: String,
pub value: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ConfigResponse {
pub key: String,
pub value: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ConfigDefinition {
pub key: String,
pub description: String,
pub value: Option<String>,
pub default_value: Option<String>,
pub required: bool,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct ConfigListResponse {
pub configs: Vec<ConfigDefinition>,
}
pub async fn get_all_configs(
auth_user: AuthUser,
State(pool): State<DbPool>,
) -> Result<Json<ConfigListResponse>, AppError> {
if auth_user.user.role != crate::utils::models::UserRole::Admin {
return Err(forbidden_error("Admin access required"));
}
let allowed_configs = vec![
ConfigDefinition {
key: "EXTERNAL_URL".to_string(),
description: "The external URL used for provisioning codes. This should be the public URL where this server can be reached.".to_string(),
value: ConfigManager::get_config(&pool, "EXTERNAL_URL").await?,
default_value: Some("https://your-domain.com".to_string()),
required: true,
},
ConfigDefinition {
key: "SESSION_TIMEOUT_HOURS".to_string(),
description: "Number of hours before user sessions expire and require re-authentication.".to_string(),
value: ConfigManager::get_config(&pool, "SESSION_TIMEOUT_HOURS").await?,
default_value: Some("24".to_string()),
required: false,
},
];
Ok(success_response(ConfigListResponse {
configs: allowed_configs,
}))
}
pub async fn set_config(
auth_user: AuthUser,
State(pool): State<DbPool>,
Json(request): Json<ConfigRequest>,
) -> Result<Json<serde_json::Value>, AppError> {
if auth_user.user.role != crate::utils::models::UserRole::Admin {
return Err(forbidden_error("Admin access required"));
}
let allowed_keys = vec!["EXTERNAL_URL", "SESSION_TIMEOUT_HOURS"];
if !allowed_keys.contains(&request.key.as_str()) {
return Err(validation_error("Invalid configuration key"));
}
match request.key.as_str() {
"EXTERNAL_URL" => {
if request.value.trim().is_empty() {
return Err(validation_error("External URL cannot be empty"));
}
if !request.value.starts_with("http://") && !request.value.starts_with("https://") {
return Err(validation_error(
"External URL must start with http:// or https://",
));
}
}
"SESSION_TIMEOUT_HOURS" => {
if request.value.parse::<i32>().is_err() || request.value.parse::<i32>().unwrap() <= 0 {
return Err(validation_error("Value must be a positive number"));
}
}
_ => {}
}
ConfigManager::set_config(&pool, &request.key, &request.value).await?;
Ok(success_message("Configuration updated successfully"))
}
pub async fn get_config(
auth_user: AuthUser,
State(pool): State<DbPool>,
axum::extract::Path(key): axum::extract::Path<String>,
) -> Result<Json<ConfigResponse>, AppError> {
if auth_user.user.role != crate::utils::models::UserRole::Admin {
return Err(forbidden_error("Admin access required"));
}
let value = ConfigManager::get_config(&pool, &key)
.await?
.ok_or_else(|| not_found_error("Configuration key not found"))?;
Ok(success_response(ConfigResponse { key, value }))
}