Skip to main content

rustauth_plugins/have_i_been_pwned/
options.rs

1//! Options for the Have I Been Pwned plugin.
2
3use std::sync::Arc;
4
5use super::checker::{HaveIBeenPwnedChecker, ReqwestHaveIBeenPwnedChecker};
6
7#[derive(Clone)]
8pub struct HaveIBeenPwnedOptions {
9    pub custom_password_compromised_message: Option<String>,
10    pub paths: Vec<String>,
11    pub enabled: bool,
12    pub checker: Option<Arc<dyn HaveIBeenPwnedChecker>>,
13}
14
15impl std::fmt::Debug for HaveIBeenPwnedOptions {
16    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17        f.debug_struct("HaveIBeenPwnedOptions")
18            .field(
19                "custom_password_compromised_message",
20                &self.custom_password_compromised_message,
21            )
22            .field("paths", &self.paths)
23            .field("enabled", &self.enabled)
24            .field("checker", &self.checker.as_ref().map(|_| "<checker>"))
25            .finish()
26    }
27}
28
29impl Default for HaveIBeenPwnedOptions {
30    fn default() -> Self {
31        Self {
32            custom_password_compromised_message: None,
33            paths: vec![
34                "/sign-up/email".to_owned(),
35                "/change-password".to_owned(),
36                "/reset-password".to_owned(),
37            ],
38            enabled: false,
39            checker: None,
40        }
41    }
42}
43
44impl HaveIBeenPwnedOptions {
45    #[must_use]
46    pub fn builder() -> HaveIBeenPwnedOptionsBuilder {
47        HaveIBeenPwnedOptionsBuilder::default()
48    }
49
50    #[must_use]
51    pub fn checker(mut self, checker: Arc<dyn HaveIBeenPwnedChecker>) -> Self {
52        self.checker = Some(checker);
53        self
54    }
55
56    pub(crate) fn resolved_checker(&self) -> Arc<dyn HaveIBeenPwnedChecker> {
57        self.checker
58            .clone()
59            .unwrap_or_else(|| Arc::new(ReqwestHaveIBeenPwnedChecker::new()))
60    }
61}
62
63#[derive(Clone, Default)]
64pub struct HaveIBeenPwnedOptionsBuilder {
65    custom_password_compromised_message: Option<Option<String>>,
66    paths: Option<Vec<String>>,
67    enabled: Option<bool>,
68    checker: Option<Arc<dyn HaveIBeenPwnedChecker>>,
69}
70
71impl HaveIBeenPwnedOptionsBuilder {
72    #[must_use]
73    pub fn custom_password_compromised_message(mut self, message: impl Into<String>) -> Self {
74        self.custom_password_compromised_message = Some(Some(message.into()));
75        self
76    }
77
78    #[must_use]
79    pub fn paths(mut self, paths: Vec<String>) -> Self {
80        self.paths = Some(paths);
81        self
82    }
83
84    #[must_use]
85    pub fn path(mut self, path: impl Into<String>) -> Self {
86        self.paths
87            .get_or_insert_with(|| HaveIBeenPwnedOptions::default().paths)
88            .push(path.into());
89        self
90    }
91
92    #[must_use]
93    pub fn enabled(mut self, enabled: bool) -> Self {
94        self.enabled = Some(enabled);
95        self
96    }
97
98    #[must_use]
99    pub fn checker(mut self, checker: Arc<dyn HaveIBeenPwnedChecker>) -> Self {
100        self.checker = Some(checker);
101        self
102    }
103
104    #[must_use]
105    pub fn build(self) -> HaveIBeenPwnedOptions {
106        let defaults = HaveIBeenPwnedOptions::default();
107        HaveIBeenPwnedOptions {
108            custom_password_compromised_message: self
109                .custom_password_compromised_message
110                .unwrap_or(defaults.custom_password_compromised_message),
111            paths: self.paths.unwrap_or(defaults.paths),
112            enabled: self.enabled.unwrap_or(defaults.enabled),
113            checker: self.checker.or(defaults.checker),
114        }
115    }
116}