use std::env; pub fn clean_database_url(url: &str) -> String { let mut cleaned = url.trim().to_string(); // 1. Strip 'psql ' command prefix if accidentally included if cleaned.to_lowercase().starts_with("psql ") { cleaned = cleaned[5..].trim().to_string(); } // 2. Strip surrounding quotes (common in shell envs) cleaned = cleaned.trim_matches(|c| c == '\'' || c == '"').to_string(); // 3. Ensure it starts with the correct scheme if !cleaned.starts_with("postgres://") && !cleaned.starts_with("postgresql://") { tracing::debug!( "Database URL scheme missing or malformed, but attempting to clean further..." ); } cleaned } pub fn database_schema() -> String { let schema = env::var("RTIX_DB_SCHEMA") .or_else(|_| env::var("INVESA_DB_SCHEMA")) .unwrap_or_else(|_| "rtix_app".to_string()); let is_valid = schema.chars().enumerate().all(|(idx, ch): (usize, char)| { ch == '_' || ch.is_ascii_alphanumeric() && (idx > 0 || ch.is_ascii_alphabetic()) }); if !is_valid { panic!("INVALID_DATABASE_SCHEMA: use only letters, numbers, and underscores, starting with a letter or underscore."); } schema } #[cfg(test)] mod tests { use super::*; #[test] fn test_clean_database_url() { // Standard URL assert_eq!( clean_database_url("postgresql://user:pass@host/db"), "postgresql://user:pass@host/db" ); // Wrapped in psql command assert_eq!( clean_database_url("psql 'postgresql://user:pass@host/db'"), "postgresql://user:pass@host/db" ); // Double quotes assert_eq!( clean_database_url("psql \"postgresql://user:pass@host/db\""), "postgresql://user:pass@host/db" ); // Whitespace and weirdness assert_eq!( clean_database_url(" psql 'postgresql://user:pass@host/db' "), "postgresql://user:pass@host/db" ); // Naked quotes without psql assert_eq!( clean_database_url("'postgresql://user:pass@host/db'"), "postgresql://user:pass@host/db" ); } }