bitwarden_exporters/cxf/
api_key.rs

1use credential_exchange_format::ApiKeyCredential;
2
3use crate::{cxf::editable_field::create_field, Field};
4
5/// Convert API key credentials to custom fields
6pub(super) fn api_key_to_fields(api_key: &ApiKeyCredential) -> Vec<Field> {
7    [
8        api_key.key.as_ref().map(|key| create_field("API Key", key)),
9        api_key
10            .username
11            .as_ref()
12            .map(|username| create_field("Username", username)),
13        api_key
14            .key_type
15            .as_ref()
16            .map(|key_type| create_field("Key Type", key_type)),
17        api_key.url.as_ref().map(|url| create_field("URL", url)),
18        api_key
19            .valid_from
20            .as_ref()
21            .map(|valid_from| create_field("Valid From", valid_from)),
22        api_key
23            .expiry_date
24            .as_ref()
25            .map(|expiry_date| create_field("Expiry Date", expiry_date)),
26    ]
27    .into_iter()
28    .flatten()
29    .collect()
30}
31
32#[cfg(test)]
33mod tests {
34    use bitwarden_vault::FieldType;
35    use chrono::NaiveDate;
36    use credential_exchange_format::{EditableFieldConcealedString, EditableFieldDate};
37
38    use super::*;
39
40    #[test]
41    fn test_api_key_to_fields_all_fields() {
42        let api_key = ApiKeyCredential {
43            key: Some(
44                EditableFieldConcealedString("AIzaSyAyRofL-VJHZofHc-qOSkqVOdhvgQoJADk".to_string())
45                    .into(),
46            ),
47            username: Some("john_doe".to_string().into()),
48            key_type: Some("Bearer".to_string().into()),
49            url: Some("https://api.example.com".to_string().into()),
50            valid_from: Some(
51                EditableFieldDate(NaiveDate::from_ymd_opt(2025, 1, 1).unwrap()).into(),
52            ),
53            expiry_date: Some(
54                EditableFieldDate(NaiveDate::from_ymd_opt(2026, 1, 1).unwrap()).into(),
55            ),
56        };
57
58        let fields = api_key_to_fields(&api_key);
59
60        let expected_fields = vec![
61            Field {
62                name: Some("API Key".to_string()),
63                value: Some("AIzaSyAyRofL-VJHZofHc-qOSkqVOdhvgQoJADk".to_string()),
64                r#type: FieldType::Hidden as u8,
65                linked_id: None,
66            },
67            Field {
68                name: Some("Username".to_string()),
69                value: Some("john_doe".to_string()),
70                r#type: FieldType::Text as u8,
71                linked_id: None,
72            },
73            Field {
74                name: Some("Key Type".to_string()),
75                value: Some("Bearer".to_string()),
76                r#type: FieldType::Text as u8,
77                linked_id: None,
78            },
79            Field {
80                name: Some("URL".to_string()),
81                value: Some("https://api.example.com".to_string()),
82                r#type: FieldType::Text as u8,
83                linked_id: None,
84            },
85            Field {
86                name: Some("Valid From".to_string()),
87                value: Some("2025-01-01".to_string()),
88                r#type: FieldType::Text as u8,
89                linked_id: None,
90            },
91            Field {
92                name: Some("Expiry Date".to_string()),
93                value: Some("2026-01-01".to_string()),
94                r#type: FieldType::Text as u8,
95                linked_id: None,
96            },
97        ];
98
99        assert_eq!(fields, expected_fields);
100    }
101
102    #[test]
103    fn test_api_key_to_fields_minimal() {
104        let api_key = ApiKeyCredential {
105            key: Some("test-api-key".to_string().into()),
106            username: None,
107            key_type: None,
108            url: None,
109            valid_from: None,
110            expiry_date: None,
111        };
112
113        let fields = api_key_to_fields(&api_key);
114
115        let expected_fields = vec![Field {
116            name: Some("API Key".to_string()),
117            value: Some("test-api-key".to_string()),
118            r#type: FieldType::Hidden as u8,
119            linked_id: None,
120        }];
121
122        assert_eq!(fields, expected_fields);
123    }
124
125    #[test]
126    fn test_api_key_to_fields_empty() {
127        let api_key = ApiKeyCredential {
128            key: None,
129            username: None,
130            key_type: None,
131            url: None,
132            valid_from: None,
133            expiry_date: None,
134        };
135
136        let fields = api_key_to_fields(&api_key);
137
138        assert_eq!(fields, vec![]);
139    }
140
141    #[test]
142    fn test_api_key_to_fields_partial() {
143        let api_key = ApiKeyCredential {
144            key: Some("secret-key".to_string().into()),
145            username: Some("test_user".to_string().into()),
146            key_type: Some("API_KEY".to_string().into()),
147            url: None,
148            valid_from: None,
149            expiry_date: None,
150        };
151
152        let fields = api_key_to_fields(&api_key);
153
154        let expected_fields = vec![
155            Field {
156                name: Some("API Key".to_string()),
157                value: Some("secret-key".to_string()),
158                r#type: FieldType::Hidden as u8,
159                linked_id: None,
160            },
161            Field {
162                name: Some("Username".to_string()),
163                value: Some("test_user".to_string()),
164                r#type: FieldType::Text as u8,
165                linked_id: None,
166            },
167            Field {
168                name: Some("Key Type".to_string()),
169                value: Some("API_KEY".to_string()),
170                r#type: FieldType::Text as u8,
171                linked_id: None,
172            },
173        ];
174
175        assert_eq!(fields, expected_fields);
176    }
177}