Skip to content

Commit 3c5ad68

Browse files
authored
RUST-1411 Move create_encrypted_collection helper to ClientEncryption (#858)
1 parent d551dab commit 3c5ad68

File tree

4 files changed

+68
-84
lines changed

4 files changed

+68
-84
lines changed

src/client/csfle/client_encryption.rs

+53
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@ use crate::{
2121
},
2222
client::options::TlsOptions,
2323
coll::options::CollectionOptions,
24+
db::options::CreateCollectionOptions,
2425
error::{Error, Result},
2526
options::{ReadConcern, WriteConcern},
2627
results::DeleteResult,
2728
Client,
2829
Collection,
2930
Cursor,
31+
Database,
3032
Namespace,
3133
};
3234

@@ -410,6 +412,57 @@ impl ClientEncryption {
410412
.ok_or_else(|| Error::internal("invalid decryption result"))?
411413
.to_raw_bson())
412414
}
415+
416+
/// Creates a new collection with encrypted fields, automatically creating new data encryption
417+
/// keys when needed based on the configured [`CreateCollectionOptions::encrypted_fields`].
418+
///
419+
/// Returns the potentially updated `encrypted_fields` along with status, as keys may have been
420+
/// created even when a failure occurs.
421+
///
422+
/// Does not affect any auto encryption settings on existing MongoClients that are already
423+
/// configured with auto encryption.
424+
pub async fn create_encrypted_collection(
425+
&self,
426+
db: &Database,
427+
name: impl AsRef<str>,
428+
master_key: MasterKey,
429+
options: CreateCollectionOptions,
430+
) -> (Document, Result<()>) {
431+
let ef = match options.encrypted_fields.as_ref() {
432+
Some(ef) => ef,
433+
None => {
434+
return (
435+
doc! {},
436+
Err(Error::invalid_argument(
437+
"no encrypted_fields defined for collection",
438+
)),
439+
);
440+
}
441+
};
442+
let mut ef_prime = ef.clone();
443+
if let Ok(fields) = ef_prime.get_array_mut("fields") {
444+
for f in fields {
445+
let f_doc = if let Some(d) = f.as_document_mut() {
446+
d
447+
} else {
448+
continue;
449+
};
450+
if f_doc.get("keyId") == Some(&Bson::Null) {
451+
let d = match self.create_data_key(master_key.clone()).run().await {
452+
Ok(v) => v,
453+
Err(e) => return (ef_prime, Err(e)),
454+
};
455+
f_doc.insert("keyId", d);
456+
}
457+
}
458+
}
459+
let mut opts_prime = options.clone();
460+
opts_prime.encrypted_fields = Some(ef_prime.clone());
461+
(
462+
ef_prime,
463+
db.create_collection(name.as_ref(), opts_prime).await,
464+
)
465+
}
413466
}
414467

415468
/// Options for creating a data key.

src/db/mod.rs

-52
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ use std::{fmt::Debug, sync::Arc};
66
use bson::doc;
77
use futures_util::stream::TryStreamExt;
88

