Skip to content

Commit

Permalink
SM-807: BWS CLI & SDK Updates (#77)
Browse files Browse the repository at this point in the history
* SM-807: Fix edit secret, allow updating the project a secret is in, and other small changes

* SM-807: Update schemas

* SM-807: Add proper error messaging when secrets or projects are deleted.

* SM-807: Make project_id a parameter rather than an argument on secret create

* SM-807: Add back project_ids that were lost in the merge conflict resolution

* SM-807: Add additional secrets / projects deletion error message when there are errors

* SM-807: Make failed messaging on projects or secrets delete optional, and other small output fixes

* SM-807: Add back the project_id help text on secret create

* SM-807: Update secret/project delete to use a filter_map and not print on 0 successes

* SM-807: Remove mut refactor
  • Loading branch information
coltonhurst authored Jul 21, 2023
1 parent 3bfaec3 commit 0a5ff9c
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 14 deletions.
3 changes: 2 additions & 1 deletion crates/bitwarden/src/secrets_manager/secrets/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub struct SecretPutRequest {
pub key: String,
pub value: String,
pub note: String,
pub project_ids: Option<Vec<Uuid>>,
}

pub(crate) async fn update_secret(
Expand All @@ -37,7 +38,7 @@ pub(crate) async fn update_secret(
key: enc.encrypt(input.key.as_bytes(), &org_id)?.to_string(),
value: enc.encrypt(input.value.as_bytes(), &org_id)?.to_string(),
note: enc.encrypt(input.note.as_bytes(), &org_id)?.to_string(),
project_ids: None,
project_ids: input.project_ids.clone(),
});

let config = client.get_api_configurations().await;
Expand Down
80 changes: 67 additions & 13 deletions crates/bws/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,16 @@ enum SecretCommand {
key: String,
value: String,

#[arg(help = "The ID of the project this secret will be added to")]
project_id: Uuid,

#[arg(long, help = "An optional note to add to the secret")]
note: Option<String>,

#[arg(long, help = "The ID of the project this secret will be added to")]
project_id: Option<Uuid>,
},
Delete {
secret_ids: Vec<Uuid>,
},
#[clap(group = ArgGroup::new("edit_field").required(true).multiple(true))]
Edit {
secret_id: Uuid,
#[arg(long, group = "edit_field")]
Expand All @@ -126,6 +127,8 @@ enum SecretCommand {
value: Option<String>,
#[arg(long, group = "edit_field")]
note: Option<String>,
#[arg(long, group = "edit_field")]
project_id: Option<Uuid>,
},
Get {
secret_id: Uuid,
Expand Down Expand Up @@ -179,7 +182,7 @@ enum CreateCommand {
note: Option<String>,

#[arg(long, help = "The ID of the project this secret will be added to")]
project_id: Option<Uuid>,
project_id: Uuid,
},
}

Expand All @@ -200,6 +203,8 @@ enum EditCommand {
value: Option<String>,
#[arg(long, group = "edit_field")]
note: Option<String>,
#[arg(long, group = "edit_field")]
project_id: Option<Uuid>,
},
}

Expand Down Expand Up @@ -383,17 +388,34 @@ async fn process_commands() -> Result<()> {
| Commands::Delete {
cmd: DeleteCommand::Project { project_ids },
} => {
let project_count = project_ids.len();
let count = project_ids.len();

client
let result = client
.projects()
.delete(ProjectsDeleteRequest { ids: project_ids })
.await?;

if project_count > 1 {
println!("Projects deleted successfully.");
} else {
println!("Project deleted successfully.");
let projects_failed: Vec<(Uuid, String)> = result
.data
.into_iter()
.filter_map(|r| r.error.map(|e| (r.id, e)))
.collect();
let deleted_projects = count - projects_failed.len();

if deleted_projects > 1 {
println!("{} projects deleted successfully.", deleted_projects);
} else if deleted_projects == 1 {
println!("{} project deleted successfully.", deleted_projects);
}

if projects_failed.len() > 1 {
println!("{} projects had errors:", projects_failed.len());
} else if projects_failed.len() == 1 {
println!("{} project had an error:", projects_failed.len());
}

for project in projects_failed {
println!("{}: {}", project.0, project.1);
}
}

Expand Down Expand Up @@ -466,7 +488,7 @@ async fn process_commands() -> Result<()> {
key,
value,
note: note.unwrap_or_default(),
project_ids: project_id.map(|p| vec![p]),
project_ids: Some(vec![project_id]),
})
.await?;
serialize_response(secret, cli.output, color);
Expand All @@ -479,6 +501,7 @@ async fn process_commands() -> Result<()> {
key,
value,
note,
project_id,
},
}
| Commands::Edit {
Expand All @@ -488,6 +511,7 @@ async fn process_commands() -> Result<()> {
key,
value,
note,
project_id,
},
} => {
let old_secret = client
Expand All @@ -505,6 +529,13 @@ async fn process_commands() -> Result<()> {
key: key.unwrap_or(old_secret.key),
value: value.unwrap_or(old_secret.value),
note: note.unwrap_or(old_secret.note),
project_ids: match project_id {
Some(id) => Some(vec![id]),
None => match old_secret.project_id {
Some(id) => Some(vec![id]),
None => bail!("Editing a secret requires a project_id."),
},
},
})
.await?;
serialize_response(secret, cli.output, color);
Expand All @@ -516,12 +547,35 @@ async fn process_commands() -> Result<()> {
| Commands::Delete {
cmd: DeleteCommand::Secret { secret_ids },
} => {
client
let count = secret_ids.len();

let result = client
.secrets()
.delete(SecretsDeleteRequest { ids: secret_ids })
.await?;

println!("Secret deleted correctly");
let secrets_failed: Vec<(Uuid, String)> = result
.data
.into_iter()
.filter_map(|r| r.error.map(|e| (r.id, e)))
.collect();
let deleted_secrets = count - secrets_failed.len();

if deleted_secrets > 1 {
println!("{} secrets deleted successfully.", deleted_secrets);
} else if deleted_secrets == 1 {
println!("{} secret deleted successfully.", deleted_secrets);
}

if secrets_failed.len() > 1 {
println!("{} secrets had errors:", secrets_failed.len());
} else if secrets_failed.len() == 1 {
println!("{} secret had an error:", secrets_failed.len());
}

for secret in secrets_failed {
println!("{}: {}", secret.0, secret.1);
}
}

Commands::Config { .. } => {
Expand Down

0 comments on commit 0a5ff9c

Please sign in to comment.