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