Skip to main content

bitwarden_vault/folder/
folder_models.rs

1use bitwarden_api_api::models::{FolderResponseModel, FolderWithIdRequestModel};
2use bitwarden_core::{
3    key_management::{KeySlotIds, SymmetricKeySlotId},
4    require,
5};
6use bitwarden_crypto::{
7    CompositeEncryptable, CryptoError, Decryptable, EncString, IdentifyKey, KeyStoreContext,
8    PrimitiveEncryptable,
9};
10use bitwarden_uuid::uuid_newtype;
11use chrono::{DateTime, Utc};
12use serde::{Deserialize, Serialize};
13
14use crate::VaultParseError;
15
16uuid_newtype!(pub FolderId);
17
18#[allow(missing_docs)]
19#[derive(Serialize, Deserialize, Debug, Clone)]
20#[serde(rename_all = "camelCase")]
21#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
22#[bitwarden_ffi::wasm_record]
23pub struct Folder {
24    pub id: Option<FolderId>,
25    pub name: EncString,
26    pub revision_date: DateTime<Utc>,
27}
28
29bitwarden_state::register_repository_item!(FolderId => Folder, "Folder");
30
31#[allow(missing_docs)]
32#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
33#[serde(rename_all = "camelCase")]
34#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
35#[bitwarden_ffi::wasm_record]
36pub struct FolderView {
37    pub id: Option<FolderId>,
38    pub name: String,
39    pub revision_date: DateTime<Utc>,
40}
41
42impl IdentifyKey<SymmetricKeySlotId> for Folder {
43    fn key_identifier(&self) -> SymmetricKeySlotId {
44        SymmetricKeySlotId::User
45    }
46}
47impl IdentifyKey<SymmetricKeySlotId> for FolderView {
48    fn key_identifier(&self) -> SymmetricKeySlotId {
49        SymmetricKeySlotId::User
50    }
51}
52
53impl CompositeEncryptable<KeySlotIds, SymmetricKeySlotId, Folder> for FolderView {
54    fn encrypt_composite(
55        &self,
56        ctx: &mut KeyStoreContext<KeySlotIds>,
57        key: SymmetricKeySlotId,
58    ) -> Result<Folder, CryptoError> {
59        Ok(Folder {
60            id: self.id,
61            name: self.name.encrypt(ctx, key)?,
62            revision_date: self.revision_date,
63        })
64    }
65}
66
67impl Decryptable<KeySlotIds, SymmetricKeySlotId, FolderView> for Folder {
68    fn decrypt(
69        &self,
70        ctx: &mut KeyStoreContext<KeySlotIds>,
71        key: SymmetricKeySlotId,
72    ) -> Result<FolderView, CryptoError> {
73        Ok(FolderView {
74            id: self.id,
75            name: self.name.decrypt(ctx, key).ok().unwrap_or_default(),
76            revision_date: self.revision_date,
77        })
78    }
79}
80
81impl TryFrom<FolderResponseModel> for Folder {
82    type Error = VaultParseError;
83
84    fn try_from(folder: FolderResponseModel) -> Result<Self, Self::Error> {
85        Ok(Folder {
86            id: folder.id.map(FolderId::new),
87            name: require!(EncString::try_from_optional(folder.name)?),
88            revision_date: require!(folder.revision_date).parse()?,
89        })
90    }
91}
92
93impl From<&Folder> for FolderWithIdRequestModel {
94    fn from(val: &Folder) -> Self {
95        FolderWithIdRequestModel {
96            name: val.name.to_string(),
97            id: val.id.map(|id| id.0),
98        }
99    }
100}