appconfig
This commit is contained in:
Generated
+42
@@ -611,6 +611,7 @@ dependencies = [
|
|||||||
"diesel",
|
"diesel",
|
||||||
"diesel_migrations",
|
"diesel_migrations",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
|
"envy",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hex",
|
"hex",
|
||||||
"http-body-util",
|
"http-body-util",
|
||||||
@@ -625,6 +626,7 @@ dependencies = [
|
|||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde-aux",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha2",
|
"sha2",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
@@ -1175,6 +1177,15 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "envy"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f47e0157f2cb54f5ae1bd371b30a2ae4311e1c028f575cd4e81de7353215965"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@@ -2160,6 +2171,15 @@ version = "0.1.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ordered-float"
|
||||||
|
version = "2.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "outref"
|
name = "outref"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
@@ -2904,6 +2924,28 @@ dependencies = [
|
|||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde-aux"
|
||||||
|
version = "4.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "207f67b28fe90fb596503a9bf0bf1ea5e831e21307658e177c5dfcdfc3ab8a0a"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"serde",
|
||||||
|
"serde-value",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde-value"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
|
||||||
|
dependencies = [
|
||||||
|
"ordered-float",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_core"
|
name = "serde_core"
|
||||||
version = "1.0.228"
|
version = "1.0.228"
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ aws-credential-types = "1.2"
|
|||||||
# Serialization
|
# Serialization
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
envy = "0.4"
|
||||||
|
serde-aux = "4.4"
|
||||||
|
|
||||||
# Utilities
|
# Utilities
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
|
|||||||
+96
-77
@@ -1,35 +1,60 @@
|
|||||||
use std::env;
|
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde_aux::field_attributes::deserialize_bool_from_anything;
|
||||||
|
|
||||||
use crate::db::DEFAULT_MAX_POOL_SIZE;
|
use crate::db::DEFAULT_MAX_POOL_SIZE;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
pub struct AppConfig {
|
pub struct AppConfig {
|
||||||
pub database_url: String,
|
pub database_url: String,
|
||||||
|
#[serde(default = "default_database_max_pool_size")]
|
||||||
pub database_max_pool_size: u32,
|
pub database_max_pool_size: u32,
|
||||||
|
#[serde(default = "default_server_host")]
|
||||||
pub server_host: String,
|
pub server_host: String,
|
||||||
|
#[serde(default = "default_server_port")]
|
||||||
pub server_port: u16,
|
pub server_port: u16,
|
||||||
|
#[serde(default = "default_webdav_host")]
|
||||||
pub webdav_host: String,
|
pub webdav_host: String,
|
||||||
|
#[serde(default = "default_webdav_port")]
|
||||||
pub webdav_port: u16,
|
pub webdav_port: u16,
|
||||||
pub jwt_secret: String,
|
pub jwt_secret: String,
|
||||||
|
#[serde(default = "default_jwt_issuer")]
|
||||||
pub jwt_issuer: String,
|
pub jwt_issuer: String,
|
||||||
|
#[serde(default = "default_jwt_audience")]
|
||||||
pub jwt_audience: String,
|
pub jwt_audience: String,
|
||||||
|
#[serde(default = "default_jwt_expiry_minutes")]
|
||||||
pub jwt_expiry_minutes: i64,
|
pub jwt_expiry_minutes: i64,
|
||||||
|
#[serde(default = "default_download_token_audience")]
|
||||||
pub download_token_audience: String,
|
pub download_token_audience: String,
|
||||||
|
#[serde(default = "default_download_token_expiry_minutes")]
|
||||||
pub download_token_expiry_minutes: i64,
|
pub download_token_expiry_minutes: i64,
|
||||||
|
#[serde(default = "default_refresh_token_expiry_days")]
|
||||||
pub refresh_token_expiry_days: i64,
|
pub refresh_token_expiry_days: i64,
|
||||||
|
#[serde(
|
||||||
|
default = "default_refresh_cookie_secure",
|
||||||
|
deserialize_with = "deserialize_bool_from_anything"
|
||||||
|
)]
|
||||||
pub refresh_cookie_secure: bool,
|
pub refresh_cookie_secure: bool,
|
||||||
|
#[serde(default)]
|
||||||
pub refresh_cookie_domain: Option<String>,
|
pub refresh_cookie_domain: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
pub cors_allowed_origin: Option<String>,
|
pub cors_allowed_origin: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
pub aws_endpoint_url: Option<String>,
|
pub aws_endpoint_url: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
pub aws_access_key_id: Option<String>,
|
pub aws_access_key_id: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
pub aws_secret_access_key: Option<String>,
|
pub aws_secret_access_key: Option<String>,
|
||||||
|
#[serde(default = "default_aws_region")]
|
||||||
pub aws_region: String,
|
pub aws_region: String,
|
||||||
pub s3_bucket: String,
|
pub s3_bucket: String,
|
||||||
|
#[serde(default)]
|
||||||
pub quickwit_endpoint: Option<String>,
|
pub quickwit_endpoint: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
pub quickwit_index: Option<String>,
|
pub quickwit_index: Option<String>,
|
||||||
|
#[serde(default = "default_tenant_slug")]
|
||||||
pub default_tenant_slug: String,
|
pub default_tenant_slug: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,80 +74,9 @@ impl AppConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_env() -> Result<Self> {
|
pub fn from_env() -> Result<Self> {
|
||||||
let database_url = env::var("DATABASE_URL").context("DATABASE_URL must be set")?;
|
let config: AppConfig = envy::from_env()
|
||||||
let database_max_pool_size = env::var("DATABASE_MAX_POOL_SIZE")
|
.context("failed to parse application configuration from environment")?;
|
||||||
.ok()
|
Ok(config.normalize())
|
||||||
.and_then(|value| value.parse().ok())
|
|
||||||
.unwrap_or(DEFAULT_MAX_POOL_SIZE);
|
|
||||||
let server_host = env::var("SERVER_HOST").unwrap_or_else(|_| "127.0.0.1".to_string());
|
|
||||||
let server_port = env::var("SERVER_PORT")
|
|
||||||
.unwrap_or_else(|_| "3000".to_string())
|
|
||||||
.parse()
|
|
||||||
.context("SERVER_PORT must be a valid u16")?;
|
|
||||||
let webdav_host = env::var("WEBDAV_HOST").unwrap_or_else(|_| server_host.clone());
|
|
||||||
let webdav_port = env::var("WEBDAV_PORT")
|
|
||||||
.unwrap_or_else(|_| "3001".to_string())
|
|
||||||
.parse()
|
|
||||||
.context("WEBDAV_PORT must be a valid u16")?;
|
|
||||||
let jwt_secret = env::var("JWT_SECRET").context("JWT_SECRET must be set")?;
|
|
||||||
let jwt_issuer = env::var("JWT_ISSUER").unwrap_or_else(|_| "papercrate".to_string());
|
|
||||||
let jwt_audience =
|
|
||||||
env::var("JWT_AUDIENCE").unwrap_or_else(|_| "papercrate-clients".to_string());
|
|
||||||
let jwt_expiry_minutes = env::var("JWT_EXPIRY_MINUTES")
|
|
||||||
.unwrap_or_else(|_| "60".to_string())
|
|
||||||
.parse()
|
|
||||||
.context("JWT_EXPIRY_MINUTES must be an integer")?;
|
|
||||||
let download_token_audience = env::var("DOWNLOAD_TOKEN_AUDIENCE")
|
|
||||||
.unwrap_or_else(|_| "papercrate-download".to_string());
|
|
||||||
let download_token_expiry_minutes = env::var("DOWNLOAD_TOKEN_EXPIRY_MINUTES")
|
|
||||||
.unwrap_or_else(|_| "60".to_string())
|
|
||||||
.parse()
|
|
||||||
.context("DOWNLOAD_TOKEN_EXPIRY_MINUTES must be an integer")?;
|
|
||||||
let refresh_token_expiry_days = env::var("REFRESH_TOKEN_EXPIRY_DAYS")
|
|
||||||
.unwrap_or_else(|_| "30".to_string())
|
|
||||||
.parse()
|
|
||||||
.context("REFRESH_TOKEN_EXPIRY_DAYS must be an integer")?;
|
|
||||||
let refresh_cookie_secure = env::var("REFRESH_COOKIE_SECURE")
|
|
||||||
.map(|v| v == "1" || v.eq_ignore_ascii_case("true"))
|
|
||||||
.unwrap_or(false);
|
|
||||||
let refresh_cookie_domain = env::var("REFRESH_COOKIE_DOMAIN").ok();
|
|
||||||
let cors_allowed_origin = env::var("CORS_ALLOWED_ORIGIN").ok();
|
|
||||||
let aws_endpoint_url = env::var("AWS_ENDPOINT_URL").ok();
|
|
||||||
let aws_access_key_id = env::var("AWS_ACCESS_KEY_ID").ok();
|
|
||||||
let aws_secret_access_key = env::var("AWS_SECRET_ACCESS_KEY").ok();
|
|
||||||
let aws_region = env::var("AWS_REGION").unwrap_or_else(|_| "us-east-1".to_string());
|
|
||||||
let s3_bucket = env::var("S3_BUCKET").context("S3_BUCKET must be set")?;
|
|
||||||
let quickwit_endpoint = env::var("QUICKWIT_ENDPOINT").ok();
|
|
||||||
let quickwit_index = env::var("QUICKWIT_INDEX").ok();
|
|
||||||
let default_tenant_slug =
|
|
||||||
env::var("DEFAULT_TENANT_SLUG").unwrap_or_else(|_| "admin".to_string());
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
database_url,
|
|
||||||
database_max_pool_size,
|
|
||||||
server_host,
|
|
||||||
server_port,
|
|
||||||
webdav_host,
|
|
||||||
webdav_port,
|
|
||||||
jwt_secret,
|
|
||||||
jwt_issuer,
|
|
||||||
jwt_audience,
|
|
||||||
jwt_expiry_minutes,
|
|
||||||
download_token_audience,
|
|
||||||
download_token_expiry_minutes,
|
|
||||||
refresh_token_expiry_days,
|
|
||||||
refresh_cookie_secure,
|
|
||||||
refresh_cookie_domain,
|
|
||||||
cors_allowed_origin,
|
|
||||||
aws_endpoint_url,
|
|
||||||
aws_access_key_id,
|
|
||||||
aws_secret_access_key,
|
|
||||||
aws_region,
|
|
||||||
s3_bucket,
|
|
||||||
quickwit_endpoint,
|
|
||||||
quickwit_index,
|
|
||||||
default_tenant_slug,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn redacted_database_url(&self) -> String {
|
pub fn redacted_database_url(&self) -> String {
|
||||||
@@ -130,6 +84,71 @@ impl AppConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AppConfig {
|
||||||
|
fn normalize(mut self) -> Self {
|
||||||
|
if self.webdav_host.is_empty() {
|
||||||
|
self.webdav_host = self.server_host.clone();
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_database_max_pool_size() -> u32 {
|
||||||
|
DEFAULT_MAX_POOL_SIZE
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_server_host() -> String {
|
||||||
|
"127.0.0.1".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_server_port() -> u16 {
|
||||||
|
3000
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_webdav_host() -> String {
|
||||||
|
String::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_webdav_port() -> u16 {
|
||||||
|
3001
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_jwt_issuer() -> String {
|
||||||
|
"papercrate".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_jwt_audience() -> String {
|
||||||
|
"papercrate-clients".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_jwt_expiry_minutes() -> i64 {
|
||||||
|
60
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_download_token_audience() -> String {
|
||||||
|
"papercrate-download".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_download_token_expiry_minutes() -> i64 {
|
||||||
|
60
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_refresh_token_expiry_days() -> i64 {
|
||||||
|
30
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_refresh_cookie_secure() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_aws_region() -> String {
|
||||||
|
"us-east-1".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_tenant_slug() -> String {
|
||||||
|
"admin".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
fn redact_database_url(raw: &str) -> String {
|
fn redact_database_url(raw: &str) -> String {
|
||||||
match Url::parse(raw) {
|
match Url::parse(raw) {
|
||||||
Ok(mut parsed) => {
|
Ok(mut parsed) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user