84 lines
2.7 KiB
Rust
84 lines
2.7 KiB
Rust
use anyhow::Context;
|
|
use minecraft_log_viewer::{
|
|
auth::{client_ip::ClientIpPolicy, whitelist::Whitelist, AuthorizationService},
|
|
config::Config,
|
|
http::{self, AppState},
|
|
logs::{
|
|
follower,
|
|
index::{HistoryIndex, HistoryStore},
|
|
},
|
|
};
|
|
use std::sync::{atomic::AtomicUsize, Arc};
|
|
use tokio::sync::broadcast;
|
|
|
|
#[tokio::main]
|
|
async fn main() -> anyhow::Result<()> {
|
|
tracing_subscriber::fmt()
|
|
.json()
|
|
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
|
|
.init();
|
|
let config = Arc::new(Config::from_env().context("configuration validation failed")?);
|
|
config
|
|
.validate_paths()
|
|
.context("filesystem validation failed")?;
|
|
let whitelist = Whitelist::load(&config.whitelist)
|
|
.context("initial whitelist load failed; refusing to start")?;
|
|
let auth = AuthorizationService::new(config.latest_log.clone(), whitelist);
|
|
auth.rebuild()
|
|
.await
|
|
.context("authorization reconstruction failed")?;
|
|
let index = HistoryIndex::scan(&config.log_dir).context("historical index scan failed")?;
|
|
let history = HistoryStore::new(
|
|
index,
|
|
config.archive_cache_max_bytes,
|
|
config.archive_cache_max_files,
|
|
config.max_archive_bytes,
|
|
config.redact_player_ips,
|
|
);
|
|
let (tx, _) = broadcast::channel(config.ws_queue_capacity);
|
|
let ip_policy = ClientIpPolicy {
|
|
trust_proxy: config.trust_proxy,
|
|
trusted_proxies: config.trusted_proxy_cidrs.clone(),
|
|
header: config.client_ip_header.clone(),
|
|
};
|
|
let state = AppState {
|
|
config: config.clone(),
|
|
auth: auth.clone(),
|
|
history: history.clone(),
|
|
live_tx: tx.clone(),
|
|
ip_policy,
|
|
ws_count: Arc::new(AtomicUsize::new(0)),
|
|
};
|
|
let _watcher = follower::spawn_watcher(
|
|
config.log_dir.clone(),
|
|
config.latest_log.clone(),
|
|
config.whitelist.clone(),
|
|
auth,
|
|
history,
|
|
tx,
|
|
config.redact_player_ips,
|
|
)
|
|
.context("filesystem watcher startup failed")?;
|
|
let listener = tokio::net::TcpListener::bind(config.listen_addr)
|
|
.await
|
|
.context("HTTP bind failed")?;
|
|
let ip_whitelist_file = config
|
|
.ip_whitelist_file
|
|
.as_deref()
|
|
.map(|path| path.display().to_string())
|
|
.unwrap_or_else(|| "disabled".into());
|
|
tracing::info!(
|
|
event = "application_startup",
|
|
listen_addr = %config.listen_addr,
|
|
trust_proxy = config.trust_proxy,
|
|
ip_whitelist_file
|
|
);
|
|
axum::serve(
|
|
listener,
|
|
http::router(state).into_make_service_with_connect_info::<std::net::SocketAddr>(),
|
|
)
|
|
.await
|
|
.context("HTTP server failed")?;
|
|
Ok(())
|
|
}
|