diff --git a/crates/meilisearch-types/src/error.rs b/crates/meilisearch-types/src/error.rs index 3916012c1..e14a06909 100644 --- a/crates/meilisearch-types/src/error.rs +++ b/crates/meilisearch-types/src/error.rs @@ -424,6 +424,7 @@ InvalidWebhooks , InvalidRequest , BAD_REQU InvalidWebhooksUrl , InvalidRequest , BAD_REQUEST ; InvalidWebhooksHeaders , InvalidRequest , BAD_REQUEST ; ReservedWebhook , InvalidRequest , BAD_REQUEST ; +InvalidWebhookUuid , InvalidRequest , BAD_REQUEST ; WebhookNotFound , InvalidRequest , NOT_FOUND } diff --git a/crates/meilisearch/src/routes/webhooks.rs b/crates/meilisearch/src/routes/webhooks.rs index 18edfb63c..2454b624b 100644 --- a/crates/meilisearch/src/routes/webhooks.rs +++ b/crates/meilisearch/src/routes/webhooks.rs @@ -1,4 +1,5 @@ use std::collections::BTreeMap; +use std::str::FromStr; use actix_http::header::{ HeaderName, HeaderValue, InvalidHeaderName as ActixInvalidHeaderName, @@ -195,6 +196,8 @@ enum WebhooksError { InvalidHeaderValue(String, ActixInvalidHeaderValue), #[error("Invalid URL `{0}`: {1}")] InvalidUrl(String, url::ParseError), + #[error("Invalid UUID: {0}")] + InvalidUuid(uuid::Error), } impl ErrorCode for WebhooksError { @@ -208,6 +211,7 @@ impl ErrorCode for WebhooksError { InvalidHeaderName(_, _) => meilisearch_types::error::Code::InvalidWebhooksHeaders, InvalidHeaderValue(_, _) => meilisearch_types::error::Code::InvalidWebhooksHeaders, InvalidUrl(_, _) => meilisearch_types::error::Code::InvalidWebhooksUrl, + InvalidUuid(_) => meilisearch_types::error::Code::InvalidWebhookUuid, } } } @@ -302,9 +306,9 @@ fn check_changed(uuid: Uuid, webhook: &Webhook) -> Result<(), WebhooksError> { )] async fn get_webhook( index_scheduler: GuardedData, Data>, - uuid: Path, + uuid: Path, ) -> Result { - let uuid = uuid.into_inner(); + let uuid = Uuid::from_str(&uuid.into_inner()).map_err(InvalidUuid)?; let mut webhooks = index_scheduler.webhooks(); let webhook = webhooks.webhooks.remove(&uuid).ok_or(WebhookNotFound(uuid))?; @@ -396,12 +400,12 @@ async fn post_webhook( )] async fn patch_webhook( index_scheduler: GuardedData, Data>, - uuid: Path, + uuid: Path, webhook_settings: AwebJson, req: HttpRequest, analytics: Data, ) -> Result { - let uuid = uuid.into_inner(); + let uuid = Uuid::from_str(&uuid.into_inner()).map_err(InvalidUuid)?; let webhook_settings = webhook_settings.into_inner(); debug!(parameters = ?(uuid, &webhook_settings), "Patch webhook"); @@ -436,11 +440,11 @@ async fn patch_webhook( )] async fn delete_webhook( index_scheduler: GuardedData, Data>, - uuid: Path, + uuid: Path, req: HttpRequest, analytics: Data, ) -> Result { - let uuid = uuid.into_inner(); + let uuid = Uuid::from_str(&uuid.into_inner()).map_err(InvalidUuid)?; debug!(parameters = ?uuid, "Delete webhook"); if uuid.is_nil() { diff --git a/crates/meilisearch/tests/tasks/webhook.rs b/crates/meilisearch/tests/tasks/webhook.rs index a1029da6d..155312b9d 100644 --- a/crates/meilisearch/tests/tasks/webhook.rs +++ b/crates/meilisearch/tests/tasks/webhook.rs @@ -520,3 +520,45 @@ async fn invalid_url_and_headers() { } "#); } + +#[actix_web::test] +async fn invalid_uuid() { + let server = Server::new().await; + + // Test get webhook with invalid UUID + let (value, code) = server.get_webhook("invalid-uuid").await; + snapshot!(code, @"400 Bad Request"); + snapshot!(value, @r#" + { + "message": "Invalid UUID: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `i` at 1", + "code": "invalid_webhook_uuid", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid_webhook_uuid" + } + "#); + + // Test update webhook with invalid UUID + let (value, code) = + server.patch_webhook("invalid-uuid", json!({ "url": "https://example.com/hook" })).await; + snapshot!(code, @"400 Bad Request"); + snapshot!(value, @r#" + { + "message": "Invalid UUID: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `i` at 1", + "code": "invalid_webhook_uuid", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid_webhook_uuid" + } + "#); + + // Test delete webhook with invalid UUID + let (value, code) = server.delete_webhook("invalid-uuid").await; + snapshot!(code, @"400 Bad Request"); + snapshot!(value, @r#" + { + "message": "Invalid UUID: invalid character: expected an optional prefix of `urn:uuid:` followed by [0-9a-fA-F-], found `i` at 1", + "code": "invalid_webhook_uuid", + "type": "invalid_request", + "link": "https://docs.meilisearch.com/errors#invalid_webhook_uuid" + } + "#); +}