Skip to main content

rush_sync_server/setup/
setup_toml.rs

1// src/setup/setup_toml.rs - Cleaned and optimized
2use crate::core::prelude::*;
3use std::path::PathBuf;
4use tokio::fs;
5
6// Consolidated DEFAULT_CONFIG - All sections in one place
7const DEFAULT_CONFIG: &str = r#"[general]
8max_messages = 1000
9typewriter_delay = 5
10input_max_length = 100
11max_history = 30
12poll_rate = 16
13log_level = "info"
14current_theme = "dark"
15
16[language]
17current = "en"
18
19# =====================================================
20# SERVER CONFIGURATION
21# =====================================================
22[server]
23# Port Management
24port_range_start = 8000      # Starting port for auto-allocation
25port_range_end = 8200        # Maximum port for auto-allocation
26max_concurrent = 50          # Maximum simultaneous servers
27shutdown_timeout = 5         # Graceful shutdown timeout (seconds)
28startup_delay_ms = 500       # Delay after server creation (milliseconds)
29workers = 1                  # Actix workers per server
30auto_open_browser = true     # Automatically open browser
31bind_address = "127.0.0.1"   # Server bind address ("0.0.0.0" for public access)
32
33# HTTPS/TLS Configuration
34enable_https = true          # Enable HTTPS support
35https_port_offset = 1000     # HTTPS port = HTTP port + offset
36cert_dir = ".rss/certs"      # Certificate storage directory
37auto_cert = true             # Generate certificates automatically
38cert_validity_days = 365     # Certificate validity (days)
39
40# Production Settings
41use_lets_encrypt = false     # Use Let's Encrypt (requires public domain)
42production_domain = "localhost"  # Production domain name
43acme_email = ""              # Email for Let's Encrypt notifications (optional)
44
45# Security: plaintext, hash ($hmac-sha256$...), or RSS_API_KEY env var
46# Generate hash: rush-sync --hash-key <your-key>
47api_key = ""                 # API key for /api/*, /.rss/*, /ws/* endpoints (empty = no auth)
48
49# Rate Limiting
50rate_limit_rps = 100         # Max requests per second per IP for /api/* endpoints
51rate_limit_enabled = true    # Enable rate limiting
52
53# =====================================================
54# REVERSE PROXY CONFIGURATION
55# =====================================================
56[proxy]
57enabled = true                  # Enable integrated reverse proxy
58port = 3000                     # Proxy listening port
59https_port_offset = 443         # Added for HTTPS offset
60bind_address = "127.0.0.1"      # Proxy bind address
61health_check_interval = 30      # Health check interval (seconds)
62timeout_ms = 5000               # Request timeout (milliseconds)
63
64# For production use:
65# port = 80                  # Standard HTTP Port
66# bind_address = "0.0.0.0"   # All interfaces (for external access)
67
68# =====================================================
69# LOGGING CONFIGURATION
70# =====================================================
71[logging]
72max_file_size_mb = 100       # Log rotation size (100MB per file)
73max_archive_files = 9        # Archive generations (9 backups)
74compress_archives = true     # GZIP compression for archives
75log_requests = true          # Enable request logging
76log_security_alerts = true  # Enable security monitoring
77log_performance = true       # Enable performance metrics
78
79# =====================================================
80# THEME DEFINITIONS
81# =====================================================
82[theme.dark]
83output_bg = "Black"
84output_text = "White"
85output_cursor = "PIPE"
86output_cursor_color = "White"
87input_bg = "White"
88input_text = "Black"
89input_cursor_prefix = "/// "
90input_cursor = "PIPE"
91input_cursor_color = "Black"
92
93[theme.light]
94output_bg = "White"
95output_text = "Black"
96output_cursor = "PIPE"
97output_cursor_color = "Black"
98input_bg = "Black"
99input_text = "White"
100input_cursor_prefix = "/// "
101input_cursor = "PIPE"
102input_cursor_color = "White"
103
104[theme.green]
105output_bg = "Black"
106output_text = "Green"
107output_cursor = "BLOCK"
108output_cursor_color = "Green"
109input_bg = "LightGreen"
110input_text = "Black"
111input_cursor_prefix = "$ "
112input_cursor = "BLOCK"
113input_cursor_color = "Black"
114
115[theme.blue]
116output_bg = "White"
117output_text = "LightBlue"
118output_cursor = "UNDERSCORE"
119output_cursor_color = "Blue"
120input_bg = "Blue"
121input_text = "White"
122input_cursor_prefix = "> "
123input_cursor = "UNDERSCORE"
124input_cursor_color = "White"
125"#;
126
127pub async fn ensure_config_exists() -> Result<PathBuf> {
128    let config_path = get_primary_config_path()?;
129
130    // Create directory if needed
131    if let Some(parent) = config_path.parent() {
132        fs::create_dir_all(parent).await.map_err(AppError::Io)?;
133    }
134
135    // Create config file if it doesn't exist
136    if !config_path.exists() {
137        fs::write(&config_path, DEFAULT_CONFIG)
138            .await
139            .map_err(AppError::Io)?;
140
141        log::info!(
142            "{}",
143            get_translation(
144                "system.config.file_created",
145                &[&config_path.display().to_string()]
146            )
147        );
148    }
149
150    Ok(config_path)
151}
152
153pub fn get_config_paths() -> Vec<PathBuf> {
154    let mut paths = Vec::new();
155
156    if let Ok(exe_path) = std::env::current_exe() {
157        if let Some(base_dir) = exe_path.parent() {
158            // Primary locations (in order of preference)
159            paths.push(base_dir.join(".rss/rush.toml"));
160            paths.push(base_dir.join("rush.toml"));
161            paths.push(base_dir.join("config/rush.toml"));
162        }
163    }
164
165    // Development fallbacks
166    #[cfg(debug_assertions)]
167    {
168        paths.push(PathBuf::from("rush.toml"));
169        paths.push(PathBuf::from("src/rush.toml"));
170    }
171
172    paths
173}
174
175fn get_primary_config_path() -> Result<PathBuf> {
176    let exe_path = std::env::current_exe().map_err(AppError::Io)?;
177    let base_dir = exe_path
178        .parent()
179        .ok_or_else(|| AppError::Validation(get_translation("system.config.dir_error", &[])))?;
180
181    Ok(base_dir.join(".rss/rush.toml"))
182}