Skip to content

Commit 9f55840

Browse files
authored
Improve error logging in project delete route (#5388)
* Improve error logging in project delete route * remove_documents more error logging * fix ci * try fix ci? idk man
1 parent 4be2f77 commit 9f55840

4 files changed

Lines changed: 69 additions & 29 deletions

File tree

apps/labrinth/src/routes/v2/projects.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,7 @@ pub async fn project_delete(
928928
session_queue,
929929
)
930930
.await
931+
.map(|()| HttpResponse::NoContent().body(""))
931932
.or_else(v2_reroute::flatten_404_error)
932933
}
933934

apps/labrinth/src/routes/v3/projects.rs

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@ use crate::queue::session::AuthQueue;
2929
use crate::routes::ApiError;
3030
use crate::search::indexing::remove_documents;
3131
use crate::search::{SearchConfig, SearchError, search_for_project};
32+
use crate::util::error::Context;
3233
use crate::util::img;
3334
use crate::util::img::{delete_old_images, upload_image_optimized};
3435
use crate::util::routes::read_limited_from_payload;
3536
use crate::util::validate::validation_errors_to_string;
3637
use actix_web::{HttpRequest, HttpResponse, web};
3738
use chrono::Utc;
39+
use eyre::eyre;
3840
use futures::TryStreamExt;
3941
use itertools::Itertools;
4042
use serde::{Deserialize, Serialize};
@@ -980,7 +982,8 @@ pub async fn project_edit(
980982
.collect::<Vec<_>>(),
981983
&search_config,
982984
)
983-
.await?;
985+
.await
986+
.wrap_internal_err("failed to remove documents")?;
984987
}
985988

