Skip to main content

openauth_core/options/
password.rs

1use std::fmt;
2use std::sync::Arc;
3
4use http::Request;
5
6use crate::db::User;
7use crate::error::OpenAuthError;
8
9/// Payload passed to password reset lifecycle callbacks.
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct PasswordResetPayload {
12    pub user: User,
13}
14
15/// Hook invoked after a password reset has updated or created the credential.
16pub trait OnPasswordReset: Send + Sync + 'static {
17    fn on_password_reset(
18        &self,
19        payload: PasswordResetPayload,
20        request: Option<&Request<Vec<u8>>>,
21    ) -> Result<(), OpenAuthError>;
22}
23
24impl<F> OnPasswordReset for F
25where
26    F: for<'a> Fn(PasswordResetPayload, Option<&'a Request<Vec<u8>>>) -> Result<(), OpenAuthError>
27        + Send
28        + Sync
29        + 'static,
30{
31    fn on_password_reset(
32        &self,
33        payload: PasswordResetPayload,
34        request: Option<&Request<Vec<u8>>>,
35    ) -> Result<(), OpenAuthError> {
36        self(payload, request)
37    }
38}
39
40/// Password policy configuration.
41#[derive(Clone)]
42pub struct PasswordOptions {
43    pub min_password_length: usize,
44    pub max_password_length: usize,
45    pub on_password_reset: Option<Arc<dyn OnPasswordReset>>,
46    pub revoke_sessions_on_password_reset: bool,
47}
48
49impl Default for PasswordOptions {
50    fn default() -> Self {
51        Self {
52            min_password_length: 8,
53            max_password_length: 128,
54            on_password_reset: None,
55            revoke_sessions_on_password_reset: false,
56        }
57    }
58}
59
60impl PasswordOptions {
61    pub fn new() -> Self {
62        Self::default()
63    }
64
65    pub fn builder() -> Self {
66        Self::new()
67    }
68
69    #[must_use]
70    pub fn min_password_length(mut self, length: usize) -> Self {
71        self.min_password_length = length;
72        self
73    }
74
75    #[must_use]
76    pub fn max_password_length(mut self, length: usize) -> Self {
77        self.max_password_length = length;
78        self
79    }
80
81    #[must_use]
82    pub fn on_password_reset<P>(mut self, handler: P) -> Self
83    where
84        P: OnPasswordReset,
85    {
86        self.on_password_reset = Some(Arc::new(handler));
87        self
88    }
89
90    #[must_use]
91    pub fn revoke_sessions_on_password_reset(mut self, enabled: bool) -> Self {
92        self.revoke_sessions_on_password_reset = enabled;
93        self
94    }
95}
96
97impl fmt::Debug for PasswordOptions {
98    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
99        formatter
100            .debug_struct("PasswordOptions")
101            .field("min_password_length", &self.min_password_length)
102            .field("max_password_length", &self.max_password_length)
103            .field(
104                "on_password_reset",
105                &self
106                    .on_password_reset
107                    .as_ref()
108                    .map(|_| "<on-password-reset>"),
109            )
110            .field(
111                "revoke_sessions_on_password_reset",
112                &self.revoke_sessions_on_password_reset,
113            )
114            .finish()
115    }
116}