Improve environment variable handling and reading (#5389)
* wip: better env var reading * move most env vars to env.rs * migrate more env vars * more migration * more migrations * More migration * 🦀 dotenvy is gone (almost) * 🦀 dotenvy is gone 🦀 * Fix mural source account env var handling * Remove defaults from admin key vars * dummy commit to update github pr * fix ci
This commit is contained in:
@@ -16,11 +16,11 @@ use util::gotenberg::GotenbergClient;
|
||||
|
||||
use crate::background_task::update_versions;
|
||||
use crate::database::{PgPool, ReadOnlyPgPool};
|
||||
use crate::env::ENV;
|
||||
use crate::queue::billing::{index_billing, index_subscriptions};
|
||||
use crate::queue::moderation::AutomatedModerationQueue;
|
||||
use crate::util::anrok;
|
||||
use crate::util::archon::ArchonClient;
|
||||
use crate::util::env::{parse_strings_from_var, parse_var};
|
||||
use crate::util::ratelimit::{AsyncRateLimiter, GCRAParameters};
|
||||
use sync::friends::handle_pubsub;
|
||||
|
||||
@@ -28,6 +28,7 @@ pub mod auth;
|
||||
pub mod background_task;
|
||||
pub mod clickhouse;
|
||||
pub mod database;
|
||||
pub mod env;
|
||||
pub mod file_hosting;
|
||||
pub mod models;
|
||||
pub mod queue;
|
||||
@@ -83,10 +84,7 @@ pub fn app_setup(
|
||||
gotenberg_client: GotenbergClient,
|
||||
enable_background_tasks: bool,
|
||||
) -> LabrinthConfig {
|
||||
info!(
|
||||
"Starting labrinth on {}",
|
||||
dotenvy::var("BIND_ADDR").unwrap()
|
||||
);
|
||||
info!("Starting labrinth on {}", &ENV.BIND_ADDR);
|
||||
|
||||
let automated_moderation_queue =
|
||||
web::Data::new(AutomatedModerationQueue::default());
|
||||
@@ -112,9 +110,8 @@ pub fn app_setup(
|
||||
if enable_background_tasks {
|
||||
// The interval in seconds at which the local database is indexed
|
||||
// for searching. Defaults to 1 hour if unset.
|
||||
let local_index_interval = Duration::from_secs(
|
||||
parse_var("LOCAL_INDEX_INTERVAL").unwrap_or(3600),
|
||||
);
|
||||
let local_index_interval =
|
||||
Duration::from_secs(ENV.LOCAL_INDEX_INTERVAL);
|
||||
let pool_ref = pool.clone();
|
||||
let search_config_ref = search_config.clone();
|
||||
let redis_pool_ref = redis_pool.clone();
|
||||
@@ -142,9 +139,8 @@ pub fn app_setup(
|
||||
}
|
||||
});
|
||||
|
||||
let version_index_interval = Duration::from_secs(
|
||||
parse_var("VERSION_INDEX_INTERVAL").unwrap_or(1800),
|
||||
);
|
||||
let version_index_interval =
|
||||
Duration::from_secs(ENV.VERSION_INDEX_INTERVAL);
|
||||
let pool_ref = pool.clone();
|
||||
let redis_pool_ref = redis_pool.clone();
|
||||
scheduler.run(version_index_interval, move || {
|
||||
@@ -349,188 +345,3 @@ pub fn utoipa_app_config(
|
||||
.configure(routes::v3::utoipa_config)
|
||||
.configure(routes::internal::utoipa_config);
|
||||
}
|
||||
|
||||
// This is so that env vars not used immediately don't panic at runtime
|
||||
pub fn check_env_vars() -> bool {
|
||||
let mut failed = false;
|
||||
|
||||
fn check_var<T: std::str::FromStr>(var: &str) -> bool {
|
||||
let check = parse_var::<T>(var).is_none();
|
||||
if check {
|
||||
warn!(
|
||||
"Variable `{}` missing in dotenv or not of type `{}`",
|
||||
var,
|
||||
std::any::type_name::<T>()
|
||||
);
|
||||
}
|
||||
check
|
||||
}
|
||||
|
||||
failed |= check_var::<String>("SENTRY_ENVIRONMENT");
|
||||
failed |= check_var::<String>("SENTRY_TRACES_SAMPLE_RATE");
|
||||
failed |= check_var::<String>("SITE_URL");
|
||||
failed |= check_var::<String>("CDN_URL");
|
||||
failed |= check_var::<String>("LABRINTH_ADMIN_KEY");
|
||||
failed |= check_var::<String>("LABRINTH_EXTERNAL_NOTIFICATION_KEY");
|
||||
failed |= check_var::<String>("RATE_LIMIT_IGNORE_KEY");
|
||||
failed |= check_var::<String>("DATABASE_URL");
|
||||
failed |= check_var::<String>("MEILISEARCH_READ_ADDR");
|
||||
failed |= check_var::<String>("MEILISEARCH_WRITE_ADDRS");
|
||||
failed |= check_var::<String>("MEILISEARCH_KEY");
|
||||
failed |= check_var::<String>("REDIS_URL");
|
||||
failed |= check_var::<String>("BIND_ADDR");
|
||||
failed |= check_var::<String>("SELF_ADDR");
|
||||
|
||||
failed |= check_var::<String>("STORAGE_BACKEND");
|
||||
|
||||
let storage_backend = dotenvy::var("STORAGE_BACKEND").ok();
|
||||
match storage_backend.as_deref() {
|
||||
Some("s3") => {
|
||||
let mut check_var_set = |var_prefix| {
|
||||
failed |= check_var::<String>(&format!(
|
||||
"S3_{var_prefix}_BUCKET_NAME"
|
||||
));
|
||||
failed |= check_var::<bool>(&format!(
|
||||
"S3_{var_prefix}_USES_PATH_STYLE_BUCKET"
|
||||
));
|
||||
failed |=
|
||||
check_var::<String>(&format!("S3_{var_prefix}_REGION"));
|
||||
failed |= check_var::<String>(&format!("S3_{var_prefix}_URL"));
|
||||
failed |= check_var::<String>(&format!(
|
||||
"S3_{var_prefix}_ACCESS_TOKEN"
|
||||
));
|
||||
failed |=
|
||||
check_var::<String>(&format!("S3_{var_prefix}_SECRET"));
|
||||
};
|
||||
|
||||
check_var_set("PUBLIC");
|
||||
check_var_set("PRIVATE");
|
||||
}
|
||||
Some("local") => {
|
||||
failed |= check_var::<String>("MOCK_FILE_PATH");
|
||||
}
|
||||
Some(backend) => {
|
||||
warn!(
|
||||
"Variable `STORAGE_BACKEND` contains an invalid value: {backend}. Expected \"s3\" or \"local\"."
|
||||
);
|
||||
failed |= true;
|
||||
}
|
||||
_ => {
|
||||
warn!("Variable `STORAGE_BACKEND` is not set!");
|
||||
failed |= true;
|
||||
}
|
||||
}
|
||||
|
||||
failed |= check_var::<usize>("LOCAL_INDEX_INTERVAL");
|
||||
failed |= check_var::<usize>("VERSION_INDEX_INTERVAL");
|
||||
|
||||
if parse_strings_from_var("WHITELISTED_MODPACK_DOMAINS").is_none() {
|
||||
warn!(
|
||||
"Variable `WHITELISTED_MODPACK_DOMAINS` missing in dotenv or not a json array of strings"
|
||||
);
|
||||
failed |= true;
|
||||
}
|
||||
|
||||
if parse_strings_from_var("ALLOWED_CALLBACK_URLS").is_none() {
|
||||
warn!(
|
||||
"Variable `ALLOWED_CALLBACK_URLS` missing in dotenv or not a json array of strings"
|
||||
);
|
||||
failed |= true;
|
||||
}
|
||||
|
||||
failed |= check_var::<String>("GITHUB_CLIENT_ID");
|
||||
failed |= check_var::<String>("GITHUB_CLIENT_SECRET");
|
||||
failed |= check_var::<String>("GITLAB_CLIENT_ID");
|
||||
failed |= check_var::<String>("GITLAB_CLIENT_SECRET");
|
||||
failed |= check_var::<String>("DISCORD_CLIENT_ID");
|
||||
failed |= check_var::<String>("DISCORD_CLIENT_SECRET");
|
||||
failed |= check_var::<String>("MICROSOFT_CLIENT_ID");
|
||||
failed |= check_var::<String>("MICROSOFT_CLIENT_SECRET");
|
||||
failed |= check_var::<String>("GOOGLE_CLIENT_ID");
|
||||
failed |= check_var::<String>("GOOGLE_CLIENT_SECRET");
|
||||
failed |= check_var::<String>("STEAM_API_KEY");
|
||||
|
||||
failed |= check_var::<String>("TREMENDOUS_API_URL");
|
||||
failed |= check_var::<String>("TREMENDOUS_API_KEY");
|
||||
failed |= check_var::<String>("TREMENDOUS_PRIVATE_KEY");
|
||||
|
||||
failed |= check_var::<String>("PAYPAL_API_URL");
|
||||
failed |= check_var::<String>("PAYPAL_WEBHOOK_ID");
|
||||
failed |= check_var::<String>("PAYPAL_CLIENT_ID");
|
||||
failed |= check_var::<String>("PAYPAL_CLIENT_SECRET");
|
||||
failed |= check_var::<String>("PAYPAL_NVP_USERNAME");
|
||||
failed |= check_var::<String>("PAYPAL_NVP_PASSWORD");
|
||||
failed |= check_var::<String>("PAYPAL_NVP_SIGNATURE");
|
||||
|
||||
failed |= check_var::<String>("HCAPTCHA_SECRET");
|
||||
|
||||
failed |= check_var::<String>("SMTP_USERNAME");
|
||||
failed |= check_var::<String>("SMTP_PASSWORD");
|
||||
failed |= check_var::<String>("SMTP_HOST");
|
||||
failed |= check_var::<u16>("SMTP_PORT");
|
||||
failed |= check_var::<String>("SMTP_TLS");
|
||||
failed |= check_var::<String>("SMTP_FROM_NAME");
|
||||
failed |= check_var::<String>("SMTP_FROM_ADDRESS");
|
||||
|
||||
failed |= check_var::<String>("SITE_VERIFY_EMAIL_PATH");
|
||||
failed |= check_var::<String>("SITE_RESET_PASSWORD_PATH");
|
||||
failed |= check_var::<String>("SITE_BILLING_PATH");
|
||||
|
||||
failed |= check_var::<String>("SENDY_URL");
|
||||
failed |= check_var::<String>("SENDY_LIST_ID");
|
||||
failed |= check_var::<String>("SENDY_API_KEY");
|
||||
|
||||
if parse_strings_from_var("ANALYTICS_ALLOWED_ORIGINS").is_none() {
|
||||
warn!(
|
||||
"Variable `ANALYTICS_ALLOWED_ORIGINS` missing in dotenv or not a json array of strings"
|
||||
);
|
||||
failed |= true;
|
||||
}
|
||||
|
||||
failed |= check_var::<bool>("CLICKHOUSE_REPLICATED");
|
||||
failed |= check_var::<String>("CLICKHOUSE_URL");
|
||||
failed |= check_var::<String>("CLICKHOUSE_USER");
|
||||
failed |= check_var::<String>("CLICKHOUSE_PASSWORD");
|
||||
failed |= check_var::<String>("CLICKHOUSE_DATABASE");
|
||||
|
||||
failed |= check_var::<String>("FLAME_ANVIL_URL");
|
||||
|
||||
failed |= check_var::<String>("GOTENBERG_URL");
|
||||
failed |= check_var::<String>("GOTENBERG_CALLBACK_BASE");
|
||||
failed |= check_var::<String>("GOTENBERG_TIMEOUT");
|
||||
|
||||
failed |= check_var::<String>("STRIPE_API_KEY");
|
||||
failed |= check_var::<String>("STRIPE_WEBHOOK_SECRET");
|
||||
|
||||
failed |= check_var::<String>("ADITUDE_API_KEY");
|
||||
|
||||
failed |= check_var::<String>("PYRO_API_KEY");
|
||||
|
||||
failed |= check_var::<String>("BREX_API_URL");
|
||||
failed |= check_var::<String>("BREX_API_KEY");
|
||||
|
||||
failed |= check_var::<String>("DELPHI_URL");
|
||||
|
||||
failed |= check_var::<String>("AVALARA_1099_API_URL");
|
||||
failed |= check_var::<String>("AVALARA_1099_API_KEY");
|
||||
failed |= check_var::<String>("AVALARA_1099_API_TEAM_ID");
|
||||
failed |= check_var::<String>("AVALARA_1099_COMPANY_ID");
|
||||
|
||||
failed |= check_var::<String>("ANROK_API_URL");
|
||||
failed |= check_var::<String>("ANROK_API_KEY");
|
||||
|
||||
failed |= check_var::<String>("COMPLIANCE_PAYOUT_THRESHOLD");
|
||||
|
||||
failed |= check_var::<String>("PAYOUT_ALERT_SLACK_WEBHOOK");
|
||||
|
||||
failed |= check_var::<String>("ARCHON_URL");
|
||||
|
||||
failed |= check_var::<String>("MURALPAY_API_URL");
|
||||
failed |= check_var::<String>("MURALPAY_API_KEY");
|
||||
failed |= check_var::<String>("MURALPAY_TRANSFER_API_KEY");
|
||||
failed |= check_var::<String>("MURALPAY_SOURCE_ACCOUNT_ID");
|
||||
|
||||
failed |= check_var::<String>("DEFAULT_AFFILIATE_REVENUE_SPLIT");
|
||||
|
||||
failed
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user