config.rs (8777B)
1 //! Configuration file and settings management 2 use config::{Config, ConfigError, File}; 3 use serde::{Deserialize, Serialize}; 4 use std::time::Duration; 5 use tracing::warn; 6 7 #[derive(Debug, Serialize, Deserialize, Clone)] 8 #[allow(unused)] 9 pub struct Info { 10 pub relay_url: Option<String>, 11 pub name: Option<String>, 12 pub description: Option<String>, 13 pub pubkey: Option<String>, 14 pub contact: Option<String>, 15 } 16 17 #[derive(Debug, Clone, Serialize, Deserialize)] 18 #[allow(unused)] 19 pub struct Database { 20 pub data_directory: String, 21 pub in_memory: bool, 22 pub min_conn: u32, 23 pub max_conn: u32, 24 } 25 26 #[derive(Debug, Clone, Serialize, Deserialize)] 27 #[allow(unused)] 28 pub struct Network { 29 pub port: u16, 30 pub address: String, 31 pub remote_ip_header: Option<String>, // retrieve client IP from this HTTP header if present 32 pub ping_interval_seconds: u32, 33 } 34 35 #[derive(Debug, Clone, Serialize, Deserialize)] 36 #[allow(unused)] 37 pub struct Options { 38 pub reject_future_seconds: Option<usize>, // if defined, reject any events with a timestamp more than X seconds in the future 39 } 40 41 #[derive(Debug, Clone, Serialize, Deserialize)] 42 #[allow(unused)] 43 pub struct Retention { 44 // TODO: implement 45 pub max_events: Option<usize>, // max events 46 pub max_bytes: Option<usize>, // max size 47 pub persist_days: Option<usize>, // oldest message 48 pub whitelist_addresses: Option<Vec<String>>, // whitelisted addresses (never delete) 49 } 50 51 #[derive(Debug, Clone, Serialize, Deserialize)] 52 #[allow(unused)] 53 pub struct Limits { 54 pub messages_per_sec: Option<u32>, // Artificially slow down event writing to limit disk consumption (averaged over 1 minute) 55 pub max_event_bytes: Option<usize>, // Maximum size of an EVENT message 56 pub max_ws_message_bytes: Option<usize>, 57 pub max_ws_frame_bytes: Option<usize>, 58 pub broadcast_buffer: usize, // events to buffer for subscribers (prevents slow readers from consuming memory) 59 pub event_persist_buffer: usize, // events to buffer for database commits (block senders if database writes are too slow) 60 } 61 62 #[derive(Debug, Clone, Serialize, Deserialize)] 63 #[allow(unused)] 64 pub struct Authorization { 65 pub pubkey_whitelist: Option<Vec<String>>, // If present, only allow these pubkeys to publish events 66 } 67 68 #[derive(Debug, Clone, Serialize, Deserialize)] 69 #[allow(unused)] 70 pub struct Diagnostics { 71 pub tracing: bool, // enables tokio console-subscriber 72 } 73 74 #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Copy)] 75 #[serde(rename_all = "lowercase")] 76 pub enum VerifiedUsersMode { 77 Enabled, 78 Passive, 79 Disabled, 80 } 81 82 #[derive(Debug, Clone, Serialize, Deserialize)] 83 #[allow(unused)] 84 pub struct VerifiedUsers { 85 pub mode: VerifiedUsersMode, // Mode of operation: "enabled" (enforce) or "passive" (check only). If none, this is simply disabled. 86 pub domain_whitelist: Option<Vec<String>>, // If present, only allow verified users from these domains can publish events 87 pub domain_blacklist: Option<Vec<String>>, // If present, allow all verified users from any domain except these 88 pub verify_expiration: Option<String>, // how long a verification is cached for before no longer being used 89 pub verify_update_frequency: Option<String>, // how often to attempt to update verification 90 pub verify_expiration_duration: Option<Duration>, // internal result of parsing verify_expiration 91 pub verify_update_frequency_duration: Option<Duration>, // internal result of parsing verify_update_frequency 92 pub max_consecutive_failures: usize, // maximum number of verification failures in a row, before ceasing future checks 93 } 94 95 impl VerifiedUsers { 96 pub fn init(&mut self) { 97 self.verify_expiration_duration = self.verify_expiration_duration(); 98 self.verify_update_frequency_duration = self.verify_update_duration(); 99 } 100 101 #[must_use] 102 pub fn is_enabled(&self) -> bool { 103 self.mode == VerifiedUsersMode::Enabled 104 } 105 106 #[must_use] 107 pub fn is_active(&self) -> bool { 108 self.mode == VerifiedUsersMode::Enabled || self.mode == VerifiedUsersMode::Passive 109 } 110 111 #[must_use] 112 pub fn is_passive(&self) -> bool { 113 self.mode == VerifiedUsersMode::Passive 114 } 115 116 #[must_use] 117 pub fn verify_expiration_duration(&self) -> Option<Duration> { 118 self.verify_expiration 119 .as_ref() 120 .and_then(|x| parse_duration::parse(x).ok()) 121 } 122 123 #[must_use] 124 pub fn verify_update_duration(&self) -> Option<Duration> { 125 self.verify_update_frequency 126 .as_ref() 127 .and_then(|x| parse_duration::parse(x).ok()) 128 } 129 130 #[must_use] 131 pub fn is_valid(&self) -> bool { 132 self.verify_expiration_duration().is_some() && self.verify_update_duration().is_some() 133 } 134 } 135 136 #[derive(Debug, Clone, Serialize, Deserialize)] 137 #[allow(unused)] 138 pub struct Settings { 139 pub info: Info, 140 pub diagnostics: Diagnostics, 141 pub database: Database, 142 pub network: Network, 143 pub limits: Limits, 144 pub authorization: Authorization, 145 pub verified_users: VerifiedUsers, 146 pub retention: Retention, 147 pub options: Options, 148 } 149 150 impl Settings { 151 #[must_use] 152 pub fn new() -> Self { 153 let default_settings = Self::default(); 154 // attempt to construct settings with file 155 let from_file = Self::new_from_default(&default_settings); 156 match from_file { 157 Ok(f) => f, 158 Err(e) => { 159 warn!("Error reading config file ({:?})", e); 160 default_settings 161 } 162 } 163 } 164 165 fn new_from_default(default: &Settings) -> Result<Self, ConfigError> { 166 let builder = Config::builder(); 167 let config: Config = builder 168 // use defaults 169 .add_source(Config::try_from(default)?) 170 // override with file contents 171 .add_source(File::with_name("config.toml")) 172 .build()?; 173 let mut settings: Settings = config.try_deserialize()?; 174 // ensure connection pool size is logical 175 assert!( 176 settings.database.min_conn <= settings.database.max_conn, 177 "Database min_conn setting ({}) cannot exceed max_conn ({})", 178 settings.database.min_conn, 179 settings.database.max_conn 180 ); 181 // ensure durations parse 182 assert!( 183 settings.verified_users.is_valid(), 184 "VerifiedUsers time settings could not be parsed" 185 ); 186 // initialize durations for verified users 187 settings.verified_users.init(); 188 Ok(settings) 189 } 190 } 191 192 impl Default for Settings { 193 fn default() -> Self { 194 Settings { 195 info: Info { 196 relay_url: None, 197 name: Some("Unnamed nostr-rs-relay".to_owned()), 198 description: None, 199 pubkey: None, 200 contact: None, 201 }, 202 diagnostics: Diagnostics { tracing: false }, 203 database: Database { 204 data_directory: ".".to_owned(), 205 in_memory: false, 206 min_conn: 4, 207 max_conn: 128, 208 }, 209 network: Network { 210 port: 8080, 211 ping_interval_seconds: 300, 212 address: "0.0.0.0".to_owned(), 213 remote_ip_header: None, 214 }, 215 limits: Limits { 216 messages_per_sec: None, 217 max_event_bytes: Some(2 << 17), // 128K 218 max_ws_message_bytes: Some(2 << 17), // 128K 219 max_ws_frame_bytes: Some(2 << 17), // 128K 220 broadcast_buffer: 16384, 221 event_persist_buffer: 4096, 222 }, 223 authorization: Authorization { 224 pubkey_whitelist: None, // Allow any address to publish 225 }, 226 verified_users: VerifiedUsers { 227 mode: VerifiedUsersMode::Disabled, 228 domain_whitelist: None, 229 domain_blacklist: None, 230 verify_expiration: Some("1 week".to_owned()), 231 verify_update_frequency: Some("1 day".to_owned()), 232 verify_expiration_duration: None, 233 verify_update_frequency_duration: None, 234 max_consecutive_failures: 20, 235 }, 236 retention: Retention { 237 max_events: None, // max events 238 max_bytes: None, // max size 239 persist_days: None, // oldest message 240 whitelist_addresses: None, // whitelisted addresses (never delete) 241 }, 242 options: Options { 243 reject_future_seconds: None, // Reject events in the future if defined 244 }, 245 } 246 } 247 }