Skip to main content

bitwarden_policies/
master_password_policy_response.rs

1use bitwarden_api_api::models::MasterPasswordPolicyResponseModel;
2use serde::{Deserialize, Serialize};
3
4/// SDK domain model for master password policy requirements.
5/// Defines the complexity requirements for a user's master password
6/// when enforced by an organization policy.
7#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
8#[serde(rename_all = "camelCase")]
9#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
10#[cfg_attr(
11    feature = "wasm",
12    derive(tsify::Tsify),
13    tsify(into_wasm_abi, from_wasm_abi)
14)]
15pub struct MasterPasswordPolicyResponse {
16    /// The minimum complexity score required for the master password.
17    /// Complexity is calculated based on password strength metrics.
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub min_complexity: Option<i32>,
20
21    /// The minimum length required for the master password.
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub min_length: Option<i32>,
24
25    /// Whether the master password must contain at least one lowercase letter.
26    #[serde(skip_serializing_if = "Option::is_none")]
27    pub require_lower: Option<bool>,
28
29    /// Whether the master password must contain at least one uppercase letter.
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub require_upper: Option<bool>,
32
33    /// Whether the master password must contain at least one numeric digit.
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub require_numbers: Option<bool>,
36
37    /// Whether the master password must contain at least one special character.
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub require_special: Option<bool>,
40
41    /// Whether this policy should be enforced when the user logs in.
42    /// If true, the user will be required to update their master password
43    /// if it doesn't meet the policy requirements.
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub enforce_on_login: Option<bool>,
46}
47
48impl From<MasterPasswordPolicyResponseModel> for MasterPasswordPolicyResponse {
49    fn from(api: MasterPasswordPolicyResponseModel) -> Self {
50        Self {
51            min_complexity: api.min_complexity,
52            min_length: api.min_length,
53            require_lower: api.require_lower,
54            require_upper: api.require_upper,
55            require_numbers: api.require_numbers,
56            require_special: api.require_special,
57            enforce_on_login: api.enforce_on_login,
58        }
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn test_master_password_policy_conversion_full() {
68        let api = MasterPasswordPolicyResponseModel {
69            object: Some("masterPasswordPolicy".to_string()),
70            min_complexity: Some(4),
71            min_length: Some(12),
72            require_lower: Some(true),
73            require_upper: Some(true),
74            require_numbers: Some(true),
75            require_special: Some(true),
76            enforce_on_login: Some(true),
77        };
78
79        let domain: MasterPasswordPolicyResponse = api.into();
80
81        assert_eq!(domain.min_complexity, Some(4));
82        assert_eq!(domain.min_length, Some(12));
83        assert_eq!(domain.require_lower, Some(true));
84        assert_eq!(domain.require_upper, Some(true));
85        assert_eq!(domain.require_numbers, Some(true));
86        assert_eq!(domain.require_special, Some(true));
87        assert_eq!(domain.enforce_on_login, Some(true));
88    }
89
90    #[test]
91    fn test_master_password_policy_conversion_minimal() {
92        let api = MasterPasswordPolicyResponseModel {
93            object: Some("masterPasswordPolicy".to_string()),
94            min_complexity: None,
95            min_length: Some(8),
96            require_lower: None,
97            require_upper: None,
98            require_numbers: None,
99            require_special: None,
100            enforce_on_login: Some(false),
101        };
102
103        let domain: MasterPasswordPolicyResponse = api.into();
104
105        assert_eq!(domain.min_complexity, None);
106        assert_eq!(domain.min_length, Some(8));
107        assert_eq!(domain.require_lower, None);
108        assert_eq!(domain.require_upper, None);
109        assert_eq!(domain.require_numbers, None);
110        assert_eq!(domain.require_special, None);
111        assert_eq!(domain.enforce_on_login, Some(false));
112    }
113
114    #[test]
115    fn test_master_password_policy_conversion_empty() {
116        let api = MasterPasswordPolicyResponseModel {
117            object: Some("masterPasswordPolicy".to_string()),
118            min_complexity: None,
119            min_length: None,
120            require_lower: None,
121            require_upper: None,
122            require_numbers: None,
123            require_special: None,
124            enforce_on_login: None,
125        };
126
127        let domain: MasterPasswordPolicyResponse = api.into();
128
129        assert_eq!(domain.min_complexity, None);
130        assert_eq!(domain.min_length, None);
131        assert_eq!(domain.require_lower, None);
132        assert_eq!(domain.require_upper, None);
133        assert_eq!(domain.require_numbers, None);
134        assert_eq!(domain.require_special, None);
135        assert_eq!(domain.enforce_on_login, None);
136    }
137}