986989
Ok(HttpResponse::NoContent().body(""))
@@ -2157,25 +2160,29 @@ pub async fn project_delete(
21572160
redis: web::Data<RedisPool>,
21582161
search_config: web::Data<SearchConfig>,
21592162
session_queue: web::Data<AuthQueue>,
2160-
) -> Result<HttpResponse, ApiError> {
2161-
let user = get_user_from_headers(
2163+
) -> Result<(), ApiError> {
2164+
let (_, user) = get_user_from_headers(
21622165
&req,
21632166
&**pool,
21642167
&redis,
21652168
&session_queue,
21662169
Scopes::PROJECT_DELETE,
21672170
)
2168-
.await?
2169-
.1;
2171+
.await?;
21702172
let string = info.into_inner().0;
21712173

2174+
// In two cases, we return `The specified project does not exist!`:
2175+
// - the project really doesn't exist
2176+
// - the project is hidden from the user
2177+
//
2178+
// We use an `ApiError::Auth` for this case instead of a `ApiError::Request`,
2179+
// because our permissions tests assert that failing under the 2nd use case
2180+
// gives a 401 or 404, but `Request` gives only a 400.
2181+
21722182
let project = db_models::DBProject::get(&string, &**pool, &redis)
2173-
.await?
2174-
.ok_or_else(|| {
2175-
ApiError::InvalidInput(
2176-
"The specified project does not exist!".to_string(),
2177-
)
2178-
})?;
2183+
.await
2184+
.wrap_internal_err("failed to get project")?
2185+
.wrap_auth_err("The specified project does not exist!")?;
21792186

21802187
if !user.role.is_admin() {
21812188
let (team_member, organization_team_member) =
@@ -2184,13 +2191,14 @@ pub async fn project_delete(
21842191
user.id.into(),
21852192
&**pool,
21862193
)
2187-
.await?;
2194+
.await
2195+
.wrap_internal_err("failed to get user team member permissions")?;
21882196

21892197
// Hide the project
21902198
if team_member.is_none() && organization_team_member.is_none() {
2191-
return Err(ApiError::CustomAuthentication(
2192-
"The specified project does not exist!".to_string(),
2193-
));
2199+
return Err(ApiError::Auth(eyre!(
2200+
"The specified project does not exist!"
2201+
)));
21942202
}
21952203

21962204
let permissions = ProjectPermissions::get_permissions_by_role(
@@ -2207,15 +2215,23 @@ pub async fn project_delete(
22072215
}
22082216
}
22092217

2210-
let mut transaction = pool.begin().await?;
2218+
let mut transaction = pool
2219+
.begin()
2220+
.await
2221+
.wrap_internal_err("failed to start transaction")?;
22112222
let context = ImageContext::Project {
22122223
project_id: Some(project.inner.id.into()),
22132224
};
22142225
let uploaded_images =
22152226
db_models::DBImage::get_many_contexted(context, &mut transaction)
2216-
.await?;
2227+
.await
2228+
.wrap_internal_err("failed to get project images")?;
22172229
for image in uploaded_images {
2218-
image_item::DBImage::remove(image.id, &mut transaction, &redis).await?;
2230+
image_item::DBImage::remove(image.id, &mut transaction, &redis)
2231+
.await
2232+
.wrap_internal_err_with(|| {
2233+
eyre!("failed to remove project image `{:?}`", image.id)
2234+
})?;
22192235
}
22202236

22212237
sqlx::query!(
@@ -2226,16 +2242,21 @@ pub async fn project_delete(
22262242
project.inner.id as db_ids::DBProjectId,
22272243
)
22282244
.execute(&mut transaction)
2229-
.await?;
2245+
.await
2246+
.wrap_internal_err("failed to delete project from collections_mods")?;
22302247

22312248
let result = db_models::DBProject::remove(
22322249
project.inner.id,
22332250
&mut transaction,
22342251
&redis,
22352252
)
2236-
.await?;
2253+
.await
2254+
.wrap_internal_err("failed to remove project")?;
22372255

2238-
transaction.commit().await?;
2256+
transaction
2257+
.commit()
2258+
.await
2259+
.wrap_internal_err("failed to commit transaction")?;
22392260

22402261
remove_documents(
22412262
&project
@@ -2245,10 +2266,11 @@ pub async fn project_delete(
22452266
.collect::<Vec<_>>(),
22462267
&search_config,
22472268
)
2248-
.await?;
2269+
.await
2270+
.wrap_internal_err("failed to remove project version documents")?;
22492271

22502272
if result.is_some() {
2251-
Ok(HttpResponse::NoContent().body(""))
2273+
Ok(())
22522274
} else {
22532275
Err(ApiError::NotFound)
22542276
}

apps/labrinth/src/routes/v3/versions.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use crate::models::teams::ProjectPermissions;
2727
use crate::queue::session::AuthQueue;
2828
use crate::search::SearchConfig;
2929
use crate::search::indexing::remove_documents;
30+
use crate::util::error::Context;
3031
use crate::util::img;
3132
use crate::util::validate::validation_errors_to_string;
3233
use actix_web::{HttpRequest, HttpResponse, web};
@@ -985,7 +986,9 @@ pub async fn version_delete(
985986
&redis,
986987
)
987988
.await?;
988-
remove_documents(&[version.inner.id.into()], &search_config).await?;
989+
remove_documents(&[version.inner.id.into()], &search_config)
990+
.await
991+
.wrap_internal_err("failed to remove documents")?;
989992

990993
if result.is_some() {
991994
Ok(HttpResponse::NoContent().body(""))

apps/labrinth/src/search/indexing/mod.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use std::time::Duration;
66
use crate::database::PgPool;
77
use crate::database::redis::RedisPool;
88
use crate::search::{SearchConfig, UploadSearchProject};
9+
use crate::util::error::Context;
910
use ariadne::ids::base62_impl::to_base62;
11+
use eyre::eyre;
1012
use futures::StreamExt;
1113
use futures::stream::FuturesOrdered;
1214
use local_import::index_local;
@@ -52,17 +54,23 @@ fn search_operation_timeout() -> std::time::Duration {
5254
pub async fn remove_documents(
5355
ids: &[crate::models::ids::VersionId],
5456
config: &SearchConfig,
55-
) -> Result<(), IndexingError> {
56-
let mut indexes = get_indexes_for_indexing(config, false, false).await?;
57-
let indexes_next = get_indexes_for_indexing(config, true, false).await?;
57+
) -> eyre::Result<()> {
58+
let mut indexes = get_indexes_for_indexing(config, false, false)
59+
.await
60+
.wrap_err("failed to get current indexes")?;
61+
let indexes_next = get_indexes_for_indexing(config, true, false)
62+
.await
63+
.wrap_err("failed to get next indexes")?;
5864

5965
for list in &mut indexes {
6066
for alt_list in &indexes_next {
6167
list.extend(alt_list.iter().cloned());
6268
}
6369
}
6470

65-
let client = config.make_batch_client()?;
71+
let client = config
72+
.make_batch_client()
73+
.wrap_err("failed to create batch client")?;
6674
let client = &client;
6775

6876
let ids_base62 = ids.iter().map(|x| to_base62(x.0)).collect::<Vec<_>>();
@@ -75,13 +83,19 @@ pub async fn remove_documents(
7583
deletion_tasks.push_back(async move {
7684
index
7785
.delete_documents(ids_base62_ref)
78-
.await?
86+
.await
87+
.wrap_err_with(|| {
88+
eyre!("failed to request to delete documents {ids_base62_ref:?}")
89+
})?
7990
.wait_for_completion(
8091
&owned_client,
8192
None,
8293
Some(Duration::from_secs(15)),
8394
)
8495
.await
96+
.wrap_err_with(|| {
97+
eyre!("failed to delete documents {ids_base62_ref:?}")
98+
})
8599
});
86100
}
87101
});

0 commit comments

Comments
 (0)