use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EndpointCreatedEventData {
#[serde(rename = "appId")]
pub app_id: String,
#[serde(rename = "endpointId")]
pub endpoint_id: String,
#[serde(rename = "appUid")]
pub app_uid: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EndpointUpdatedEventData {
#[serde(rename = "appId")]
pub app_id: String,
#[serde(rename = "endpointId")]
pub endpoint_id: String,
#[serde(rename = "appUid")]
pub app_uid: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EndpointDeletedEventData {
#[serde(rename = "appId")]
pub app_id: String,
#[serde(rename = "endpointId")]
pub endpoint_id: String,
#[serde(rename = "appUid")]
pub app_uid: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EndpointEnabledEventData {
#[serde(rename = "appId")]
pub app_id: String,
#[serde(rename = "endpointId")]
pub endpoint_id: String,
#[serde(rename = "appUid")]
pub app_uid: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EndpointDisabledEventData {
#[serde(rename = "appId")]
pub app_id: String,
#[serde(rename = "endpointId")]
pub endpoint_id: String,
#[serde(rename = "appUid")]
pub app_uid: Option<String>,
#[serde(rename = "failSince")]
pub fail_since: Option<String>,
pub trigger: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LastAttemptInfo {
pub id: String,
pub timestamp: String,
#[serde(rename = "responseStatusCode")]
pub response_status_code: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AttemptInfo {
pub id: String,
pub timestamp: String,
#[serde(rename = "responseStatusCode")]
pub response_status_code: i32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageAttemptExhaustedEventData {
#[serde(rename = "appId")]
pub app_id: String,
#[serde(rename = "msgId")]
pub msg_id: String,
#[serde(rename = "lastAttempt")]
pub last_attempt: LastAttemptInfo,
#[serde(rename = "appUid")]
pub app_uid: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageAttemptFailingEventData {
#[serde(rename = "appId")]
pub app_id: String,
#[serde(rename = "msgId")]
pub msg_id: String,
pub attempt: AttemptInfo,
#[serde(rename = "appUid")]
pub app_uid: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MessageAttemptRecoveredEventData {
#[serde(rename = "appId")]
pub app_id: String,
#[serde(rename = "msgId")]
pub msg_id: String,
pub attempt: AttemptInfo,
#[serde(rename = "appUid")]
pub app_uid: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "event", content = "data")]
pub enum TypedWebhookEvent {
#[serde(rename = "endpoint.created")]
EndpointCreated(EndpointCreatedEventData),
#[serde(rename = "endpoint.updated")]
EndpointUpdated(EndpointUpdatedEventData),
#[serde(rename = "endpoint.deleted")]
EndpointDeleted(EndpointDeletedEventData),
#[serde(rename = "endpoint.enabled")]
EndpointEnabled(EndpointEnabledEventData),
#[serde(rename = "endpoint.disabled")]
EndpointDisabled(EndpointDisabledEventData),
#[serde(rename = "message.attempt.exhausted")]
MessageAttemptExhausted(MessageAttemptExhaustedEventData),
#[serde(rename = "message.attempt.failing")]
MessageAttemptFailing(MessageAttemptFailingEventData),
#[serde(rename = "message.attempt.recovered")]
MessageAttemptRecovered(MessageAttemptRecoveredEventData),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WebhookEvent {
pub event: String,
pub data: serde_json::Value,
pub timestamp: String,
}
impl WebhookEvent {
pub fn event_type(&self) -> &str {
&self.event
}
pub fn get(&self, key: &str) -> Option<&serde_json::Value> {
self.data.get(key)
}
pub fn typed(&self) -> Option<TypedWebhookEvent> {
let wrapper = serde_json::json!({
"event": self.event,
"data": self.data,
});
serde_json::from_value(wrapper).ok()
}
pub fn parse_data<T: serde::de::DeserializeOwned>(&self) -> Result<T, serde_json::Error> {
serde_json::from_value(self.data.clone())
}
}
impl crate::webhooks::Webhook {
pub fn verify_and_parse<HM: crate::webhooks::HeaderMap>(
&self,
payload: &[u8],
headers: &HM,
) -> Result<WebhookEvent, crate::webhooks::WebhookError> {
self.verify_inner(payload, headers, true)?;
let event: WebhookEvent =
serde_json::from_slice(payload).map_err(|_| crate::webhooks::WebhookError::InvalidPayload)?;
Ok(event)
}
pub fn verify_and_parse_ignoring_timestamp<HM: crate::webhooks::HeaderMap>(
&self,
payload: &[u8],
headers: &HM,
) -> Result<WebhookEvent, crate::webhooks::WebhookError> {
self.verify_inner(payload, headers, false)?;
let event: WebhookEvent =
serde_json::from_slice(payload).map_err(|_| crate::webhooks::WebhookError::InvalidPayload)?;
Ok(event)
}
pub fn verify_and_parse_typed<HM: crate::webhooks::HeaderMap>(
&self,
payload: &[u8],
headers: &HM,
) -> Result<TypedWebhookEvent, crate::webhooks::WebhookError> {
self.verify_inner(payload, headers, true)?;
let event: TypedWebhookEvent =
serde_json::from_slice(payload).map_err(|_| crate::webhooks::WebhookError::InvalidPayload)?;
Ok(event)
}
}