Sfoglia il codice sorgente

Check labels added against a whitelist for non team members.

Mark Rousskov 6 anni fa
parent
commit
345f4043d2
5 ha cambiato i file con 91 aggiunte e 0 eliminazioni
  1. 14 0
      Cargo.lock
  2. 1 0
      Cargo.toml
  3. 7 0
      parser/src/command/label.rs
  4. 19 0
      src/github.rs
  5. 50 0
      src/handlers/label.rs

+ 14 - 0
Cargo.lock

@@ -502,6 +502,9 @@ dependencies = [
 name = "indexmap"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "inotify"
@@ -1160,6 +1163,15 @@ dependencies = [
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rust_team_data"
+version = "1.0.0"
+source = "git+https://github.com/rust-lang/team#3bc6edd71fe5db86a61950cb4bf1f725f0b1a11e"
+dependencies = [
+ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc-demangle"
 version = "0.1.13"
@@ -1513,6 +1525,7 @@ dependencies = [
  "reqwest 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "rocket 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rocket_contrib 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rust_team_data 1.0.0 (git+https://github.com/rust-lang/team)",
  "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1836,6 +1849,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rocket_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d907d6d458c859651c1cf4c8fa99b77685082bde0561db6a4600b365058f710"
 "checksum rocket_contrib 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f73e161dad5730435f51c815a5c6831d2e57b6b4299b1bf609d31b09aa9a2fa7"
 "checksum rocket_http 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba9d4f2ce5bba6e1b6d3100493bbad63879e99bbf6b4365d61e6f781daab324d"
+"checksum rust_team_data 1.0.0 (git+https://github.com/rust-lang/team)" = "<none>"
 "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619"
 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
 "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"

+ 1 - 0
Cargo.toml

@@ -20,6 +20,7 @@ failure = "0.1"
 hex = "0.3.2"
 env_logger = "0.6"
 parser = { path = "parser" }
+rust_team_data = { git = "https://github.com/rust-lang/team" }
 
 [dependencies.serde]
 version = "1"

+ 7 - 0
parser/src/command/label.rs

@@ -104,6 +104,13 @@ impl LabelDelta {
             ))
         }
     }
+
+    pub fn label(&self) -> &Label {
+        match self {
+            LabelDelta::Add(l) => l,
+            LabelDelta::Remove(l) => l,
+        }
+    }
 }
 
 #[test]

+ 19 - 0
src/github.rs

@@ -8,6 +8,21 @@ pub struct User {
     pub login: String,
 }
 
+impl User {
+    pub fn is_team_member(&self, client: &GithubClient) -> Result<bool, Error> {
+        let client = client.raw();
+        let url = format!("{}/teams.json", rust_team_data::v1::BASE_URL);
+        let permission: rust_team_data::v1::Teams = client
+            .get(&url)
+            .send()
+            .and_then(|r| r.error_for_status())
+            .and_then(|mut r| r.json())
+            .context("could not get team data")?;
+        let map = permission.teams;
+        Ok(map["all"].members.iter().any(|g| g.github == self.login))
+    }
+}
+
 #[derive(Debug, Clone, serde::Deserialize)]
 pub struct Label {
     pub name: String,
@@ -162,6 +177,10 @@ impl GithubClient {
         }
     }
 
+    pub fn raw(&self) -> &Client {
+        &self.client
+    }
+
     pub fn username(&self) -> &str {
         self.username.as_str()
     }

+ 50 - 0
src/handlers/label.rs

@@ -56,6 +56,11 @@ impl Handler for LabelHandler {
 
         let mut changed = false;
         for delta in &deltas {
+            let name = delta.label().as_str();
+            if let Err(msg) = check_filter(name, &event.comment.user, &self.client) {
+                ErrorComment::new(&event.issue, msg).post(&self.client)?;
+                return Ok(());
+            }
             match delta {
                 LabelDelta::Add(label) => {
                     if !issue_labels.iter().any(|l| l.name == label.as_str()) {
@@ -81,3 +86,48 @@ impl Handler for LabelHandler {
         Ok(())
     }
 }
+
+fn check_filter(label: &str, user: &github::User, client: &GithubClient) -> Result<(), String> {
+    let is_team_member;
+    match user.is_team_member(client) {
+        Ok(true) => return Ok(()),
+        Ok(false) => {
+            is_team_member = Ok(());
+        }
+        Err(err) => {
+            eprintln!("failed to check team membership: {:?}", err);
+            is_team_member = Err(());
+            // continue on; if we failed to check their membership assume that they are not members.
+        }
+    }
+    if label.starts_with("C-") // categories
+    || label.starts_with("A-") // areas
+    || label.starts_with("E-") // easy, mentor, etc.
+    || label.starts_with("NLL-")
+    || label.starts_with("O-") // operating systems
+    || label.starts_with("S-") // status labels
+    || label.starts_with("T-")
+    || label.starts_with("WG-")
+    {
+        return Ok(());
+    }
+    match label {
+        "I-compilemem" | "I-compiletime" | "I-crash" | "I-hang" | "I-ICE" | "I-slow" => {
+            return Ok(());
+        }
+        _ => {}
+    }
+
+    if is_team_member.is_ok() {
+        Err(format!(
+            "Label {} can only be set by Rust team members",
+            label
+        ))
+    } else {
+        Err(format!(
+            "Label {} can only be set by Rust team members;\
+             we were unable to check if you are a team member.",
+            label
+        ))
+    }
+}