bitwarden_vault/
collection.rs

1use bitwarden_api_api::models::CollectionDetailsResponseModel;
2use bitwarden_core::{
3    key_management::{KeyIds, SymmetricKeyId},
4    require,
5};
6use bitwarden_crypto::{CryptoError, Decryptable, EncString, IdentifyKey, KeyStoreContext};
7use serde::{Deserialize, Serialize};
8use uuid::Uuid;
9
10use crate::VaultParseError;
11
12#[derive(Serialize, Deserialize, Debug)]
13#[serde(rename_all = "camelCase", deny_unknown_fields)]
14#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
15#[cfg_attr(
16    feature = "wasm",
17    derive(tsify_next::Tsify),
18    tsify(into_wasm_abi, from_wasm_abi)
19)]
20pub struct Collection {
21    pub id: Option<Uuid>,
22    pub organization_id: Uuid,
23
24    pub name: EncString,
25
26    pub external_id: Option<String>,
27    pub hide_passwords: bool,
28    pub read_only: bool,
29    pub manage: bool,
30}
31
32#[derive(Serialize, Deserialize, Debug)]
33#[serde(rename_all = "camelCase", deny_unknown_fields)]
34#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
35pub struct CollectionView {
36    pub id: Option<Uuid>,
37    pub organization_id: Uuid,
38
39    pub name: String,
40
41    pub external_id: Option<String>,
42    pub hide_passwords: bool,
43    pub read_only: bool,
44    pub manage: bool,
45}
46
47impl IdentifyKey<SymmetricKeyId> for Collection {
48    fn key_identifier(&self) -> SymmetricKeyId {
49        SymmetricKeyId::Organization(self.organization_id)
50    }
51}
52
53impl Decryptable<KeyIds, SymmetricKeyId, CollectionView> for Collection {
54    fn decrypt(
55        &self,
56        ctx: &mut KeyStoreContext<KeyIds>,
57        key: SymmetricKeyId,
58    ) -> Result<CollectionView, CryptoError> {
59        Ok(CollectionView {
60            id: self.id,
61            organization_id: self.organization_id,
62
63            name: self.name.decrypt(ctx, key).ok().unwrap_or_default(),
64
65            external_id: self.external_id.clone(),
66            hide_passwords: self.hide_passwords,
67            read_only: self.read_only,
68            manage: self.manage,
69        })
70    }
71}
72
73impl TryFrom<CollectionDetailsResponseModel> for Collection {
74    type Error = VaultParseError;
75
76    fn try_from(collection: CollectionDetailsResponseModel) -> Result<Self, Self::Error> {
77        Ok(Collection {
78            id: collection.id,
79            organization_id: require!(collection.organization_id),
80            name: require!(collection.name).parse()?,
81            external_id: collection.external_id,
82            hide_passwords: collection.hide_passwords.unwrap_or(false),
83            read_only: collection.read_only.unwrap_or(false),
84            manage: collection.manage.unwrap_or(false),
85        })
86    }
87}