use std::{
path::PathBuf,
sync::{Mutex, OnceLock},
};
use axum::{
body::Body,
http::{HeaderValue, Method},
};
use tracing::debug;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
use crate::{
acl::{init_acl, Acl},
auth::{init_auth, Auth},
config::{
default_data_dir, AclSettings, HtpasswdSettings, RusticServerConfig, StorageSettings,
},
storage::{init_storage, LocalStorage, Storage},
};
pub fn request_uri_for_test(uri: &str, method: Method) -> axum::http::Request<Body> {
axum::http::Request::builder()
.uri(uri)
.method(method)
.header(
"Authorization",
basic_auth_header_value("rustic", Some("rustic")),
)
.body(Body::empty())
.unwrap()
}
pub(crate) fn init_tracing() {
init_mutex();
}
static TRACER: OnceLock<Mutex<usize>> = OnceLock::new();
fn init_mutex() {
let _ = TRACER.get_or_init(|| {
tracing_subscriber::registry()
.with(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| "RUSTIC_SERVER_LOG_LEVEL=debug".into()),
)
.with(tracing_subscriber::fmt::layer())
.init();
Mutex::new(0)
});
}
pub(crate) fn test_data_path() -> PathBuf {
PathBuf::from("tests/fixtures/test_data")
}
pub(crate) fn server_config() -> RusticServerConfig {
let server_config_path = test_data_path().join("rustic_server.toml");
RusticServerConfig::from_file(&server_config_path).unwrap()
}
pub(crate) fn init_test_environment(server_config: RusticServerConfig) {
init_tracing();
init_static_htpasswd(server_config.auth);
init_static_auth(server_config.acl);
init_static_storage(server_config.storage);
}
fn init_static_htpasswd(htpasswd_settings: HtpasswdSettings) {
let auth = Auth::from_config(&htpasswd_settings, test_data_path().join(".htpasswd")).unwrap();
debug!(?auth, "Loaded Auth.");
init_auth(auth).unwrap();
}
fn init_static_auth(acl_settings: AclSettings) {
let acl = Acl::from_config(&acl_settings.clone(), acl_settings.acl_path).unwrap();
debug!(?acl, "Loaded Acl.");
init_acl(acl).unwrap();
}
fn init_static_storage(storage_settings: StorageSettings) {
let local_storage = LocalStorage::init(
storage_settings
.data_dir
.unwrap_or_else(default_data_dir)
.as_ref(),
)
.unwrap();
debug!(?local_storage, "Loaded Storage.");
init_storage(local_storage).unwrap();
}
pub(crate) fn basic_auth_header_value<U, P>(username: U, password: Option<P>) -> HeaderValue
where
U: std::fmt::Display,
P: std::fmt::Display,
{
use base64::prelude::BASE64_STANDARD;
use base64::write::EncoderWriter;
use std::io::Write;
let mut buf = b"Basic ".to_vec();
{
let mut encoder = EncoderWriter::new(&mut buf, &BASE64_STANDARD);
let _ = write!(encoder, "{}:", username);
if let Some(password) = password {
let _ = write!(encoder, "{}", password);
}
}
let mut header = HeaderValue::from_bytes(&buf).expect("base64 is always valid HeaderValue");
header.set_sensitive(true);
header
}