9-
#[cfg(feature = "in-use-encryption-unstable")]
10-
use crate::client_encryption::{ClientEncryption, MasterKey};
119
use crate::{
1210
bson::{Bson, Document},
1311
change_stream::{
@@ -423,56 +421,6 @@ impl Database {
423421
self.create_collection_common(name, options, session).await
424422
}
425423

426-
/// Creates a new collection with encrypted fields, automatically creating new data encryption
427-
/// keys when needed based on the configured [`CreateCollectionOptions::encrypted_fields`].
428-
///
429-
/// Returns the potentially updated `encrypted_fields` along with status, as keys may have been
430-
/// created even when a failure occurs.
431-
///
432-
/// Does not affect any auto encryption settings on existing MongoClients that are already
433-
/// configured with auto encryption.
434-
#[cfg(feature = "in-use-encryption-unstable")]
435-
pub async fn create_encrypted_collection(
436-
&self,
437-
ce: &ClientEncryption,
438-
name: impl AsRef<str>,
439-
options: impl Into<Option<CreateCollectionOptions>>,
440-
master_key: MasterKey,
441-
) -> (Document, Result<()>) {
442-
let options: Option<CreateCollectionOptions> = options.into();
443-
let ef = match options.as_ref().and_then(|o| o.encrypted_fields.as_ref()) {
444-
Some(ef) => ef,
445-
None => {
446-
return (
447-
doc! {},
448-
Err(Error::invalid_argument(
449-
"no encrypted_fields defined for collection",
450-
)),
451-
);
452-
}
453-
};
454-
let mut ef_prime = ef.clone();
455-
if let Ok(fields) = ef_prime.get_array_mut("fields") {
456-
for f in fields {
457-
let f_doc = if let Some(d) = f.as_document_mut() {
458-
d
459-
} else {
460-
continue;
461-
};
462-
if f_doc.get("keyId") == Some(&Bson::Null) {
463-
let d = match ce.create_data_key(master_key.clone()).run().await {
464-
Ok(v) => v,
465-
Err(e) => return (ef_prime, Err(e)),
466-
};
467-
f_doc.insert("keyId", d);
468-
}
469-
}
470-
}
471-
let mut opts_prime = options.unwrap().clone(); // safe unwrap: no options would be caught by the encrypted_fields check
472-
opts_prime.encrypted_fields = Some(ef_prime.clone());
473-
(ef_prime, self.create_collection(name, opts_prime).await)
474-
}
475-
476424
pub(crate) async fn run_command_common(
477425
&self,
478426
command: Document,

src/sync/db.rs

-22
Original file line numberDiff line numberDiff line change
@@ -219,28 +219,6 @@ impl Database {
219219
))
220220
}
221221

222-
/// Creates a new collection with encrypted fields, automatically creating new data encryption
223-
/// keys when needed based on the configured [`CreateCollectionOptions::encrypted_fields`].
224-
///
225-
/// Returns the potentially updated `encrypted_fields` along with status, as keys may have been
226-
/// created even when a failure occurs.
227-
///
228-
/// Does not affect any auto encryption settings on existing MongoClients that are already
229-
/// configured with auto encryption.
230-
#[cfg(feature = "in-use-encryption-unstable")]
231-
pub fn create_encrypted_collection(
232-
&self,
233-
ce: &crate::client_encryption::ClientEncryption,
234-
name: impl AsRef<str>,
235-
options: impl Into<Option<CreateCollectionOptions>>,
236-
master_key: crate::client_encryption::MasterKey,
237-
) -> (Document, Result<()>) {
238-
runtime::block_on(
239-
self.async_database
240-
.create_encrypted_collection(ce, name, options, master_key),
241-
)
242-
}
243-
244222
/// Runs a database-level command.
245223
///
246224
/// Note that no inspection is done on `doc`, so the command will not use the database's default

src/test/csfle.rs

+15-10
Original file line numberDiff line numberDiff line change
@@ -2928,7 +2928,7 @@ async fn auto_encryption_keys(master_key: MasterKey) -> Result<()> {
29282928
)?;
29292929

29302930
// Case 1: Simple Creation and Validation
2931-
let opts = CreateCollectionOptions::builder()
2931+
let options = CreateCollectionOptions::builder()
29322932
.encrypted_fields(doc! {
29332933
"fields": [{
29342934
"path": "ssn",
@@ -2937,7 +2937,7 @@ async fn auto_encryption_keys(master_key: MasterKey) -> Result<()> {
29372937
}],
29382938
})
29392939
.build();
2940-
db.create_encrypted_collection(&ce, "case_1", opts, master_key.clone())
2940+
ce.create_encrypted_collection(&db, "case_1", master_key.clone(), options)
29412941
.await
29422942
.1?;
29432943
let coll = db.collection::<Document>("case_1");
@@ -2949,8 +2949,13 @@ async fn auto_encryption_keys(master_key: MasterKey) -> Result<()> {
29492949
);
29502950

29512951
// Case 2: Missing encryptedFields
2952-
let result = db
2953-
.create_encrypted_collection(&ce, "case_2", None, master_key.clone())
2952+
let result = ce
2953+
.create_encrypted_collection(
2954+
&db,
2955+
"case_2",
2956+
master_key.clone(),
2957+
CreateCollectionOptions::default(),
2958+
)
29542959
.await
29552960
.1;
29562961
assert!(
@@ -2960,7 +2965,7 @@ async fn auto_encryption_keys(master_key: MasterKey) -> Result<()> {
29602965
);
29612966

29622967
// Case 3: Invalid keyId
2963-
let opts = CreateCollectionOptions::builder()
2968+
let options = CreateCollectionOptions::builder()
29642969
.encrypted_fields(doc! {
29652970
"fields": [{
29662971
"path": "ssn",
@@ -2969,8 +2974,8 @@ async fn auto_encryption_keys(master_key: MasterKey) -> Result<()> {
29692974
}],
29702975
})
29712976
.build();
2972-
let result = db
2973-
.create_encrypted_collection(&ce, "case_1", opts, master_key.clone())
2977+
let result = ce
2978+
.create_encrypted_collection(&db, "case_1", master_key.clone(), options)
29742979
.await
29752980
.1;
29762981
assert!(
@@ -2980,7 +2985,7 @@ async fn auto_encryption_keys(master_key: MasterKey) -> Result<()> {
29802985
);
29812986

29822987
// Case 4: Insert encrypted value
2983-
let opts = CreateCollectionOptions::builder()
2988+
let options = CreateCollectionOptions::builder()
29842989
.encrypted_fields(doc! {
29852990
"fields": [{
29862991
"path": "ssn",
@@ -2989,8 +2994,8 @@ async fn auto_encryption_keys(master_key: MasterKey) -> Result<()> {
29892994
}],
29902995
})
29912996
.build();
2992-
let (ef, result) = db
2993-
.create_encrypted_collection(&ce, "case_4", opts, master_key.clone())
2997+
let (ef, result) = ce
2998+
.create_encrypted_collection(&db, "case_4", master_key.clone(), options)
29942999
.await;
29953000
result?;
29963001
let key = match ef.get_array("fields")?[0]

0 commit comments

Comments
 (0)