refactor: labrinth ApiError and error reporting (#6981)

* refactor: labrinth `ApiError` and error reporting

* fix clippy

* fix ci
This commit is contained in:
aecsocket
2026-08-07 15:47:54 +00:00
committed by GitHub
parent d344cbcb7a
commit 3fa6905006
102 changed files with 6449 additions and 3791 deletions
+48 -16
View File
@@ -13,6 +13,8 @@ use crate::queue::session::AuthQueue;
use crate::routes::v3::projects::ProjectIds;
use crate::routes::{ApiError, v2_reroute, v3};
use crate::search::{SearchBackend, SearchRequest, SearchState};
use crate::util::error::ApiContext as _;
use crate::util::error::Context as _;
use actix_web::{HttpRequest, HttpResponse, delete, get, patch, post, web};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
@@ -79,7 +81,8 @@ pub async fn project_search(
// While the backend for this has changed, it doesnt affect much
// in the API calls except that 'versions:x' is now 'game_versions:x'
let facets: Option<Vec<Vec<String>>> = if let Some(facets) = info.facets {
let facets = serde_json::from_str::<Vec<Vec<String>>>(&facets)?;
let facets = serde_json::from_str::<Vec<Vec<String>>>(&facets)
.wrap_request_err("deserializing JSON data")?;
Some(
facets
@@ -119,7 +122,10 @@ pub async fn project_search(
..info
};
let results = search_backend.search_for_project(&info, &redis).await?;
let results = search_backend
.search_for_project(&info, &redis)
.await
.wrap_api_err("searching projects")?;
let results = LegacySearchResults::from(results);
@@ -194,12 +200,17 @@ pub async fn random_projects_get(
)
.await
.or_else(v2_reroute::flatten_404_error)
.or_else(v2_reroute::flatten_404_error)?;
.or_else(v2_reroute::flatten_404_error)
.wrap_api_err("flattening v2 not-found response")?;
// Convert response to V2 format
match v2_reroute::extract_ok_json::<Vec<Project>>(response).await {
Ok(project) => {
let legacy_projects =
LegacyProject::from_many(project, &**pool, &redis).await?;
LegacyProject::from_many(project, &**pool, &redis)
.await
.wrap_internal_err(
"executing `LegacyProject::from_many`",
)?;
Ok(HttpResponse::Ok().json(legacy_projects))
}
Err(response) => Ok(response),
@@ -234,13 +245,18 @@ pub async fn projects_get(
)
.await
.or_else(v2_reroute::flatten_404_error)
.or_else(v2_reroute::flatten_404_error)?;
.or_else(v2_reroute::flatten_404_error)
.wrap_api_err("flattening v2 not-found response")?;
// Convert response to V2 format
match v2_reroute::extract_ok_json::<Vec<Project>>(response).await {
Ok(project) => {
let legacy_projects =
LegacyProject::from_many(project, &**pool, &redis).await?;
LegacyProject::from_many(project, &**pool, &redis)
.await
.wrap_internal_err(
"executing `LegacyProject::from_many`",
)?;
Ok(HttpResponse::Ok().json(legacy_projects))
}
Err(response) => Ok(response),
@@ -284,14 +300,18 @@ pub async fn project_get(
.await
{
Ok(resp) => resp.0,
Err(ApiError::NotFound) => return Ok(HttpResponse::NotFound().body("")),
Err(ApiError::NotFound(_)) => {
return Ok(HttpResponse::NotFound().body(""));
}
Err(err) => return Err(err),
};
// Convert response to V2 format
let version_item = match project.versions.first() {
Some(vid) => {
version_item::DBVersion::get((*vid).into(), &**pool, &redis).await?
version_item::DBVersion::get((*vid).into(), &**pool, &redis)
.await
.wrap_internal_err("fetching version from database")?
}
None => None,
};
@@ -371,7 +391,8 @@ pub async fn dependency_list(
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)?;
.or_else(v2_reroute::flatten_404_error)
.wrap_api_err("flattening v2 not-found response")?;
match v2_reroute::extract_ok_json::<
crate::routes::v3::projects::DependencyInfo,
@@ -384,7 +405,10 @@ pub async fn dependency_list(
&**pool,
&redis,
)
.await?;
.await
.wrap_internal_err(
"converting dependency projects to legacy responses",
)?;
let converted_versions = dependency_info
.versions
.into_iter()
@@ -585,7 +609,9 @@ pub async fn project_edit(
if let Some(donation_urls) = v2_new_project.donation_urls {
// Fetch current donation links from project so we know what to delete
let fetched_example_project =
project_item::DBProject::get(&info.0, &**pool, &redis).await?;
project_item::DBProject::get(&info.0, &**pool, &redis)
.await
.wrap_api_err("fetching project from database")?;
let donation_links = fetched_example_project
.map(|x| {
x.urls
@@ -647,7 +673,8 @@ pub async fn project_edit(
search_state.clone(),
)
.await
.or_else(v2_reroute::flatten_404_error)?;
.or_else(v2_reroute::flatten_404_error)
.wrap_api_err("flattening v2 not-found response")?;
// If client and server side were set, we will call
// the version setting route for each version to set the side types for each of them.
@@ -659,11 +686,13 @@ pub async fn project_edit(
&**pool,
&redis,
)
.await?;
.await
.wrap_api_err("fetching project from database")?;
let version_ids = project_item.map(|x| x.versions).unwrap_or_default();
let versions =
version_item::DBVersion::get_many(&version_ids, &**pool, &redis)
.await?;
.await
.wrap_internal_err("fetching versions from database")?;
for version in versions {
let version = Version::from(version);
let mut fields = version.fields;
@@ -690,7 +719,8 @@ pub async fn project_edit(
session_queue.clone(),
search_state.clone(),
)
.await?;
.await
.wrap_api_err("editing project")?;
}
}
Ok(response)
@@ -795,7 +825,9 @@ pub async fn projects_edit(
// If we are *setting* donation links, we will set every possible donation link to None, as
// setting will delete all of them then 're-add' the ones we want to keep
if let Some(donation_url) = bulk_edit_project.donation_urls {
let link_platforms = LinkPlatform::list(&**pool, &redis).await?;
let link_platforms = LinkPlatform::list(&**pool, &redis)
.await
.wrap_internal_err("fetching link platform from Redis")?;
for link in link_platforms {
if link.donation {
link_urls.insert(link.name, None);