bitwarden_sm/secrets/
list.rs

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