bitwarden_sm/secrets/
secret_response.rs

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