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#[allow(missing_docs)]
41#[derive(Serialize, Deserialize, Debug, Clone)]
42#[serde(rename_all = "camelCase", deny_unknown_fields)]
43#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
44#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
45pub struct FieldView {
46 pub name: Option<String>,
47 pub value: Option<String>,
48 pub r#type: FieldType,
49
50 pub linked_id: Option<LinkedIdType>,
51}
52
53impl Encryptable<KeyIds, SymmetricKeyId, Field> for FieldView {
54 fn encrypt(
55 &self,
56 ctx: &mut KeyStoreContext<KeyIds>,
57 key: SymmetricKeyId,
58 ) -> Result<Field, CryptoError> {
59 Ok(Field {
60 name: self.name.encrypt(ctx, key)?,
61 value: self.value.encrypt(ctx, key)?,
62 r#type: self.r#type,
63 linked_id: self.linked_id,
64 })
65 }
66}
67
68impl Decryptable<KeyIds, SymmetricKeyId, FieldView> for Field {
69 fn decrypt(
70 &self,
71 ctx: &mut KeyStoreContext<KeyIds>,
72 key: SymmetricKeyId,
73 ) -> Result<FieldView, CryptoError> {
74 Ok(FieldView {
75 name: self.name.decrypt(ctx, key).ok().flatten(),
76 value: self.value.decrypt(ctx, key).ok().flatten(),
77 r#type: self.r#type,
78 linked_id: self.linked_id,
79 })
80 }
81}
82
83impl TryFrom<CipherFieldModel> for Field {
84 type Error = VaultParseError;
85
86 fn try_from(model: CipherFieldModel) -> Result<Self, Self::Error> {
87 Ok(Self {
88 name: EncString::try_from_optional(model.name)?,
89 value: EncString::try_from_optional(model.value)?,
90 r#type: require!(model.r#type).into(),
91 linked_id: model
92 .linked_id
93 .map(|id| (id as u32).try_into())
94 .transpose()?,
95 })
96 }
97}
98
99impl From<bitwarden_api_api::models::FieldType> for FieldType {
100 fn from(model: bitwarden_api_api::models::FieldType) -> Self {
101 match model {
102 bitwarden_api_api::models::FieldType::Text => FieldType::Text,
103 bitwarden_api_api::models::FieldType::Hidden => FieldType::Hidden,
104 bitwarden_api_api::models::FieldType::Boolean => FieldType::Boolean,
105 bitwarden_api_api::models::FieldType::Linked => FieldType::Linked,
106 }
107 }
108}