Skip to content

Commit 8f0ea14

Browse files
authored
[PM-20094] Generate Password/Passphrase Generator WASM (#197)
## 🎟️ Tracking https://bitwarden.atlassian.net/browse/PM-20094 ## 📔 Objective Add WASM generation for generating passwords and passphrases. ## ⏰ Reminders before review - Contributor guidelines followed - All formatters and local linters executed and passed - Written new unit and / or integration tests where applicable - Protected functional changes with optionality (feature flags) - Used internationalization (i18n) for all UI strings - CI builds passed - Communicated to DevOps any deployment requirements - Updated any necessary documentation (Confluence, contributing docs) or informed the documentation team ## 🦮 Reviewer guidelines <!-- Suggested interactions but feel free to use (or not) as you desire! --> - 👍 (`:+1:`) or similar for great changes - 📝 (`:memo:`) or ℹ️ (`:information_source:`) for notes or general info - ❓ (`:question:`) for questions - 🤔 (`:thinking:`) or 💭 (`:thought_balloon:`) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion - 🎨 (`:art:`) for suggestions / improvements - ❌ (`:x:`) or ⚠️ (`:warning:`) for more significant problems or concerns needing attention - 🌱 (`:seedling:`) or ♻️ (`:recycle:`) for future improvements or indications of technical debt - ⛏ (`:pick:`) for minor or nitpick changes
1 parent 1972351 commit 8f0ea14

File tree

8 files changed

+81
-1
lines changed

8 files changed

+81
-1
lines changed

Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/bitwarden-generators/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,21 @@ keywords.workspace = true
1616

1717
[features]
1818
uniffi = ["dep:uniffi"] # Uniffi bindings
19+
wasm = ["dep:tsify-next", "dep:wasm-bindgen"]
1920

2021
[dependencies]
2122
bitwarden-core = { workspace = true, features = ["internal"] }
2223
bitwarden-crypto = { workspace = true }
24+
bitwarden-error = { workspace = true }
2325
rand = ">=0.8.5, <0.9"
2426
reqwest = { workspace = true }
2527
schemars = { workspace = true }
2628
serde = { workspace = true }
2729
serde_json = { workspace = true }
2830
thiserror = { workspace = true }
31+
tsify-next = { workspace = true, optional = true }
2932
uniffi = { workspace = true, optional = true }
33+
wasm-bindgen = { workspace = true, optional = true }
3034

3135
[dev-dependencies]
3236
rand_chacha = "0.3.1"

crates/bitwarden-generators/src/passphrase.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
use bitwarden_crypto::EFF_LONG_WORD_LIST;
2+
use bitwarden_error::bitwarden_error;
23
use rand::{seq::SliceRandom, Rng, RngCore};
34
use schemars::JsonSchema;
45
use serde::{Deserialize, Serialize};
56
use thiserror::Error;
7+
#[cfg(feature = "wasm")]
8+
use tsify_next::Tsify;
69

710
use crate::util::capitalize_first_letter;
811

12+
#[bitwarden_error(flat)]
913
#[derive(Debug, Error)]
1014
pub enum PassphraseError {
1115
#[error("'num_words' must be between {} and {}", minimum, maximum)]
@@ -16,6 +20,7 @@ pub enum PassphraseError {
1620
#[derive(Serialize, Deserialize, Debug, JsonSchema)]
1721
#[serde(rename_all = "camelCase", deny_unknown_fields)]
1822
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
23+
#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
1924
pub struct PassphraseGeneratorRequest {
2025
/// Number of words in the generated passphrase.
2126
/// This value must be between 3 and 20.

crates/bitwarden-generators/src/password.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
use std::collections::BTreeSet;
22

3+
use bitwarden_error::bitwarden_error;
34
use rand::{distributions::Distribution, seq::SliceRandom, RngCore};
45
use schemars::JsonSchema;
56
use serde::{Deserialize, Serialize};
67
use thiserror::Error;
8+
#[cfg(feature = "wasm")]
9+
use tsify_next::Tsify;
710

11+
#[bitwarden_error(flat)]
812
#[derive(Debug, Error)]
913
pub enum PasswordError {
1014
#[error("No character set enabled")]
@@ -17,6 +21,7 @@ pub enum PasswordError {
1721
#[derive(Serialize, Deserialize, Debug, JsonSchema)]
1822
#[serde(rename_all = "camelCase", deny_unknown_fields)]
1923
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
24+
#[cfg_attr(feature = "wasm", derive(Tsify), tsify(into_wasm_abi, from_wasm_abi))]
2025
pub struct PasswordGeneratorRequest {
2126
/// Include lowercase characters (a-z).
2227
pub lowercase: bool,

crates/bitwarden-wasm-internal/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ crate-type = ["cdylib"]
1919
bitwarden-core = { workspace = true, features = ["wasm", "internal"] }
2020
bitwarden-crypto = { workspace = true, features = ["wasm"] }
2121
bitwarden-error = { workspace = true }
22+
bitwarden-generators = { workspace = true, features = ["wasm"] }
2223
bitwarden-ipc = { workspace = true, features = ["wasm"] }
2324
bitwarden-ssh = { workspace = true, features = ["wasm"] }
2425
bitwarden-vault = { workspace = true, features = ["wasm"] }

crates/bitwarden-wasm-internal/src/client.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use bitwarden_error::bitwarden_error;
66
use bitwarden_vault::VaultClientExt;
77
use wasm_bindgen::prelude::*;
88

9-
use crate::{CryptoClient, VaultClient};
9+
use crate::{CryptoClient, GeneratorClient, VaultClient};
1010

1111
#[wasm_bindgen]
1212
pub struct BitwardenClient(pub(crate) Client);
@@ -46,6 +46,11 @@ impl BitwardenClient {
4646
pub fn vault(&self) -> VaultClient {
4747
VaultClient::new(self.0.vault())
4848
}
49+
50+
/// Constructs a specific client for generating passwords and passphrases
51+
pub fn generator(&self) -> GeneratorClient {
52+
GeneratorClient::new(self.0.clone())
53+
}
4954
}
5055

5156
#[bitwarden_error(basic)]
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use bitwarden_core::Client;
2+
use bitwarden_generators::{
3+
GeneratorClientsExt, PassphraseGeneratorRequest, PasswordGeneratorRequest,
4+
};
5+
use wasm_bindgen::prelude::*;
6+
7+
#[wasm_bindgen]
8+
pub struct GeneratorClient(Client);
9+
10+
impl GeneratorClient {
11+
/// Constructs a new SDK client for generating random passwords and passphrases
12+
///
13+
/// # Arguments
14+
/// - `client` - The client used to access the SDK
15+
///
16+
/// # Returns
17+
/// - `Self` - Returns newly constructed client
18+
pub fn new(client: Client) -> Self {
19+
Self(client)
20+
}
21+
}
22+
23+
#[wasm_bindgen]
24+
impl GeneratorClient {
25+
/// Generates a password from a provided request
26+
///
27+
/// # Arguments
28+
/// - `request` - Settings for the character sets and password length
29+
///
30+
/// # Returns
31+
/// - `Ok(String)` containing the generated password
32+
/// - `Err(PasswordError)` if password generation fails
33+
pub fn password(
34+
&self,
35+
request: PasswordGeneratorRequest,
36+
) -> Result<String, bitwarden_generators::PasswordError> {
37+
self.0.generator().password(request)
38+
}
39+
40+
/// Generates a passphrase from a provided request
41+
///
42+
/// # Arguments
43+
/// - `request` - Settings for the word count, word separators character sets
44+
///
45+
/// # Returns
46+
/// - `Ok(String)` containing the generated passphrase
47+
/// - `Err(PassphraseError)` if passphrase generation fails
48+
pub fn passphrase(
49+
&self,
50+
request: PassphraseGeneratorRequest,
51+
) -> Result<String, bitwarden_generators::PassphraseError> {
52+
self.0.generator().passphrase(request)
53+
}
54+
}

crates/bitwarden-wasm-internal/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
mod client;
44
mod crypto;
55
mod custom_types;
6+
mod generators;
67
mod init;
78
mod pure_crypto;
89
mod ssh;
@@ -11,5 +12,6 @@ mod vault;
1112
pub use bitwarden_ipc::wasm::*;
1213
pub use client::BitwardenClient;
1314
pub use crypto::CryptoClient;
15+
pub use generators::GeneratorClient;
1416
pub use init::init_sdk;
1517
pub use vault::{folders::ClientFolders, VaultClient};

0 commit comments

Comments
 (0)