bitwarden_vault/cipher/
field.rs1use bitwarden_api_api::models::CipherFieldModel;
2use bitwarden_core::{
3 key_management::{KeyIds, SymmetricKeyId},
4 require,
5};
6use bitwarden_crypto::{CryptoError, Decryptable, EncString, Encryptable, KeyStoreContext};
7use serde::{Deserialize, Serialize};
8use serde_repr::{Deserialize_repr, Serialize_repr};
9#[cfg(feature = "wasm")]
10use tsify_next::Tsify;
11#[cfg(feature = "wasm")]
12use wasm_bindgen::prelude::wasm_bindgen;
13
14use super::linked_id::LinkedIdType;
15use crate::VaultParseError;
16
17#[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug)]
18#[repr(u8)]
19#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
20#[cfg_attr(feature = "wasm", wasm_bindgen)]
21pub enum FieldType {
22 Text = 0,
23 Hidden = 1,
24 Boolean = 2,
25 Linked = 3,
26}
27
28#[derive(Serialize, Deserialize, Debug, Clone)]
29#[serde(rename_all = "camelCase", deny_unknown_fields)]
30#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
31#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
32pub struct Field {
33 name: Option<EncString>,
34 value: Option<EncString>,
35 r#type: FieldType,
36
37 linked_id: Option<LinkedIdType>,
38}
39
40#[derive(Serialize, Deserialize, Debug, Clone)]
41#[serde(rename_all = "camelCase", deny_unknown_fields)]
42#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
43#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
44pub struct FieldView {
45 pub name: Option<String>,
46 pub value: Option<String>,
47 pub r#type: FieldType,
48
49 pub linked_id: Option<LinkedIdType>,
50}
51
52impl Encryptable<KeyIds, SymmetricKeyId, Field> for FieldView {
53 fn encrypt(
54 &self,
55 ctx: &mut KeyStoreContext<KeyIds>,
56 key: SymmetricKeyId,
57 ) -> Result<Field, CryptoError> {
58 Ok(Field {
59 name: self.name.encrypt(ctx, key)?,
60 value: self.value.encrypt(ctx, key)?,
61 r#type: self.r#type,
62 linked_id: self.linked_id,
63 })
64 }
65}
66
67impl Decryptable<KeyIds, SymmetricKeyId, FieldView> for Field {
68 fn decrypt(
69 &self,
70 ctx: &mut KeyStoreContext<KeyIds>,
71 key: SymmetricKeyId,
72 ) -> Result<FieldView, CryptoError> {
73 Ok(FieldView {
74 name: self.name.decrypt(ctx, key).ok().flatten(),
75 value: self.value.decrypt(ctx, key).ok().flatten(),
76 r#type: self.r#type,
77 linked_id: self.linked_id,
78 })
79 }
80}
81
82impl TryFrom<CipherFieldModel> for Field {
83 type Error = VaultParseError;
84
85 fn try_from(model: CipherFieldModel) -> Result<Self, Self::Error> {
86 Ok(Self {
87 name: EncString::try_from_optional(model.name)?,
88 value: EncString::try_from_optional(model.value)?,
89 r#type: require!(model.r#type).into(),
90 linked_id: model
91 .linked_id
92 .map(|id| (id as u32).try_into())
93 .transpose()?,
94 })
95 }
96}
97
98impl From<bitwarden_api_api::models::FieldType> for FieldType {
99 fn from(model: bitwarden_api_api::models::FieldType) -> Self {
100 match model {
101 bitwarden_api_api::models::FieldType::Text => FieldType::Text,
102 bitwarden_api_api::models::FieldType::Hidden => FieldType::Hidden,
103 bitwarden_api_api::models::FieldType::Boolean => FieldType::Boolean,
104 bitwarden_api_api::models::FieldType::Linked => FieldType::Linked,
105 }
106 }
107}