bitwarden_sm/secrets/
list.rs

1use bitwarden_api_api::models::{
2    SecretWithProjectsListResponseModel, SecretsWithProjectsInnerSecret,
3};
4use bitwarden_core::{
5    client::Client,
6    key_management::{KeyIds, SymmetricKeyId},
7    require,
8};
9use bitwarden_crypto::{Decryptable, EncString, KeyStoreContext};
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 SecretIdentifiersRequest {
20    /// Organization to retrieve all the secrets from
21    pub organization_id: Uuid,
22}
23
24pub(crate) async fn list_secrets(
25    client: &Client,
26    input: &SecretIdentifiersRequest,
27) -> Result<SecretIdentifiersResponse, SecretsManagerError> {
28    let config = client.internal.get_api_configurations().await;
29    let res = bitwarden_api_api::apis::secrets_api::organizations_organization_id_secrets_get(
30        &config.api,
31        input.organization_id,
32    )
33    .await?;
34
35    let key_store = client.internal.get_key_store();
36
37    SecretIdentifiersResponse::process_response(res, &mut key_store.context())
38}
39
40#[allow(missing_docs)]
41#[derive(Serialize, Deserialize, Debug, JsonSchema)]
42#[serde(rename_all = "camelCase", deny_unknown_fields)]
43pub struct SecretIdentifiersByProjectRequest {
44    /// Project to retrieve all the secrets from
45    pub project_id: Uuid,
46}
47
48pub(crate) async fn list_secrets_by_project(
49    client: &Client,
50    input: &SecretIdentifiersByProjectRequest,
51) -> Result<SecretIdentifiersResponse, SecretsManagerError> {
52    let config = client.internal.get_api_configurations().await;
53    let res = bitwarden_api_api::apis::secrets_api::projects_project_id_secrets_get(
54        &config.api,
55        input.project_id,
56    )
57    .await?;
58
59    let key_store = client.internal.get_key_store();
60
61    SecretIdentifiersResponse::process_response(res, &mut key_store.context())
62}
63
64#[allow(missing_docs)]
65#[derive(Serialize, Deserialize, Debug, JsonSchema)]
66#[serde(rename_all = "camelCase", deny_unknown_fields)]
67pub struct SecretIdentifiersResponse {
68    pub data: Vec<SecretIdentifierResponse>,
69}
70
71impl SecretIdentifiersResponse {
72    pub(crate) fn process_response(
73        response: SecretWithProjectsListResponseModel,
74        ctx: &mut KeyStoreContext<KeyIds>,
75    ) -> Result<SecretIdentifiersResponse, SecretsManagerError> {
76        Ok(SecretIdentifiersResponse {
77            data: response
78                .secrets
79                .unwrap_or_default()
80                .into_iter()
81                .map(|r| SecretIdentifierResponse::process_response(r, ctx))
82                .collect::<Result<_, _>>()?,
83        })
84    }
85}
86
87#[derive(Serialize, Deserialize, Debug, JsonSchema)]
88#[serde(rename_all = "camelCase", deny_unknown_fields)]
89pub struct SecretIdentifierResponse {
90    pub id: Uuid,
91    pub organization_id: Uuid,
92
93    pub key: String,
94}
95
96impl SecretIdentifierResponse {
97    pub(crate) fn process_response(
98        response: SecretsWithProjectsInnerSecret,
99        ctx: &mut KeyStoreContext<KeyIds>,
100    ) -> Result<SecretIdentifierResponse, SecretsManagerError> {
101        let organization_id = require!(response.organization_id);
102        let enc_key = SymmetricKeyId::Organization(organization_id);
103
104        let key = require!(response.key)
105            .parse::<EncString>()?
106            .decrypt(ctx, enc_key)?;
107
108        Ok(SecretIdentifierResponse {
109            id: require!(response.id),
110            organization_id,
111            key,
112        })
113    }
114}