Update botserver: Multiple improvements across core modules
All checks were successful
BotServer CI/CD / build (push) Successful in 10m41s
All checks were successful
BotServer CI/CD / build (push) Successful in 10m41s
This commit is contained in:
parent
4cc1e3aa4b
commit
5576378b3f
44 changed files with 320 additions and 334 deletions
|
|
@ -78,15 +78,12 @@ jobs:
|
|||
ssh $SSH_ARGS system "find /opt/gbo/data -maxdepth 2 ! -path '*/botserver' ! -path '*/gb-ws' -print0 2>/dev/null | xargs -0 rm -rf || true"
|
||||
# Clean old log files
|
||||
ssh $SSH_ARGS system "find /tmp -name '*.log' -type f -mtime +7 -print0 2>/dev/null | xargs -0 rm -f || true"
|
||||
# Show disk space
|
||||
ssh $SSH_ARGS system "df -h /opt/gbo/data"
|
||||
echo "=== Workspace cleanup complete ==="
|
||||
|
||||
- name: Build BotServer
|
||||
working-directory: /opt/gbo/data/botserver
|
||||
run: |
|
||||
sccache --start-server 2>/dev/null || true
|
||||
cargo build -p botserver --features chat -j 8 2>&1 | tee /tmp/build.log
|
||||
cargo build -p botserver -j 8 2>&1 | tee /tmp/build.log
|
||||
sccache --show-stats
|
||||
ls -lh target/debug/botserver
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ use crate::core::shared::schema::{okr_checkins, okr_key_results, okr_objectives,
|
|||
use crate::core::shared::state::AppState;
|
||||
|
||||
fn get_bot_context() -> (Uuid, Uuid) {
|
||||
let sm = crate::core::secrets::SecretsManager::from_env().ok();
|
||||
let sm = crate::core::secrets::SecretsManager::get().ok().map(|sm| sm.clone());
|
||||
let (org_id, bot_id) = if let Some(sm) = sm {
|
||||
let sm_owned = sm.clone();
|
||||
let (tx, rx) = std::sync::mpsc::channel();
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ impl AgentExecutor {
|
|||
}
|
||||
});
|
||||
|
||||
self.broadcast_browser_ready("http://localhost:8000", 8000);
|
||||
self.broadcast_browser_ready("", 8000);
|
||||
self.broadcast_step("Agent Ready", 2, 10);
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -634,19 +634,23 @@ impl ReflectionEngine {
|
|||
.load(&mut conn)
|
||||
.unwrap_or_default();
|
||||
|
||||
let mut llm_url = "http://localhost:8081".to_string();
|
||||
let mut llm_model = "default".to_string();
|
||||
let mut llm_key = "none".to_string();
|
||||
let mut llm_url: Option<String> = None;
|
||||
let mut llm_model: Option<String> = None;
|
||||
let mut llm_key: Option<String> = None;
|
||||
|
||||
for config in configs {
|
||||
match config.config_key.as_str() {
|
||||
"llm-url" => llm_url = config.config_value,
|
||||
"llm-model" => llm_model = config.config_value,
|
||||
"llm-key" => llm_key = config.config_value,
|
||||
"llm-url" => llm_url = Some(config.config_value),
|
||||
"llm-model" => llm_model = Some(config.config_value),
|
||||
"llm-key" => llm_key = Some(config.config_value),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let llm_url = llm_url.ok_or_else(|| "LLM URL not configured".to_string())?;
|
||||
let llm_model = llm_model.ok_or_else(|| "LLM model not configured".to_string())?;
|
||||
let llm_key = llm_key.ok_or_else(|| "LLM key not configured".to_string())?;
|
||||
|
||||
Ok((llm_url, llm_model, llm_key))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -184,9 +184,9 @@ async fn translate_text(
|
|||
target_lang: &str,
|
||||
) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let llm_url = if let Some(sm) = crate::core::shared::utils::get_secrets_manager().await {
|
||||
sm.get_value("gbo/llm", "url").await.unwrap_or_else(|_| "http://localhost:8081".to_string())
|
||||
sm.get_value("gbo/llm", "url").await.unwrap_or_else(|_| "".to_string())
|
||||
} else {
|
||||
"http://localhost:8081".to_string()
|
||||
"".to_string()
|
||||
};
|
||||
let prompt = format!(
|
||||
"Translate to {}. Return ONLY the translation:\n\n{}",
|
||||
|
|
@ -212,7 +212,7 @@ async fn translate_text(
|
|||
|
||||
async fn perform_ocr(image_path: &str) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let botmodels_url =
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "http://localhost:8001".to_string());
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "".to_string());
|
||||
let client = reqwest::Client::new();
|
||||
let image_data = if image_path.starts_with("http") {
|
||||
client.get(image_path).send().await?.bytes().await?.to_vec()
|
||||
|
|
@ -237,9 +237,9 @@ async fn analyze_sentiment(
|
|||
text: &str,
|
||||
) -> Result<Dynamic, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let llm_url = if let Some(sm) = crate::core::shared::utils::get_secrets_manager().await {
|
||||
sm.get_value("gbo/llm", "url").await.unwrap_or_else(|_| "http://localhost:8081".to_string())
|
||||
sm.get_value("gbo/llm", "url").await.unwrap_or_else(|_| "".to_string())
|
||||
} else {
|
||||
"http://localhost:8081".to_string()
|
||||
"".to_string()
|
||||
};
|
||||
let prompt = format!(
|
||||
r#"Analyze sentiment. Return JSON only:
|
||||
|
|
@ -346,9 +346,9 @@ async fn classify_text(
|
|||
categories: &[String],
|
||||
) -> Result<Dynamic, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let llm_url = if let Some(sm) = crate::core::shared::utils::get_secrets_manager().await {
|
||||
sm.get_value("gbo/llm", "url").await.unwrap_or_else(|_| "http://localhost:8081".to_string())
|
||||
sm.get_value("gbo/llm", "url").await.unwrap_or_else(|_| "".to_string())
|
||||
} else {
|
||||
"http://localhost:8081".to_string()
|
||||
"".to_string()
|
||||
};
|
||||
let cats = categories.join(", ");
|
||||
let prompt = format!(
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ async fn detect_anomalies_in_table(
|
|||
}
|
||||
|
||||
let botmodels_host =
|
||||
std::env::var("BOTMODELS_HOST").unwrap_or_else(|_| "http://localhost:8085".to_string());
|
||||
std::env::var("BOTMODELS_HOST").unwrap_or_else(|_| "".to_string());
|
||||
let botmodels_key =
|
||||
std::env::var("BOTMODELS_API_KEY").unwrap_or_else(|_| "starter".to_string());
|
||||
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ pub async fn process_qrcode(
|
|||
.ok()
|
||||
});
|
||||
config_url.unwrap_or_else(|| {
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "http://localhost:8001".to_string())
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "".to_string())
|
||||
})
|
||||
};
|
||||
|
||||
|
|
@ -188,7 +188,7 @@ pub async fn process_audio_to_text(
|
|||
audio_url: &str,
|
||||
) -> Result<(String, Option<serde_json::Value>), String> {
|
||||
let botmodels_url =
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "http://localhost:8001".to_string());
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "".to_string());
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
|
||||
|
|
@ -237,7 +237,7 @@ pub async fn process_video_description(
|
|||
video_url: &str,
|
||||
) -> Result<(String, Option<serde_json::Value>), String> {
|
||||
let botmodels_url =
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "http://localhost:8001".to_string());
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "".to_string());
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ impl Default for McpConnection {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
connection_type: ConnectionType::Http,
|
||||
url: "http://localhost:8080".to_string(),
|
||||
url: "".to_string(),
|
||||
port: None,
|
||||
timeout_seconds: 30,
|
||||
max_retries: 3,
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ pub async fn export_test(
|
|||
let script = r#"
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('Recorded test', async ({ page }) => {
|
||||
await page.goto('http://localhost:3000');
|
||||
await page.goto('');
|
||||
// Add actions
|
||||
});
|
||||
"#;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ pub mod caldav;
|
|||
pub mod ui;
|
||||
|
||||
fn get_bot_context() -> (Uuid, Uuid) {
|
||||
let sm = crate::core::secrets::SecretsManager::from_env().ok();
|
||||
let sm = crate::core::secrets::SecretsManager::get().ok().map(|sm| sm.clone());
|
||||
let (org_id, bot_id) = if let Some(sm) = sm {
|
||||
let sm_owned = sm.clone();
|
||||
let (tx, rx) = std::sync::mpsc::channel();
|
||||
|
|
|
|||
|
|
@ -894,7 +894,7 @@ pub fn apply_wizard_config(config: &WizardConfig) -> io::Result<()> {
|
|||
println!(" Data directory: {}", config.data_dir.display());
|
||||
println!("\n Next steps:");
|
||||
println!(" 1. Run: botserver start");
|
||||
println!(" 2. Open: http://localhost:4242");
|
||||
println!(" 2. Open: ");
|
||||
println!(" 3. Login with: {}", config.admin.username);
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -162,10 +162,10 @@ pub fn cache_health_check() -> bool {
|
|||
|
||||
/// Check if Qdrant vector database is healthy
|
||||
pub fn vector_db_health_check() -> bool {
|
||||
let qdrant_url = if let Ok(sm) = crate::core::secrets::SecretsManager::from_env() {
|
||||
let qdrant_url = if let Ok(sm) = crate::core::secrets::SecretsManager::get() {
|
||||
sm.get_vectordb_config_sync().0
|
||||
} else {
|
||||
"http://localhost:6333".to_string()
|
||||
"".to_string()
|
||||
};
|
||||
|
||||
let urls = [
|
||||
|
|
@ -226,7 +226,7 @@ pub fn zitadel_health_check() -> bool {
|
|||
"2",
|
||||
"-m",
|
||||
"3",
|
||||
"http://localhost:8300/debug/healthz",
|
||||
"/debug/healthz",
|
||||
])
|
||||
})
|
||||
.and_then(|c| c.execute());
|
||||
|
|
@ -327,7 +327,7 @@ pub fn drive_health_check() -> bool {
|
|||
|
||||
/// Check if ALM (Forgejo) is healthy
|
||||
pub fn alm_health_check() -> bool {
|
||||
let urls = ["http://localhost:3000", "https://localhost:3000"];
|
||||
let urls = ["", "https://localhost:3000"];
|
||||
|
||||
for url in &urls {
|
||||
if let Ok(output) = SafeCommand::new("curl")
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ impl CustomDatabaseConfig {
|
|||
.first::<String>(&mut conn)
|
||||
.ok()
|
||||
.filter(|s| !s.is_empty())
|
||||
.unwrap_or_else(|| "localhost".to_string());
|
||||
.unwrap_or_else(|| "".to_string());
|
||||
|
||||
let port: u16 = bot_configuration
|
||||
.filter(bot_id.eq(target_bot_id))
|
||||
|
|
@ -272,27 +272,21 @@ impl AppConfig {
|
|||
.unwrap_or_else(|| default.to_string())
|
||||
};
|
||||
|
||||
let get_u16 = |key: &str, default: u16| -> u16 {
|
||||
config_map
|
||||
.get(key)
|
||||
.and_then(|v| v.parse().ok())
|
||||
.unwrap_or(default)
|
||||
};
|
||||
let get_u16 = |key: &str, default: u16| -> u16 {
|
||||
config_map
|
||||
.get(key)
|
||||
.and_then(|v| v.parse().ok())
|
||||
.unwrap_or(default)
|
||||
};
|
||||
|
||||
// Read from Vault with fallback to defaults
|
||||
let secrets = SecretsManager::from_env().ok();
|
||||
let (drive_server, drive_access, drive_secret) = secrets
|
||||
.as_ref()
|
||||
.map(|s| s.get_drive_config())
|
||||
.unwrap_or_else(|| {
|
||||
(
|
||||
crate::core::urls::InternalUrls::DRIVE.to_string(),
|
||||
"minioadmin".to_string(),
|
||||
"minioadmin".to_string(),
|
||||
)
|
||||
});
|
||||
// Read from Vault with fallback to defaults
|
||||
let secrets = SecretsManager::get().ok().map(|sm| sm.clone());
|
||||
let (drive_server, drive_access, drive_secret) = secrets
|
||||
.as_ref()
|
||||
.and_then(|s| s.get_drive_config().ok())
|
||||
.unwrap_or((String::new(), String::new(), String::new()));
|
||||
|
||||
let drive = DriveConfig {
|
||||
let drive = DriveConfig {
|
||||
server: drive_server,
|
||||
access_key: drive_access,
|
||||
secret_key: drive_secret,
|
||||
|
|
@ -317,7 +311,7 @@ impl AppConfig {
|
|||
server: ServerConfig {
|
||||
host: get_str("server_host", "0.0.0.0"),
|
||||
port,
|
||||
base_url: config_map.get("server_base_url").cloned().unwrap_or_else(|| "http://localhost:8080".to_string()),
|
||||
base_url: config_map.get("server_base_url").cloned().unwrap_or_else(|| String::new()),
|
||||
},
|
||||
site_path: {
|
||||
ConfigManager::new(pool.clone()).get_config(
|
||||
|
|
@ -331,17 +325,11 @@ impl AppConfig {
|
|||
}
|
||||
pub fn from_env() -> Result<Self, anyhow::Error> {
|
||||
// Read from Vault with fallback to defaults
|
||||
let secrets = SecretsManager::from_env().ok();
|
||||
let secrets = SecretsManager::get().ok().map(|sm| sm.clone());
|
||||
let (drive_server, drive_access, drive_secret) = secrets
|
||||
.as_ref()
|
||||
.map(|s| s.get_drive_config())
|
||||
.unwrap_or_else(|| {
|
||||
(
|
||||
crate::core::urls::InternalUrls::DRIVE.to_string(),
|
||||
"minioadmin".to_string(),
|
||||
"minioadmin".to_string(),
|
||||
)
|
||||
});
|
||||
.and_then(|s| s.get_drive_config().ok())
|
||||
.unwrap_or((String::new(), String::new(), String::new()));
|
||||
|
||||
let minio = DriveConfig {
|
||||
server: drive_server,
|
||||
|
|
@ -368,7 +356,7 @@ impl AppConfig {
|
|||
server: ServerConfig {
|
||||
host: "0.0.0.0".to_string(),
|
||||
port,
|
||||
base_url: "http://localhost:8080".to_string(),
|
||||
base_url: "".to_string(),
|
||||
},
|
||||
|
||||
site_path: format!("{}/sites", crate::core::shared::utils::get_stack_path()),
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ pub async fn reload_config(
|
|||
|
||||
// Get LLM config
|
||||
let llm_url = config_manager
|
||||
.get_config(&default_bot_id, "llm-url", Some("http://localhost:8081"))
|
||||
.unwrap_or_else(|_| "http://localhost:8081".to_string());
|
||||
.get_config(&default_bot_id, "llm-url", Some(""))
|
||||
.unwrap_or_else(|_| "".to_string());
|
||||
|
||||
let llm_model = config_manager
|
||||
.get_config(&default_bot_id, "llm-model", Some("local"))
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ pub async fn provision_user_handler(
|
|||
.config
|
||||
.as_ref()
|
||||
.map(|c| c.server.base_url.clone())
|
||||
.unwrap_or_else(|| "http://localhost:9000".to_string());
|
||||
.unwrap_or_else(|| "".to_string());
|
||||
|
||||
let provisioning = UserProvisioningService::new(state.conn.clone(), s3_client, base_url);
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ pub async fn deprovision_user_handler(
|
|||
.config
|
||||
.as_ref()
|
||||
.map(|c| c.server.base_url.clone())
|
||||
.unwrap_or_else(|| "http://localhost:9000".to_string());
|
||||
.unwrap_or_else(|| "".to_string());
|
||||
|
||||
let provisioning = UserProvisioningService::new(state.conn.clone(), s3_client, base_url);
|
||||
|
||||
|
|
@ -257,7 +257,7 @@ pub async fn check_services_status(State(state): State<Arc<AppState>>) -> impl I
|
|||
|
||||
let client = create_tls_client(Some(2));
|
||||
|
||||
if let Ok(response) = client.get("http://localhost:8300/healthz").send().await {
|
||||
if let Ok(response) = client.get("/healthz").send().await {
|
||||
status.directory = response.status().is_success();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ pub struct EmbeddingConfig {
|
|||
impl Default for EmbeddingConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
embedding_url: "http://localhost:8082".to_string(),
|
||||
embedding_url: "".to_string(),
|
||||
embedding_model: "BAAI/bge-multilingual-gemma2".to_string(),
|
||||
embedding_key: None,
|
||||
dimensions: 2048,
|
||||
|
|
@ -58,7 +58,7 @@ impl EmbeddingConfig {
|
|||
|
||||
/// Load embedding config from bot's config.csv (similar to llm-url, llm-model)
|
||||
/// This allows configuring embedding server per-bot in config.csv:
|
||||
/// embedding-url,http://localhost:8082
|
||||
/// embedding-url,
|
||||
/// embedding-model,bge-small-en-v1.5
|
||||
/// embedding-dimensions,384
|
||||
/// embedding-batch-size,16
|
||||
|
|
@ -77,7 +77,7 @@ impl EmbeddingConfig {
|
|||
.ok()
|
||||
.filter(|s| !s.is_empty()),
|
||||
Err(_) => None,
|
||||
}.unwrap_or_else(|| "http://localhost:8082".to_string());
|
||||
}.unwrap_or_else(|| "".to_string());
|
||||
|
||||
let embedding_model = match pool.get() {
|
||||
Ok(mut conn) => bot_configuration
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ pub struct QdrantConfig {
|
|||
impl Default for QdrantConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
url: "http://localhost:6333".to_string(),
|
||||
url: "".to_string(),
|
||||
api_key: None,
|
||||
timeout_secs: 30,
|
||||
}
|
||||
|
|
@ -36,8 +36,8 @@ impl QdrantConfig {
|
|||
} else {
|
||||
let config_manager = ConfigManager::new(pool);
|
||||
let url = config_manager
|
||||
.get_config(bot_id, "vectordb-url", Some("http://localhost:6333"))
|
||||
.unwrap_or_else(|_| "http://localhost:6333".to_string());
|
||||
.get_config(bot_id, "vectordb-url", Some(""))
|
||||
.unwrap_or_else(|_| "".to_string());
|
||||
(url, None)
|
||||
};
|
||||
Self {
|
||||
|
|
|
|||
|
|
@ -439,7 +439,7 @@ async fn get_bot_config(state: &AppState) -> HashMap<String, String> {
|
|||
|
||||
fn get_base_url(state: &AppState) -> String {
|
||||
let _ = state;
|
||||
"http://localhost:9000".to_string()
|
||||
"".to_string()
|
||||
}
|
||||
|
||||
async fn create_or_get_oauth_user(
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ pub async fn setup_alm() -> anyhow::Result<()> {
|
|||
let config_path = stack_path.join("conf/alm-ci/config.yaml");
|
||||
|
||||
// Check Vault if already set up
|
||||
if let Ok(secrets_manager) = crate::core::secrets::SecretsManager::from_env() {
|
||||
if let Ok(secrets_manager) = crate::core::secrets::SecretsManager::get() {
|
||||
if secrets_manager.is_enabled() {
|
||||
if let Ok(secrets) = secrets_manager.get_secret(crate::core::secrets::SecretPaths::ALM).await {
|
||||
if let (Some(user), Some(token)) = (secrets.get("username"), secrets.get("runner_token")) {
|
||||
|
|
@ -52,7 +52,7 @@ PATH = {}/data/alm/gitea.db
|
|||
[server]
|
||||
HTTP_PORT = 3000
|
||||
DOMAIN = localhost
|
||||
ROOT_URL = http://localhost:3000
|
||||
ROOT_URL =
|
||||
|
||||
[security]
|
||||
INSTALL_LOCK = true
|
||||
|
|
@ -67,7 +67,7 @@ INSTALL_LOCK = true
|
|||
// Generate credentials and attempt to configure via HTTP API
|
||||
let username = "botserver";
|
||||
let password = generate_random_string(32);
|
||||
let alm_url = "http://localhost:3000";
|
||||
let alm_url = "";
|
||||
|
||||
// Try to create admin user and get runner token via HTTP API
|
||||
// Note: Forgejo CLI binary may segfault on some systems, so we use curl
|
||||
|
|
@ -95,7 +95,7 @@ INSTALL_LOCK = true
|
|||
}
|
||||
|
||||
// Store in Vault
|
||||
if let Ok(secrets_manager) = crate::core::secrets::SecretsManager::from_env() {
|
||||
if let Ok(secrets_manager) = crate::core::secrets::SecretsManager::get() {
|
||||
if secrets_manager.is_enabled() {
|
||||
let mut secrets = HashMap::new();
|
||||
secrets.insert("url".to_string(), alm_url.to_string());
|
||||
|
|
|
|||
|
|
@ -437,7 +437,7 @@ async fn vault_migrate(env_file: &str) -> Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
let manager = SecretsManager::from_env()?;
|
||||
let manager = SecretsManager::get()?.clone();
|
||||
if !manager.is_enabled() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Vault not configured. Set VAULT_ADDR and VAULT_TOKEN"
|
||||
|
|
@ -605,7 +605,7 @@ async fn vault_migrate(env_file: &str) -> Result<()> {
|
|||
}
|
||||
|
||||
async fn vault_put(path: &str, kvs: &[&str]) -> Result<()> {
|
||||
let manager = SecretsManager::from_env()?;
|
||||
let manager = SecretsManager::get()?.clone();
|
||||
if !manager.is_enabled() {
|
||||
return Err(anyhow::anyhow!("Vault not configured"));
|
||||
}
|
||||
|
|
@ -669,7 +669,7 @@ async fn vault_put(path: &str, kvs: &[&str]) -> Result<()> {
|
|||
}
|
||||
|
||||
async fn vault_get(path: &str, key: Option<&str>) -> Result<()> {
|
||||
let manager = SecretsManager::from_env()?;
|
||||
let manager = SecretsManager::get()?.clone();
|
||||
if !manager.is_enabled() {
|
||||
return Err(anyhow::anyhow!("Vault not configured"));
|
||||
}
|
||||
|
|
@ -751,7 +751,7 @@ async fn print_version(show_all: bool) -> Result<()> {
|
|||
|
||||
println!();
|
||||
println!("Secrets:");
|
||||
if let Ok(manager) = SecretsManager::from_env() {
|
||||
if let Ok(manager) = SecretsManager::get() {
|
||||
if manager.is_enabled() {
|
||||
match manager.health_check().await {
|
||||
Ok(true) => println!(" Vault: connected"),
|
||||
|
|
@ -805,7 +805,7 @@ fn generate_secret_key() -> String {
|
|||
}
|
||||
|
||||
async fn rotate_secret(component: &str) -> Result<()> {
|
||||
let manager = SecretsManager::from_env()?;
|
||||
let manager = SecretsManager::get()?.clone();
|
||||
if !manager.is_enabled() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Vault not configured. Set VAULT_ADDR and VAULT_TOKEN"
|
||||
|
|
@ -1096,7 +1096,7 @@ async fn rotate_all_secrets() -> Result<()> {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
let manager = SecretsManager::from_env()?;
|
||||
let manager = SecretsManager::get()?.clone();
|
||||
if !manager.is_enabled() {
|
||||
return Err(anyhow::anyhow!("Vault not configured"));
|
||||
}
|
||||
|
|
@ -1183,7 +1183,7 @@ async fn verify_rotation(component: &str) -> Result<()> {
|
|||
|
||||
match component {
|
||||
"tables" => {
|
||||
let manager = SecretsManager::from_env()?;
|
||||
let manager = SecretsManager::get()?.clone();
|
||||
let secrets = manager.get_secret(SecretPaths::TABLES).await?;
|
||||
|
||||
let host = secrets.get("host").cloned().unwrap_or_else(|| "localhost".to_string());
|
||||
|
|
@ -1228,9 +1228,9 @@ async fn verify_rotation(component: &str) -> Result<()> {
|
|||
|
||||
// Try to determine the health endpoint
|
||||
let health_urls = vec![
|
||||
"http://localhost:8080/health",
|
||||
"http://localhost:5858/health",
|
||||
"http://localhost:3000/health",
|
||||
"/health",
|
||||
"/health",
|
||||
"/health",
|
||||
];
|
||||
|
||||
let mut success = false;
|
||||
|
|
@ -1268,7 +1268,7 @@ async fn verify_rotation(component: &str) -> Result<()> {
|
|||
}
|
||||
|
||||
async fn vault_health() -> Result<()> {
|
||||
let manager = SecretsManager::from_env()?;
|
||||
let manager = SecretsManager::get()?.clone();
|
||||
|
||||
if !manager.is_enabled() {
|
||||
println!("x Vault not configured");
|
||||
|
|
|
|||
|
|
@ -74,11 +74,11 @@ pub async fn setup_directory() -> anyhow::Result<crate::core::package_manager::s
|
|||
|
||||
let stack_path = get_stack_path();
|
||||
|
||||
let base_url = "http://localhost:8300".to_string();
|
||||
let base_url = "".to_string();
|
||||
let config_path = PathBuf::from(&stack_path).join("conf/system/directory_config.json");
|
||||
|
||||
// Check if config already exists in Vault first
|
||||
if let Ok(secrets_manager) = crate::core::secrets::SecretsManager::from_env() {
|
||||
if let Ok(secrets_manager) = crate::core::secrets::SecretsManager::get() {
|
||||
if secrets_manager.is_enabled() {
|
||||
if let Ok(secrets) = secrets_manager.get_secret(crate::core::secrets::SecretPaths::DIRECTORY).await {
|
||||
if let (Some(client_id), Some(client_secret)) = (secrets.get("client_id"), secrets.get("client_secret")) {
|
||||
|
|
@ -98,7 +98,7 @@ pub async fn setup_directory() -> anyhow::Result<crate::core::package_manager::s
|
|||
issuer: secrets.get("issuer").cloned().unwrap_or_else(|| base_url.clone()),
|
||||
client_id: client_id.clone(),
|
||||
client_secret: client_secret.clone(),
|
||||
redirect_uri: secrets.get("redirect_uri").cloned().unwrap_or_else(|| "http://localhost:3000/auth/callback".to_string()),
|
||||
redirect_uri: secrets.get("redirect_uri").cloned().unwrap_or_else(|| "/auth/callback".to_string()),
|
||||
project_id: secrets.get("project_id").cloned().unwrap_or_default(),
|
||||
api_url: secrets.get("api_url").cloned().unwrap_or_else(|| base_url.clone()),
|
||||
service_account_key: secrets.get("service_account_key").cloned(),
|
||||
|
|
@ -135,7 +135,7 @@ pub async fn setup_directory() -> anyhow::Result<crate::core::package_manager::s
|
|||
.map_err(|e| anyhow::anyhow!("Failed to initialize directory: {}", e))?;
|
||||
|
||||
// Store credentials in Vault
|
||||
if let Ok(secrets_manager) = crate::core::secrets::SecretsManager::from_env() {
|
||||
if let Ok(secrets_manager) = crate::core::secrets::SecretsManager::get() {
|
||||
if secrets_manager.is_enabled() {
|
||||
let mut secrets = HashMap::new();
|
||||
secrets.insert("url".to_string(), config.base_url.clone());
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ impl DirectorySetup {
|
|||
issuer: self.base_url.clone(),
|
||||
client_id,
|
||||
client_secret,
|
||||
redirect_uri: "http://localhost:3000/auth/callback".to_string(),
|
||||
redirect_uri: "/auth/callback".to_string(),
|
||||
project_id,
|
||||
api_url: self.base_url.clone(),
|
||||
service_account_key: None,
|
||||
|
|
@ -227,8 +227,8 @@ impl DirectorySetup {
|
|||
let app_body = serde_json::json!({
|
||||
"name": "BotServer",
|
||||
"redirectUris": [
|
||||
"http://localhost:3000/auth/callback",
|
||||
"http://localhost:8080/auth/callback"
|
||||
"/auth/callback",
|
||||
"/auth/callback"
|
||||
],
|
||||
"responseTypes": ["OIDC_RESPONSE_TYPE_CODE"],
|
||||
"grantTypes": [
|
||||
|
|
@ -237,7 +237,7 @@ impl DirectorySetup {
|
|||
],
|
||||
"appType": "OIDC_APP_TYPE_WEB",
|
||||
"authMethodType": "OIDC_AUTH_METHOD_TYPE_POST",
|
||||
"postLogoutRedirectUris": ["http://localhost:3000"],
|
||||
"postLogoutRedirectUris": [""],
|
||||
"devMode": true
|
||||
});
|
||||
|
||||
|
|
@ -320,14 +320,14 @@ mod tests {
|
|||
#[test]
|
||||
fn test_directory_config_serialization() {
|
||||
let config = DirectoryConfig {
|
||||
base_url: "http://localhost:8300".to_string(),
|
||||
issuer_url: "http://localhost:8300".to_string(),
|
||||
issuer: "http://localhost:8300".to_string(),
|
||||
base_url: "".to_string(),
|
||||
issuer_url: "".to_string(),
|
||||
issuer: "".to_string(),
|
||||
client_id: "test_client".to_string(),
|
||||
client_secret: "test_secret".to_string(),
|
||||
redirect_uri: "http://localhost:3000/callback".to_string(),
|
||||
redirect_uri: "/callback".to_string(),
|
||||
project_id: "12345".to_string(),
|
||||
api_url: "http://localhost:8300".to_string(),
|
||||
api_url: "".to_string(),
|
||||
service_account_key: None,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use std::env;
|
|||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Arc as StdArc;
|
||||
use std::sync::OnceLock;
|
||||
use std::sync::RwLock as StdRwLock;
|
||||
use uuid::Uuid;
|
||||
use vaultrs::client::{VaultClient, VaultClientSettingsBuilder};
|
||||
|
|
@ -130,19 +131,19 @@ impl SecretsManager {
|
|||
settings_builder.verify(true);
|
||||
|
||||
if ca_path.exists() {
|
||||
info!("Using CA certificate for Vault: {}", ca_cert);
|
||||
debug!("Using CA certificate for Vault: {}", ca_cert);
|
||||
settings_builder.ca_certs(vec![ca_cert]);
|
||||
}
|
||||
}
|
||||
|
||||
if cert_path.exists() && key_path.exists() && !skip_verify {
|
||||
info!("Using mTLS client certificate for Vault: {}", client_cert);
|
||||
debug!("Using mTLS client certificate for Vault: {}", client_cert);
|
||||
}
|
||||
|
||||
let settings = settings_builder.build()?;
|
||||
let client = VaultClient::new(settings)?;
|
||||
|
||||
info!("Vault client initialized with TLS: {}", addr);
|
||||
debug!("Vault client initialized with TLS: {}", addr);
|
||||
|
||||
Ok(Self {
|
||||
client: Some(StdArc::new(client)),
|
||||
|
|
@ -152,6 +153,26 @@ impl SecretsManager {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn get() -> Result<&'static SecretsManager> {
|
||||
static INIT: OnceLock<Result<SecretsManager>> = OnceLock::new();
|
||||
INIT.get_or_init(|| {
|
||||
match Self::from_env() {
|
||||
Ok(manager) => {
|
||||
info!("SecretsManager singleton initialized (Vault: {})", env::var("VAULT_ADDR").unwrap_or_default());
|
||||
Ok(manager)
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to initialize SecretsManager: {}", e);
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}).as_ref().map_err(|e| anyhow!("SecretsManager initialization failed: {}", e))
|
||||
}
|
||||
|
||||
pub fn get_clone() -> Result<SecretsManager> {
|
||||
Self::get().map(|sm| sm.clone())
|
||||
}
|
||||
|
||||
pub fn is_enabled(&self) -> bool {
|
||||
self.enabled
|
||||
}
|
||||
|
|
@ -208,30 +229,33 @@ impl SecretsManager {
|
|||
default.to_string()
|
||||
}
|
||||
|
||||
pub fn get_drive_config(&self) -> (String, String, String) {
|
||||
pub fn get_drive_config(&self) -> Result<(String, String, String)> {
|
||||
// Try to read from Vault using std process (curl)
|
||||
if let Ok(vault_addr) = std::env::var("VAULT_ADDR") {
|
||||
if let Ok(vault_token) = std::env::var("VAULT_TOKEN") {
|
||||
let ca_cert = std::env::var("VAULT_CACERT").unwrap_or_default();
|
||||
|
||||
|
||||
log::info!("Attempting to read drive config from Vault: {}", vault_addr);
|
||||
|
||||
|
||||
let url = format!("{}/v1/secret/data/gbo/drive", vault_addr);
|
||||
|
||||
|
||||
// Use curl via Command for reliable TLS
|
||||
let result = std::process::Command::new("curl")
|
||||
.args(&["-sf", "--cacert", &ca_cert, "-H", &format!("X-Vault-Token: {}", &vault_token), &url])
|
||||
.output();
|
||||
|
||||
|
||||
match result {
|
||||
Ok(output) if output.status.success() => {
|
||||
if let Ok(data) = serde_json::from_slice::<serde_json::Value>(&output.stdout) {
|
||||
if let Some(secret_data) = data.get("data").and_then(|d| d.get("data")) {
|
||||
let host = secret_data.get("host").and_then(|v| v.as_str()).unwrap_or("localhost:9100");
|
||||
let accesskey = secret_data.get("accesskey").and_then(|v| v.as_str()).unwrap_or("minioadmin");
|
||||
let secret = secret_data.get("secret").and_then(|v| v.as_str()).unwrap_or("minioadmin");
|
||||
let host = secret_data.get("host").and_then(|v| v.as_str())
|
||||
.ok_or_else(|| anyhow!("drive host not configured in Vault"))?;
|
||||
let accesskey = secret_data.get("accesskey").and_then(|v| v.as_str())
|
||||
.ok_or_else(|| anyhow!("drive accesskey not configured in Vault"))?;
|
||||
let secret = secret_data.get("secret").and_then(|v| v.as_str())
|
||||
.ok_or_else(|| anyhow!("drive secret not configured in Vault"))?;
|
||||
log::info!("get_drive_config: Successfully read from Vault - host={}", host);
|
||||
return (host.to_string(), accesskey.to_string(), secret.to_string());
|
||||
return Ok((host.to_string(), accesskey.to_string(), secret.to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -245,82 +269,86 @@ impl SecretsManager {
|
|||
}
|
||||
}
|
||||
|
||||
log::warn!("get_drive_config: Falling back to defaults - Vault not available");
|
||||
("localhost:9100".to_string(), "minioadmin".to_string(), "minioadmin".to_string())
|
||||
Err(anyhow!("Drive configuration not available in Vault and VAULT_ADDR/VAULT_TOKEN not set"))
|
||||
}
|
||||
|
||||
pub fn get_cache_config(&self) -> (String, u16, Option<String>) {
|
||||
pub fn get_cache_config(&self) -> Result<(String, u16, Option<String>)> {
|
||||
if let Ok(vault_addr) = std::env::var("VAULT_ADDR") {
|
||||
if let Ok(vault_token) = std::env::var("VAULT_TOKEN") {
|
||||
let ca_cert = std::env::var("VAULT_CACERT").unwrap_or_default();
|
||||
|
||||
|
||||
log::info!("Attempting to read cache config from Vault: {}", vault_addr);
|
||||
let url = format!("{}/v1/secret/data/gbo/cache", vault_addr);
|
||||
|
||||
|
||||
let result = std::process::Command::new("curl")
|
||||
.args(&["-sf", "--cacert", &ca_cert, "-H", &format!("X-Vault-Token: {}", &vault_token), &url])
|
||||
.output();
|
||||
|
||||
|
||||
if let Ok(output) = result {
|
||||
if output.status.success() {
|
||||
if let Ok(data) = serde_json::from_slice::<serde_json::Value>(&output.stdout) {
|
||||
if let Some(secret_data) = data.get("data").and_then(|d| d.get("data")) {
|
||||
let host = secret_data.get("host").and_then(|v| v.as_str()).unwrap_or("localhost");
|
||||
let port = secret_data.get("port").and_then(|v| v.as_str()).unwrap_or("6379").parse().unwrap_or(6379);
|
||||
let host = secret_data.get("host").and_then(|v| v.as_str())
|
||||
.ok_or_else(|| anyhow!("cache host not configured in Vault"))?;
|
||||
let port = secret_data.get("port").and_then(|v| v.as_str())
|
||||
.ok_or_else(|| anyhow!("cache port not configured in Vault"))?
|
||||
.parse().map_err(|e| anyhow!("Invalid cache port: {}", e))?;
|
||||
let password = secret_data.get("password").and_then(|v| v.as_str()).map(|s| s.to_string());
|
||||
log::info!("get_cache_config: Successfully read from Vault - host={}", host);
|
||||
return (host.to_string(), port, password);
|
||||
return Ok((host.to_string(), port, password));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
log::warn!("get_cache_config: Falling back to defaults");
|
||||
("localhost".to_string(), 6379, None)
|
||||
Err(anyhow!("Cache configuration not available in Vault and VAULT_ADDR/VAULT_TOKEN not set"))
|
||||
}
|
||||
|
||||
pub fn get_qdrant_config(&self) -> (String, Option<String>) {
|
||||
pub fn get_qdrant_config(&self) -> Result<(String, Option<String>)> {
|
||||
if let Ok(vault_addr) = std::env::var("VAULT_ADDR") {
|
||||
if let Ok(vault_token) = std::env::var("VAULT_TOKEN") {
|
||||
let ca_cert = std::env::var("VAULT_CACERT").unwrap_or_default();
|
||||
|
||||
|
||||
log::info!("Attempting to read qdrant config from Vault: {}", vault_addr);
|
||||
let url = format!("{}/v1/secret/data/gbo/vectordb", vault_addr);
|
||||
|
||||
|
||||
let result = std::process::Command::new("curl")
|
||||
.args(&["-sf", "--cacert", &ca_cert, "-H", &format!("X-Vault-Token: {}", &vault_token), &url])
|
||||
.output();
|
||||
|
||||
|
||||
if let Ok(output) = result {
|
||||
if output.status.success() {
|
||||
if let Ok(data) = serde_json::from_slice::<serde_json::Value>(&output.stdout) {
|
||||
if let Some(secret_data) = data.get("data").and_then(|d| d.get("data")) {
|
||||
let url = secret_data.get("url").and_then(|v| v.as_str()).unwrap_or("http://localhost:6333");
|
||||
let url = secret_data.get("url").and_then(|v| v.as_str())
|
||||
.ok_or_else(|| anyhow!("vectordb url not configured in Vault"))?;
|
||||
let api_key = secret_data.get("api_key").and_then(|v| v.as_str()).map(|s| s.to_string());
|
||||
log::info!("get_qdrant_config: Successfully read from Vault - url={}", url);
|
||||
return (url.to_string(), api_key);
|
||||
return Ok((url.to_string(), api_key));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
log::warn!("get_qdrant_config: Falling back to defaults");
|
||||
("http://localhost:6333".to_string(), None)
|
||||
Err(anyhow!("VectorDB configuration not available in Vault and VAULT_ADDR/VAULT_TOKEN not set"))
|
||||
}
|
||||
|
||||
pub fn get_database_config_sync(&self) -> (String, u16, String, String, String) {
|
||||
pub fn get_database_config_sync(&self) -> Result<(String, u16, String, String, String)> {
|
||||
if let Ok(secrets) = Self::get_from_env(SecretPaths::TABLES) {
|
||||
return (
|
||||
secrets.get("host").cloned().unwrap_or_else(|| "localhost".to_string()),
|
||||
secrets.get("port").and_then(|p| p.parse().ok()).unwrap_or(5432),
|
||||
secrets.get("database").cloned().unwrap_or_else(|| "botserver".to_string()),
|
||||
secrets.get("username").cloned().unwrap_or_else(|| "gbuser".to_string()),
|
||||
secrets.get("password").cloned().unwrap_or_default(),
|
||||
);
|
||||
let host = secrets.get("host").cloned()
|
||||
.ok_or_else(|| anyhow!("database host not configured"))?;
|
||||
let port = secrets.get("port").and_then(|p| p.parse().ok())
|
||||
.ok_or_else(|| anyhow!("database port not configured"))?;
|
||||
let database = secrets.get("database").cloned()
|
||||
.ok_or_else(|| anyhow!("database name not configured"))?;
|
||||
let username = secrets.get("username").cloned()
|
||||
.ok_or_else(|| anyhow!("database username not configured"))?;
|
||||
let password = secrets.get("password").cloned().unwrap_or_default();
|
||||
return Ok((host, port, database, username, password));
|
||||
}
|
||||
("localhost".to_string(), 5432, "botserver".to_string(), "gbuser".to_string(), "changeme".to_string())
|
||||
Err(anyhow!("Database configuration not available"))
|
||||
}
|
||||
|
||||
pub async fn get_drive_credentials(&self) -> Result<(String, String)> {
|
||||
|
|
@ -333,17 +361,16 @@ impl SecretsManager {
|
|||
|
||||
pub async fn get_database_config(&self) -> Result<(String, u16, String, String, String)> {
|
||||
let s = self.get_secret(SecretPaths::TABLES).await?;
|
||||
Ok((
|
||||
s.get("host").cloned().unwrap_or_else(|| "localhost".into()),
|
||||
s.get("port").and_then(|p| p.parse().ok()).unwrap_or(5432),
|
||||
s.get("database")
|
||||
.cloned()
|
||||
.unwrap_or_else(|| "botserver".into()),
|
||||
s.get("username")
|
||||
.cloned()
|
||||
.unwrap_or_else(|| "gbuser".into()),
|
||||
s.get("password").cloned().unwrap_or_default(),
|
||||
))
|
||||
let host = s.get("host").cloned()
|
||||
.ok_or_else(|| anyhow!("database host not configured in Vault"))?;
|
||||
let port = s.get("port").and_then(|p| p.parse().ok())
|
||||
.ok_or_else(|| anyhow!("database port not configured in Vault"))?;
|
||||
let database = s.get("database").cloned()
|
||||
.ok_or_else(|| anyhow!("database name not configured in Vault"))?;
|
||||
let username = s.get("username").cloned()
|
||||
.ok_or_else(|| anyhow!("database username not configured in Vault"))?;
|
||||
let password = s.get("password").cloned().unwrap_or_default();
|
||||
Ok((host, port, database, username, password))
|
||||
}
|
||||
|
||||
pub async fn get_database_url(&self) -> Result<String> {
|
||||
|
|
@ -374,10 +401,10 @@ impl SecretsManager {
|
|||
|
||||
pub async fn get_directory_config(&self) -> Result<(String, String, String, String)> {
|
||||
let s = self.get_secret(SecretPaths::DIRECTORY).await?;
|
||||
let url = s.get("url").cloned()
|
||||
.ok_or_else(|| anyhow!("directory url not configured in Vault"))?;
|
||||
Ok((
|
||||
s.get("url")
|
||||
.cloned()
|
||||
.unwrap_or_else(|| "http://localhost:9000".into()),
|
||||
url,
|
||||
s.get("project_id").cloned().unwrap_or_default(),
|
||||
s.get("client_id").cloned().unwrap_or_default(),
|
||||
s.get("client_secret").cloned().unwrap_or_default(),
|
||||
|
|
@ -394,20 +421,17 @@ impl SecretsManager {
|
|||
|
||||
pub async fn get_vectordb_config(&self) -> Result<(String, Option<String>)> {
|
||||
let s = self.get_secret(SecretPaths::VECTORDB).await?;
|
||||
Ok((
|
||||
s.get("url")
|
||||
.cloned()
|
||||
.unwrap_or_else(|| "http://localhost:6333".into()),
|
||||
s.get("api_key").cloned(),
|
||||
))
|
||||
let url = s.get("url").cloned()
|
||||
.ok_or_else(|| anyhow!("vectordb url not configured in Vault"))?;
|
||||
Ok((url, s.get("api_key").cloned()))
|
||||
}
|
||||
|
||||
pub async fn get_observability_config(&self) -> Result<(String, String, String, String)> {
|
||||
let s = self.get_secret(SecretPaths::OBSERVABILITY).await?;
|
||||
let url = s.get("url").cloned()
|
||||
.ok_or_else(|| anyhow!("observability url not configured in Vault"))?;
|
||||
Ok((
|
||||
s.get("url")
|
||||
.cloned()
|
||||
.unwrap_or_else(|| "http://localhost:8086".into()),
|
||||
url,
|
||||
s.get("org").cloned().unwrap_or_else(|| "system".into()),
|
||||
s.get("bucket").cloned().unwrap_or_else(|| "metrics".into()),
|
||||
s.get("token").cloned().unwrap_or_default(),
|
||||
|
|
@ -441,13 +465,13 @@ impl SecretsManager {
|
|||
});
|
||||
if let Ok(Some(secrets)) = rx.recv() {
|
||||
return (
|
||||
secrets.get("url").cloned().unwrap_or_else(|| "http://localhost:9000".into()),
|
||||
secrets.get("url").cloned().unwrap_or_else(|| "".into()),
|
||||
secrets.get("project_id").cloned().unwrap_or_default(),
|
||||
secrets.get("client_id").cloned().unwrap_or_default(),
|
||||
secrets.get("client_secret").cloned().unwrap_or_default(),
|
||||
);
|
||||
}
|
||||
("http://localhost:9000".to_string(), String::new(), String::new(), String::new())
|
||||
("".to_string(), String::new(), String::new(), String::new())
|
||||
}
|
||||
|
||||
pub fn get_email_config(&self) -> (String, u16, String, String, String) {
|
||||
|
|
@ -496,14 +520,14 @@ impl SecretsManager {
|
|||
});
|
||||
if let Ok(Some(secrets)) = rx.recv() {
|
||||
return (
|
||||
secrets.get("url").cloned().unwrap_or_else(|| "http://localhost:8081".into()),
|
||||
secrets.get("url").cloned().unwrap_or_else(|| "".into()),
|
||||
secrets.get("model").cloned().unwrap_or_else(|| "gpt-4".into()),
|
||||
secrets.get("openai_key").cloned(),
|
||||
secrets.get("anthropic_key").cloned(),
|
||||
secrets.get("ollama_url").cloned().unwrap_or_else(|| "http://localhost:11434".into()),
|
||||
secrets.get("ollama_url").cloned().unwrap_or_else(|| "".into()),
|
||||
);
|
||||
}
|
||||
("http://localhost:8081".to_string(), "gpt-4".to_string(), None, None, "http://localhost:11434".to_string())
|
||||
("".to_string(), "gpt-4".to_string(), None, None, "".to_string())
|
||||
}
|
||||
|
||||
pub fn get_meet_config(&self) -> (String, String, String) {
|
||||
|
|
@ -524,12 +548,12 @@ impl SecretsManager {
|
|||
});
|
||||
if let Ok(Some(secrets)) = rx.recv() {
|
||||
return (
|
||||
secrets.get("url").cloned().unwrap_or_else(|| "http://localhost:7880".into()),
|
||||
secrets.get("url").cloned().unwrap_or_else(|| "".into()),
|
||||
secrets.get("app_id").cloned().unwrap_or_default(),
|
||||
secrets.get("app_secret").cloned().unwrap_or_default(),
|
||||
);
|
||||
}
|
||||
("http://localhost:7880".to_string(), String::new(), String::new())
|
||||
("".to_string(), String::new(), String::new())
|
||||
}
|
||||
|
||||
pub fn get_vectordb_config_sync(&self) -> (String, Option<String>) {
|
||||
|
|
@ -550,11 +574,11 @@ impl SecretsManager {
|
|||
});
|
||||
if let Ok(Some(secrets)) = rx.recv() {
|
||||
return (
|
||||
secrets.get("url").cloned().unwrap_or_else(|| "http://localhost:6333".into()),
|
||||
secrets.get("url").cloned().unwrap_or_else(|| "".into()),
|
||||
secrets.get("api_key").cloned(),
|
||||
);
|
||||
}
|
||||
("http://localhost:6333".to_string(), None)
|
||||
("".to_string(), None)
|
||||
}
|
||||
|
||||
pub fn get_observability_config_sync(&self) -> (String, String, String, String) {
|
||||
|
|
@ -575,13 +599,13 @@ impl SecretsManager {
|
|||
});
|
||||
if let Ok(Some(secrets)) = rx.recv() {
|
||||
return (
|
||||
secrets.get("url").cloned().unwrap_or_else(|| "http://localhost:8086".into()),
|
||||
secrets.get("url").cloned().unwrap_or_else(|| "".into()),
|
||||
secrets.get("org").cloned().unwrap_or_else(|| "system".into()),
|
||||
secrets.get("bucket").cloned().unwrap_or_else(|| "metrics".into()),
|
||||
secrets.get("token").cloned().unwrap_or_default(),
|
||||
);
|
||||
}
|
||||
("http://localhost:8086".to_string(), "system".to_string(), "metrics".to_string(), String::new())
|
||||
("".to_string(), "system".to_string(), "metrics".to_string(), String::new())
|
||||
}
|
||||
|
||||
pub fn get_alm_config(&self) -> (String, String, String) {
|
||||
|
|
@ -602,12 +626,12 @@ impl SecretsManager {
|
|||
});
|
||||
if let Ok(Some(secrets)) = rx.recv() {
|
||||
return (
|
||||
secrets.get("url").cloned().unwrap_or_else(|| "http://localhost:9000".into()),
|
||||
secrets.get("url").cloned().unwrap_or_else(|| "".into()),
|
||||
secrets.get("token").cloned().unwrap_or_default(),
|
||||
secrets.get("default_org").cloned().unwrap_or_default(),
|
||||
);
|
||||
}
|
||||
("http://localhost:9000".to_string(), String::new(), String::new())
|
||||
("".to_string(), String::new(), String::new())
|
||||
}
|
||||
|
||||
pub fn get_jwt_secret_sync(&self) -> String {
|
||||
|
|
@ -712,12 +736,14 @@ impl SecretsManager {
|
|||
secrets.insert("username".into(), "gbuser".into());
|
||||
secrets.insert("password".into(), "changeme".into());
|
||||
}
|
||||
"directory" | "gbo/directory" | "system/directory" => {
|
||||
secrets.insert("url".into(), "http://localhost:9000".into());
|
||||
secrets.insert("project_id".into(), String::new());
|
||||
secrets.insert("client_id".into(), String::new());
|
||||
secrets.insert("client_secret".into(), String::new());
|
||||
}
|
||||
"directory" | "gbo/directory" | "system/directory" => {
|
||||
secrets.insert("url".into(), "".into());
|
||||
secrets.insert("host".into(), "localhost".into());
|
||||
secrets.insert("port".into(), "9000".into());
|
||||
secrets.insert("project_id".into(), String::new());
|
||||
secrets.insert("client_id".into(), String::new());
|
||||
secrets.insert("client_secret".into(), String::new());
|
||||
}
|
||||
"drive" | "gbo/drive" | "system/drive" => {
|
||||
secrets.insert("host".into(), "localhost".into());
|
||||
secrets.insert("port".into(), "9000".into());
|
||||
|
|
@ -737,35 +763,35 @@ impl SecretsManager {
|
|||
secrets.insert("smtp_from".into(), String::new());
|
||||
}
|
||||
"llm" | "gbo/llm" | "system/llm" => {
|
||||
secrets.insert("url".into(), "http://localhost:8081".into());
|
||||
secrets.insert("url".into(), "".into());
|
||||
secrets.insert("model".into(), "gpt-4".into());
|
||||
secrets.insert("openai_key".into(), String::new());
|
||||
secrets.insert("anthropic_key".into(), String::new());
|
||||
secrets.insert("ollama_url".into(), "http://localhost:11434".into());
|
||||
secrets.insert("ollama_url".into(), "".into());
|
||||
}
|
||||
"encryption" | "gbo/encryption" | "system/encryption" => {
|
||||
secrets.insert("master_key".into(), String::new());
|
||||
}
|
||||
"meet" | "gbo/meet" | "system/meet" => {
|
||||
secrets.insert("url".into(), "http://localhost:7880".into());
|
||||
secrets.insert("url".into(), "".into());
|
||||
secrets.insert("app_id".into(), String::new());
|
||||
secrets.insert("app_secret".into(), String::new());
|
||||
}
|
||||
"vectordb" | "gbo/vectordb" | "system/vectordb" => {
|
||||
secrets.insert("url".to_string(), "http://localhost:6333".into());
|
||||
secrets.insert("url".to_string(), "".into());
|
||||
secrets.insert("host".to_string(), "localhost".into());
|
||||
secrets.insert("port".to_string(), "6333".into());
|
||||
secrets.insert("grpc_port".to_string(), "6334".into());
|
||||
secrets.insert("api_key".to_string(), String::new());
|
||||
}
|
||||
"observability" | "gbo/observability" | "system/observability" => {
|
||||
secrets.insert("url".into(), "http://localhost:8086".into());
|
||||
secrets.insert("url".into(), "".into());
|
||||
secrets.insert("org".into(), "system".into());
|
||||
secrets.insert("bucket".into(), "metrics".into());
|
||||
secrets.insert("token".into(), String::new());
|
||||
}
|
||||
"alm" | "gbo/alm" | "system/alm" => {
|
||||
secrets.insert("url".into(), "http://localhost:3000".into());
|
||||
secrets.insert("url".into(), "".into());
|
||||
secrets.insert("token".into(), String::new());
|
||||
secrets.insert("default_org".into(), String::new());
|
||||
}
|
||||
|
|
@ -779,14 +805,14 @@ impl SecretsManager {
|
|||
secrets.insert("secret_key".into(), String::new());
|
||||
}
|
||||
"app" | "gbo/app" | "system/app" => {
|
||||
secrets.insert("url".into(), "http://localhost:8080".into());
|
||||
secrets.insert("url".into(), "".into());
|
||||
secrets.insert("environment".into(), "development".into());
|
||||
}
|
||||
"jwt" | "gbo/jwt" | "system/jwt" => {
|
||||
secrets.insert("secret".into(), String::new());
|
||||
}
|
||||
"models" | "gbo/models" | "system/models" => {
|
||||
secrets.insert("url".into(), "http://localhost:8001".into());
|
||||
secrets.insert("url".into(), "".into());
|
||||
}
|
||||
_ => {
|
||||
log::debug!("No default values for secret path: {}", path);
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ pub async fn send_invitation_email(
|
|||
custom_message: Option<String>,
|
||||
invitation_id: Uuid,
|
||||
) -> Result<(), String> {
|
||||
let smtp = crate::core::secrets::SecretsManager::from_env()
|
||||
let smtp = crate::core::secrets::SecretsManager::get()
|
||||
.ok()
|
||||
.and_then(|sm| {
|
||||
let sm_owned = sm.clone();
|
||||
|
|
@ -28,9 +28,7 @@ pub async fn send_invitation_email(
|
|||
.enable_all()
|
||||
.build();
|
||||
let result = if let Ok(rt) = rt {
|
||||
rt.block_on(async move {
|
||||
sm_owned.get_secret(crate::core::secrets::SecretPaths::EMAIL).await.ok()
|
||||
})
|
||||
rt.block_on(async move { sm_owned.get_secret(crate::core::secrets::SecretPaths::EMAIL).await.ok() })
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
|
|||
|
|
@ -250,13 +250,13 @@ impl Default for TestAppStateBuilder {
|
|||
#[cfg(feature = "directory")]
|
||||
pub fn create_mock_auth_service() -> AuthService {
|
||||
let config = ZitadelConfig {
|
||||
issuer_url: "http://localhost:9000".to_string(),
|
||||
issuer: "http://localhost:9000".to_string(),
|
||||
issuer_url: "".to_string(),
|
||||
issuer: "".to_string(),
|
||||
client_id: "mock_client_id".to_string(),
|
||||
client_secret: "mock_client_secret".to_string(),
|
||||
redirect_uri: "http://localhost:3000/callback".to_string(),
|
||||
redirect_uri: "/callback".to_string(),
|
||||
project_id: "mock_project_id".to_string(),
|
||||
api_url: "http://localhost:9000".to_string(),
|
||||
api_url: "".to_string(),
|
||||
service_account_key: None,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ static SECRETS_MANAGER: std::sync::LazyLock<Arc<RwLock<Option<SecretsManager>>>>
|
|||
std::sync::LazyLock::new(|| Arc::new(RwLock::new(None)));
|
||||
|
||||
pub async fn init_secrets_manager() -> Result<()> {
|
||||
let manager = SecretsManager::from_env()?;
|
||||
let manager = SecretsManager::get()?.clone();
|
||||
let mut guard = SECRETS_MANAGER.write().map_err(|e| anyhow::anyhow!("Lock poisoned: {}", e))?;
|
||||
*guard = Some(manager);
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -490,16 +490,7 @@ impl ApiUrls {
|
|||
pub struct InternalUrls;
|
||||
|
||||
impl InternalUrls {
|
||||
pub const DIRECTORY_BASE: &'static str = "http://localhost:8300";
|
||||
pub const DATABASE: &'static str = "postgres://localhost:5432";
|
||||
pub const CACHE: &'static str = "redis://localhost:6379";
|
||||
pub const DRIVE: &'static str = "http://localhost:9100";
|
||||
pub const EMAIL: &'static str = "http://localhost:8025";
|
||||
pub const LLM: &'static str = "http://localhost:8081";
|
||||
pub const EMBEDDING: &'static str = "http://localhost:8082";
|
||||
pub const QDRANT: &'static str = "http://localhost:6334";
|
||||
pub const FORGEJO: &'static str = "http://localhost:3000";
|
||||
pub const LIVEKIT: &'static str = "http://localhost:7880";
|
||||
// No localhost defaults - services must be configured via Vault or env vars
|
||||
pub const BOTMODELS_VISION_QRCODE: &'static str = "/api/vision/qrcode";
|
||||
pub const BOTMODELS_SPEECH_TO_TEXT: &'static str = "/api/speech/to-text";
|
||||
pub const BOTMODELS_VISION_DESCRIBE_VIDEO: &'static str = "/api/vision/describe-video";
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ fn save_setup_credentials(result: &BootstrapResult) {
|
|||
║ Password: {:<46}║
|
||||
║ Email: {:<46}║
|
||||
║ ║
|
||||
║ 🌐 LOGIN NOW: http://localhost:8080/suite/login ║
|
||||
║ 🌐 LOGIN NOW: /suite/login ║
|
||||
║ ║
|
||||
╚════════════════════════════════════════════════════════════╝
|
||||
|
||||
|
|
@ -358,7 +358,7 @@ fn print_bootstrap_credentials(result: &BootstrapResult) {
|
|||
println!("║{:^60}║", "");
|
||||
println!("║ {:56}║", "🌐 LOGIN NOW:");
|
||||
println!("║{:^60}║", "");
|
||||
println!("║ {:56}║", "http://localhost:8080/suite/login");
|
||||
println!("║ {:56}║", "/suite/login");
|
||||
println!("║{:^60}║", "");
|
||||
println!("╠{}╣", separator);
|
||||
println!("║{:^60}║", "");
|
||||
|
|
|
|||
|
|
@ -65,8 +65,8 @@ fn is_tracking_pixel_enabled(state: &Arc<AppState>, bot_id: Option<Uuid>) -> boo
|
|||
fn inject_tracking_pixel(html_body: &str, tracking_id: &str, state: &Arc<AppState>) -> String {
|
||||
let config_manager = crate::core::config::ConfigManager::new(state.conn.clone());
|
||||
let base_url = config_manager
|
||||
.get_config(&Uuid::nil(), "server-url", Some("http://localhost:9000"))
|
||||
.unwrap_or_else(|_| "http://localhost:9000".to_string());
|
||||
.get_config(&Uuid::nil(), "server-url", Some(""))
|
||||
.unwrap_or_else(|_| "".to_string());
|
||||
|
||||
let pixel_url = format!("{}/api/email/tracking/pixel/{}", base_url, tracking_id);
|
||||
let pixel_html = format!(
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ pub fn is_tracking_pixel_enabled(state: &Arc<AppState>, bot_id: Option<Uuid>) ->
|
|||
pub fn inject_tracking_pixel(html_body: &str, tracking_id: &str, state: &Arc<AppState>) -> String {
|
||||
let config_manager = crate::core::config::ConfigManager::new(state.conn.clone());
|
||||
let base_url = config_manager
|
||||
.get_config(&Uuid::nil(), "server-url", Some("http://localhost:9000"))
|
||||
.unwrap_or_else(|_| "http://localhost:9000".to_string());
|
||||
.get_config(&Uuid::nil(), "server-url", Some(""))
|
||||
.unwrap_or_else(|_| "".to_string());
|
||||
|
||||
let pixel_url = format!("{}/api/email/tracking/pixel/{}", base_url, tracking_id);
|
||||
let pixel_html = format!(
|
||||
|
|
|
|||
|
|
@ -421,11 +421,11 @@ impl EmailEmbeddingGenerator {
|
|||
}
|
||||
|
||||
pub async fn generate_text_embedding(&self, text: &str) -> Result<Vec<f32>> {
|
||||
let embedding_url = if let Ok(sm) = crate::core::secrets::SecretsManager::from_env() {
|
||||
let embedding_url = if let Ok(sm) = crate::core::secrets::SecretsManager::get() {
|
||||
let (llm_url, _, _, _, ollama_url) = sm.get_llm_config();
|
||||
if !ollama_url.is_empty() { ollama_url } else { llm_url }
|
||||
} else {
|
||||
"http://localhost:8082".to_string()
|
||||
"".to_string()
|
||||
};
|
||||
match self.generate_local_embedding(text, &embedding_url).await {
|
||||
Ok(embedding) => Ok(embedding),
|
||||
|
|
|
|||
|
|
@ -45,14 +45,14 @@ pub async fn ensure_llama_servers_running(
|
|||
.get_config(&default_bot_id, "llm-server", Some("true"))
|
||||
.unwrap_or_else(|_| "true".to_string()),
|
||||
config_manager
|
||||
.get_config(&default_bot_id, "llm-url", Some("http://localhost:8081"))
|
||||
.unwrap_or_else(|_| "http://localhost:8081".to_string()),
|
||||
.get_config(&default_bot_id, "llm-url", Some(""))
|
||||
.unwrap_or_else(|_| "".to_string()),
|
||||
config_manager
|
||||
.get_config(&default_bot_id, "llm-model", None)
|
||||
.unwrap_or_default(),
|
||||
config_manager
|
||||
.get_config(&default_bot_id, "embedding-url", Some("http://localhost:8082"))
|
||||
.unwrap_or_else(|_| "http://localhost:8082".to_string()),
|
||||
.get_config(&default_bot_id, "embedding-url", Some(""))
|
||||
.unwrap_or_else(|_| "".to_string()),
|
||||
embedding_model_result.unwrap_or_default(),
|
||||
config_manager
|
||||
.get_config(&default_bot_id, "llm-server-path", None)
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ impl LLMProvider for OpenAIClient {
|
|||
128000 // Cerebras gpt-oss models and GPT-4 variants
|
||||
} else if model.contains("gpt-3.5") {
|
||||
16385
|
||||
} else if model.starts_with("http://localhost:808") || model == "local" {
|
||||
} else if model.starts_with("") || model == "local" {
|
||||
768 // Local llama.cpp server context limit
|
||||
} else {
|
||||
32768 // Default conservative limit for modern models
|
||||
|
|
@ -378,7 +378,7 @@ impl LLMProvider for OpenAIClient {
|
|||
128000 // Cerebras gpt-oss models and GPT-4 variants
|
||||
} else if model.contains("gpt-3.5") {
|
||||
16385
|
||||
} else if model.starts_with("http://localhost:808") || model == "local" {
|
||||
} else if model.starts_with("") || model == "local" {
|
||||
768 // Local llama.cpp server context limit
|
||||
} else {
|
||||
32768 // Default conservative limit for modern models
|
||||
|
|
@ -885,10 +885,10 @@ mod tests {
|
|||
fn test_openai_client_new_custom_url() {
|
||||
let client = OpenAIClient::new(
|
||||
"test_key".to_string(),
|
||||
Some("http://localhost:9000".to_string()),
|
||||
Some("".to_string()),
|
||||
None,
|
||||
);
|
||||
assert_eq!(client.base_url, "http://localhost:9000");
|
||||
assert_eq!(client.base_url, "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -305,16 +305,16 @@ pub async fn init_redis() -> Option<Arc<redis::Client>> {
|
|||
let mut urls: Vec<String> = Vec::new();
|
||||
if let Some(url) = env_url {
|
||||
urls.push(url);
|
||||
} else if let Ok(secrets) = SecretsManager::from_env() {
|
||||
} else if let Ok(secrets) = SecretsManager::get() {
|
||||
if let Ok(data) = secrets.get_secret(SecretPaths::CACHE).await {
|
||||
let host = data.get("host").cloned().unwrap_or_else(|| "localhost".into());
|
||||
let host = data.get("host").cloned().unwrap_or_else(|| "".into());
|
||||
let port = data.get("port").and_then(|p| p.parse().ok()).unwrap_or(6379);
|
||||
urls.push(format!("redis://{}:{}", host, port));
|
||||
if let Some(pass) = data.get("password") {
|
||||
urls.push(format!("redis://:{}@{}:{}", pass, host, port));
|
||||
}
|
||||
} else {
|
||||
urls.push("redis://localhost:6379".to_string());
|
||||
urls.push(String::new());
|
||||
}
|
||||
} else {
|
||||
urls.push("redis://localhost:6379".to_string());
|
||||
|
|
@ -453,8 +453,8 @@ pub async fn create_app_state(
|
|||
url
|
||||
} else {
|
||||
config_manager
|
||||
.get_config(&default_bot_id, "llm-url", Some("http://localhost:8081"))
|
||||
.unwrap_or_else(|_| "http://localhost:8081".to_string())
|
||||
.get_config(&default_bot_id, "llm-url", Some(""))
|
||||
.unwrap_or_else(|_| "".to_string())
|
||||
};
|
||||
info!("LLM URL: {}", llm_url);
|
||||
|
||||
|
|
@ -486,8 +486,8 @@ pub async fn create_app_state(
|
|||
&& !llm_url.contains("127.0.0.1")
|
||||
&& (llm_url.contains("api.z.ai") || llm_url.contains("openai.com") || llm_url.contains("anthropic.com"))
|
||||
{
|
||||
warn!("External LLM URL configured ({}), but no API key provided. Falling back to local LLM at http://localhost:8081", llm_url);
|
||||
"http://localhost:8081".to_string()
|
||||
warn!("External LLM URL configured ({}), but no API key provided. Falling back to local LLM at ", llm_url);
|
||||
"".to_string()
|
||||
} else {
|
||||
llm_url
|
||||
};
|
||||
|
|
@ -660,7 +660,7 @@ fn init_directory_service() -> Result<(Arc<Mutex<crate::directory::AuthService>>
|
|||
let base_url = json
|
||||
.get("base_url")
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or("http://localhost:8300");
|
||||
.unwrap_or("");
|
||||
let client_id = json.get("client_id").and_then(|v| v.as_str()).unwrap_or("");
|
||||
let client_secret = json
|
||||
.get("client_secret")
|
||||
|
|
@ -703,13 +703,13 @@ fn init_directory_service() -> Result<(Arc<Mutex<crate::directory::AuthService>>
|
|||
#[cfg(feature = "directory")]
|
||||
fn default_zitadel_config() -> crate::directory::ZitadelConfig {
|
||||
crate::directory::ZitadelConfig {
|
||||
issuer_url: "http://localhost:8300".to_string(),
|
||||
issuer: "http://localhost:8300".to_string(),
|
||||
issuer_url: "".to_string(),
|
||||
issuer: "".to_string(),
|
||||
client_id: String::new(),
|
||||
client_secret: String::new(),
|
||||
redirect_uri: "http://localhost:8300/callback".to_string(),
|
||||
redirect_uri: "/callback".to_string(),
|
||||
project_id: "default".to_string(),
|
||||
api_url: "http://localhost:8300".to_string(),
|
||||
api_url: "".to_string(),
|
||||
service_account_key: None,
|
||||
}
|
||||
}
|
||||
|
|
@ -787,9 +787,9 @@ fn init_llm_provider(
|
|||
.get_config(
|
||||
&bot_id,
|
||||
"embedding-url",
|
||||
Some("http://localhost:8082"),
|
||||
Some(""),
|
||||
)
|
||||
.unwrap_or_else(|_| "http://localhost:8082".to_string());
|
||||
.unwrap_or_else(|_| "".to_string());
|
||||
let embedding_model = config_manager
|
||||
.get_config(&bot_id, "embedding-model", Some("all-MiniLM-L6-v2"))
|
||||
.unwrap_or_else(|_| "all-MiniLM-L6-v2".to_string());
|
||||
|
|
|
|||
|
|
@ -161,8 +161,8 @@ async fn get_llm_config(state: &Arc<AppState>, bot_id: Uuid) -> Result<(String,
|
|||
let config = ConfigManager::new(state.conn.clone());
|
||||
|
||||
let llm_url = config
|
||||
.get_config(&bot_id, "llm-url", Some("http://localhost:8081"))
|
||||
.unwrap_or_else(|_| "http://localhost:8081".to_string());
|
||||
.get_config(&bot_id, "llm-url", Some(""))
|
||||
.unwrap_or_else(|_| "".to_string());
|
||||
|
||||
let llm_model = config
|
||||
.get_config(&bot_id, "llm-model", None)
|
||||
|
|
|
|||
|
|
@ -97,8 +97,8 @@ pub async fn send_campaign_email(
|
|||
|
||||
let config = ConfigManager::new(state.conn.clone());
|
||||
let base_url = config
|
||||
.get_config(&bot_id, "server-url", Some("http://localhost:3000"))
|
||||
.unwrap_or_else(|_| "http://localhost:3000".to_string());
|
||||
.get_config(&bot_id, "server-url", Some(""))
|
||||
.unwrap_or_else(|_| "".to_string());
|
||||
|
||||
let body_html = payload
|
||||
.body_html
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@ impl Default for ExporterConfig {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
exporter_type: ExporterType::Otlp,
|
||||
endpoint: "http://localhost:4317".to_string(),
|
||||
endpoint: "".to_string(),
|
||||
headers: HashMap::new(),
|
||||
batch_size: 512,
|
||||
flush_interval_ms: 5000,
|
||||
|
|
|
|||
|
|
@ -100,9 +100,9 @@ impl CorsConfig {
|
|||
pub fn development() -> Self {
|
||||
Self {
|
||||
allowed_origins: vec![
|
||||
"http://localhost:3000".to_string(),
|
||||
"http://localhost:8080".to_string(),
|
||||
"http://localhost:9000".to_string(),
|
||||
"".to_string(),
|
||||
"".to_string(),
|
||||
"".to_string(),
|
||||
"http://127.0.0.1:3000".to_string(),
|
||||
"http://127.0.0.1:8080".to_string(),
|
||||
"http://127.0.0.1:9000".to_string(),
|
||||
|
|
@ -502,7 +502,7 @@ mod tests {
|
|||
fn test_development_config() {
|
||||
let config = CorsConfig::development();
|
||||
assert!(!config.allowed_origins.is_empty());
|
||||
assert!(config.allowed_origins.contains(&"http://localhost:3000".to_string()));
|
||||
assert!(config.allowed_origins.contains(&"".to_string()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -542,7 +542,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_valid_origin_format() {
|
||||
assert!(is_valid_origin_format("https://example.com"));
|
||||
assert!(is_valid_origin_format("http://localhost:3000"));
|
||||
assert!(is_valid_origin_format(""));
|
||||
assert!(is_valid_origin_format("https://api.example.com:8443"));
|
||||
|
||||
assert!(!is_valid_origin_format("ftp://example.com"));
|
||||
|
|
@ -557,7 +557,7 @@ mod tests {
|
|||
.allow_localhost(true);
|
||||
|
||||
assert!(validator.is_allowed("https://example.com"));
|
||||
assert!(validator.is_allowed("http://localhost:3000"));
|
||||
assert!(validator.is_allowed(""));
|
||||
assert!(!validator.is_allowed("https://evil.com"));
|
||||
}
|
||||
|
||||
|
|
@ -573,7 +573,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_localhost_detection() {
|
||||
assert!(is_localhost_origin("http://localhost"));
|
||||
assert!(is_localhost_origin("http://localhost:3000"));
|
||||
assert!(is_localhost_origin(""));
|
||||
assert!(is_localhost_origin("https://localhost:8443"));
|
||||
assert!(is_localhost_origin("http://127.0.0.1"));
|
||||
assert!(is_localhost_origin("http://127.0.0.1:9000"));
|
||||
|
|
@ -584,7 +584,7 @@ mod tests {
|
|||
fn test_extract_host() {
|
||||
assert_eq!(extract_host("https://example.com"), Some("example.com"));
|
||||
assert_eq!(extract_host("https://example.com:8443"), Some("example.com"));
|
||||
assert_eq!(extract_host("http://localhost:3000"), Some("localhost"));
|
||||
assert_eq!(extract_host(""), Some("localhost"));
|
||||
assert_eq!(extract_host("invalid"), None);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,11 +30,12 @@ pub struct TlsIntegration {
|
|||
|
||||
impl TlsIntegration {
|
||||
pub fn new(tls_enabled: bool) -> Self {
|
||||
let (qdrant_url, _) = if let Ok(sm) = crate::core::secrets::SecretsManager::from_env() {
|
||||
sm.get_vectordb_config_sync()
|
||||
} else {
|
||||
("http://localhost:6333".to_string(), None)
|
||||
};
|
||||
let sm = crate::core::secrets::SecretsManager::get().ok();
|
||||
|
||||
let (qdrant_url, _) = sm
|
||||
.as_ref()
|
||||
.map(|sm| sm.get_vectordb_config_sync())
|
||||
.unwrap_or((String::new(), None));
|
||||
let qdrant_secure = qdrant_url.replace("http://", "https://");
|
||||
let qdrant_port: u16 = qdrant_url
|
||||
.split(':')
|
||||
|
|
@ -47,18 +48,13 @@ impl TlsIntegration {
|
|||
.and_then(|p| p.parse().ok())
|
||||
.unwrap_or(6334);
|
||||
|
||||
let (llm_url, _, _, _, _) = if let Ok(sm) = crate::core::secrets::SecretsManager::from_env()
|
||||
{
|
||||
sm.get_llm_config()
|
||||
} else {
|
||||
(
|
||||
"http://localhost:8081".to_string(),
|
||||
"gpt-4".to_string(),
|
||||
None,
|
||||
None,
|
||||
"http://localhost:11434".to_string(),
|
||||
)
|
||||
};
|
||||
let (llm_url, _, _, _, _) = sm.as_ref().map(|sm| sm.get_llm_config()).unwrap_or((
|
||||
String::new(),
|
||||
String::new(),
|
||||
None,
|
||||
None,
|
||||
String::new(),
|
||||
));
|
||||
let llm_secure = llm_url.replace("http://", "https://");
|
||||
let llm_port: u16 = llm_url
|
||||
.split(':')
|
||||
|
|
@ -71,55 +67,41 @@ impl TlsIntegration {
|
|||
.and_then(|p| p.parse().ok())
|
||||
.unwrap_or(8444);
|
||||
|
||||
let (cache_host, cache_port, _) =
|
||||
if let Ok(sm) = crate::core::secrets::SecretsManager::from_env() {
|
||||
sm.get_cache_config()
|
||||
} else {
|
||||
("localhost".to_string(), 6379, None)
|
||||
};
|
||||
let (cache_host, cache_port, _) = sm
|
||||
.as_ref()
|
||||
.map(|sm| sm.get_cache_config())
|
||||
.and_then(|r| r.ok())
|
||||
.unwrap_or((String::new(), 6379, None));
|
||||
let cache_tls_port = cache_port + 1;
|
||||
|
||||
let (db_host, db_port, _, _, _) =
|
||||
if let Ok(sm) = crate::core::secrets::SecretsManager::from_env() {
|
||||
sm.get_database_config_sync()
|
||||
} else {
|
||||
(
|
||||
"localhost".to_string(),
|
||||
5432,
|
||||
"botserver".to_string(),
|
||||
"gbuser".to_string(),
|
||||
"changeme".to_string(),
|
||||
)
|
||||
};
|
||||
let (db_host, db_port, _, _, _) = sm
|
||||
.as_ref()
|
||||
.map(|sm| sm.get_database_config_sync())
|
||||
.and_then(|r| r.ok())
|
||||
.unwrap_or((
|
||||
String::new(),
|
||||
5432,
|
||||
String::new(),
|
||||
String::new(),
|
||||
String::new(),
|
||||
));
|
||||
let db_tls_port = db_port + 1;
|
||||
|
||||
let (drive_host, _drive_accesskey, _drive_secret) =
|
||||
if let Ok(sm) = crate::core::secrets::SecretsManager::from_env() {
|
||||
sm.get_drive_config()
|
||||
} else {
|
||||
(
|
||||
"localhost:9100".to_string(),
|
||||
"minioadmin".to_string(),
|
||||
"minioadmin".to_string(),
|
||||
)
|
||||
};
|
||||
let (drive_host, _, _) = sm
|
||||
.as_ref()
|
||||
.map(|sm| sm.get_drive_config())
|
||||
.and_then(|r| r.ok())
|
||||
.unwrap_or((String::new(), String::new(), String::new()));
|
||||
let drive_port: u16 = drive_host
|
||||
.split(':')
|
||||
.next_back()
|
||||
.and_then(|p| p.parse().ok())
|
||||
.unwrap_or(9100);
|
||||
|
||||
let (directory_url, _, _, _) =
|
||||
if let Ok(sm) = crate::core::secrets::SecretsManager::from_env() {
|
||||
sm.get_directory_config_sync()
|
||||
} else {
|
||||
(
|
||||
"http://localhost:9000".to_string(),
|
||||
String::new(),
|
||||
String::new(),
|
||||
String::new(),
|
||||
)
|
||||
};
|
||||
let (directory_url, _, _, _) = sm
|
||||
.as_ref()
|
||||
.map(|sm| sm.get_directory_config_sync())
|
||||
.unwrap_or((String::new(), String::new(), String::new(), String::new()));
|
||||
let directory_secure = directory_url.replace("http://", "https://");
|
||||
let directory_port: u16 = directory_url
|
||||
.split(':')
|
||||
|
|
@ -137,8 +119,8 @@ impl TlsIntegration {
|
|||
services.insert(
|
||||
"api".to_string(),
|
||||
ServiceUrls {
|
||||
original: "http://localhost:8080".to_string(),
|
||||
secure: "https://localhost:8443".to_string(),
|
||||
original: String::new(),
|
||||
secure: String::new(),
|
||||
port: 8080,
|
||||
tls_port: 8443,
|
||||
},
|
||||
|
|
@ -157,8 +139,8 @@ impl TlsIntegration {
|
|||
services.insert(
|
||||
"embedding".to_string(),
|
||||
ServiceUrls {
|
||||
original: "http://localhost:8082".to_string(),
|
||||
secure: "https://localhost:8445".to_string(),
|
||||
original: String::new(),
|
||||
secure: String::new(),
|
||||
port: 8082,
|
||||
tls_port: 8445,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ pub struct ZitadelAuthConfig {
|
|||
impl Default for ZitadelAuthConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
issuer_url: "http://localhost:9000".to_string(),
|
||||
api_url: "http://localhost:9000".to_string(),
|
||||
issuer_url: "".to_string(),
|
||||
api_url: "".to_string(),
|
||||
client_id: String::new(),
|
||||
client_secret: String::new(),
|
||||
project_id: String::new(),
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ pub struct TimeSeriesConfig {
|
|||
impl Default for TimeSeriesConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
url: "http://localhost:8086".to_string(),
|
||||
url: "".to_string(),
|
||||
token: String::new(),
|
||||
org: "system".to_string(),
|
||||
bucket: "metrics".to_string(),
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ impl EmbeddingGenerator {
|
|||
}
|
||||
|
||||
pub async fn generate_text_embedding(&self, text: &str) -> Result<Vec<f32>> {
|
||||
let embedding_url = "http://localhost:8082".to_string();
|
||||
let embedding_url = "".to_string();
|
||||
match self.generate_local_embedding(text, &embedding_url).await {
|
||||
Ok(embedding) => Ok(embedding),
|
||||
Err(e) => {
|
||||
|
|
|
|||
|
|
@ -586,7 +586,7 @@ impl VideoEngine {
|
|||
};
|
||||
|
||||
let botmodels_url =
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "http://localhost:8001".to_string());
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "".to_string());
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let response = client
|
||||
|
|
@ -691,7 +691,7 @@ impl VideoEngine {
|
|||
output_dir: &str,
|
||||
) -> Result<TTSResponse, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let botmodels_url =
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "http://localhost:8001".to_string());
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "".to_string());
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let response = client
|
||||
|
|
@ -1022,7 +1022,7 @@ impl VideoEngine {
|
|||
let clip = clips.iter().find(|c| c.id == clip_id).ok_or("Clip not found")?;
|
||||
|
||||
let botmodels_url =
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "http://localhost:8001".to_string());
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "".to_string());
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let response = client
|
||||
|
|
@ -1056,7 +1056,7 @@ impl VideoEngine {
|
|||
let clip = clips.iter().find(|c| c.id == req.clip_id).ok_or("Clip not found")?;
|
||||
|
||||
let botmodels_url =
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "http://localhost:8001".to_string());
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "".to_string());
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let response = client
|
||||
|
|
@ -1097,7 +1097,7 @@ impl VideoEngine {
|
|||
let track = tracks.iter().find(|t| t.id == audio_track_id).ok_or("Audio track not found")?;
|
||||
|
||||
let botmodels_url =
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "http://localhost:8001".to_string());
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "".to_string());
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let response = client
|
||||
|
|
@ -1143,7 +1143,7 @@ impl VideoEngine {
|
|||
let track = tracks.iter().find(|t| t.id == audio_track_id).ok_or("Audio track not found")?;
|
||||
|
||||
let botmodels_url =
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "http://localhost:8001".to_string());
|
||||
std::env::var("BOTMODELS_URL").unwrap_or_else(|_| "".to_string());
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let response = client
|
||||
|
|
|
|||
|
|
@ -992,26 +992,26 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_page_url_patterns() {
|
||||
let login = LoginPage::new("http://localhost:4242");
|
||||
let login = LoginPage::new("");
|
||||
assert_eq!(LoginPage::url_pattern(), "/login");
|
||||
assert_eq!(login.base_url(), "http://localhost:4242");
|
||||
assert_eq!(login.base_url(), "");
|
||||
|
||||
let dashboard = DashboardPage::new("http://localhost:4242");
|
||||
let dashboard = DashboardPage::new("");
|
||||
assert_eq!(DashboardPage::url_pattern(), "/dashboard");
|
||||
assert_eq!(dashboard.base_url(), "http://localhost:4242");
|
||||
assert_eq!(dashboard.base_url(), "");
|
||||
|
||||
let chat = ChatPage::new("http://localhost:4242", "test-bot");
|
||||
let chat = ChatPage::new("", "test-bot");
|
||||
assert_eq!(ChatPage::url_pattern(), "/chat/");
|
||||
assert_eq!(chat.base_url(), "http://localhost:4242");
|
||||
assert_eq!(chat.base_url(), "");
|
||||
assert_eq!(chat.bot_name(), "test-bot");
|
||||
|
||||
let queue = QueuePage::new("http://localhost:4242");
|
||||
let queue = QueuePage::new("");
|
||||
assert_eq!(QueuePage::url_pattern(), "/queue");
|
||||
assert_eq!(queue.base_url(), "http://localhost:4242");
|
||||
assert_eq!(queue.base_url(), "");
|
||||
|
||||
let bots = BotManagementPage::new("http://localhost:4242");
|
||||
let bots = BotManagementPage::new("");
|
||||
assert_eq!(BotManagementPage::url_pattern(), "/admin/bots");
|
||||
assert_eq!(bots.base_url(), "http://localhost:4242");
|
||||
assert_eq!(bots.base_url(), "");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue