From d96048018797a6ea7a85beed4de7c5f7fc9d28db Mon Sep 17 00:00:00 2001 From: KunoiSayami Date: Thu, 9 Dec 2021 01:39:22 +0800 Subject: [PATCH] feat: Optimize message format * feat(auth): Allow empty secrets to skip secrets check Signed-off-by: KunoiSayami --- Cargo.lock | 2 +- Cargo.toml | 4 ++-- src/configure.rs | 23 ++++++++++++++--------- src/datastructures.rs | 31 ++++++++++++++++++++++++++----- src/main.rs | 36 +++++++++++++++++++++++++----------- 5 files changed, 68 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d9a38d3..74983ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "github-webhook-notification" -version = "0.1.0" +version = "0.1.1" dependencies = [ "actix", "actix-rt", diff --git a/Cargo.toml b/Cargo.toml index 2278267..48805ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "github-webhook-notification" -version = "0.1.0" +version = "0.1.1" edition = "2021" [dependencies] @@ -14,8 +14,8 @@ log = { version = "0.4", features = ["max_level_trace", "release_max_level_debug serde = { version = "1.0", features = ["derive"] } serde_derive = "1" serde_json = "1" +sha2 = "0.10" teloxide = { version = "0.5", default-features = false, features = ["rustls"] } teloxide-macros = "0.4" tokio = { version = "1", features = ["full"] } toml = "0.5" -sha2 = "0.10" \ No newline at end of file diff --git a/src/configure.rs b/src/configure.rs index ca00d87..dd35fb4 100644 --- a/src/configure.rs +++ b/src/configure.rs @@ -15,9 +15,10 @@ ** along with this program. If not, see . */ +use log::warn; use serde_derive::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; use std::path::Path; -use sha2::{Sha256, Digest}; #[derive(Deserialize, Serialize)] pub struct TomlConfig { @@ -39,7 +40,6 @@ impl TomlConfig { pub fn telegram(&self) -> &Telegram { &self.telegram } - } #[derive(Deserialize, Serialize, Debug, Clone)] @@ -81,14 +81,13 @@ impl Config { let config = TomlConfig::new(path)?; Ok(Self::from(&config)) } - } impl From<&TomlConfig> for Config { fn from(config: &TomlConfig) -> Self { Self { server: Server::from(config.server()), - telegram: config.telegram().clone() + telegram: config.telegram().clone(), } } } @@ -120,12 +119,18 @@ pub struct Server { impl From<&TomlServer> for Server { fn from(s: &TomlServer) -> Self { - let mut hasher = Sha256::new(); - hasher.update(s.secrets()); - let result = hasher.finalize(); + let secrets = if !s.secrets().is_empty() { + let mut hasher = Sha256::new(); + hasher.update(s.secrets()); + let result = hasher.finalize(); + format!("sha256={:x}", result).to_lowercase() + } else { + warn!("You should set a token to protect your webhook server"); + "".to_string() + }; Self { bind: format!("{}:{}", s.bind(), s.port()), - secrets_sha256: format!("sha256={:x}", result).to_lowercase() + secrets_sha256: secrets, } } } @@ -137,4 +142,4 @@ impl Server { pub fn secrets(&self) -> &str { &self.secrets_sha256 } -} \ No newline at end of file +} diff --git a/src/datastructures.rs b/src/datastructures.rs index e27a5bf..a5bde71 100644 --- a/src/datastructures.rs +++ b/src/datastructures.rs @@ -17,10 +17,10 @@ use actix_web::dev::RequestHead; use actix_web::guard::Guard; +use log::debug; use serde_derive::{Deserialize, Serialize}; use std::fmt::Formatter; use std::ops::Index; -use log::debug; #[derive(Deserialize, Serialize, Debug)] pub struct Request { @@ -28,6 +28,7 @@ pub struct Request { remote_ref: String, commits: Vec, compare: String, + repository: Repository, } impl Request { @@ -40,18 +41,23 @@ impl Request { pub fn compare(&self) -> &str { &self.compare } + pub fn repository(&self) -> &Repository { + &self.repository + } } impl std::fmt::Display for Request { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let branch = self.remote_ref().rsplit_once("/").unwrap().1; + let git_ref = format!("{}:{}", self.repository(), branch); if self.commits.len() == 1 { let item = self.commits().index(0); write!( f, - "🔨 {count} new commit to {git_ref}:\n{commits}", + "🔨 {count} new commit to {git_ref}:\n\n{commits}", url = item.url(), count = 1, - git_ref = self.remote_ref(), + git_ref = git_ref, commits = item ) } else { @@ -63,10 +69,10 @@ impl std::fmt::Display for Request { .join("\n"); write!( f, - "🔨 {count} new commits to {git_ref}:\n{commits}", + "🔨 {count} new commits to {git_ref}:\n\n{commits}", url = self.compare(), count = self.commits.len(), - git_ref = self.remote_ref(), + git_ref = git_ref, commits = l, ) } @@ -116,6 +122,17 @@ impl std::fmt::Display for Commit { } } +#[derive(Deserialize, Serialize, Debug)] +pub struct Repository { + full_name: String, +} + +impl std::fmt::Display for Repository { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.full_name) + } +} + #[derive(Deserialize, Serialize, Debug, Default)] pub struct Response { version: String, @@ -169,6 +186,10 @@ impl From<&str> for AuthorizationGuard { impl Guard for AuthorizationGuard { fn check(&self, request: &RequestHead) -> bool { + if self.token.is_empty() { + return true; + } + // TODO: Implement HMAC check if let Some(val) = request.headers.get("X-Hub-Signature-256") { debug!("{:?}, {}", val, &self.token); return self.token.len() != 7 && val == &self.token; diff --git a/src/main.rs b/src/main.rs index 57b432c..17b5d78 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,7 @@ use crate::Command::Text; use actix_web::http::Method; use actix_web::{web, App, HttpRequest, HttpResponse, HttpServer}; use log::{debug, error, info, warn}; +use std::path::Path; use std::sync::Arc; use teloxide::prelude::{Request, Requester, RequesterExt}; use teloxide::types::ParseMode; @@ -50,9 +51,8 @@ async fn process_send_message( if bot_token.is_empty() { warn!("Token is empty, skipped all send message request."); while let Some(cmd) = rx.recv().await { - match cmd { - Command::Terminate => break, - _ => {} + if let Command::Terminate = cmd { + break; } } return Ok(()); @@ -63,12 +63,13 @@ async fn process_send_message( None => bot, }; - // TODO: Disable preview web page let bot = bot.parse_mode(ParseMode::Html); while let Some(cmd) = rx.recv().await { match cmd { Command::Text(text) => { - if let Err(e) = bot.send_message(owner, text).send().await { + let mut payload = bot.send_message(owner, text); + payload.disable_web_page_preview = Option::from(true); + if let Err(e) = payload.send().await { error!("Got error in send message {:?}", e); } } @@ -89,8 +90,8 @@ async fn route_post( Ok(HttpResponse::Ok().json(Response::new_ok())) } -async fn async_main() -> anyhow::Result<()> { - let config = crate::configure::Config::new("data/config.toml")?; +async fn async_main>(path: P) -> anyhow::Result<()> { + let config = crate::configure::Config::new(path)?; let (bot_tx, bot_rx) = mpsc::channel(1024); @@ -138,16 +139,29 @@ async fn async_main() -> anyhow::Result<()> { } fn main() -> anyhow::Result<()> { - env_logger::Builder::from_default_env().init(); - - clap::App::new("github-webhook-notification") + env_logger::Builder::from_default_env() + .filter_module("rustls::client", log::LevelFilter::Warn) + .init(); + + let arg_matches = clap::App::new("github-webhook-notification") + .arg( + clap::Arg::with_name("cfg") + .long("cfg") + .short("c") + .help("Specify configure file location") + .takes_value(true), + ) .version(SERVER_VERSION) .get_matches(); let system = actix::System::new(); info!("Server version: {}", SERVER_VERSION); - system.block_on(async_main())?; + system.block_on(async_main( + arg_matches + .value_of("cfg") + .unwrap_or("data/probe_client.toml"), + ))?; system.run()?;