bitwarden_exporters/cxf/
wifi.rs

1use credential_exchange_format::WifiCredential;
2
3use crate::{Field, cxf::editable_field::create_field};
4
5/// Convert WiFi credentials to custom fields following the CXF mapping convention
6pub(super) fn wifi_to_fields(wifi: &WifiCredential) -> Vec<Field> {
7    [
8        // SSID: Text field
9        wifi.ssid
10            .as_ref()
11            .map(|ssid| create_field(ssid, Some("SSID"))),
12        // Passphrase: Hidden field (concealed-string)
13        wifi.passphrase
14            .as_ref()
15            .map(|passphrase| create_field(passphrase, Some("Passphrase"))),
16        // Network Security Type: Text field
17        wifi.network_security_type
18            .as_ref()
19            .map(|security| create_field(security, Some("Network Security Type"))),
20        // Hidden: Boolean field
21        wifi.hidden
22            .as_ref()
23            .map(|hidden| create_field(hidden, Some("Hidden"))),
24    ]
25    .into_iter()
26    .flatten()
27    .collect()
28}
29
30#[cfg(test)]
31mod tests {
32    use bitwarden_vault::FieldType;
33    use credential_exchange_format::EditableFieldWifiNetworkSecurityType;
34
35    use super::*;
36
37    #[test]
38    fn test_wifi_to_fields_all_fields() {
39        let wifi = WifiCredential {
40            ssid: Some("MyWiFi".to_owned().into()),
41            passphrase: Some("secret123".to_owned().into()),
42            network_security_type: Some(EditableFieldWifiNetworkSecurityType::Wpa2Personal.into()),
43            hidden: Some(false.into()),
44        };
45
46        let fields = wifi_to_fields(&wifi);
47
48        assert_eq!(
49            fields,
50            vec![
51                Field {
52                    name: Some("SSID".to_string()),
53                    value: Some("MyWiFi".to_string()),
54                    r#type: FieldType::Text as u8,
55                    linked_id: None,
56                },
57                Field {
58                    name: Some("Passphrase".to_string()),
59                    value: Some("secret123".to_string()),
60                    r#type: FieldType::Hidden as u8,
61                    linked_id: None,
62                },
63                Field {
64                    name: Some("Network Security Type".to_string()),
65                    value: Some("WPA2 Personal".to_string()),
66                    r#type: FieldType::Text as u8,
67                    linked_id: None,
68                },
69                Field {
70                    name: Some("Hidden".to_string()),
71                    value: Some("false".to_string()),
72                    r#type: FieldType::Boolean as u8,
73                    linked_id: None,
74                },
75            ]
76        );
77    }
78
79    #[test]
80    fn test_wifi_to_fields_minimal() {
81        let wifi = WifiCredential {
82            ssid: Some("BasicWiFi".to_owned().into()),
83            passphrase: None,
84            network_security_type: None,
85            hidden: None,
86        };
87
88        let fields = wifi_to_fields(&wifi);
89
90        assert_eq!(
91            fields,
92            vec![Field {
93                name: Some("SSID".to_string()),
94                value: Some("BasicWiFi".to_string()),
95                r#type: FieldType::Text as u8,
96                linked_id: None,
97            }]
98        );
99    }
100
101    #[test]
102    fn test_wifi_to_fields_empty() {
103        let wifi = WifiCredential {
104            ssid: None,
105            passphrase: None,
106            network_security_type: None,
107            hidden: None,
108        };
109
110        let fields = wifi_to_fields(&wifi);
111
112        assert_eq!(fields, vec![]);
113    }
114
115    #[test]
116    fn test_wifi_to_fields_wpa3_security() {
117        let wifi = WifiCredential {
118            ssid: Some("SecureWiFi".to_owned().into()),
119            passphrase: Some("password123".to_owned().into()),
120            network_security_type: Some(EditableFieldWifiNetworkSecurityType::Wpa3Personal.into()),
121            hidden: Some(true.into()),
122        };
123
124        let fields = wifi_to_fields(&wifi);
125
126        assert_eq!(
127            fields,
128            vec![
129                Field {
130                    name: Some("SSID".to_string()),
131                    value: Some("SecureWiFi".to_string()),
132                    r#type: FieldType::Text as u8,
133                    linked_id: None,
134                },
135                Field {
136                    name: Some("Passphrase".to_string()),
137                    value: Some("password123".to_string()),
138                    r#type: FieldType::Hidden as u8,
139                    linked_id: None,
140                },
141                Field {
142                    name: Some("Network Security Type".to_string()),
143                    value: Some("WPA3 Personal".to_string()),
144                    r#type: FieldType::Text as u8,
145                    linked_id: None,
146                },
147                Field {
148                    name: Some("Hidden".to_string()),
149                    value: Some("true".to_string()),
150                    r#type: FieldType::Boolean as u8,
151                    linked_id: None,
152                },
153            ]
154        );
155    }
156
157    #[test]
158    fn test_wifi_to_fields_unsecured() {
159        let wifi = WifiCredential {
160            ssid: Some("OpenWiFi".to_owned().into()),
161            passphrase: None,
162            network_security_type: Some(EditableFieldWifiNetworkSecurityType::Unsecured.into()),
163            hidden: None,
164        };
165
166        let fields = wifi_to_fields(&wifi);
167
168        assert_eq!(
169            fields,
170            vec![
171                Field {
172                    name: Some("SSID".to_string()),
173                    value: Some("OpenWiFi".to_string()),
174                    r#type: FieldType::Text as u8,
175                    linked_id: None,
176                },
177                Field {
178                    name: Some("Network Security Type".to_string()),
179                    value: Some("Unsecured".to_string()),
180                    r#type: FieldType::Text as u8,
181                    linked_id: None,
182                },
183            ]
184        );
185    }
186
187    #[test]
188    fn test_wifi_to_fields_wep_security() {
189        let wifi = WifiCredential {
190            ssid: Some("LegacyWiFi".to_owned().into()),
191            passphrase: Some("wepkey123".to_owned().into()),
192            network_security_type: Some(EditableFieldWifiNetworkSecurityType::Wep.into()),
193            hidden: None,
194        };
195
196        let fields = wifi_to_fields(&wifi);
197
198        assert_eq!(
199            fields,
200            vec![
201                Field {
202                    name: Some("SSID".to_string()),
203                    value: Some("LegacyWiFi".to_string()),
204                    r#type: FieldType::Text as u8,
205                    linked_id: None,
206                },
207                Field {
208                    name: Some("Passphrase".to_string()),
209                    value: Some("wepkey123".to_string()),
210                    r#type: FieldType::Hidden as u8,
211                    linked_id: None,
212                },
213                Field {
214                    name: Some("Network Security Type".to_string()),
215                    value: Some("WEP".to_string()),
216                    r#type: FieldType::Text as u8,
217                    linked_id: None,
218                },
219            ]
220        );
221    }
222}