add a log for each person accessing the chat api

This commit is contained in:
Marcel Märtens 2023-10-18 13:05:22 +02:00
parent 0baab58928
commit 9e5bd1e463
3 changed files with 35 additions and 4 deletions

View File

@ -60,7 +60,7 @@ where
"veloren_server::events::entity_manipulation=info", "veloren_server::events::entity_manipulation=info",
"hyper=info", "hyper=info",
"prometheus_hyper=info", "prometheus_hyper=info",
"mio::pool=info", "mio::poll=info",
"mio::sys::windows=info", "mio::sys::windows=info",
"h2=info", "h2=info",
"tokio_util=info", "tokio_util=info",

View File

@ -1,5 +1,5 @@
use axum::{ use axum::{
extract::{Query, State}, extract::{ConnectInfo, Query, State},
middleware::Next, middleware::Next,
response::{IntoResponse, Response}, response::{IntoResponse, Response},
routing::get, routing::get,
@ -9,7 +9,13 @@ use chrono::DateTime;
use hyper::{Request, StatusCode}; use hyper::{Request, StatusCode};
use serde::{Deserialize, Deserializer}; use serde::{Deserialize, Deserializer};
use server::chat::ChatCache; use server::chat::ChatCache;
use std::str::FromStr; use std::{
collections::HashSet,
net::{IpAddr, SocketAddr},
str::FromStr,
sync::Arc,
};
use tokio::sync::Mutex;
/// Keep Size small, so we dont have to Clone much for each request. /// Keep Size small, so we dont have to Clone much for each request.
#[derive(Clone)] #[derive(Clone)]
@ -17,6 +23,11 @@ struct ChatToken {
secret_token: Option<String>, secret_token: Option<String>,
} }
#[derive(Clone, Default)]
struct IpAddresses {
users: Arc<Mutex<HashSet<IpAddr>>>,
}
async fn validate_secret<B>( async fn validate_secret<B>(
State(token): State<ChatToken>, State(token): State<ChatToken>,
req: Request<B>, req: Request<B>,
@ -38,10 +49,29 @@ async fn validate_secret<B>(
Ok(next.run(req).await) Ok(next.run(req).await)
} }
/// Logs each new IP address that accesses this API authenticated
async fn log_users<B>(
State(ip_addresses): State<IpAddresses>,
ConnectInfo(addr): ConnectInfo<SocketAddr>,
req: Request<B>,
next: Next<B>,
) -> Result<Response, StatusCode> {
let mut ip_addresses = ip_addresses.users.lock().await;
let ip_addr = addr.ip();
if !ip_addresses.contains(&ip_addr) {
ip_addresses.insert(ip_addr);
let users_so_far = ip_addresses.len();
tracing::info!(?ip_addr, ?users_so_far, "Is accessing the /chat endpoint");
}
Ok(next.run(req).await)
}
pub fn router(cache: ChatCache, secret_token: Option<String>) -> Router { pub fn router(cache: ChatCache, secret_token: Option<String>) -> Router {
let token = ChatToken { secret_token }; let token = ChatToken { secret_token };
let ip_addrs = IpAddresses::default();
Router::new() Router::new()
.route("/history", get(history)) .route("/history", get(history))
.layer(axum::middleware::from_fn_with_state(ip_addrs, log_users))
.layer(axum::middleware::from_fn_with_state(token, validate_secret)) .layer(axum::middleware::from_fn_with_state(token, validate_secret))
.with_state(cache) .with_state(cache)
} }

View File

@ -30,7 +30,8 @@ where
// run it // run it
let addr = addr.into(); let addr = addr.into();
let server = axum::Server::bind(&addr).serve(app.into_make_service()); let server =
axum::Server::bind(&addr).serve(app.into_make_service_with_connect_info::<SocketAddr>());
let server = server.with_graceful_shutdown(shutdown); let server = server.with_graceful_shutdown(shutdown);
tracing::info!("listening on {}", addr); tracing::info!("listening on {}", addr);
match server.await { match server.await {