diff --git a/CHANGELOG.md b/CHANGELOG.md index ac9f868..d1ab3db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ and this project adheres to +## [0.32.2] - 2026-09-10 + +### Added + +- `webhook::rotate_signing_secret` + ## [0.32.1] - 2026-09-04 ### Added @@ -621,6 +627,7 @@ Disabled `reqwest`'s default features and enabled `rustls-tls`. Initial release. +[0.32.2]: https://crates.io/crates/resend-rs/0.32.2 [0.32.1]: https://crates.io/crates/resend-rs/0.32.1 [0.32.0]: https://crates.io/crates/resend-rs/0.32.0 [0.31.1]: https://crates.io/crates/resend-rs/0.31.1 diff --git a/Cargo.toml b/Cargo.toml index 96779d3..ef1eba5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "resend-rs" -version = "0.32.1" +version = "0.32.2" edition = "2024" license = "MIT" diff --git a/src/lib.rs b/src/lib.rs index 312bd00..7d5eed1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -184,10 +184,10 @@ pub mod types { }; pub use super::webhooks::types::{ CreateWebhookOptions, CreateWebhookResponse, DeleteWebhookResponse, - ReplayWebhookEventResponse, UpdateWebhookOptions, UpdateWebhookResponse, Webhook, - WebhookEvent, WebhookEventAttempt, WebhookEventAttemptId, WebhookEventAttemptListResponse, - WebhookEventDetails, WebhookEventId, WebhookEventListResponse, WebhookEventStatus, - WebhookId, WebhookStatus, + ReplayWebhookEventResponse, RotateWebhookSigningSecretResponse, UpdateWebhookOptions, + UpdateWebhookResponse, Webhook, WebhookEvent, WebhookEventAttempt, WebhookEventAttemptId, + WebhookEventAttemptListResponse, WebhookEventDetails, WebhookEventId, + WebhookEventListResponse, WebhookEventStatus, WebhookId, WebhookStatus, }; } diff --git a/src/webhooks.rs b/src/webhooks.rs index 09a7e3d..d986511 100644 --- a/src/webhooks.rs +++ b/src/webhooks.rs @@ -7,8 +7,9 @@ use crate::{ list_opts::{AfterPagination, ListOptions, ListResponse}, types::{ CreateWebhookOptions, CreateWebhookResponse, DeleteWebhookResponse, - ReplayWebhookEventResponse, UpdateWebhookOptions, UpdateWebhookResponse, Webhook, - WebhookEventAttemptListResponse, WebhookEventDetails, WebhookEventListResponse, + ReplayWebhookEventResponse, RotateWebhookSigningSecretResponse, UpdateWebhookOptions, + UpdateWebhookResponse, Webhook, WebhookEventAttemptListResponse, WebhookEventDetails, + WebhookEventListResponse, }, }; @@ -118,6 +119,24 @@ impl WebhookSvc { Ok(content) } + /// Rotate the signing secret of a webhook. The previous secret keeps working for 24 hours. + /// + /// + #[maybe_async::maybe_async] + pub async fn rotate_signing_secret( + &self, + webhook_id: &str, + ) -> Result { + let path = format!("/webhooks/{webhook_id}/signing-secret/rotate"); + let request = self.0.build(Method::POST, &path); + let response = self.0.send(request).await?; + let content = response + .json::() + .await?; + + Ok(content) + } + /// Retrieve the delivery attempts for a webhook event. /// /// @@ -253,6 +272,14 @@ pub mod types { pub signing_secret: String, } + #[must_use] + #[derive(Debug, Clone, Serialize, Deserialize)] + pub struct RotateWebhookSigningSecretResponse { + pub object: String, + pub id: WebhookId, + pub signing_secret: String, + } + #[must_use] #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Webhook { @@ -328,7 +355,8 @@ mod test { list_opts::ListOptions, types::{CreateWebhookOptions, CreateWebhookResponse}, types::{ - Webhook, WebhookEventAttemptListResponse, WebhookEventDetails, WebhookEventListResponse, + RotateWebhookSigningSecretResponse, Webhook, WebhookEventAttemptListResponse, + WebhookEventDetails, WebhookEventListResponse, }, }; #[cfg(not(feature = "blocking"))] @@ -413,6 +441,22 @@ mod test { assert!(res.is_ok()); } + #[test] + fn deserialize_rotate_signing_secret_response() -> serde_json::Result<()> { + let rotated = r#"{ + "object": "webhook", + "id": "4dd369bc-aa82-4ff3-97de-514ae3000ee0", + "signing_secret": "whsec_yyyyyyyyyy" +}"#; + + let rotated = serde_json::from_str::(rotated)?; + + assert_eq!(rotated.id.as_ref(), "4dd369bc-aa82-4ff3-97de-514ae3000ee0"); + assert_eq!(rotated.signing_secret, "whsec_yyyyyyyyyy"); + + Ok(()) + } + #[test] fn deserialize_webhook_event_responses() -> serde_json::Result<()> { let events = r#"{