pub mod logger;
use crate::options::{DeploymentMode, RustAuthOptions};
pub fn env_var(suffix: &str) -> Option<String> {
let key = format!("RUSTAUTH_{suffix}");
std::env::var(&key).ok().filter(|value| !value.is_empty())
}
pub fn is_production() -> bool {
std::env::var("RUST_ENV").is_ok_and(|value| value == "production")
}
fn is_development_env() -> bool {
match std::env::var("RUST_ENV") {
Ok(value) => value == "development" || value == "test",
Err(_) => is_test_runtime(),
}
}
fn is_test_runtime() -> bool {
std::env::var("RUST_TEST_THREADS").is_ok()
|| std::env::var("NEXTEST").is_ok_and(|value| value == "1")
|| std::env::var("TEST")
.is_ok_and(|value| !value.is_empty() && value != "0" && value.to_lowercase() != "false")
}
pub fn is_production_posture(options: &RustAuthOptions) -> bool {
!allows_development_defaults(options)
}
pub fn allows_development_defaults(options: &RustAuthOptions) -> bool {
match options.mode {
DeploymentMode::Production => false,
DeploymentMode::Development => !is_production(),
DeploymentMode::Auto => !is_production() && is_development_env(),
}
}
#[cfg(test)]
mod tests {
use std::sync::{Mutex, MutexGuard, OnceLock};
use super::*;
struct EnvRestore(Vec<(&'static str, Option<String>)>);
impl EnvRestore {
fn unset(keys: &[&'static str]) -> Self {
let saved = keys
.iter()
.map(|key| (*key, std::env::var(key).ok()))
.collect::<Vec<_>>();
for key in keys {
std::env::remove_var(key);
}
Self(saved)
}
}
impl Drop for EnvRestore {
fn drop(&mut self) {
for (key, value) in &self.0 {
match value {
Some(value) => std::env::set_var(key, value),
None => std::env::remove_var(key),
}
}
}
}
fn env_lock() -> &'static Mutex<()> {
static LOCK: OnceLock<Mutex<()>> = OnceLock::new();
LOCK.get_or_init(|| Mutex::new(()))
}
fn lock_env() -> MutexGuard<'static, ()> {
env_lock()
.lock()
.unwrap_or_else(|poisoned| poisoned.into_inner())
}
#[test]
fn env_var_reads_rustauth_prefix() {
let _guard = lock_env();
let _restore = EnvRestore::unset(&["RUSTAUTH_SECRET"]);
std::env::set_var("RUSTAUTH_SECRET", "rustauth-secret");
assert_eq!(env_var("SECRET").as_deref(), Some("rustauth-secret"));
}
#[test]
fn env_var_ignores_empty_values() {
let _guard = lock_env();
let _restore = EnvRestore::unset(&["RUSTAUTH_SECRET"]);
std::env::set_var("RUSTAUTH_SECRET", "");
assert_eq!(env_var("SECRET"), None);
}
#[test]
fn env_var_returns_none_when_unset() {
let _guard = lock_env();
let _restore = EnvRestore::unset(&["RUSTAUTH_SECRET"]);
assert_eq!(env_var("SECRET"), None);
}
}