bitwarden_vault/cipher/
identity.rs

1use bitwarden_api_api::models::CipherIdentityModel;
2use bitwarden_core::key_management::{KeyIds, SymmetricKeyId};
3use bitwarden_crypto::{CryptoError, Decryptable, EncString, Encryptable, KeyStoreContext};
4use serde::{Deserialize, Serialize};
5#[cfg(feature = "wasm")]
6use tsify_next::Tsify;
7
8use crate::VaultParseError;
9
10#[derive(Serialize, Deserialize, Debug, Clone)]
11#[serde(rename_all = "camelCase", deny_unknown_fields)]
12#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
13#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
14pub struct Identity {
15    pub title: Option<EncString>,
16    pub first_name: Option<EncString>,
17    pub middle_name: Option<EncString>,
18    pub last_name: Option<EncString>,
19    pub address1: Option<EncString>,
20    pub address2: Option<EncString>,
21    pub address3: Option<EncString>,
22    pub city: Option<EncString>,
23    pub state: Option<EncString>,
24    pub postal_code: Option<EncString>,
25    pub country: Option<EncString>,
26    pub company: Option<EncString>,
27    pub email: Option<EncString>,
28    pub phone: Option<EncString>,
29    pub ssn: Option<EncString>,
30    pub username: Option<EncString>,
31    pub passport_number: Option<EncString>,
32    pub license_number: Option<EncString>,
33}
34
35#[derive(Serialize, Deserialize, Debug, Clone)]
36#[serde(rename_all = "camelCase", deny_unknown_fields)]
37#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
38#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
39pub struct IdentityView {
40    pub title: Option<String>,
41    pub first_name: Option<String>,
42    pub middle_name: Option<String>,
43    pub last_name: Option<String>,
44    pub address1: Option<String>,
45    pub address2: Option<String>,
46    pub address3: Option<String>,
47    pub city: Option<String>,
48    pub state: Option<String>,
49    pub postal_code: Option<String>,
50    pub country: Option<String>,
51    pub company: Option<String>,
52    pub email: Option<String>,
53    pub phone: Option<String>,
54    pub ssn: Option<String>,
55    pub username: Option<String>,
56    pub passport_number: Option<String>,
57    pub license_number: Option<String>,
58}
59
60impl Encryptable<KeyIds, SymmetricKeyId, Identity> for IdentityView {
61    fn encrypt(
62        &self,
63        ctx: &mut KeyStoreContext<KeyIds>,
64        key: SymmetricKeyId,
65    ) -> Result<Identity, CryptoError> {
66        Ok(Identity {
67            title: self.title.encrypt(ctx, key)?,
68            first_name: self.first_name.encrypt(ctx, key)?,
69            middle_name: self.middle_name.encrypt(ctx, key)?,
70            last_name: self.last_name.encrypt(ctx, key)?,
71            address1: self.address1.encrypt(ctx, key)?,
72            address2: self.address2.encrypt(ctx, key)?,
73            address3: self.address3.encrypt(ctx, key)?,
74            city: self.city.encrypt(ctx, key)?,
75            state: self.state.encrypt(ctx, key)?,
76            postal_code: self.postal_code.encrypt(ctx, key)?,
77            country: self.country.encrypt(ctx, key)?,
78            company: self.company.encrypt(ctx, key)?,
79            email: self.email.encrypt(ctx, key)?,
80            phone: self.phone.encrypt(ctx, key)?,
81            ssn: self.ssn.encrypt(ctx, key)?,
82            username: self.username.encrypt(ctx, key)?,
83            passport_number: self.passport_number.encrypt(ctx, key)?,
84            license_number: self.license_number.encrypt(ctx, key)?,
85        })
86    }
87}
88
89impl Decryptable<KeyIds, SymmetricKeyId, IdentityView> for Identity {
90    fn decrypt(
91        &self,
92        ctx: &mut KeyStoreContext<KeyIds>,
93        key: SymmetricKeyId,
94    ) -> Result<IdentityView, CryptoError> {
95        Ok(IdentityView {
96            title: self.title.decrypt(ctx, key).ok().flatten(),
97            first_name: self.first_name.decrypt(ctx, key).ok().flatten(),
98            middle_name: self.middle_name.decrypt(ctx, key).ok().flatten(),
99            last_name: self.last_name.decrypt(ctx, key).ok().flatten(),
100            address1: self.address1.decrypt(ctx, key).ok().flatten(),
101            address2: self.address2.decrypt(ctx, key).ok().flatten(),
102            address3: self.address3.decrypt(ctx, key).ok().flatten(),
103            city: self.city.decrypt(ctx, key).ok().flatten(),
104            state: self.state.decrypt(ctx, key).ok().flatten(),
105            postal_code: self.postal_code.decrypt(ctx, key).ok().flatten(),
106            country: self.country.decrypt(ctx, key).ok().flatten(),
107            company: self.company.decrypt(ctx, key).ok().flatten(),
108            email: self.email.decrypt(ctx, key).ok().flatten(),
109            phone: self.phone.decrypt(ctx, key).ok().flatten(),
110            ssn: self.ssn.decrypt(ctx, key).ok().flatten(),
111            username: self.username.decrypt(ctx, key).ok().flatten(),
112            passport_number: self.passport_number.decrypt(ctx, key).ok().flatten(),
113            license_number: self.license_number.decrypt(ctx, key).ok().flatten(),
114        })
115    }
116}
117
118impl TryFrom<CipherIdentityModel> for Identity {
119    type Error = VaultParseError;
120
121    fn try_from(identity: CipherIdentityModel) -> Result<Self, Self::Error> {
122        Ok(Self {
123            title: EncString::try_from_optional(identity.title)?,
124            first_name: EncString::try_from_optional(identity.first_name)?,
125            middle_name: EncString::try_from_optional(identity.middle_name)?,
126            last_name: EncString::try_from_optional(identity.last_name)?,
127            address1: EncString::try_from_optional(identity.address1)?,
128            address2: EncString::try_from_optional(identity.address2)?,
129            address3: EncString::try_from_optional(identity.address3)?,
130            city: EncString::try_from_optional(identity.city)?,
131            state: EncString::try_from_optional(identity.state)?,
132            postal_code: EncString::try_from_optional(identity.postal_code)?,
133            country: EncString::try_from_optional(identity.country)?,
134            company: EncString::try_from_optional(identity.company)?,
135            email: EncString::try_from_optional(identity.email)?,
136            phone: EncString::try_from_optional(identity.phone)?,
137            ssn: EncString::try_from_optional(identity.ssn)?,
138            username: EncString::try_from_optional(identity.username)?,
139            passport_number: EncString::try_from_optional(identity.passport_number)?,
140            license_number: EncString::try_from_optional(identity.license_number)?,
141        })
142    }
143}