From 831b0f8aa5246dc30c7c28ebbbd846f96d1db52b 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 41269067214a1c7ec85de2d9d60fce511790e64f 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 016d86715c4aa483b6ec56c9d1e4864b271ed840 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 }