diff --git a/apps/labrinth/src/auth/mod.rs b/apps/labrinth/src/auth/mod.rs index 953d978c5..4e51d86d7 100644 --- a/apps/labrinth/src/auth/mod.rs +++ b/apps/labrinth/src/auth/mod.rs @@ -85,6 +85,7 @@ impl actix_web::ResponseError for AuthenticationError { HttpResponse::build(self.status_code()).json(ApiError { error: self.error_name(), description: self.to_string(), + details: None, }) } } diff --git a/apps/labrinth/src/auth/oauth/errors.rs b/apps/labrinth/src/auth/oauth/errors.rs index 06656a52e..09691afe8 100644 --- a/apps/labrinth/src/auth/oauth/errors.rs +++ b/apps/labrinth/src/auth/oauth/errors.rs @@ -105,6 +105,7 @@ impl actix_web::ResponseError for OAuthError { HttpResponse::build(self.status_code()).json(ApiError { error: &self.error_type.error_name(), description: self.error_type.to_string(), + details: None, }) } } diff --git a/apps/labrinth/src/models/error.rs b/apps/labrinth/src/models/error.rs index 28f737c16..354c96ab7 100644 --- a/apps/labrinth/src/models/error.rs +++ b/apps/labrinth/src/models/error.rs @@ -5,4 +5,6 @@ use serde::{Deserialize, Serialize}; pub struct ApiError<'a> { pub error: &'a str, pub description: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub details: Option, } diff --git a/apps/labrinth/src/queue/payouts/mural.rs b/apps/labrinth/src/queue/payouts/mural.rs index d825bff3e..d90d8c7f4 100644 --- a/apps/labrinth/src/queue/payouts/mural.rs +++ b/apps/labrinth/src/queue/payouts/mural.rs @@ -177,7 +177,7 @@ impl PayoutsQueue { ) .await .map_err(|err| match err { - MuralError::Api(err) => ApiError::Request(err.into()), + MuralError::Api(err) => ApiError::Mural(Box::new(err)), err => ApiError::Internal( eyre!(err).wrap_err("failed to create payout request"), ), diff --git a/apps/labrinth/src/routes/mod.rs b/apps/labrinth/src/routes/mod.rs index ca55240b8..5b4c1f086 100644 --- a/apps/labrinth/src/routes/mod.rs +++ b/apps/labrinth/src/routes/mod.rs @@ -161,6 +161,8 @@ pub enum ApiError { RateLimitError(u128, u32), #[error("Error while interacting with payment processor: {0}")] Stripe(#[from] stripe::StripeError), + #[error(transparent)] + Mural(#[from] Box), } impl ApiError { @@ -201,6 +203,7 @@ impl ApiError { Self::Stripe(..) => "stripe_error", Self::TaxProcessor(..) => "tax_processor_error", Self::Slack(..) => "slack_error", + Self::Mural(..) => "mural_error", }, description: match self { Self::Internal(e) => format!("{e:#?}"), @@ -208,6 +211,10 @@ impl ApiError { Self::Auth(e) => format!("{e:#?}"), _ => self.to_string(), }, + details: match self { + Self::Mural(err) => serde_json::to_value(err.clone()).ok(), + _ => None, + }, } } } @@ -249,6 +256,7 @@ impl actix_web::ResponseError for ApiError { Self::Stripe(..) => StatusCode::FAILED_DEPENDENCY, Self::TaxProcessor(..) => StatusCode::INTERNAL_SERVER_ERROR, Self::Slack(..) => StatusCode::INTERNAL_SERVER_ERROR, + Self::Mural(..) => StatusCode::BAD_REQUEST, } } diff --git a/apps/labrinth/src/routes/not_found.rs b/apps/labrinth/src/routes/not_found.rs index 2da930bd7..4d9840050 100644 --- a/apps/labrinth/src/routes/not_found.rs +++ b/apps/labrinth/src/routes/not_found.rs @@ -5,6 +5,7 @@ pub async fn not_found() -> impl Responder { let data = ApiError { error: "not_found", description: "the requested route does not exist".to_string(), + details: None, }; HttpResponse::NotFound().json(data) diff --git a/apps/labrinth/src/routes/v3/project_creation.rs b/apps/labrinth/src/routes/v3/project_creation.rs index 4984adbd5..61376e5b0 100644 --- a/apps/labrinth/src/routes/v3/project_creation.rs +++ b/apps/labrinth/src/routes/v3/project_creation.rs @@ -151,6 +151,7 @@ impl actix_web::ResponseError for CreateError { CreateError::LimitReached => "limit_reached", }, description: self.to_string(), + details: None, }) } } diff --git a/apps/labrinth/src/search/mod.rs b/apps/labrinth/src/search/mod.rs index 663e1a83f..78e9941ea 100644 --- a/apps/labrinth/src/search/mod.rs +++ b/apps/labrinth/src/search/mod.rs @@ -53,6 +53,7 @@ impl actix_web::ResponseError for SearchError { SearchError::FormatError(..) => "invalid_input", }, description: self.to_string(), + details: None, }) } }