Skip to content

Commit

Permalink
[SM-865] Part 2 Use new get secrets by IDs endpoint (#150)
Browse files Browse the repository at this point in the history
* Add auto generated Api bindings

* Expose new endpoint methods in SDK

* Use in bws CLI

* Expose new command in JSON schemas

* restructure and rename response

* Expose getByIds in napi

* fix cargo check

* Add openapi auto generation

* Regenerated open api doc

* revert back to original binding.js

* remove .clone()

* Add to changelog

* run cargo fmt
  • Loading branch information
Thomas-Avery authored Aug 28, 2023
1 parent 8941a8a commit 76865d9
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 14 deletions.
3 changes: 3 additions & 0 deletions crates/bitwarden-json/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ impl Client {
#[cfg(feature = "secrets")]
Command::Secrets(cmd) => match cmd {
SecretsCommand::Get(req) => self.0.secrets().get(&req).await.into_string(),
SecretsCommand::GetByIds(req) => {
self.0.secrets().get_by_ids(req).await.into_string()
}
SecretsCommand::Create(req) => self.0.secrets().create(&req).await.into_string(),
SecretsCommand::List(req) => self.0.secrets().list(&req).await.into_string(),
SecretsCommand::Update(req) => self.0.secrets().update(&req).await.into_string(),
Expand Down
10 changes: 9 additions & 1 deletion crates/bitwarden-json/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use bitwarden::{
},
secrets::{
SecretCreateRequest, SecretGetRequest, SecretIdentifiersRequest, SecretPutRequest,
SecretsDeleteRequest,
SecretsDeleteRequest, SecretsGetRequest,
},
},
};
Expand Down Expand Up @@ -97,6 +97,14 @@ pub enum SecretsCommand {
///
Get(SecretGetRequest),

/// > Requires Authentication
/// > Requires using an Access Token for login or calling Sync at least once
/// Retrieve secrets by the provided identifiers
///
/// Returns: [SecretsResponse](bitwarden::secrets_manager::secrets::SecretsResponse)
///
GetByIds(SecretsGetRequest),

/// > Requires Authentication
/// > Requires using an Access Token for login or calling Sync at least once
/// Creates a new secret in the provided organization using the given data
Expand Down
13 changes: 13 additions & 0 deletions crates/bitwarden-napi/src-ts/bitwarden_client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ResponseForSecretIdentifiersResponse,
ResponseForSecretResponse,
ResponseForSecretsDeleteResponse,
ResponseForSecretsResponse,
} from "./schemas";

export class BitwardenClient {
Expand Down Expand Up @@ -80,6 +81,18 @@ export class SecretsClient {
return Convert.toResponseForSecretResponse(response);
}

async getByIds(ids: string[]): Promise<ResponseForSecretsResponse> {
const response = await this.client.runCommand(
Convert.commandToJson({
secrets: {
getByIds: { ids },
},
}),
);

return Convert.toResponseForSecretsResponse(response);
}

async create(
key: string,
note: string,
Expand Down
2 changes: 2 additions & 0 deletions crates/bitwarden/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- `auth::request::AccessTokenLoginRequest` moved to `auth::login::AccessTokenLoginRequest` (#178)

- Support for fetching multiple secrets by ids (#150)

## [0.3.0] - 2023-07-26

### Deprecated
Expand Down
13 changes: 9 additions & 4 deletions crates/bitwarden/src/secrets_manager/client_secrets.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::{
error::Result,
secrets_manager::secrets::{
create_secret, delete_secrets, get_secret, list_secrets, list_secrets_by_project,
update_secret, SecretCreateRequest, SecretGetRequest, SecretIdentifiersByProjectRequest,
SecretIdentifiersRequest, SecretIdentifiersResponse, SecretPutRequest, SecretResponse,
SecretsDeleteRequest, SecretsDeleteResponse,
create_secret, delete_secrets, get_secret, get_secrets_by_ids, list_secrets,
list_secrets_by_project, update_secret, SecretCreateRequest, SecretGetRequest,
SecretIdentifiersByProjectRequest, SecretIdentifiersRequest, SecretIdentifiersResponse,
SecretPutRequest, SecretResponse, SecretsDeleteRequest, SecretsDeleteResponse,
SecretsGetRequest, SecretsResponse,
},
Client,
};
Expand All @@ -18,6 +19,10 @@ impl<'a> ClientSecrets<'a> {
get_secret(self.client, input).await
}

pub async fn get_by_ids(&mut self, input: SecretsGetRequest) -> Result<SecretsResponse> {
get_secrets_by_ids(self.client, input).await
}

pub async fn create(&mut self, input: &SecretCreateRequest) -> Result<SecretResponse> {
create_secret(self.client, input).await
}
Expand Down
30 changes: 30 additions & 0 deletions crates/bitwarden/src/secrets_manager/secrets/get_by_ids.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use bitwarden_api_api::models::GetSecretsRequestModel;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use uuid::Uuid;

use super::SecretsResponse;
use crate::{client::Client, error::Result};

#[derive(Serialize, Deserialize, Debug, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct SecretsGetRequest {
/// IDs of the secrets to retrieve
pub ids: Vec<Uuid>,
}

pub(crate) async fn get_secrets_by_ids(
client: &mut Client,
input: SecretsGetRequest,
) -> Result<SecretsResponse> {
let request = Some(GetSecretsRequestModel { ids: input.ids });

let config = client.get_api_configurations().await;

let res =
bitwarden_api_api::apis::secrets_api::secrets_get_by_ids_post(&config.api, request).await?;

let enc = client.get_encryption_settings()?;

SecretsResponse::process_response(res, enc)
}
5 changes: 4 additions & 1 deletion crates/bitwarden/src/secrets_manager/secrets/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod create;
mod delete;
mod get;
mod get_by_ids;
mod list;
mod secret_response;
mod update;
Expand All @@ -11,10 +12,12 @@ pub(crate) use delete::delete_secrets;
pub use delete::{SecretsDeleteRequest, SecretsDeleteResponse};
pub(crate) use get::get_secret;
pub use get::SecretGetRequest;
pub(crate) use get_by_ids::get_secrets_by_ids;
pub use get_by_ids::SecretsGetRequest;
pub(crate) use list::{list_secrets, list_secrets_by_project};
pub use list::{
SecretIdentifiersByProjectRequest, SecretIdentifiersRequest, SecretIdentifiersResponse,
};
pub use secret_response::SecretResponse;
pub use secret_response::{SecretResponse, SecretsResponse};
pub(crate) use update::update_secret;
pub use update::SecretPutRequest;
43 changes: 42 additions & 1 deletion crates/bitwarden/src/secrets_manager/secrets/secret_response.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use bitwarden_api_api::models::SecretResponseModel;
use bitwarden_api_api::models::{
BaseSecretResponseModel, BaseSecretResponseModelListResponseModel, SecretResponseModel,
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
Expand Down Expand Up @@ -29,6 +31,23 @@ impl SecretResponse {
pub(crate) fn process_response(
response: SecretResponseModel,
enc: &EncryptionSettings,
) -> Result<SecretResponse> {
let base = BaseSecretResponseModel {
object: response.object,
id: response.id,
organization_id: response.organization_id,
key: response.key,
value: response.value,
note: response.note,
creation_date: response.creation_date,
revision_date: response.revision_date,
projects: response.projects,
};
Self::process_base_response(base, enc)
}
pub(crate) fn process_base_response(
response: BaseSecretResponseModel,
enc: &EncryptionSettings,
) -> Result<SecretResponse> {
let org_id = response.organization_id;

Expand Down Expand Up @@ -67,3 +86,25 @@ impl SecretResponse {
})
}
}

#[derive(Serialize, Deserialize, Debug, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct SecretsResponse {
pub data: Vec<SecretResponse>,
}

impl SecretsResponse {
pub(crate) fn process_response(
response: BaseSecretResponseModelListResponseModel,
enc: &EncryptionSettings,
) -> Result<SecretsResponse> {
Ok(SecretsResponse {
data: response
.data
.unwrap_or_default()
.into_iter()
.map(|r| SecretResponse::process_base_response(r, enc))
.collect::<Result<_, _>>()?,
})
}
}
14 changes: 7 additions & 7 deletions crates/bws/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use bitwarden::{
},
secrets::{
SecretCreateRequest, SecretGetRequest, SecretIdentifiersByProjectRequest,
SecretIdentifiersRequest, SecretPutRequest, SecretsDeleteRequest,
SecretIdentifiersRequest, SecretPutRequest, SecretsDeleteRequest, SecretsGetRequest,
},
},
};
Expand Down Expand Up @@ -456,12 +456,12 @@ async fn process_commands() -> Result<()> {
.await?
};

let mut secrets = Vec::new();

for s in res.data {
let secret = client.secrets().get(&SecretGetRequest { id: s.id }).await?;
secrets.push(secret);
}
let secret_ids = res.data.into_iter().map(|e| e.id).collect();
let secrets = client
.secrets()
.get_by_ids(SecretsGetRequest { ids: secret_ids })
.await?
.data;
serialize_response(secrets, cli.output, color);
}

Expand Down
1 change: 1 addition & 0 deletions crates/sdk-schemas/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ fn main() -> Result<()> {
bitwarden::auth::login::PasswordLoginResponse,
bitwarden::secrets_manager::secrets::SecretIdentifiersResponse,
bitwarden::secrets_manager::secrets::SecretResponse,
bitwarden::secrets_manager::secrets::SecretsResponse,
bitwarden::secrets_manager::secrets::SecretsDeleteResponse,
bitwarden::secrets_manager::projects::ProjectResponse,
bitwarden::secrets_manager::projects::ProjectsResponse,
Expand Down

0 comments on commit 76865d9

Please sign in to comment.