Browse Source

Warning-free code

Restructure and allow unused warnings on a few functions
Mark Rousskov 6 years ago
parent
commit
1c343c84d9
4 changed files with 79 additions and 85 deletions
  1. 1 0
      src/github.rs
  2. 12 74
      src/main.rs
  3. 66 0
      src/payload.rs
  4. 0 11
      src/team.rs

+ 1 - 0
src/github.rs

@@ -80,6 +80,7 @@ impl Issue {
         &self.labels
     }
 
+    #[allow(unused)]
     pub fn add_assignee(&mut self, client: &GithubClient, user: &str) -> Result<(), Error> {
         unimplemented!()
     }

+ 12 - 74
src/main.rs

@@ -6,26 +6,23 @@ extern crate rocket;
 use failure::Error;
 use failure::ResultExt;
 use lazy_static::lazy_static;
-use openssl::hash::MessageDigest;
-use openssl::memcmp;
-use openssl::pkey::PKey;
-use openssl::sign::Signer;
 use regex::Regex;
 use reqwest::Client;
-use rocket::data::{self, FromDataSimple};
 use rocket::request;
 use rocket::State;
-use rocket::{http::Status, Data, Outcome, Request};
+use rocket::{http::Status, Outcome, Request};
 use std::env;
-use std::io::Read;
 
 mod github;
-mod permissions;
+mod payload;
+mod team;
+
+use payload::SignedPayload;
 
 static BOT_USER_NAME: &str = "rust-highfive";
 
 use github::{Comment, GithubClient, Issue, Label};
-use permissions::{Permissions, Team};
+use team::Team;
 
 #[derive(PartialEq, Eq, Debug, serde::Deserialize)]
 #[serde(rename_all = "lowercase")]
