bitwarden_sm/secrets/
secret_response.rs

1use bitwarden_api_api::models::{
2    BaseSecretResponseModel, BaseSecretResponseModelListResponseModel, SecretResponseModel,
3};
4use bitwarden_core::{
5    key_management::{KeyIds, SymmetricKeyId},
6    require,
7};
8use bitwarden_crypto::{Decryptable, EncString, KeyStoreContext};
9use chrono::{DateTime, Utc};
10use schemars::JsonSchema;
11use serde::{Deserialize, Serialize};
12use uuid::Uuid;
13
14use crate::error::SecretsManagerError;
15
16#[allow(missing_docs)]
17#[derive(Serialize, Deserialize, Debug, JsonSchema)]
18#[serde(rename_all = "camelCase", deny_unknown_fields)]
19pub struct SecretResponse {
20    pub id: Uuid,
21    pub organization_id: Uuid,
22    pub project_id: Option<Uuid>,
23
24    pub key: String,
25    pub value: String,
26    pub note: String,
27
28    pub creation_date: DateTime<Utc>,
29    pub revision_date: DateTime<Utc>,
30}
31
32impl SecretResponse {
33    pub(crate) fn process_response(
34        response: SecretResponseModel,
35        ctx: &mut KeyStoreContext<KeyIds>,
36    ) -> Result<SecretResponse, SecretsManagerError> {
37        let base = BaseSecretResponseModel {
38            object: response.object,
39            id: response.id,
40            organization_id: response.organization_id,
41            key: response.key,
42            value: response.value,
43            note: response.note,
44            creation_date: response.creation_date,
45            revision_date: response.revision_date,
46            projects: response.projects,
47        };
48        Self::process_base_response(base, ctx)
49    }
50    pub(crate) fn process_base_response(
51        response: BaseSecretResponseModel,
52        ctx: &mut KeyStoreContext<KeyIds>,
53    ) -> Result<SecretResponse, SecretsManagerError> {
54        let organization_id = require!(response.organization_id);
55        let enc_key = SymmetricKeyId::Organization(organization_id);
56
57        let key = require!(response.key)
58            .parse::<EncString>()?
59            .decrypt(ctx, enc_key)?;
60
61        let value = require!(response.value)
62            .parse::<EncString>()?
63            .decrypt(ctx, enc_key)?;
64
65        let note = require!(response.note)
66            .parse::<EncString>()?
67            .decrypt(ctx, enc_key)?;
68
69        let project = response
70            .projects
71            .and_then(|p| p.into_iter().next())
72            .and_then(|p| p.id);
73
74        Ok(SecretResponse {
75            id: require!(response.id),
76            organization_id,
77            project_id: project,
78            key,
79            value,
80            note,
81
82            creation_date: require!(response.creation_date).parse()?,
83            revision_date: require!(response.revision_date).parse()?,
84        })
85    }
86}
87
88#[allow(missing_docs)]
89#[derive(Serialize, Deserialize, Debug, JsonSchema)]
90#[serde(rename_all = "camelCase", deny_unknown_fields)]
91pub struct SecretsResponse {
92    pub data: Vec<SecretResponse>,
93}
94
95impl SecretsResponse {
96    pub(crate) fn process_response(
97        response: BaseSecretResponseModelListResponseModel,
98        ctx: &mut KeyStoreContext<KeyIds>,
99    ) -> Result<SecretsResponse, SecretsManagerError> {
100        Ok(SecretsResponse {
101            data: response
102                .data
103                .unwrap_or_default()
104                .into_iter()
105                .map(|r| SecretResponse::process_base_response(r, ctx))
106                .collect::<Result<_, _>>()?,
107        })
108    }
109}