From 24bec6baba038e4b8f80f6b0f835361a49f49a27 Mon Sep 17 00:00:00 2001 From: aecsocket Date: Mon, 20 Oct 2025 08:58:31 -0700 Subject: [PATCH] Fix MaxMind (#4590) --- apps/labrinth/src/lib.rs | 3 ++- apps/labrinth/src/models/v3/analytics.rs | 4 ++-- apps/labrinth/src/queue/maxmind.rs | 23 ---------------------- apps/labrinth/src/queue/mod.rs | 1 - apps/labrinth/src/routes/analytics.rs | 8 +++++--- apps/labrinth/src/routes/internal/admin.rs | 6 +++--- packages/modrinth-maxmind/src/lib.rs | 14 +++++++++++++ 7 files changed, 26 insertions(+), 33 deletions(-) delete mode 100644 apps/labrinth/src/queue/maxmind.rs diff --git a/apps/labrinth/src/lib.rs b/apps/labrinth/src/lib.rs index 899297c4..02857f71 100644 --- a/apps/labrinth/src/lib.rs +++ b/apps/labrinth/src/lib.rs @@ -315,7 +315,7 @@ pub fn app_config( .app_data(web::Data::new(labrinth_config.ip_salt.clone())) .app_data(web::Data::new(labrinth_config.analytics_queue.clone())) .app_data(web::Data::new(labrinth_config.clickhouse.clone())) - .app_data(web::Data::new(labrinth_config.maxmind.clone())) + .app_data(labrinth_config.maxmind.clone()) .app_data(labrinth_config.active_sockets.clone()) .app_data(labrinth_config.automated_moderation_queue.clone()) .app_data(web::Data::new(labrinth_config.stripe_client.clone())) @@ -478,6 +478,7 @@ pub fn check_env_vars() -> bool { failed |= check_var::("CLICKHOUSE_PASSWORD"); failed |= check_var::("CLICKHOUSE_DATABASE"); + failed |= check_var::("MAXMIND_ACCOUNT_ID"); failed |= check_var::("MAXMIND_LICENSE_KEY"); failed |= check_var::("FLAME_ANVIL_URL"); diff --git a/apps/labrinth/src/models/v3/analytics.rs b/apps/labrinth/src/models/v3/analytics.rs index b59254a7..6296d7e0 100644 --- a/apps/labrinth/src/models/v3/analytics.rs +++ b/apps/labrinth/src/models/v3/analytics.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use std::hash::Hash; use std::net::Ipv6Addr; -#[derive(Row, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Row, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)] pub struct Download { pub recorded: i64, pub domain: String, @@ -24,7 +24,7 @@ pub struct Download { pub headers: Vec<(String, String)>, } -#[derive(Row, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Row, Serialize, Deserialize, Clone, Eq, PartialEq, Hash)] pub struct PageView { pub recorded: i64, pub domain: String, diff --git a/apps/labrinth/src/queue/maxmind.rs b/apps/labrinth/src/queue/maxmind.rs deleted file mode 100644 index 050dd1c0..00000000 --- a/apps/labrinth/src/queue/maxmind.rs +++ /dev/null @@ -1,23 +0,0 @@ -use modrinth_maxmind::{MaxMind, geoip2}; -use std::net::Ipv6Addr; - -pub struct MaxMindIndexer { - pub maxmind: MaxMind, -} - -impl MaxMindIndexer { - pub async fn new() -> Self { - Self { - maxmind: MaxMind::new().await, - } - } - - pub async fn query(&self, ip: Ipv6Addr) -> Option { - let reader = self.maxmind.reader.as_ref()?; - reader - .lookup::(ip.into()) - .ok()? - .and_then(|c| c.country) - .and_then(|c| c.iso_code.map(|s| s.to_string())) - } -} diff --git a/apps/labrinth/src/queue/mod.rs b/apps/labrinth/src/queue/mod.rs index a0fd5827..5ad33d01 100644 --- a/apps/labrinth/src/queue/mod.rs +++ b/apps/labrinth/src/queue/mod.rs @@ -1,7 +1,6 @@ pub mod analytics; pub mod billing; pub mod email; -pub mod maxmind; pub mod moderation; pub mod payouts; pub mod session; diff --git a/apps/labrinth/src/routes/analytics.rs b/apps/labrinth/src/routes/analytics.rs index 2bdd5ffa..b15b9117 100644 --- a/apps/labrinth/src/routes/analytics.rs +++ b/apps/labrinth/src/routes/analytics.rs @@ -3,18 +3,19 @@ use crate::database::redis::RedisPool; use crate::models::analytics::{PageView, Playtime}; use crate::models::pats::Scopes; use crate::queue::analytics::AnalyticsQueue; -use crate::queue::maxmind::MaxMindIndexer; use crate::queue::session::AuthQueue; use crate::routes::ApiError; use crate::util::date::get_current_tenths_of_ms; use crate::util::env::parse_strings_from_var; use actix_web::{HttpRequest, HttpResponse}; use actix_web::{post, web}; +use modrinth_maxmind::MaxMind; use serde::Deserialize; use sqlx::PgPool; use std::collections::HashMap; use std::net::Ipv4Addr; use std::sync::Arc; +use tracing::trace; use url::Url; pub const FILTERED_HEADERS: &[&str] = &[ @@ -48,7 +49,7 @@ pub struct UrlInput { #[post("view")] pub async fn page_view_ingest( req: HttpRequest, - maxmind: web::Data>, + maxmind: web::Data, analytics_queue: web::Data>, session_queue: web::Data, url_input: web::Json, @@ -113,7 +114,7 @@ pub async fn page_view_ingest( user_id: 0, project_id: 0, ip, - country: maxmind.query(ip).await.unwrap_or_default(), + country: maxmind.query_country(ip).await.unwrap_or_default(), user_agent: headers.get("user-agent").cloned().unwrap_or_default(), headers: headers .into_iter() @@ -154,6 +155,7 @@ pub async fn page_view_ingest( view.user_id = user.id.0; } + trace!("Ingested page view {view:?}"); analytics_queue.add_view(view); Ok(HttpResponse::NoContent().body("")) diff --git a/apps/labrinth/src/routes/internal/admin.rs b/apps/labrinth/src/routes/internal/admin.rs index 9d9de667..518a315a 100644 --- a/apps/labrinth/src/routes/internal/admin.rs +++ b/apps/labrinth/src/routes/internal/admin.rs @@ -6,7 +6,6 @@ use crate::models::ids::ProjectId; use crate::models::pats::Scopes; use crate::models::threads::MessageBody; use crate::queue::analytics::AnalyticsQueue; -use crate::queue::maxmind::MaxMindIndexer; use crate::queue::moderation::AUTOMOD_ID; use crate::queue::session::AuthQueue; use crate::routes::ApiError; @@ -14,6 +13,7 @@ use crate::search::SearchConfig; use crate::util::date::get_current_tenths_of_ms; use crate::util::guards::admin_key_guard; use actix_web::{HttpRequest, HttpResponse, patch, post, web}; +use modrinth_maxmind::MaxMind; use serde::Deserialize; use sqlx::PgPool; use std::collections::HashMap; @@ -48,7 +48,7 @@ pub async fn count_download( req: HttpRequest, pool: web::Data, redis: web::Data, - maxmind: web::Data>, + maxmind: web::Data, analytics_queue: web::Data>, session_queue: web::Data, download_body: web::Json, @@ -132,7 +132,7 @@ pub async fn count_download( project_id: project_id as u64, version_id: version_id as u64, ip, - country: maxmind.query(ip).await.unwrap_or_default(), + country: maxmind.query_country(ip).await.unwrap_or_default(), user_agent: download_body .headers .get("user-agent") diff --git a/packages/modrinth-maxmind/src/lib.rs b/packages/modrinth-maxmind/src/lib.rs index 835538aa..22080967 100644 --- a/packages/modrinth-maxmind/src/lib.rs +++ b/packages/modrinth-maxmind/src/lib.rs @@ -2,6 +2,7 @@ use std::{ io::{Cursor, Read}, + net::IpAddr, path::Path, sync::Arc, }; @@ -49,6 +50,19 @@ impl MaxMind { .ok(), } } + + /// Queries the MaxMind database for the ISO country code of an IP address. + /// + /// If MaxMind is not configured or the database could not be read, returns + /// [`None`]. + pub async fn query_country(&self, ip: impl Into) -> Option { + let reader = self.reader.as_ref()?; + reader + .lookup::(ip.into()) + .ok()? + .and_then(|c| c.country) + .and_then(|c| c.iso_code.map(|s| s.to_string())) + } } /// Creates a [`maxminddb::Reader`] for use in [`MaxMind::reader`].