Browse Source

Update HIBP to v3, requires paid API key, fixes #583

Daniel García 6 years ago
parent
commit
515b87755a
4 changed files with 38 additions and 14 deletions
  1. 24 9
      src/api/core/mod.rs
  2. 5 5
      src/api/web.rs
  3. 3 0
      src/config.rs
  4. 6 0
      src/static/images/error-x.svg

+ 24 - 9
src/api/core/mod.rs

@@ -132,18 +132,33 @@ fn put_eq_domains(data: JsonUpcase<EquivDomainData>, headers: Headers, conn: DbC
 
 #[get("/hibp/breach?<username>")]
 fn hibp_breach(username: String) -> JsonResult {
-    let url = format!("https://haveibeenpwned.com/api/v2/breachedaccount/{}", username);
     let user_agent = "Bitwarden_RS";
+    let url = format!(
+        "https://haveibeenpwned.com/api/v3/breachedaccount/{}?truncateResponse=false&includeUnverified=false",
+        username
+    );
 
     use reqwest::{header::USER_AGENT, Client};
 
-    let res = Client::new().get(&url).header(USER_AGENT, user_agent).send()?;
-
-    // If we get a 404, return a 404, it means no breached accounts
-    if res.status() == 404 {
-        return Err(Error::empty().with_code(404));
+    if let Some(api_key) = crate::CONFIG.hibp_api_key() {
+        let res = Client::new()
+            .get(&url)
+            .header(USER_AGENT, user_agent)
+            .header("hibp-api-key", api_key)
+            .send()?;
+
+        // If we get a 404, return a 404, it means no breached accounts
+        if res.status() == 404 {
+            return Err(Error::empty().with_code(404));
+        }
+
+        let value: Value = res.error_for_status()?.json()?;
+        Ok(Json(value))
+    } else {
+        Ok(Json(json!([{
+            "title": "--- Error! ---",
+            "description": "HaveIBeenPwned API key not set! Go to https://haveibeenpwned.com/API/Key",
+            "logopath": "/bwrs_images/error-x.svg"
+        }])))
     }
-
-    let value: Value = res.error_for_status()?.json()?;
-    Ok(Json(value))
 }

+ 5 - 5
src/api/web.rs

@@ -65,11 +65,11 @@ fn alive() -> Json<String> {
 }
 
 #[get("/bwrs_images/<filename>")]
-fn images(filename: String) -> Result<Content<Vec<u8>>, Error> {
-    let image_type = ContentType::new("image", "png");
+fn images(filename: String) -> Result<Content<&'static [u8]>, Error> {
     match filename.as_ref() {
-        "mail-github.png" => Ok(Content(image_type , include_bytes!("../static/images/mail-github.png").to_vec())),
-        "logo-gray.png" => Ok(Content(image_type, include_bytes!("../static/images/logo-gray.png").to_vec())),
-        _ => err!("Image not found")
+        "mail-github.png" => Ok(Content(ContentType::PNG, include_bytes!("../static/images/mail-github.png"))),
+        "logo-gray.png" => Ok(Content(ContentType::PNG, include_bytes!("../static/images/logo-gray.png"))),
+        "error-x.svg" => Ok(Content(ContentType::SVG, include_bytes!("../static/images/error-x.svg"))),
+        _ => err!("Image not found"),
     }
 }

+ 3 - 0
src/config.rs

@@ -234,6 +234,9 @@ make_config! {
         /// Enable web vault
         web_vault_enabled:      bool,   false,  def,    true;
 
+        /// HIBP Api Key |> HaveIBeenPwned API Key, request it here: https://haveibeenpwned.com/API/Key
+        hibp_api_key:           String, false,  option;
+
         /// Disable icon downloads |> Set to true to disable icon downloading, this would still serve icons from
         /// $ICON_CACHE_FOLDER, but it won't produce any external network request. Needs to set $ICON_CACHE_TTL to 0,
         /// otherwise it will delete them and they won't be downloaded again.

+ 6 - 0
src/static/images/error-x.svg

@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="450" height="450" version="1">
+  <circle cx="225" cy="225" r="225" fill="#C33"/>
+  <g fill="#FFF" stroke="#FFF" stroke-width="70">
+    <path d="M107 110l236 237M107 347l236-237"/>
+  </g>
+</svg>