darkwing/config.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
//! Configuration management for the Darkwing application.
//!
//! This module handles all configuration settings that can be set via
//! environment variables or command line arguments using the `clap` crate. It
//! provides structured access to application settings including:
//!
//! - Environment selection (Development/Test/Production)
//! - Server configuration
//! - Database settings
//! - Redis cache settings
//! - JWT authentication settings
//! - AWS S3 configuration for both primary and backup storage
//! - Encryption keys and security settings
//! - Rate limiting parameters
//! - Monitoring configuration (Sentry)
use std::{str::FromStr, time::Duration};
use anyhow::Context;
use jsonwebtoken::Algorithm;
/// Represents the running environment of the application.
///
/// This enum is used to determine the behavior and settings of the application
/// based on its deployment environment.
#[derive(clap::ValueEnum, Clone, Debug, Copy, Default, PartialEq)]
pub enum CargoEnv {
/// Development environment for local development and testing
#[default]
Development,
/// Test environment for running automated tests
Test,
/// Production environment for deployed applications
Production,
}
/// Main configuration structure for the Darkwing application.
///
/// This struct is populated using command line arguments or environment
/// variables through the `clap` crate's derive functionality. Each field
/// corresponds to a configurable aspect of the application.
#[derive(clap::Parser, Clone, Debug, Default)]
pub struct DarkwingConfig {
/// The environment in which the application is running
#[clap(long, env = "CARGO_ENV", value_enum)]
pub cargo_env: CargoEnv,
/// Port number on which the server will listen
#[clap(long, env = "PORT", default_value = "1337")]
pub port: u16,
/// Database connection string
#[clap(long, env = "DATABASE_URL")]
pub database_url: String,
/// Maximum number of connections in the database connection pool
#[clap(long, env = "DATABASE_CONNECTION_POOL_SIZE", default_value = "5")]
pub database_connection_pool_size: u32,
/// Redis server connection string
#[clap(long, env = "REDIS_URL")]
pub redis_url: String,
/// Maximum number of connections in the Redis connection pool
#[clap(long, env = "REDIS_CONNECTION_POOL_SIZE", default_value = "5")]
pub redis_connection_pool_size: u32,
/// Default timeout for Redis operations in seconds
#[clap(long, env = "REDIS_DEFAULT_TIMEOUT_SECONDS", default_value = "5")]
pub redis_default_timeout_seconds: u64,
/// Time-to-live for Redis cache entries in seconds
#[clap(long, env = "REDIS_EXPIRATION_SECONDS", default_value = "3600")]
pub redis_expiration_seconds: u64,
/// Public key used for JWT token verification
#[clap(long, env = "JWT_TOKEN_PUBLIC_KEY")]
pub jwt_token_public_key: String,
/// Algorithm used for JWT token signing/verification (e.g., "RS256")
#[clap(long, env = "JWT_TOKEN_ALGORITHM", default_value = "RS256")]
pub jwt_token_algorithm: String,
/// Key used for encrypting configuration values
#[clap(long, env = "CONFIG_ENCRYPTION_KEY")]
pub config_encryption_key: String,
/// Maximum number of requests allowed per second for rate limiting
#[clap(long, env = "RATE_LIMIT_PER_SECOND", default_value = "100")]
pub rate_limit_per_second: u64,
/// AWS S3 access key ID for primary storage
#[clap(long, env = "AWS_S3_ACCESS_KEY_ID")]
pub aws_s3_access_key_id: String,
/// AWS S3 secret access key for primary storage
#[clap(long, env = "AWS_S3_SECRET_ACCESS_KEY")]
pub aws_s3_secret_access_key: String,
/// AWS S3 endpoint URL for primary storage
#[clap(long, env = "AWS_S3_ENDPOINT")]
pub aws_s3_endpoint: String,
/// AWS S3 bucket name for primary storage
#[clap(long, env = "AWS_S3_BUCKET")]
pub aws_s3_bucket: String,
/// AWS S3 region for primary storage
#[clap(long, env = "AWS_S3_REGION")]
pub aws_s3_region: String,
/// Public URL for accessing S3 objects
#[clap(long, env = "AWS_S3_PUBLIC_URL")]
pub aws_s3_public_url: String,
/// AWS S3 access key ID for backup storage
#[clap(long, env = "AWS_S3_BACKUP_ACCESS_KEY_ID")]
pub aws_s3_backup_access_key_id: String,
/// AWS S3 secret access key for backup storage
#[clap(long, env = "AWS_S3_BACKUP_SECRET_ACCESS_KEY")]
pub aws_s3_backup_secret_access_key: String,
/// AWS S3 endpoint URL for backup storage
#[clap(long, env = "AWS_S3_BACKUP_ENDPOINT")]
pub aws_s3_backup_endpoint: String,
/// AWS S3 bucket name for backup storage
#[clap(long, env = "AWS_S3_BACKUP_BUCKET")]
pub aws_s3_backup_bucket: String,
/// AWS S3 region for backup storage
#[clap(long, env = "AWS_S3_BACKUP_REGION")]
pub aws_s3_backup_region: String,
/// First part of the database encryption key (split for security)
#[clap(long, env = "DATABASE_ENCRYPTION_KEY_PART_1")]
pub database_encryption_key_part_1: String,
/// Second part of the database encryption key (split for security)
#[clap(long, env = "DATABASE_ENCRYPTION_KEY_PART_2")]
pub database_encryption_key_part_2: String,
/// Expiration time in seconds for S3 presigned URLs
#[clap(
long,
env = "AWS_S3_PRESIGNED_URL_EXPIRATION_SECONDS",
default_value = "300"
)]
pub aws_s3_presigned_url_expiration_seconds: u64,
/// Encryption key for S3 path encryption
#[clap(long, env = "S3_PATH_ENCRYPTION_KEY")]
pub s3_path_encryption_key: String,
/// Optional Sentry DSN for error tracking
#[clap(long, env = "SENTRY_DSN")]
pub sentry_dsn: Option<String>,
}
impl DarkwingConfig {
/// Converts the JWT algorithm string to the corresponding Algorithm enum
/// value.
pub fn get_jwt_token_algorithm(&self) -> anyhow::Result<Algorithm> {
Algorithm::from_str(&self.jwt_token_algorithm)
.context("Invalid JWT token algorithm in config transform")
}
/// Returns the Redis timeout duration.
pub fn redis_timeout(&self) -> Duration {
Duration::from_secs(self.redis_default_timeout_seconds)
}
/// Returns the expiration duration for presigned URLs.
pub fn presigned_url_expiration(&self) -> Duration {
Duration::from_secs(self.aws_s3_presigned_url_expiration_seconds)
}
}