nostr-rs-relay

My dev fork of nostr-rs-relay
git clone git://jb55.com/nostr-rs-relay
Log | Files | Refs | README | LICENSE

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 }