Skip to main content

bitwarden_vault/cipher/blob/conversions/
passport.rs

1use super::{PassportDataV1, PassportView};
2
3impl From<&PassportView> for PassportDataV1 {
4    fn from(src: &PassportView) -> Self {
5        Self {
6            surname: src.surname.clone(),
7            given_name: src.given_name.clone(),
8            date_of_birth: src.date_of_birth.map(|d| d.to_string()),
9            sex: src.sex.clone(),
10            birth_place: src.birth_place.clone(),
11            nationality: src.nationality.clone(),
12            issuing_country: src.issuing_country.clone(),
13            passport_number: src.passport_number.clone(),
14            passport_type: src.passport_type.clone(),
15            national_identification_number: src.national_identification_number.clone(),
16            issuing_authority: src.issuing_authority.clone(),
17            issue_date: src.issue_date.map(|d| d.to_string()),
18            expiration_date: src.expiration_date.map(|d| d.to_string()),
19        }
20    }
21}
22
23impl From<&PassportDataV1> for PassportView {
24    fn from(src: &PassportDataV1) -> Self {
25        Self {
26            surname: src.surname.clone(),
27            given_name: src.given_name.clone(),
28            date_of_birth: src.date_of_birth.as_deref().and_then(|s| s.parse().ok()),
29            sex: src.sex.clone(),
30            birth_place: src.birth_place.clone(),
31            nationality: src.nationality.clone(),
32            issuing_country: src.issuing_country.clone(),
33            passport_number: src.passport_number.clone(),
34            passport_type: src.passport_type.clone(),
35            national_identification_number: src.national_identification_number.clone(),
36            issuing_authority: src.issuing_authority.clone(),
37            issue_date: src.issue_date.as_deref().and_then(|s| s.parse().ok()),
38            expiration_date: src.expiration_date.as_deref().and_then(|s| s.parse().ok()),
39        }
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::super::{CipherBlobV1, test_support::*};
46    use crate::cipher::{cipher::CipherType, passport::PassportView};
47
48    #[test]
49    fn test_passport_cipher_round_trip() {
50        let original = crate::CipherView {
51            name: "My Passport".to_string(),
52            notes: None,
53            r#type: CipherType::Passport,
54            passport: Some(PassportView {
55                surname: Some("Doe".to_string()),
56                given_name: Some("Jane".to_string()),
57                date_of_birth: chrono::NaiveDate::from_ymd_opt(1990, 1, 1),
58                sex: Some("F".to_string()),
59                birth_place: Some("New York".to_string()),
60                nationality: Some("American".to_string()),
61                issuing_country: Some("US".to_string()),
62                passport_number: Some("P12345678".to_string()),
63                passport_type: Some("P".to_string()),
64                national_identification_number: Some("123-45-6789".to_string()),
65                issuing_authority: Some("US State Department".to_string()),
66                issue_date: chrono::NaiveDate::from_ymd_opt(2020, 1, 1),
67                expiration_date: chrono::NaiveDate::from_ymd_opt(2030, 1, 1),
68            }),
69            ..create_shell_cipher_view(CipherType::Passport)
70        };
71
72        let blob = CipherBlobV1::from_cipher_view(&original).unwrap();
73        let mut restored = create_shell_cipher_view(CipherType::Passport);
74        blob.apply_to_cipher_view(&mut restored).unwrap();
75
76        assert_eq!(restored.name, "My Passport");
77        assert_eq!(restored.r#type, CipherType::Passport);
78        let passport = restored.passport.unwrap();
79        assert_eq!(passport.surname, Some("Doe".to_string()));
80        assert_eq!(passport.passport_number, Some("P12345678".to_string()));
81        assert!(restored.login.is_none());
82    }
83}