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