diff --git a/Cargo.toml b/Cargo.toml index 2cea98b..351a9bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,3 +16,6 @@ name = "rustsec-advisory-db" gumdrop = "0.4" gumdrop_derive = "0.4" rustsec = "0.9" +reqwest = "0.9" +serde = "1.0" +serde_derive = "1.0" diff --git a/src/main.rs b/src/main.rs index b743605..b469a41 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,11 @@ extern crate gumdrop; #[macro_use] extern crate gumdrop_derive; +extern crate reqwest; extern crate rustsec; +extern crate serde; +#[macro_use] +extern crate serde_derive; use gumdrop::Options; use rustsec::{AdvisoryDatabase, Repository}; @@ -65,21 +69,64 @@ fn check() { let repo = Repository::open(".").unwrap(); // Ensure Advisories.toml parses - let advisory_count = AdvisoryDatabase::from_repository(&repo) - .unwrap() - .advisories() - .count(); + let db = AdvisoryDatabase::from_repository(&repo).unwrap(); + let advisories = db.advisories(); // Ensure we're parsing some advisories - if advisory_count > MIN_EXPECTED_ADVISORIES { + if advisories.len() > MIN_EXPECTED_ADVISORIES { println!( "*** Check succeeded! Successfully parsed {} advisories.", - advisory_count + advisories.len() ); } else { panic!( "Missing advisories! Expected at least {}, but got {}", - MIN_EXPECTED_ADVISORIES, advisory_count + MIN_EXPECTED_ADVISORIES, + advisories.len() + ); + } + + let http_client = reqwest::Client::new(); + for advisory in advisories { + check_advisory(&http_client, advisory); + } + println!("*** Check succeeded! All advisories refer to valid crates."); +} + +#[derive(Deserialize)] +struct CratesResponse { + #[serde(rename = "crate")] + krate: Crate, +} + +#[derive(Deserialize)] +struct Crate { + name: String, +} + +fn check_advisory(http_client: &reqwest::Client, advisory: &rustsec::Advisory) { + let mut response = http_client + .get(&format!( + "https://crates.io/api/v1/crates/{}", + advisory.package.as_str() + )) + .send() + .expect("Failed to make HTTP request to crates.io"); + if !response.status().is_success() { + panic!( + "crates.io returned an HTTP error ({}) trying to lookup the crate '{}', does it exist?", + response.status(), + advisory.package.as_str() + ); + } + + let parsed_response = response + .json::() + .expect("Failed to parse crates.io response as JSON"); + if parsed_response.krate.name != advisory.package.as_str() { + panic!( + "crates.io package name does not match package name in advisory for {}", + advisory.package.as_str() ); } }