prololo: provide more context in errors

This commit is contained in:
Antoine Martin 2021-09-12 15:59:06 +02:00
parent ff398e2c15
commit e6926d5ba2
4 changed files with 35 additions and 10 deletions

View file

@ -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()];

View file

@ -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]);

View file

@ -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::<GitHubEventType>(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::<GitHubEventType>(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)
}
}

View file

@ -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))
}
}