Skip to content

Commit b99e954

Browse files
authored
[PM-19966] Remove subclient lifetimes (#198)
## 🎟️ Tracking https://bitwarden.atlassian.net/browse/PM-19966 ## 📔 Objective The subclient lifetimes have been a pain point that cause us to need to have create our duplicate copies of the structs for WASM and Uniffi that don't deal with them. If instead of doing that we wrap the `Client`s `InternalClient` in `Arc`, we can just cheaply clone the `Arc` and remove all the lifetimes from the subclients. This opens up the posibility of using the same API for Rust/WASM/UniFFI in the future, and also simplifies the bindings a bit in the short term. This does have the negative that each subclient access requires an atomic operation clone, but that's negligible for our usecases. (And we were already doing basically the same thing for Uniffi and WASM anyway) ## ⏰ 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 c2434ae commit b99e954

File tree

40 files changed

+335
-562
lines changed

40 files changed

+335
-562
lines changed

bitwarden_license/bitwarden-sm/src/client_projects.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,57 +9,57 @@ use crate::{
99
},
1010
};
1111

12-
pub struct ClientProjects<'a> {
13-
pub client: &'a Client,
12+
pub struct ClientProjects {
13+
pub client: Client,
1414
}
1515

16-
impl<'a> ClientProjects<'a> {
17-
pub fn new(client: &'a Client) -> Self {
16+
impl ClientProjects {
17+
pub fn new(client: Client) -> Self {
1818
Self { client }
1919
}
2020

2121
pub async fn get(
2222
&self,
2323
input: &ProjectGetRequest,
2424
) -> Result<ProjectResponse, SecretsManagerError> {
25-
get_project(self.client, input).await
25+
get_project(&self.client, input).await
2626
}
2727

2828
pub async fn create(
2929
&self,
3030
input: &ProjectCreateRequest,
3131
) -> Result<ProjectResponse, SecretsManagerError> {
32-
create_project(self.client, input).await
32+
create_project(&self.client, input).await
3333
}
3434

3535
pub async fn list(
3636
&self,
3737
input: &ProjectsListRequest,
3838
) -> Result<ProjectsResponse, SecretsManagerError> {
39-
list_projects(self.client, input).await
39+
list_projects(&self.client, input).await
4040
}
4141

4242
pub async fn update(
4343
&self,
4444
input: &ProjectPutRequest,
4545
) -> Result<ProjectResponse, SecretsManagerError> {
46-
update_project(self.client, input).await
46+
update_project(&self.client, input).await
4747
}
4848

4949
pub async fn delete(
5050
&self,
5151
input: ProjectsDeleteRequest,
5252
) -> Result<ProjectsDeleteResponse, SecretsManagerError> {
53-
delete_projects(self.client, input).await
53+
delete_projects(&self.client, input).await
5454
}
5555
}
5656

57-
pub trait ClientProjectsExt<'a> {
58-
fn projects(&'a self) -> ClientProjects<'a>;
57+
pub trait ClientProjectsExt {
58+
fn projects(&self) -> ClientProjects;
5959
}
6060

61-
impl<'a> ClientProjectsExt<'a> for Client {
62-
fn projects(&'a self) -> ClientProjects<'a> {
63-
ClientProjects::new(self)
61+
impl ClientProjectsExt for Client {
62+
fn projects(&self) -> ClientProjects {
63+
ClientProjects::new(self.clone())
6464
}
6565
}

bitwarden_license/bitwarden-sm/src/client_secrets.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,78 +12,78 @@ use crate::{
1212
},
1313
};
1414

15-
pub struct ClientSecrets<'a> {
16-
client: &'a Client,
15+
pub struct ClientSecrets {
16+
client: Client,
1717
}
1818

19-
impl<'a> ClientSecrets<'a> {
20-
pub fn new(client: &'a Client) -> Self {
19+
impl ClientSecrets {
20+
pub fn new(client: Client) -> Self {
2121
Self { client }
2222
}
2323

2424
pub async fn get(
2525
&self,
2626
input: &SecretGetRequest,
2727
) -> Result<SecretResponse, SecretsManagerError> {
28-
get_secret(self.client, input).await
28+
get_secret(&self.client, input).await
2929
}
3030

3131
pub async fn get_by_ids(
3232
&self,
3333
input: SecretsGetRequest,
3434
) -> Result<SecretsResponse, SecretsManagerError> {
35-
get_secrets_by_ids(self.client, input).await
35+
get_secrets_by_ids(&self.client, input).await
3636
}
3737

3838
pub async fn create(
3939
&self,
4040
input: &SecretCreateRequest,
4141
) -> Result<SecretResponse, SecretsManagerError> {
42-
create_secret(self.client, input).await
42+
create_secret(&self.client, input).await
4343
}
4444

4545
pub async fn list(
4646
&self,
4747
input: &SecretIdentifiersRequest,
4848
) -> Result<SecretIdentifiersResponse, SecretsManagerError> {
49-
list_secrets(self.client, input).await
49+
list_secrets(&self.client, input).await
5050
}
5151

5252
pub async fn list_by_project(
5353
&self,
5454
input: &SecretIdentifiersByProjectRequest,
5555
) -> Result<SecretIdentifiersResponse, SecretsManagerError> {
56-
list_secrets_by_project(self.client, input).await
56+
list_secrets_by_project(&self.client, input).await
5757
}
5858

5959
pub async fn update(
6060
&self,
6161
input: &SecretPutRequest,
6262
) -> Result<SecretResponse, SecretsManagerError> {
63-
update_secret(self.client, input).await
63+
update_secret(&self.client, input).await
6464
}
6565

6666
pub async fn delete(
6767
&self,
6868
input: SecretsDeleteRequest,
6969
) -> Result<SecretsDeleteResponse, SecretsManagerError> {
70-
delete_secrets(self.client, input).await
70+
delete_secrets(&self.client, input).await
7171
}
7272

7373
pub async fn sync(
7474
&self,
7575
input: &SecretsSyncRequest,
7676
) -> Result<SecretsSyncResponse, SecretsManagerError> {
77-
sync_secrets(self.client, input).await
77+
sync_secrets(&self.client, input).await
7878
}
7979
}
8080

81-
pub trait ClientSecretsExt<'a> {
82-
fn secrets(&'a self) -> ClientSecrets<'a>;
81+
pub trait ClientSecretsExt {
82+
fn secrets(&self) -> ClientSecrets;
8383
}
8484

85-
impl<'a> ClientSecretsExt<'a> for Client {
86-
fn secrets(&'a self) -> ClientSecrets<'a> {
87-
ClientSecrets::new(self)
85+
impl ClientSecretsExt for Client {
86+
fn secrets(&self) -> ClientSecrets {
87+
ClientSecrets::new(self.clone())
8888
}
8989
}

crates/bitwarden-core/src/auth/auth_client.rs

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ use crate::{
2929
client::encryption_settings::EncryptionSettingsError,
3030
};
3131

32-
pub struct AuthClient<'a> {
33-
pub(crate) client: &'a crate::Client,
32+
pub struct AuthClient {
33+
pub(crate) client: crate::Client,
3434
}
3535

36-
impl AuthClient<'_> {
36+
impl AuthClient {
3737
pub async fn renew_token(&self) -> Result<(), LoginError> {
3838
renew_token(&self.client.internal).await
3939
}
@@ -43,12 +43,12 @@ impl AuthClient<'_> {
4343
&self,
4444
input: &AccessTokenLoginRequest,
4545
) -> Result<AccessTokenLoginResponse, LoginError> {
46-
login_access_token(self.client, input).await
46+
login_access_token(&self.client, input).await
4747
}
4848
}
4949

5050
#[cfg(feature = "internal")]
51-
impl AuthClient<'_> {
51+
impl AuthClient {
5252
pub fn password_strength(
5353
&self,
5454
password: String,
@@ -82,7 +82,7 @@ impl AuthClient<'_> {
8282
org_public_key: String,
8383
remember_device: bool,
8484
) -> Result<RegisterTdeKeyResponse, EncryptionSettingsError> {
85-
make_register_tde_keys(self.client, email, org_public_key, remember_device)
85+
make_register_tde_keys(&self.client, email, org_public_key, remember_device)
8686
}
8787

8888
pub fn make_key_connector_keys(&self) -> Result<KeyConnectorResponse, CryptoError> {
@@ -91,58 +91,58 @@ impl AuthClient<'_> {
9191
}
9292

9393
pub async fn register(&self, input: &RegisterRequest) -> Result<(), RegisterError> {
94-
register(self.client, input).await
94+
register(&self.client, input).await
9595
}
9696

9797
pub async fn prelogin(&self, email: String) -> Result<Kdf, PreloginError> {
9898
use crate::auth::login::prelogin;
9999

100-
prelogin(self.client, email).await
100+
prelogin(&self.client, email).await
101101
}
102102

103103
pub async fn login_password(
104104
&self,
105105
input: &PasswordLoginRequest,
106106
) -> Result<PasswordLoginResponse, LoginError> {
107-
login_password(self.client, input).await
107+
login_password(&self.client, input).await
108108
}
109109

110110
pub async fn login_api_key(
111111
&self,
112112
input: &ApiKeyLoginRequest,
113113
) -> Result<ApiKeyLoginResponse, LoginError> {
114-
login_api_key(self.client, input).await
114+
login_api_key(&self.client, input).await
115115
}
116116

117117
pub async fn send_two_factor_email(
118118
&self,
119119
tf: &TwoFactorEmailRequest,
120120
) -> Result<(), TwoFactorEmailError> {
121-
send_two_factor_email(self.client, tf).await
121+
send_two_factor_email(&self.client, tf).await
122122
}
123123

124124
pub fn validate_password(
125125
&self,
126126
password: String,
127127
password_hash: String,
128128
) -> Result<bool, AuthValidateError> {
129-
validate_password(self.client, password, password_hash)
129+
validate_password(&self.client, password, password_hash)
130130
}
131131

132132
pub fn validate_password_user_key(
133133
&self,
134134
password: String,
135135
encrypted_user_key: String,
136136
) -> Result<String, AuthValidateError> {
137-
validate_password_user_key(self.client, password, encrypted_user_key)
137+
validate_password_user_key(&self.client, password, encrypted_user_key)
138138
}
139139

140140
pub fn validate_pin(
141141
&self,
142142
pin: String,
143143
pin_protected_user_key: EncString,
144144
) -> Result<bool, AuthValidateError> {
145-
validate_pin(self.client, pin, pin_protected_user_key)
145+
validate_pin(&self.client, pin, pin_protected_user_key)
146146
}
147147

148148
pub fn new_auth_request(&self, email: &str) -> Result<AuthRequestResponse, CryptoError> {
@@ -153,24 +153,24 @@ impl AuthClient<'_> {
153153
&self,
154154
public_key: String,
155155
) -> Result<AsymmetricEncString, ApproveAuthRequestError> {
156-
approve_auth_request(self.client, public_key)
156+
approve_auth_request(&self.client, public_key)
157157
}
158158

159159
pub fn trust_device(&self) -> Result<TrustDeviceResponse, TrustDeviceError> {
160-
trust_device(self.client)
160+
trust_device(&self.client)
161161
}
162162
}
163163

164164
#[cfg(feature = "internal")]
165-
impl AuthClient<'_> {
165+
impl AuthClient {
166166
pub async fn login_device(
167167
&self,
168168
email: String,
169169
device_identifier: String,
170170
) -> Result<NewAuthRequestResponse, LoginError> {
171171
use crate::auth::login::send_new_auth_request;
172172

173-
send_new_auth_request(self.client, email, device_identifier).await
173+
send_new_auth_request(&self.client, email, device_identifier).await
174174
}
175175

176176
pub async fn login_device_complete(
@@ -179,7 +179,7 @@ impl AuthClient<'_> {
179179
) -> Result<(), LoginError> {
180180
use crate::auth::login::complete_auth_request;
181181

182-
complete_auth_request(self.client, auth_req).await
182+
complete_auth_request(&self.client, auth_req).await
183183
}
184184
}
185185

@@ -205,9 +205,11 @@ fn trust_device(client: &Client) -> Result<TrustDeviceResponse, TrustDeviceError
205205
Ok(DeviceKey::trust_device(user_key)?)
206206
}
207207

208-
impl<'a> Client {
209-
pub fn auth(&'a self) -> AuthClient<'a> {
210-
AuthClient { client: self }
208+
impl Client {
209+
pub fn auth(&self) -> AuthClient {
210+
AuthClient {
211+
client: self.clone(),
212+
}
211213
}
212214
}
213215

crates/bitwarden-core/src/client/client.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,14 @@ use crate::client::{
1212
};
1313

1414
/// The main struct to interact with the Bitwarden SDK.
15-
#[derive(Debug)]
15+
#[derive(Debug, Clone)]
1616
pub struct Client {
17+
// Important: The [`Client`] struct requires its `Clone` implementation to return an owned
18+
// reference to the same instance. This is required to properly use the FFI API, where we can't
19+
// just use normal Rust references effectively. For this to happen, any mutable state needs
20+
// to be behind an Arc, ideally as part of the existing [`InternalClient`] struct.
1721
#[doc(hidden)]
18-
pub internal: InternalClient,
22+
pub internal: Arc<InternalClient>,
1923
}
2024

2125
impl Client {
@@ -70,7 +74,7 @@ impl Client {
7074
};
7175

7276
Self {
73-
internal: InternalClient {
77+
internal: Arc::new(InternalClient {
7478
tokens: RwLock::new(Tokens::default()),
7579
login_method: RwLock::new(None),
7680
#[cfg(feature = "internal")]
@@ -82,7 +86,7 @@ impl Client {
8286
})),
8387
external_client,
8488
key_store: KeyStore::default(),
85-
},
89+
}),
8690
}
8791
}
8892
}

crates/bitwarden-core/src/mobile/client_kdf.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ use bitwarden_crypto::{CryptoError, HashPurpose, Kdf};
22

33
use crate::{mobile::kdf::hash_password, Client};
44

5-
pub struct ClientKdf<'a> {
6-
pub(crate) _client: &'a crate::Client,
5+
pub struct ClientKdf {
6+
pub(crate) _client: crate::Client,
77
}
88

9-
impl ClientKdf<'_> {
9+
impl ClientKdf {
1010
pub async fn hash_password(
1111
&self,
1212
email: String,
@@ -18,8 +18,10 @@ impl ClientKdf<'_> {
1818
}
1919
}
2020

21-
impl<'a> Client {
22-
pub fn kdf(&'a self) -> ClientKdf<'a> {
23-
ClientKdf { _client: self }
21+
impl Client {
22+
pub fn kdf(&self) -> ClientKdf {
23+
ClientKdf {
24+
_client: self.clone(),
25+
}
2426
}
2527
}

0 commit comments

Comments
 (0)