mockforge_collab/
config.rs

1//! Configuration for collaboration server
2
3use serde::{Deserialize, Serialize};
4use std::time::Duration;
5
6/// Collaboration server configuration
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct CollabConfig {
9    /// JWT secret for authentication
10    pub jwt_secret: String,
11    /// Database URL (`SQLite` or `PostgreSQL`)
12    pub database_url: String,
13    /// Server bind address
14    pub bind_address: String,
15    /// Maximum connections per workspace
16    pub max_connections_per_workspace: usize,
17    /// Event bus capacity
18    pub event_bus_capacity: usize,
19    /// Enable auto-commit for changes
20    pub auto_commit: bool,
21    /// Session timeout duration
22    pub session_timeout: Duration,
23    /// WebSocket ping interval
24    pub websocket_ping_interval: Duration,
25    /// Maximum message size (bytes)
26    pub max_message_size: usize,
27    /// Directory for workspace storage (for `CoreBridge`)
28    pub workspace_dir: Option<String>,
29    /// Directory for backup storage
30    pub backup_dir: Option<String>,
31}
32
33impl Default for CollabConfig {
34    fn default() -> Self {
35        Self {
36            jwt_secret: "change-me-in-production".to_string(),
37            database_url: "sqlite://mockforge-collab.db".to_string(),
38            bind_address: "127.0.0.1:8080".to_string(),
39            max_connections_per_workspace: 100,
40            event_bus_capacity: 1000,
41            auto_commit: true,
42            session_timeout: Duration::from_secs(24 * 3600), // 24 hours
43            websocket_ping_interval: Duration::from_secs(30),
44            max_message_size: 1024 * 1024, // 1 MB
45            workspace_dir: Some("./workspaces".to_string()),
46            backup_dir: Some("./backups".to_string()),
47        }
48    }
49}
50
51impl CollabConfig {
52    /// Load configuration from environment variables
53    #[must_use]
54    pub fn from_env() -> Self {
55        Self {
56            jwt_secret: std::env::var("MOCKFORGE_JWT_SECRET")
57                .unwrap_or_else(|_| "change-me-in-production".to_string()),
58            database_url: std::env::var("MOCKFORGE_DATABASE_URL")
59                .unwrap_or_else(|_| "sqlite://mockforge-collab.db".to_string()),
60            bind_address: std::env::var("MOCKFORGE_BIND_ADDRESS")
61                .unwrap_or_else(|_| "127.0.0.1:8080".to_string()),
62            ..Default::default()
63        }
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::*;
70
71    #[test]
72    fn test_default_config() {
73        let config = CollabConfig::default();
74
75        assert_eq!(config.jwt_secret, "change-me-in-production");
76        assert_eq!(config.database_url, "sqlite://mockforge-collab.db");
77        assert_eq!(config.bind_address, "127.0.0.1:8080");
78        assert_eq!(config.max_connections_per_workspace, 100);
79        assert_eq!(config.event_bus_capacity, 1000);
80        assert!(config.auto_commit);
81        assert_eq!(config.session_timeout, Duration::from_secs(24 * 3600));
82        assert_eq!(config.websocket_ping_interval, Duration::from_secs(30));
83        assert_eq!(config.max_message_size, 1024 * 1024);
84        assert_eq!(config.workspace_dir, Some("./workspaces".to_string()));
85        assert_eq!(config.backup_dir, Some("./backups".to_string()));
86    }
87
88    #[test]
89    fn test_from_env_defaults() {
90        // Clear environment variables
91        std::env::remove_var("MOCKFORGE_JWT_SECRET");
92        std::env::remove_var("MOCKFORGE_DATABASE_URL");
93        std::env::remove_var("MOCKFORGE_BIND_ADDRESS");
94
95        let config = CollabConfig::from_env();
96
97        assert_eq!(config.jwt_secret, "change-me-in-production");
98        assert_eq!(config.database_url, "sqlite://mockforge-collab.db");
99        assert_eq!(config.bind_address, "127.0.0.1:8080");
100    }
101
102    #[test]
103    fn test_from_env_with_values() {
104        // Set environment variables
105        std::env::set_var("MOCKFORGE_JWT_SECRET", "test-secret");
106        std::env::set_var("MOCKFORGE_DATABASE_URL", "postgres://localhost/test");
107        std::env::set_var("MOCKFORGE_BIND_ADDRESS", "0.0.0.0:9090");
108
109        let config = CollabConfig::from_env();
110
111        assert_eq!(config.jwt_secret, "test-secret");
112        assert_eq!(config.database_url, "postgres://localhost/test");
113        assert_eq!(config.bind_address, "0.0.0.0:9090");
114
115        // Clean up
116        std::env::remove_var("MOCKFORGE_JWT_SECRET");
117        std::env::remove_var("MOCKFORGE_DATABASE_URL");
118        std::env::remove_var("MOCKFORGE_BIND_ADDRESS");
119    }
120
121    #[test]
122    fn test_config_serialization() {
123        let config = CollabConfig::default();
124        let serialized = serde_json::to_string(&config).unwrap();
125        let deserialized: CollabConfig = serde_json::from_str(&serialized).unwrap();
126
127        assert_eq!(config.jwt_secret, deserialized.jwt_secret);
128        assert_eq!(config.database_url, deserialized.database_url);
129        assert_eq!(config.bind_address, deserialized.bind_address);
130    }
131
132    #[test]
133    fn test_config_clone() {
134        let config = CollabConfig::default();
135        let cloned = config.clone();
136
137        assert_eq!(config.jwt_secret, cloned.jwt_secret);
138        assert_eq!(config.max_connections_per_workspace, cloned.max_connections_per_workspace);
139    }
140
141    #[test]
142    fn test_config_debug() {
143        let config = CollabConfig::default();
144        let debug_str = format!("{:?}", config);
145
146        assert!(debug_str.contains("CollabConfig"));
147        assert!(debug_str.contains("jwt_secret"));
148    }
149}