Skip to content

Commit 4a71a26

Browse files
RUST-352 Support for 'authorizedDatabases' option (#165)
1 parent 09d4ce6 commit 4a71a26

File tree

9 files changed

+176
-30
lines changed

9 files changed

+176
-30
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ client_options.app_name = Some("My App".to_string());
4949
let client = Client::with_options(client_options)?;
5050

5151
// List the names of the databases in that deployment.
52-
for db_name in client.list_database_names(None)? {
52+
for db_name in client.list_database_names(None, None)? {
5353
println!("{}", db_name);
5454
}
5555
```

src/client/mod.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@ use crate::{
1717
error::{ErrorKind, Result},
1818
event::command::CommandEventHandler,
1919
operation::ListDatabases,
20-
options::{ClientOptions, DatabaseOptions, ReadPreference, SelectionCriteria},
20+
options::{
21+
ClientOptions,
22+
DatabaseOptions,
23+
ListDatabasesOptions,
24+
ReadPreference,
25+
SelectionCriteria,
26+
},
2127
sdam::{Server, Topology},
2228
};
2329

@@ -133,17 +139,19 @@ impl Client {
133139
pub async fn list_databases(
134140
&self,
135141
filter: impl Into<Option<Document>>,
142+
options: impl Into<Option<ListDatabasesOptions>>,
136143
) -> Result<Vec<Document>> {
137-
let op = ListDatabases::new(filter.into(), false);
144+
let op = ListDatabases::new(filter.into(), false, options.into());
138145
self.execute_operation(&op, None).await
139146
}
140147

141148
/// Gets the names of the databases present in the cluster the Client is connected to.
142149
pub async fn list_database_names(
143150
&self,
144151
filter: impl Into<Option<Document>>,
152+
options: impl Into<Option<ListDatabasesOptions>>,
145153
) -> Result<Vec<String>> {
146-
let op = ListDatabases::new(filter.into(), true);
154+
let op = ListDatabases::new(filter.into(), true, options.into());
147155
match self.execute_operation(&op, None).await {
148156
Ok(databases) => databases
149157
.into_iter()

src/db/options.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,14 @@ pub struct ListCollectionsOptions {
136136
#[serde(serialize_with = "bson_util::serialize_batch_size", rename = "cursor")]
137137
pub batch_size: Option<u32>,
138138
}
139+
140+
/// Specifies the options to a
141+
/// [`Client::list_databases`](../struct.Client.html#method.list_databases) operation.
142+
#[derive(Debug, Default, TypedBuilder, Serialize)]
143+
#[serde(rename_all = "camelCase")]
144+
pub struct ListDatabasesOptions {
145+
/// Determines which databases to return based on the user's access privileges. This option is
146+
/// only supported on server versions 4.0.5+.
147+
#[builder(default)]
148+
pub authorized_databases: Option<bool>,
149+
}

src/operation/list_databases/mod.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,37 @@ use serde::Deserialize;
77
use crate::{
88
cmap::{Command, CommandResponse, StreamDescription},
99
error::Result,
10-
operation::Operation,
10+
operation::{append_options, Operation},
11+
options::ListDatabasesOptions,
1112
selection_criteria::{ReadPreference, SelectionCriteria},
1213
};
1314

1415
#[derive(Debug)]
1516
pub(crate) struct ListDatabases {
1617
filter: Option<Document>,
1718
name_only: bool,
19+
options: Option<ListDatabasesOptions>,
1820
}
1921

2022
impl ListDatabases {
21-
pub fn new(filter: Option<Document>, name_only: bool) -> Self {
22-
ListDatabases { filter, name_only }
23+
pub fn new(
24+
filter: Option<Document>,
25+
name_only: bool,
26+
options: Option<ListDatabasesOptions>,
27+
) -> Self {
28+
ListDatabases {
29+
filter,
30+
name_only,
31+
options,
32+
}
2333
}
2434

2535
#[cfg(test)]
2636
pub(crate) fn empty() -> Self {
2737
ListDatabases {
2838
filter: None,
2939
name_only: false,
40+
options: None,
3041
}
3142
}
3243
}
@@ -45,6 +56,8 @@ impl Operation for ListDatabases {
4556
body.insert("filter", filter.clone());
4657
}
4758

59+
append_options(&mut body, self.options.as_ref())?;
60+
4861
Ok(Command::new(
4962
Self::NAME.to_string(),
5063
"admin".to_string(),

src/operation/list_databases/test.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{
55
cmap::{CommandResponse, StreamDescription},
66
error::ErrorKind,
77
operation::{ListDatabases, Operation},
8+
options::ListDatabasesOptions,
89
selection_criteria::ReadPreference,
910
};
1011

@@ -31,7 +32,7 @@ async fn build() {
3132
async fn build_with_name_only() {
3233
let name_only = true;
3334

34-
let list_databases_op = ListDatabases::new(None, name_only);
35+
let list_databases_op = ListDatabases::new(None, name_only, None);
3536
let list_databases_command = list_databases_op
3637
.build(&StreamDescription::new_testing())
3738
.expect("error on build");
@@ -52,7 +53,7 @@ async fn build_with_name_only() {
5253
async fn build_with_filter() {
5354
let filter = doc! {"something" : "something else"};
5455

55-
let list_databases_op = ListDatabases::new(Some(filter.clone()), false);
56+
let list_databases_op = ListDatabases::new(Some(filter.clone()), false, None);
5657
let list_databases_command = list_databases_op
5758
.build(&StreamDescription::new_testing())
5859
.unwrap();
@@ -68,6 +69,29 @@ async fn build_with_filter() {
6869
assert_eq!(list_databases_command.read_pref, None);
6970
}
7071

72+
#[cfg_attr(feature = "tokio-runtime", tokio::test)]
73+
#[cfg_attr(feature = "async-std-runtime", async_std::test)]
74+
async fn build_with_options() {
75+
let options = ListDatabasesOptions::builder()
76+
.authorized_databases(true)
77+
.build();
78+
79+
let list_databases_op = ListDatabases::new(None, false, Some(options));
80+
let list_databases_command = list_databases_op
81+
.build(&StreamDescription::new_testing())
82+
.unwrap();
83+
assert_eq!(
84+
list_databases_command.body,
85+
doc! {
86+
"listDatabases": 1,
87+
"nameOnly": false,
88+
"authorizedDatabases": true
89+
}
90+
);
91+
assert_eq!(list_databases_command.target_db, "admin");
92+
assert_eq!(list_databases_command.read_pref, None);
93+
}
94+
7195
#[cfg_attr(feature = "tokio-runtime", tokio::test)]
7296
#[cfg_attr(feature = "async-std-runtime", async_std::test)]
7397
async fn handle_success() {

src/sync/client.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use super::Database;
44
use crate::{
55
concern::{ReadConcern, WriteConcern},
66
error::Result,
7-
options::{ClientOptions, DatabaseOptions, SelectionCriteria},
7+
options::{ClientOptions, DatabaseOptions, ListDatabasesOptions, SelectionCriteria},
88
Client as AsyncClient,
99
RUNTIME,
1010
};
@@ -100,12 +100,26 @@ impl Client {
100100
}
101101

102102
/// Gets information about each database present in the cluster the Client is connected to.
103-
pub fn list_databases(&self, filter: impl Into<Option<Document>>) -> Result<Vec<Document>> {
104-
RUNTIME.block_on(self.async_client.list_databases(filter.into()))
103+
pub fn list_databases(
104+
&self,
105+
filter: impl Into<Option<Document>>,
106+
options: impl Into<Option<ListDatabasesOptions>>,
107+
) -> Result<Vec<Document>> {
108+
RUNTIME.block_on(
109+
self.async_client
110+
.list_databases(filter.into(), options.into()),
111+
)
105112
}
106113

107114
/// Gets the names of the databases present in the cluster the Client is connected to.
108-
pub fn list_database_names(&self, filter: impl Into<Option<Document>>) -> Result<Vec<String>> {
109-
RUNTIME.block_on(self.async_client.list_database_names(filter.into()))
115+
pub fn list_database_names(
116+
&self,
117+
filter: impl Into<Option<Document>>,
118+
options: impl Into<Option<ListDatabasesOptions>>,
119+
) -> Result<Vec<String>> {
120+
RUNTIME.block_on(
121+
self.async_client
122+
.list_database_names(filter.into(), options.into()),
123+
)
110124
}
111125
}

src/sync/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fn client() {
3535
.expect("insert should succeed");
3636

3737
let db_names = client
38-
.list_database_names(None)
38+
.list_database_names(None, None)
3939
.expect("list_database_names should succeed");
4040
assert!(db_names.contains(&function_name!().to_string()));
4141
}

0 commit comments

Comments
 (0)