use serde::Deserialize;
use super::job::Job;
#[derive(Debug, Deserialize, PartialEq, Eq)]
pub enum EventKind {
#[serde(rename = "job.created")]
JobCreated,
#[serde(rename = "job.finished")]
JobFinished,
#[serde(rename = "job.failed")]
JobFailed,
}
#[derive(Debug)]
pub struct Event {
pub event: EventKind,
pub job: Job,
signature: [u8; 32],
}
#[derive(Debug)]
pub enum ParseError {
SignatureMismatch,
HexDecodeSignature(hex::FromHexError),
Json(serde_json::Error),
}
impl Event {
pub fn signature(&self) -> [u8; 32] {
self.signature
}
pub fn from_json(
json: &[u8],
signature: &str,
signing_secret: &[u8],
) -> Result<Event, ParseError> {
use hmac::{Hmac, Mac};
let mut expected_signature = [0; 32];
hex::decode_to_slice(signature, &mut expected_signature[..])
.map_err(ParseError::HexDecodeSignature)?;
let mut mac = Hmac::<sha2::Sha256>::new_from_slice(signing_secret).unwrap();
mac.update(json);
let actual_signature = mac.finalize();
let actual_signature: [u8; 32] = actual_signature.into_bytes().into();
if actual_signature != expected_signature {
return Err(ParseError::SignatureMismatch);
}
#[derive(Deserialize)]
struct EventJson {
event: EventKind,
job: Job,
}
let event: EventJson = serde_json::from_slice(json).map_err(ParseError::Json)?;
Ok(Event {
event: event.event,
job: event.job,
signature: actual_signature,
})
}
}