From df8f4f2791ee25cd4bdad07cdec8b9837b72ffb3 Mon Sep 17 00:00:00 2001 From: Oscar Beaumont Date: Thu, 30 Dec 2021 13:53:22 +0800 Subject: [PATCH 1/3] feat: added min_password_strength validator --- Cargo.toml | 2 ++ derive/src/validators.rs | 8 ++++++ src/validators/min_password_strength.rs | 34 +++++++++++++++++++++++++ src/validators/mod.rs | 2 ++ 4 files changed, 46 insertions(+) create mode 100644 src/validators/min_password_strength.rs diff --git a/Cargo.toml b/Cargo.toml index b7c3dc18..e38ad786 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ tracing = ["tracinglib", "tracing-futures"] decimal = ["rust_decimal"] cbor = ["serde_cbor"] chrono-duration = ["chrono", "iso8601-duration"] +password-strength-validator = ["zxcvbn"] [dependencies] async-graphql-derive = { path = "derive", version = "3.0.19" } @@ -63,6 +64,7 @@ uuid = { version = "0.8.2", optional = true, features = ["v4", "serde"] } rust_decimal = { version = "1.14.3", optional = true } url = { version = "2.2.1", optional = true } smol_str = { version = "0.1.21", optional = true } +zxcvbn = { version = "2.1.2", optional = true } # Non-feature optional dependencies blocking = { version = "1.0.2", optional = true } diff --git a/derive/src/validators.rs b/derive/src/validators.rs index 17eb7dfe..ed50eb28 100644 --- a/derive/src/validators.rs +++ b/derive/src/validators.rs @@ -34,6 +34,8 @@ pub struct Validators { #[darling(default)] multiple_of: Option, #[darling(default)] + min_password_strength: Option, + #[darling(default)] maximum: Option, #[darling(default)] minimum: Option, @@ -93,6 +95,12 @@ impl Validators { }); } + if let Some(n) = &self.min_password_strength { + elem_validators.push(quote! { + #crate_name::validators::min_password_strength(__raw_value, #n) + }); + } + if let Some(n) = &self.maximum { elem_validators.push(quote! { #crate_name::validators::maximum(__raw_value, #n) diff --git a/src/validators/min_password_strength.rs b/src/validators/min_password_strength.rs new file mode 100644 index 00000000..510a6dfd --- /dev/null +++ b/src/validators/min_password_strength.rs @@ -0,0 +1,34 @@ +use crate::{InputType, InputValueError}; +use zxcvbn::{zxcvbn, ZxcvbnError}; + +pub fn min_password_strength + InputType>( + value: &T, + min_score: u8, +) -> Result<(), InputValueError> { + match zxcvbn(value.as_ref(), &[]) { + Ok(password_strength) => { + if password_strength.score() < min_score { + Err("password is too weak".into()) + } else { + Ok(()) + } + } + Err(ZxcvbnError::BlankPassword) => Err("password is too weak".into()), + _ => Err("error processing password strength".into()), + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_min_password_strength() { + assert!(min_password_strength(&"password".to_string(), 3).is_err()); + assert!(min_password_strength(&"query".to_string(), 3).is_err()); + assert!(min_password_strength(&"P@ssword1".to_string(), 3).is_err()); + assert!(min_password_strength(&"".to_string(), 3).is_err()); + + assert!(min_password_strength(&"Some!Secure!Password".to_string(), 3).is_ok()); + } +} diff --git a/src/validators/mod.rs b/src/validators/mod.rs index 4270dd4c..6cb55de2 100644 --- a/src/validators/mod.rs +++ b/src/validators/mod.rs @@ -7,6 +7,8 @@ mod max_length; mod maximum; mod min_items; mod min_length; +#[cfg(feature = "password-strength-validator")] +mod min_password_strength; mod minimum; mod multiple_of; mod regex; From c06179950f545ca0dfb88705d5e8157d8fed65b7 Mon Sep 17 00:00:00 2001 From: Oscar Beaumont Date: Thu, 30 Dec 2021 17:35:33 +0800 Subject: [PATCH 2/3] fix: export min_password_strength validator --- src/validators/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/validators/mod.rs b/src/validators/mod.rs index 6cb55de2..f5e8537b 100644 --- a/src/validators/mod.rs +++ b/src/validators/mod.rs @@ -25,6 +25,8 @@ pub use max_length::max_length; pub use maximum::maximum; pub use min_items::min_items; pub use min_length::min_length; +#[cfg(feature = "password-strength-validator")] +pub use min_password_strength::min_password_strength; pub use minimum::minimum; pub use multiple_of::multiple_of; From c5b3bfb2c75c8b52687586337466e7be3e610491 Mon Sep 17 00:00:00 2001 From: Quentin Perez Date: Thu, 30 Dec 2021 16:49:01 +0100 Subject: [PATCH 3/3] Bump lru to 0.7.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The advisory script brought up a RUSTSEC error: --- error[A001]: Use after free in lru crate ┌─ /home/haptop/Developer/radicle-link/Cargo.lock:207:1 │ 207 │ lru 0.6.6 registry+https://github.com/rust-lang/crates.io-index │ --------------------------------------------------------------- security vulnerability detected │ = ID: RUSTSEC-2021-0130 = Advisory: https://rustsec.org/advisories/RUSTSEC-2021-0130 = Lru crate has use after free vulnerability. Lru crate has two functions for getting an iterator. Both iterators give references to key and value. Calling specific functions, like pop(), will remove and free the value, and but it's still possible to access the reference of value which is already dropped causing use after free. = Announcement: jeromefroe/lru-rs#120 = Solution: Upgrade to >=0.7.1 --- This patch follows the recommended solution and pins the `lru` crate to 0.7.1. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index b7c3dc18..252f32f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,7 +66,7 @@ smol_str = { version = "0.1.21", optional = true } # Non-feature optional dependencies blocking = { version = "1.0.2", optional = true } -lru = { version = "0.6.5", optional = true } +lru = { version = "0.7.1", optional = true } sha2 = { version = "0.9.3", optional = true } futures-timer = { version = "3.0.2", optional = true } futures-channel = { version = "0.3.13", optional = true }