prololo: provide more context in errors
This commit is contained in:
parent
ff398e2c15
commit
e6926d5ba2
|
@ -4,6 +4,7 @@ use std::{
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
use matrix_sdk::{
|
use matrix_sdk::{
|
||||||
room::Room,
|
room::Room,
|
||||||
ruma::events::{room::member::MemberEventContent, StrippedStateEvent},
|
ruma::events::{room::member::MemberEventContent, StrippedStateEvent},
|
||||||
|
@ -37,7 +38,9 @@ impl Prololo {
|
||||||
///
|
///
|
||||||
/// The bot is ready to run once this function has been called.
|
/// The bot is ready to run once this function has been called.
|
||||||
pub async fn init(&self) -> anyhow::Result<()> {
|
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()];
|
let authorized_rooms = vec![self.config.matrix_room_id.clone()];
|
||||||
|
|
||||||
|
|
11
src/main.rs
11
src/main.rs
|
@ -2,6 +2,7 @@ use std::fs::File;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
use clap::Clap;
|
use clap::Clap;
|
||||||
use rocket::routes;
|
use rocket::routes;
|
||||||
|
|
||||||
|
@ -27,11 +28,13 @@ async fn main() -> anyhow::Result<()> {
|
||||||
tracing_subscriber::fmt::init();
|
tracing_subscriber::fmt::init();
|
||||||
|
|
||||||
let opts = Opts::parse();
|
let opts = Opts::parse();
|
||||||
let config_file = opts.config;
|
let config_file = File::open(&opts.config)
|
||||||
let config: ProloloConfig = serde_yaml::from_reader(BufReader::new(File::open(config_file)?))?;
|
.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)?;
|
let prololo = Prololo::new(config).context("failed to create prololo bot")?;
|
||||||
prololo.init().await?;
|
prololo.init().await.context("failed to init prololo bot")?;
|
||||||
tokio::spawn(async move { prololo.run().await });
|
tokio::spawn(async move { prololo.run().await });
|
||||||
|
|
||||||
let rocket = rocket::build().mount("/", routes![github_webhook]);
|
let rocket = rocket::build().mount("/", routes![github_webhook]);
|
||||||
|
|
|
@ -8,7 +8,7 @@ use serde::Deserialize;
|
||||||
|
|
||||||
mod signing;
|
mod signing;
|
||||||
use signing::SignedGitHubPayload;
|
use signing::SignedGitHubPayload;
|
||||||
use tracing::info;
|
use tracing::{debug, info, warn};
|
||||||
|
|
||||||
const X_GITHUB_EVENT: &str = "X-GitHub-Event";
|
const X_GITHUB_EVENT: &str = "X-GitHub-Event";
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ pub enum GitHubEventType {
|
||||||
Issues,
|
Issues,
|
||||||
IssueComment,
|
IssueComment,
|
||||||
Push,
|
Push,
|
||||||
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rocket::async_trait]
|
#[rocket::async_trait]
|
||||||
|
@ -48,10 +49,24 @@ impl<'r> FromRequest<'r> for GitHubEventType {
|
||||||
|
|
||||||
let event_type = event_types[0];
|
let event_type = event_types[0];
|
||||||
|
|
||||||
match serde_json::from_str::<GitHubEventType>(event_type) {
|
// HACK: serialize the Rust String to a JSON string so that it's deserializable into the
|
||||||
Ok(ev_type) => Outcome::Success(ev_type),
|
// GitHubEventType enum correctly:
|
||||||
Err(e) => Outcome::Failure((Status::BadRequest, anyhow!(e))),
|
//
|
||||||
|
// - `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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,14 @@ use rocket::{
|
||||||
http::{ContentType, Status},
|
http::{ContentType, Status},
|
||||||
Data, Request, State,
|
Data, Request, State,
|
||||||
};
|
};
|
||||||
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::webhooks::github::GitHubSecret;
|
use crate::webhooks::github::GitHubSecret;
|
||||||
|
|
||||||
const X_GITHUB_SIGNATURE: &str = "X-Hub-Signature-256";
|
const X_GITHUB_SIGNATURE: &str = "X-Hub-Signature-256";
|
||||||
|
|
||||||
fn validate_signature(secret: &str, signature: &str, data: &str) -> bool {
|
fn validate_signature(secret: &str, signature: &str, data: &str) -> bool {
|
||||||
|
trace!("validating signature...");
|
||||||
use hmac::{Hmac, Mac, NewMac};
|
use hmac::{Hmac, Mac, NewMac};
|
||||||
use sha2::Sha256;
|
use sha2::Sha256;
|
||||||
|
|
||||||
|
@ -54,6 +56,7 @@ impl<'r> FromData<'r> for SignedGitHubPayload {
|
||||||
type Error = anyhow::Error;
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
async fn from_data(request: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {
|
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");
|
let json_ct = ContentType::new("application", "json");
|
||||||
if request.content_type() != Some(&json_ct) {
|
if request.content_type() != Some(&json_ct) {
|
||||||
return Outcome::Failure((Status::BadRequest, anyhow!("wrong content type")));
|
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")));
|
return Outcome::Failure((Status::BadRequest, anyhow!("couldn't verify signature")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace!("validated GitHub payload");
|
||||||
Outcome::Success(SignedGitHubPayload(content))
|
Outcome::Success(SignedGitHubPayload(content))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue