Fix MaxMind (#4590)

This commit is contained in:
aecsocket
2025-10-20 08:58:31 -07:00
committed by GitHub
parent 63d8f70e20
commit 24bec6baba
7 changed files with 26 additions and 33 deletions

View File

@@ -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::<String>("CLICKHOUSE_PASSWORD");
failed |= check_var::<String>("CLICKHOUSE_DATABASE");
failed |= check_var::<String>("MAXMIND_ACCOUNT_ID");
failed |= check_var::<String>("MAXMIND_LICENSE_KEY");
failed |= check_var::<String>("FLAME_ANVIL_URL");

View File

@@ -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,

View File

@@ -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<String> {
let reader = self.maxmind.reader.as_ref()?;
reader
.lookup::<geoip2::Country>(ip.into())
.ok()?
.and_then(|c| c.country)
.and_then(|c| c.iso_code.map(|s| s.to_string()))
}
}

View File

@@ -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;

View File

@@ -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<Arc<MaxMindIndexer>>,
maxmind: web::Data<MaxMind>,
analytics_queue: web::Data<Arc<AnalyticsQueue>>,
session_queue: web::Data<AuthQueue>,
url_input: web::Json<UrlInput>,
@@ -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(""))

View File

@@ -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<PgPool>,
redis: web::Data<RedisPool>,
maxmind: web::Data<Arc<MaxMindIndexer>>,
maxmind: web::Data<MaxMind>,
analytics_queue: web::Data<Arc<AnalyticsQueue>>,
session_queue: web::Data<AuthQueue>,
download_body: web::Json<DownloadBody>,
@@ -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")

View File

@@ -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<IpAddr>) -> Option<String> {
let reader = self.reader.as_ref()?;
reader
.lookup::<geoip2::Country>(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`].