You've already forked AstralRinth
forked from didirus/AstralRinth
Fix MaxMind (#4590)
This commit is contained in:
@@ -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.ip_salt.clone()))
|
||||||
.app_data(web::Data::new(labrinth_config.analytics_queue.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.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.active_sockets.clone())
|
||||||
.app_data(labrinth_config.automated_moderation_queue.clone())
|
.app_data(labrinth_config.automated_moderation_queue.clone())
|
||||||
.app_data(web::Data::new(labrinth_config.stripe_client.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_PASSWORD");
|
||||||
failed |= check_var::<String>("CLICKHOUSE_DATABASE");
|
failed |= check_var::<String>("CLICKHOUSE_DATABASE");
|
||||||
|
|
||||||
|
failed |= check_var::<String>("MAXMIND_ACCOUNT_ID");
|
||||||
failed |= check_var::<String>("MAXMIND_LICENSE_KEY");
|
failed |= check_var::<String>("MAXMIND_LICENSE_KEY");
|
||||||
|
|
||||||
failed |= check_var::<String>("FLAME_ANVIL_URL");
|
failed |= check_var::<String>("FLAME_ANVIL_URL");
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::net::Ipv6Addr;
|
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 struct Download {
|
||||||
pub recorded: i64,
|
pub recorded: i64,
|
||||||
pub domain: String,
|
pub domain: String,
|
||||||
@@ -24,7 +24,7 @@ pub struct Download {
|
|||||||
pub headers: Vec<(String, String)>,
|
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 struct PageView {
|
||||||
pub recorded: i64,
|
pub recorded: i64,
|
||||||
pub domain: String,
|
pub domain: String,
|
||||||
|
|||||||
@@ -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()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
pub mod analytics;
|
pub mod analytics;
|
||||||
pub mod billing;
|
pub mod billing;
|
||||||
pub mod email;
|
pub mod email;
|
||||||
pub mod maxmind;
|
|
||||||
pub mod moderation;
|
pub mod moderation;
|
||||||
pub mod payouts;
|
pub mod payouts;
|
||||||
pub mod session;
|
pub mod session;
|
||||||
|
|||||||
@@ -3,18 +3,19 @@ use crate::database::redis::RedisPool;
|
|||||||
use crate::models::analytics::{PageView, Playtime};
|
use crate::models::analytics::{PageView, Playtime};
|
||||||
use crate::models::pats::Scopes;
|
use crate::models::pats::Scopes;
|
||||||
use crate::queue::analytics::AnalyticsQueue;
|
use crate::queue::analytics::AnalyticsQueue;
|
||||||
use crate::queue::maxmind::MaxMindIndexer;
|
|
||||||
use crate::queue::session::AuthQueue;
|
use crate::queue::session::AuthQueue;
|
||||||
use crate::routes::ApiError;
|
use crate::routes::ApiError;
|
||||||
use crate::util::date::get_current_tenths_of_ms;
|
use crate::util::date::get_current_tenths_of_ms;
|
||||||
use crate::util::env::parse_strings_from_var;
|
use crate::util::env::parse_strings_from_var;
|
||||||
use actix_web::{HttpRequest, HttpResponse};
|
use actix_web::{HttpRequest, HttpResponse};
|
||||||
use actix_web::{post, web};
|
use actix_web::{post, web};
|
||||||
|
use modrinth_maxmind::MaxMind;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use tracing::trace;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub const FILTERED_HEADERS: &[&str] = &[
|
pub const FILTERED_HEADERS: &[&str] = &[
|
||||||
@@ -48,7 +49,7 @@ pub struct UrlInput {
|
|||||||
#[post("view")]
|
#[post("view")]
|
||||||
pub async fn page_view_ingest(
|
pub async fn page_view_ingest(
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
maxmind: web::Data<Arc<MaxMindIndexer>>,
|
maxmind: web::Data<MaxMind>,
|
||||||
analytics_queue: web::Data<Arc<AnalyticsQueue>>,
|
analytics_queue: web::Data<Arc<AnalyticsQueue>>,
|
||||||
session_queue: web::Data<AuthQueue>,
|
session_queue: web::Data<AuthQueue>,
|
||||||
url_input: web::Json<UrlInput>,
|
url_input: web::Json<UrlInput>,
|
||||||
@@ -113,7 +114,7 @@ pub async fn page_view_ingest(
|
|||||||
user_id: 0,
|
user_id: 0,
|
||||||
project_id: 0,
|
project_id: 0,
|
||||||
ip,
|
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(),
|
user_agent: headers.get("user-agent").cloned().unwrap_or_default(),
|
||||||
headers: headers
|
headers: headers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -154,6 +155,7 @@ pub async fn page_view_ingest(
|
|||||||
view.user_id = user.id.0;
|
view.user_id = user.id.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace!("Ingested page view {view:?}");
|
||||||
analytics_queue.add_view(view);
|
analytics_queue.add_view(view);
|
||||||
|
|
||||||
Ok(HttpResponse::NoContent().body(""))
|
Ok(HttpResponse::NoContent().body(""))
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ use crate::models::ids::ProjectId;
|
|||||||
use crate::models::pats::Scopes;
|
use crate::models::pats::Scopes;
|
||||||
use crate::models::threads::MessageBody;
|
use crate::models::threads::MessageBody;
|
||||||
use crate::queue::analytics::AnalyticsQueue;
|
use crate::queue::analytics::AnalyticsQueue;
|
||||||
use crate::queue::maxmind::MaxMindIndexer;
|
|
||||||
use crate::queue::moderation::AUTOMOD_ID;
|
use crate::queue::moderation::AUTOMOD_ID;
|
||||||
use crate::queue::session::AuthQueue;
|
use crate::queue::session::AuthQueue;
|
||||||
use crate::routes::ApiError;
|
use crate::routes::ApiError;
|
||||||
@@ -14,6 +13,7 @@ use crate::search::SearchConfig;
|
|||||||
use crate::util::date::get_current_tenths_of_ms;
|
use crate::util::date::get_current_tenths_of_ms;
|
||||||
use crate::util::guards::admin_key_guard;
|
use crate::util::guards::admin_key_guard;
|
||||||
use actix_web::{HttpRequest, HttpResponse, patch, post, web};
|
use actix_web::{HttpRequest, HttpResponse, patch, post, web};
|
||||||
|
use modrinth_maxmind::MaxMind;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
@@ -48,7 +48,7 @@ pub async fn count_download(
|
|||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
pool: web::Data<PgPool>,
|
pool: web::Data<PgPool>,
|
||||||
redis: web::Data<RedisPool>,
|
redis: web::Data<RedisPool>,
|
||||||
maxmind: web::Data<Arc<MaxMindIndexer>>,
|
maxmind: web::Data<MaxMind>,
|
||||||
analytics_queue: web::Data<Arc<AnalyticsQueue>>,
|
analytics_queue: web::Data<Arc<AnalyticsQueue>>,
|
||||||
session_queue: web::Data<AuthQueue>,
|
session_queue: web::Data<AuthQueue>,
|
||||||
download_body: web::Json<DownloadBody>,
|
download_body: web::Json<DownloadBody>,
|
||||||
@@ -132,7 +132,7 @@ pub async fn count_download(
|
|||||||
project_id: project_id as u64,
|
project_id: project_id as u64,
|
||||||
version_id: version_id as u64,
|
version_id: version_id as u64,
|
||||||
ip,
|
ip,
|
||||||
country: maxmind.query(ip).await.unwrap_or_default(),
|
country: maxmind.query_country(ip).await.unwrap_or_default(),
|
||||||
user_agent: download_body
|
user_agent: download_body
|
||||||
.headers
|
.headers
|
||||||
.get("user-agent")
|
.get("user-agent")
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
io::{Cursor, Read},
|
io::{Cursor, Read},
|
||||||
|
net::IpAddr,
|
||||||
path::Path,
|
path::Path,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
@@ -49,6 +50,19 @@ impl MaxMind {
|
|||||||
.ok(),
|
.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`].
|
/// Creates a [`maxminddb::Reader`] for use in [`MaxMind::reader`].
|
||||||
|
|||||||
Reference in New Issue
Block a user