diff --git a/src/bot/mod.rs b/src/bot/mod.rs index f8ae65c..e48cd90 100644 --- a/src/bot/mod.rs +++ b/src/bot/mod.rs @@ -4,6 +4,7 @@ use std::{ path::PathBuf, }; +use anyhow::Context; use matrix_sdk::{ room::Room, ruma::events::{room::member::MemberEventContent, StrippedStateEvent}, @@ -37,7 +38,9 @@ impl Prololo { /// /// The bot is ready to run once this function has been called. pub async fn init(&self) -> anyhow::Result<()> { - self.load_or_init_session().await?; + self.load_or_init_session() + .await + .context("couldn't init session for matrix bot")?; let authorized_rooms = vec![self.config.matrix_room_id.clone()]; diff --git a/src/main.rs b/src/main.rs index 33e9315..7a3d1f6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ use std::fs::File; use std::io::BufReader; use std::path::PathBuf; +use anyhow::Context; use clap::Clap; use rocket::routes; @@ -27,11 +28,13 @@ async fn main() -> anyhow::Result<()> { tracing_subscriber::fmt::init(); let opts = Opts::parse(); - let config_file = opts.config; - let config: ProloloConfig = serde_yaml::from_reader(BufReader::new(File::open(config_file)?))?; + let config_file = File::open(&opts.config) + .with_context(|| format!("couldn't open {}:", opts.config.display()))?; + let config: ProloloConfig = serde_yaml::from_reader(BufReader::new(config_file)) + .context("couldn't parse config file")?; - let prololo = Prololo::new(config)?; - prololo.init().await?; + let prololo = Prololo::new(config).context("failed to create prololo bot")?; + prololo.init().await.context("failed to init prololo bot")?; tokio::spawn(async move { prololo.run().await }); let rocket = rocket::build().mount("/", routes![github_webhook]); diff --git a/src/webhooks/github.rs b/src/webhooks/github.rs index 83c20a2..f1bfcbc 100644 --- a/src/webhooks/github.rs +++ b/src/webhooks/github.rs @@ -8,7 +8,7 @@ use serde::Deserialize; mod signing; use signing::SignedGitHubPayload; -use tracing::info; +use tracing::{debug, info, warn}; const X_GITHUB_EVENT: &str = "X-GitHub-Event"; @@ -31,6 +31,7 @@ pub enum GitHubEventType { Issues, IssueComment, Push, + Unknown, } #[rocket::async_trait] @@ -48,10 +49,24 @@ impl<'r> FromRequest<'r> for GitHubEventType { let event_type = event_types[0]; - match serde_json::from_str::(event_type) { - Ok(ev_type) => Outcome::Success(ev_type), - Err(e) => Outcome::Failure((Status::BadRequest, anyhow!(e))), - } + // HACK: serialize the Rust String to a JSON string so that it's deserializable into the + // GitHubEventType enum correctly: + // + // - `create` is not a valid JSON string + // - `"create"` is! + let event_type_json_value = + serde_json::to_value(event_type).expect("`String` serialization should never fail"); + let event_type = match serde_json::from_value::(event_type_json_value) { + Ok(ev_type) => ev_type, + Err(e) => { + warn!("received unknown event type: {}, {}", event_type, e); + GitHubEventType::Unknown + } + }; + + debug!("received request with type {:?}", event_type); + + Outcome::Success(event_type) } } diff --git a/src/webhooks/github/signing.rs b/src/webhooks/github/signing.rs index 32c550e..eca3614 100644 --- a/src/webhooks/github/signing.rs +++ b/src/webhooks/github/signing.rs @@ -7,12 +7,14 @@ use rocket::{ http::{ContentType, Status}, Data, Request, State, }; +use tracing::trace; use crate::webhooks::github::GitHubSecret; const X_GITHUB_SIGNATURE: &str = "X-Hub-Signature-256"; fn validate_signature(secret: &str, signature: &str, data: &str) -> bool { + trace!("validating signature..."); use hmac::{Hmac, Mac, NewMac}; use sha2::Sha256; @@ -54,6 +56,7 @@ impl<'r> FromData<'r> for SignedGitHubPayload { type Error = anyhow::Error; async fn from_data(request: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> { + trace!("received payload on GitHub webhook endpoint"); let json_ct = ContentType::new("application", "json"); if request.content_type() != Some(&json_ct) { return Outcome::Failure((Status::BadRequest, anyhow!("wrong content type"))); @@ -90,6 +93,7 @@ impl<'r> FromData<'r> for SignedGitHubPayload { return Outcome::Failure((Status::BadRequest, anyhow!("couldn't verify signature"))); } + trace!("validated GitHub payload"); Outcome::Success(SignedGitHubPayload(content)) } }