kych

OAuth 2.0 API for Swiyu to enable Taler integration of Swiyu for KYC (experimental)
Log | Files | Refs

config.rs (5346B)


      1 use anyhow::{Context, Result};
      2 use serde::{Deserialize, Serialize};
      3 use ini::Ini;
      4 use std::path::Path;
      5 
      6 #[derive(Debug, Clone, Serialize, Deserialize)]
      7 pub struct Config {
      8     pub server: ServerConfig,
      9     pub database: DatabaseConfig,
     10     pub crypto: CryptoConfig,
     11     pub webhook_worker: WebhookWorkerConfig,
     12 }
     13 
     14 #[derive(Debug, Clone, Serialize, Deserialize)]
     15 pub struct ServerConfig {
     16     pub host: Option<String>,
     17     pub port: Option<u16>,
     18     pub socket_path: Option<String>,
     19 }
     20 
     21 impl ServerConfig {
     22     pub fn validate(&self) -> Result<()> {
     23         let has_tcp = self.host.is_some() || self.port.is_some();
     24         let has_unix = self.socket_path.is_some();
     25 
     26         if has_tcp && has_unix {
     27             anyhow::bail!("Cannot specify both TCP (host/port) and Unix socket (socket_path)");
     28         }
     29 
     30         if !has_tcp && !has_unix {
     31             anyhow::bail!("Must specify either TCP (host/port) or Unix socket (socket_path)");
     32         }
     33 
     34         if has_tcp && (self.host.is_none() || self.port.is_none()) {
     35             anyhow::bail!("Host and port must be specified for TCP");
     36         }
     37 
     38         Ok(())
     39     }
     40 
     41     pub fn is_unix_socket(&self) -> bool {
     42         self.socket_path.is_some()
     43     }
     44 }
     45 
     46 #[derive(Debug, Clone, Serialize, Deserialize)]
     47 pub struct DatabaseConfig {
     48     pub url: String,
     49 }
     50 
     51 #[derive(Debug, Clone, Serialize, Deserialize)]
     52 pub struct CryptoConfig {
     53     pub nonce_bytes: usize,
     54     pub token_bytes: usize,
     55     pub authorization_code_bytes: usize,
     56 }
     57 
     58 #[derive(Debug, Clone, Serialize, Deserialize)]
     59 pub struct WebhookWorkerConfig {
     60     pub retry_delay_server_error: i64,
     61     pub retry_delay_forbidden: i64,
     62     pub retry_delay_other: i64,
     63     pub fallback_poll_secs: u64,
     64     pub batch_size: i64,
     65 }
     66 
     67 impl Config {
     68     pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
     69         let ini = Ini::load_from_file(path.as_ref())
     70             .context("Failed to load config file")?;
     71 
     72         let server_section = ini
     73             .section(Some("server"))
     74             .context("Missing [server] section")?;
     75 
     76         let host = server_section.get("host").map(|s| s.to_string());
     77         let port = server_section
     78             .get("port")
     79             .map(|s| s.parse::<u16>())
     80             .transpose()
     81             .context("Invalid port")?;
     82         let socket_path = server_section.get("socket_path").map(|s| s.to_string());
     83 
     84         let server = ServerConfig {
     85             host,
     86             port,
     87             socket_path,
     88         };
     89 
     90         server.validate()?;
     91 
     92         let database_section = ini
     93             .section(Some("database"))
     94             .context("Missing [database] section")?;
     95 
     96         let database = DatabaseConfig {
     97             url: database_section
     98                 .get("url")
     99                 .context("Missing database.url")?
    100                 .to_string(),
    101         };
    102 
    103         let crypto_section = ini
    104             .section(Some("crypto"))
    105             .context("Missing [crypto] section")?;
    106 
    107         let crypto = CryptoConfig {
    108             nonce_bytes: crypto_section
    109                 .get("nonce_bytes")
    110                 .context("Missing crypto.nonce_bytes")?
    111                 .parse()
    112                 .context("Invalid crypto.nonce_bytes")?,
    113             token_bytes: crypto_section
    114                 .get("token_bytes")
    115                 .context("Missing crypto.token_bytes")?
    116                 .parse()
    117                 .context("Invalid crypto.token_bytes")?,
    118             authorization_code_bytes: crypto_section
    119                 .get("authorization_code_bytes")
    120                 .context("Missing crypto.authorization_code_bytes")?
    121                 .parse()
    122                 .context("Invalid crypto.authorization_code_bytes")?,
    123         };
    124 
    125         let webhook_worker_section = ini
    126             .section(Some("webhook_worker"))
    127             .context("Missing [webhook_worker] section")?;
    128 
    129         let webhook_worker = WebhookWorkerConfig {
    130             retry_delay_server_error: webhook_worker_section
    131                 .get("retry_delay_server_error")
    132                 .context("Missing webhook_worker.retry_delay_server_error")?
    133                 .parse()
    134                 .context("Invalid webhook_worker.retry_delay_server_error")?,
    135             retry_delay_forbidden: webhook_worker_section
    136                 .get("retry_delay_forbidden")
    137                 .context("Missing webhook_worker.retry_delay_forbidden")?
    138                 .parse()
    139                 .context("Invalid webhook_worker.retry_delay_forbidden")?,
    140             retry_delay_other: webhook_worker_section
    141                 .get("retry_delay_other")
    142                 .context("Missing webhook_worker.retry_delay_other")?
    143                 .parse()
    144                 .context("Invalid webhook_worker.retry_delay_other")?,
    145             fallback_poll_secs: webhook_worker_section
    146                 .get("fallback_poll_secs")
    147                 .context("Missing webhook_worker.fallback_poll_secs")?
    148                 .parse()
    149                 .context("Invalid webhook_worker.fallback_poll_secs")?,
    150             batch_size: webhook_worker_section
    151                 .get("batch_size")
    152                 .context("Missing webhook_worker.batch_size")?
    153                 .parse()
    154                 .context("Invalid webhook_worker.batch_size")?,
    155         };
    156 
    157         Ok(Config {
    158             server,
    159             database,
    160             crypto,
    161             webhook_worker,
    162         })
    163     }
    164 }
    165