Analytics request loader and game version validation (#6064)

* Analytics request loader and game version validation

* tweak agents

* factor tags into its own util

* lock cache refresh to avoid cache stampede

* Make analytics fields opptional
This commit is contained in:
aecsocket
2026-05-11 14:45:50 +00:00
committed by GitHub
parent a5417e0851
commit ca1b36efde
4 changed files with 132 additions and 7 deletions
+35 -6
View File
@@ -11,7 +11,9 @@ use crate::search::SearchBackend;
use crate::util::date::get_current_tenths_of_ms;
use crate::util::error::Context;
use crate::util::guards::admin_key_guard;
use crate::util::tags::valid_download_tags;
use actix_web::{HttpRequest, HttpResponse, patch, post, web};
use eyre::eyre;
use serde::Deserialize;
use std::collections::HashMap;
use std::net::Ipv4Addr;
@@ -40,9 +42,9 @@ pub struct DownloadBody {
/// [`DOWNLOAD_META_HEADER`] header.
#[derive(Debug, Clone, Deserialize)]
pub struct DownloadMeta {
pub reason: DownloadReason,
pub game_version: String,
pub loader: String,
pub reason: Option<DownloadReason>,
pub game_version: Option<String>,
pub loader: Option<String>,
}
pub const DOWNLOAD_META_HEADER: &str = "modrinth-download-meta";
@@ -139,6 +141,27 @@ pub async fn count_download(
None
};
if let Some(meta) = &meta {
let valid_download_tags = valid_download_tags(&pool, &redis)
.await
.wrap_internal_err("failed to fetch valid download tags")?;
if let Some(loader) = &meta.loader
&& !valid_download_tags.loaders.contains(loader)
{
return Err(ApiError::Request(eyre!(
"invalid download loader specified"
)));
}
if let Some(game_version) = &meta.game_version
&& !valid_download_tags.game_versions.contains(game_version)
{
return Err(ApiError::Request(eyre!(
"invalid download game version specified"
)));
}
}
let download = Download {
recorded: get_current_tenths_of_ms(),
domain: url.host_str().unwrap_or_default().to_string(),
@@ -176,13 +199,19 @@ pub async fn count_download(
.collect(),
reason: meta
.as_ref()
.map(|m| m.reason.to_string())
.and_then(|m| m.reason.as_ref())
.map(|s| s.to_string())
.unwrap_or_default(),
game_version: meta
.as_ref()
.map(|m| m.game_version.clone())
.and_then(|m| m.game_version.as_ref())
.map(|s| s.to_string())
.unwrap_or_default(),
loader: meta
.as_ref()
.and_then(|m| m.loader.as_ref())
.map(|s| s.to_string())
.unwrap_or_default(),
loader: meta.as_ref().map(|m| m.loader.clone()).unwrap_or_default(),
};
trace!("added download {download:#?}");