@@ -102,6 +99,7 @@ impl IssueCommentEvent {
     /// the issue if necessary.
     ///
     /// Assign users with `assign: @gh-user` or `@bot claim` (self-claim).
+    #[allow(unused)]
     fn handle_assign(&mut self, g: &GithubClient) -> Result<(), Error> {
         lazy_static! {
             static ref RE_ASSIGN: Regex = Regex::new(r"\bassign: @(\S+)").unwrap();
@@ -145,11 +143,8 @@ impl IssueCommentEvent {
     /// Long-term, this will also create a thread on internals and lock the tracking issue,
     /// directing commentary to the thread, but for the time being we limit the scope of work as
     /// well as project impact.
-    fn handle_create_tracking_issue(
-        &mut self,
-        g: &GithubClient,
-        auth: &Permissions,
-    ) -> Result<(), Error> {
+    #[allow(unused)]
+    fn handle_create_tracking_issue(&mut self, g: &GithubClient) -> Result<(), Error> {
         lazy_static! {
             static ref RE_TRACKING: Regex = Regex::new(&format!(
                 r#"\b@{} tracking-issue create feature=("[^"]+|\S+) team=(libs|lang)"#,
@@ -191,11 +186,12 @@ impl IssueCommentEvent {
     /// TODO: Check the checkbox in the tracking issue when `tracked-bug` is closed.
     ///
     /// Syntax: `link: #xxx`
+    #[allow(unused)]
     fn handle_link_tracking_issue(&mut self, g: &GithubClient) -> Result<(), Error> {
         unimplemented!()
     }
 
-    fn run(mut self, g: &GithubClient, permissions: &Permissions) -> Result<(), Error> {
+    fn run(mut self, g: &GithubClient) -> Result<(), Error> {
         // Don't do anything on deleted comments.
         //
         // XXX: Should we attempt to roll back the action instead?
@@ -228,74 +224,17 @@ impl<'a, 'r> request::FromRequest<'a, 'r> for Event {
     }
 }
 
-struct SignedPayload(Vec<u8>);
-
-impl FromDataSimple for SignedPayload {
-    type Error = String;
-    fn from_data(req: &Request, data: Data) -> data::Outcome<Self, Self::Error> {
-        let signature = match req.headers().get_one("X-Hub-Signature") {
-            Some(s) => s,
-            None => {
-                return Outcome::Failure((
-                    Status::Unauthorized,
-                    format!("Unauthorized, no signature"),
-                ));
-            }
-        };
-        let signature = &signature["sha1=".len()..];
-        let signature = match hex::decode(&signature) {
-            Ok(e) => e,
-            Err(e) => {
-                return Outcome::Failure((
-                    Status::BadRequest,
-                    format!(
-                        "failed to convert signature {:?} from hex: {:?}",
-                        signature, e
-                    ),
-                ));
-            }
-        };
-
-        let mut stream = data.open().take(1024 * 1024 * 5); // 5 Megabytes
-        let mut buf = Vec::new();
-        if let Err(err) = stream.read_to_end(&mut buf) {
-            return Outcome::Failure((
-                Status::InternalServerError,
-                format!("failed to read request body to string: {:?}", err),
-            ));
-        }
-
-        let key = PKey::hmac(env::var("GITHUB_WEBHOOK_SECRET").unwrap().as_bytes()).unwrap();
-        let mut signer = Signer::new(MessageDigest::sha1(), &key).unwrap();
-        signer.update(&buf).unwrap();
-        let hmac = signer.sign_to_vec().unwrap();
-
-        if !memcmp::eq(&hmac, &signature) {
-            return Outcome::Failure((Status::Unauthorized, format!("HMAC not correct")));
-        }
-
-        Outcome::Success(SignedPayload(buf))
-    }
-}
-
-impl SignedPayload {
-    fn deserialize<T: serde::de::DeserializeOwned>(self) -> Result<T, serde_json::Error> {
-        serde_json::from_slice(&self.0)
-    }
-}
-
 #[post("/github-hook", data = "<payload>")]
 fn webhook(
     event: Event,
     payload: SignedPayload,
     client: State<GithubClient>,
-    permissions: State<Permissions>,
 ) -> Result<(), String> {
     match event {
         Event::IssueComment => payload
             .deserialize::<IssueCommentEvent>()
             .map_err(|e| format!("IssueCommentEvent failed to deserialize: {:?}", e))?
-            .run(&client, &permissions)
+            .run(&client)
             .map_err(|e| format!("{:?}", e))?,
         // Other events need not be handled
         Event::Other => {}
@@ -316,7 +255,6 @@ fn main() {
             client.clone(),
             env::var("GITHUB_API_TOKEN").unwrap(),
         ))
-        .manage(Permissions::new(client))
         .mount("/", routes![webhook])
         .register(catchers![not_found])
         .launch();

+ 66 - 0
src/payload.rs

@@ -0,0 +1,66 @@
+//! This module implements the payload verification for GitHub webhook events.
+
+use openssl::{hash::MessageDigest, memcmp, pkey::PKey, sign::Signer};
+use rocket::{
+    data::{self, Data, FromDataSimple},
+    http::Status,
+    request::Request,
+    Outcome,
+};
+use std::{env, io::Read};
+
+pub struct SignedPayload(Vec<u8>);
+
+impl FromDataSimple for SignedPayload {
+    type Error = String;
+    fn from_data(req: &Request, data: Data) -> data::Outcome<Self, Self::Error> {
+        let signature = match req.headers().get_one("X-Hub-Signature") {
+            Some(s) => s,
+            None => {
+                return Outcome::Failure((
+                    Status::Unauthorized,
+                    format!("Unauthorized, no signature"),
+                ));
+            }
+        };
+        let signature = &signature["sha1=".len()..];
+        let signature = match hex::decode(&signature) {
+            Ok(e) => e,
+            Err(e) => {
+                return Outcome::Failure((
+                    Status::BadRequest,
+                    format!(
+                        "failed to convert signature {:?} from hex: {:?}",
+                        signature, e
+                    ),
+                ));
+            }
+        };
+
+        let mut stream = data.open().take(1024 * 1024 * 5); // 5 Megabytes
+        let mut buf = Vec::new();
+        if let Err(err) = stream.read_to_end(&mut buf) {
+            return Outcome::Failure((
+                Status::InternalServerError,
+                format!("failed to read request body to string: {:?}", err),
+            ));
+        }
+
+        let key = PKey::hmac(env::var("GITHUB_WEBHOOK_SECRET").unwrap().as_bytes()).unwrap();
+        let mut signer = Signer::new(MessageDigest::sha1(), &key).unwrap();
+        signer.update(&buf).unwrap();
+        let hmac = signer.sign_to_vec().unwrap();
+
+        if !memcmp::eq(&hmac, &signature) {
+            return Outcome::Failure((Status::Unauthorized, format!("HMAC not correct")));
+        }
+
+        Outcome::Success(SignedPayload(buf))
+    }
+}
+
+impl SignedPayload {
+    pub fn deserialize<T: serde::de::DeserializeOwned>(self) -> Result<T, serde_json::Error> {
+        serde_json::from_slice(&self.0)
+    }
+}

+ 0 - 11
src/permissions.rs → src/team.rs

@@ -1,11 +1,6 @@
 use failure::Error;
-use reqwest::Client;
 use std::str::FromStr;
 
-pub struct Permissions {
-    client: Client,
-}
-
 #[derive(Debug, PartialEq, Eq)]
 pub enum Team {
     Libs,
@@ -40,9 +35,3 @@ impl FromStr for Team {
         })
     }
 }
-
-impl Permissions {
-    pub fn new(client: Client) -> Permissions {
-        Permissions { client }
-    }
-}