1
use std::collections::HashMap;
2
use std::marker::PhantomData;
3
use std::net::{Ipv6Addr, SocketAddr, SocketAddrV6};
4
use std::path::Path;
5
use std::sync::Arc;
6

            
7
use bonsaidb_core::api;
8
use bonsaidb_core::api::ApiName;
9
#[cfg(feature = "encryption")]
10
use bonsaidb_core::document::KeyId;
11
use bonsaidb_core::permissions::{Permissions, Statement};
12
use bonsaidb_core::schema::Schema;
13
#[cfg(feature = "compression")]
14
use bonsaidb_local::config::Compression;
15
use bonsaidb_local::config::{Builder, KeyValuePersistence, StorageConfiguration};
16
#[cfg(feature = "encryption")]
17
use bonsaidb_local::vault::AnyVaultKeyStorage;
18

            
19
use crate::api::{AnyHandler, AnyWrapper, Handler};
20
use crate::{Backend, Error, NoBackend};
21

            
22
/// Configuration options for [`Server`](crate::Server)
23
#[derive(Debug, Clone)]
24
#[must_use]
25
#[non_exhaustive]
26
pub struct ServerConfiguration<B: Backend = NoBackend> {
27
    /// The [`Backend`] for the server.
28
    pub backend: B,
29
    /// The DNS name of the server.
30
    pub server_name: String,
31
    /// Number of sumultaneous requests a single client can have in flight at a
32
    /// time. Default value is 16. It is important to have this number be tuned
33
    /// relative to `request_workers` such that one client cannot overwhelm the
34
    /// entire queue.
35
    pub client_simultaneous_request_limit: usize,
36
    /// Number of simultaneous requests to be processed. Default value is 16.
37
    pub request_workers: usize,
38
    /// Configuration options for individual databases.
39
    pub storage: StorageConfiguration,
40
    /// The permissions granted to all connections to this server.
41
    pub default_permissions: DefaultPermissions,
42
    /// The ACME settings for automatic TLS certificate management.
43
    #[cfg(feature = "acme")]
44
    pub acme: AcmeConfiguration,
45

            
46
    pub(crate) custom_apis: HashMap<ApiName, Arc<dyn AnyHandler<B>>>,
47
}
48

            
49
impl<B: Backend> ServerConfiguration<B> {
50
    /// Returns a default configuration for the given backend.
51
620
    pub fn default_for(backend: B) -> Self {
52
620
        Self {
53
620
            backend,
54
620
            server_name: String::from("bonsaidb"),
55
620
            client_simultaneous_request_limit: 16,
56
620
            // TODO this was arbitrarily picked, it probably should be higher,
57
620
            // but it also should probably be based on the cpu's capabilities
58
620
            request_workers: 16,
59
620
            storage: bonsaidb_local::config::StorageConfiguration::default(),
60
620
            default_permissions: DefaultPermissions::Permissions(Permissions::default()),
61
620
            custom_apis: HashMap::default(),
62
620
            #[cfg(feature = "acme")]
63
620
            acme: AcmeConfiguration::default(),
64
620
        }
65
620
    }
66

            
67
    /// Returns a default configuration for the given backend and path.
68
    pub fn new_with_backend<P: AsRef<Path>>(path: P, backend: B) -> Self {
69
        Self::default_for(backend).path(path)
70
    }
71

            
72
    /// Sets [`Self::server_name`](Self#structfield.server_name) to `server_name` and returns self.
73
38
    pub fn server_name(mut self, server_name: impl Into<String>) -> Self {
74
38
        self.server_name = server_name.into();
75
38
        self
76
38
    }
77

            
78
    /// Sets [`Self::client_simultaneous_request_limit`](Self#structfield.client_simultaneous_request_limit) to `request_limit` and returns self.
79
    pub const fn client_simultaneous_request_limit(mut self, request_limit: usize) -> Self {
80
        self.client_simultaneous_request_limit = request_limit;
81
        self
82
    }
83

            
84
    /// Sets [`Self::request_workers`](Self#structfield.request_workers) to `workers` and returns self.
85
    pub const fn request_workers(mut self, workers: usize) -> Self {
86
        self.request_workers = workers;
87
        self
88
    }
89

            
90
    /// Sets [`Self::default_permissions`](Self#structfield.default_permissions) to `default_permissions` and returns self.
91
92
    pub fn default_permissions<P: Into<DefaultPermissions>>(
92
92
        mut self,
93
92
        default_permissions: P,
94
92
    ) -> Self {
95
92
        self.default_permissions = default_permissions.into();
96
92
        self
97
92
    }
98

            
99
    /// Sets [`AcmeConfiguration::contact_email`] to `contact_email` and returns self.
100
    #[cfg(feature = "acme")]
101
    pub fn acme_contact_email(mut self, contact_email: impl Into<String>) -> Self {
102
        self.acme.contact_email = Some(contact_email.into());
103
        self
104
    }
105

            
106
    /// Sets [`AcmeConfiguration::directory`] to `directory` and returns self.
107
    #[cfg(feature = "acme")]
108
    pub fn acme_directory(mut self, directory: impl Into<String>) -> Self {
109
        self.acme.directory = directory.into();
110
        self
111
    }
112

            
113
    /// Registers a `handler` for a [`Api`][api::Api]. When an [`Api`][api::Api] is
114
    /// received by the server, the handler will be invoked
115
3224
    pub fn register_custom_api<Dispatcher: Handler<Api, B> + 'static, Api: api::Api>(
116
3224
        &mut self,
117
3224
    ) -> Result<(), Error> {
118
3224
        // TODO this should error on duplicate registration.
119
3224
        self.custom_apis.insert(
120
3224
            Api::name(),
121
3224
            Arc::new(AnyWrapper::<Dispatcher, B, Api>(PhantomData)),
122
3224
        );
123
3224
        Ok(())
124
3224
    }
125

            
126
    /// Registers the custom api dispatcher and returns self.
127
3224
    pub fn with_api<Dispatcher: Handler<Api, B> + 'static, Api: api::Api>(
128
3224
        mut self,
129
3224
    ) -> Result<Self, Error> {
130
3224
        self.register_custom_api::<Dispatcher, Api>()?;
131
3224
        Ok(self)
132
3224
    }
133
}
134

            
135
impl<B> Default for ServerConfiguration<B>
136
where
137
    B: Backend + Default,
138
{
139
620
    fn default() -> Self {
140
620
        Self::default_for(B::default())
141
620
    }
142
}
143

            
144
#[cfg(feature = "acme")]
145
mod acme {
146
    /// The Automated Certificate Management Environment (ACME) configuration.
147
    #[derive(Debug, Clone)]
148
    pub struct AcmeConfiguration {
149
        /// The contact email to register with the ACME directory for the account.
150
        pub contact_email: Option<String>,
151
        /// The ACME directory to use for registration. The default is
152
        /// [`LETS_ENCRYPT_PRODUCTION_DIRECTORY`].
153
        pub directory: String,
154
    }
155

            
156
    impl Default for AcmeConfiguration {
157
807
        fn default() -> Self {
158
807
            Self {
159
807
                contact_email: None,
160
807
                directory: LETS_ENCRYPT_PRODUCTION_DIRECTORY.to_string(),
161
807
            }
162
807
        }
163
    }
164

            
165
    pub use async_acme::acme::{LETS_ENCRYPT_PRODUCTION_DIRECTORY, LETS_ENCRYPT_STAGING_DIRECTORY};
166
}
167

            
168
#[cfg(feature = "acme")]
169
pub use acme::*;
170

            
171
/// The default permissions to use for all connections to the server.
172
#[derive(Debug, Clone)]
173
pub enum DefaultPermissions {
174
    /// Allow all permissions. Do not use outside of completely trusted environments.
175
    AllowAll,
176
    /// A defined set of permissions.
177
    Permissions(Permissions),
178
}
179

            
180
impl From<DefaultPermissions> for Permissions {
181
821
    fn from(permissions: DefaultPermissions) -> Self {
182
821
        match permissions {
183
70
            DefaultPermissions::Permissions(permissions) => permissions,
184
751
            DefaultPermissions::AllowAll => Self::allow_all(),
185
        }
186
821
    }
187
}
188

            
189
impl From<Permissions> for DefaultPermissions {
190
70
    fn from(permissions: Permissions) -> Self {
191
70
        Self::Permissions(permissions)
192
70
    }
193
}
194

            
195
impl From<Vec<Statement>> for DefaultPermissions {
196
    fn from(permissions: Vec<Statement>) -> Self {
197
        Self::from(Permissions::from(permissions))
198
    }
199
}
200

            
201
impl From<Statement> for DefaultPermissions {
202
    fn from(permissions: Statement) -> Self {
203
        Self::from(Permissions::from(permissions))
204
    }
205
}
206

            
207
impl<B: Backend> Builder for ServerConfiguration<B> {
208
90
    fn with_schema<S: Schema>(mut self) -> Result<Self, bonsaidb_local::Error> {
209
90
        self.storage.register_schema::<S>()?;
210
90
        Ok(self)
211
90
    }
212

            
213
    fn memory_only(mut self) -> Self {
214
        self.storage.memory_only = true;
215
        self
216
    }
217

            
218
92
    fn path<P: AsRef<Path>>(mut self, path: P) -> Self {
219
92
        self.storage.path = Some(path.as_ref().to_owned());
220
92
        self
221
92
    }
222

            
223
    fn unique_id(mut self, unique_id: u64) -> Self {
224
        self.storage.unique_id = Some(unique_id);
225
        self
226
    }
227

            
228
    #[cfg(feature = "encryption")]
229
    fn vault_key_storage<VaultKeyStorage: AnyVaultKeyStorage>(
230
        mut self,
231
        key_storage: VaultKeyStorage,
232
    ) -> Self {
233
        self.storage.vault_key_storage = Some(std::sync::Arc::new(key_storage));
234
        self
235
    }
236

            
237
    #[cfg(feature = "encryption")]
238
    fn default_encryption_key(mut self, key: KeyId) -> Self {
239
        self.storage.default_encryption_key = Some(key);
240
        self
241
    }
242

            
243
    fn tasks_worker_count(mut self, worker_count: usize) -> Self {
244
        self.storage.workers.worker_count = worker_count;
245
        self
246
    }
247

            
248
    fn tasks_parallelization(mut self, parallelization: usize) -> Self {
249
        self.storage.workers.parallelization = parallelization;
250
        self
251
    }
252

            
253
    fn check_view_integrity_on_open(mut self, check: bool) -> Self {
254
        self.storage.views.check_integrity_on_open = check;
255
        self
256
    }
257

            
258
    #[cfg(feature = "compression")]
259
42
    fn default_compression(mut self, compression: Compression) -> Self {
260
42
        self.storage.default_compression = Some(compression);
261
42
        self
262
42
    }
263

            
264
18
    fn key_value_persistence(mut self, persistence: KeyValuePersistence) -> Self {
265
18
        self.storage.key_value_persistence = persistence;
266
18
        self
267
18
    }
268

            
269
2
    fn authenticated_permissions<P: Into<Permissions>>(
270
2
        mut self,
271
2
        authenticated_permissions: P,
272
2
    ) -> Self {
273
2
        self.storage.authenticated_permissions = authenticated_permissions.into();
274
2
        self
275
2
    }
276

            
277
    #[cfg(feature = "password-hashing")]
278
    fn argon(mut self, argon: bonsaidb_local::config::ArgonConfiguration) -> Self {
279
        self.storage.argon = argon;
280
        self
281
    }
282
}
283

            
284
/// Configuration for the BonsaiDb network protocol.
285
///
286
/// The BonsaiDb network protocol is built using QUIC, which uses UDP instead of
287
/// TCP.
288
#[derive(Clone, Copy, Debug)]
289
#[non_exhaustive]
290
pub struct BonsaiListenConfig {
291
    /// The socket port to listen for connections on.
292
    ///
293
    /// By default, this is `[::]:5645`.
294
    pub address: SocketAddr,
295

            
296
    /// If this is set to true, the `SO_REUSEADDR` flag will be set on the
297
    /// listening socket.
298
    ///
299
    /// This informs the operating system that it should allow reusing the exact
300
    /// same address/port combination in the future, which enables restarting a
301
    /// BonsaiDb network protocol listener without restarting the process
302
    /// itself. In general, this is not needed for users in regular deployments,
303
    /// and is more useful for specific kinds of testing.
304
    pub reuse_address: bool,
305
}
306

            
307
impl Default for BonsaiListenConfig {
308
364
    fn default() -> Self {
309
364
        Self {
310
364
            address: SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 5645, 0, 0)),
311
364
            reuse_address: false,
312
364
        }
313
364
    }
314
}
315

            
316
impl BonsaiListenConfig {
317
    /// Sets the port for the socket address, and returns the updated config.
318
    #[must_use]
319
350
    pub fn port(mut self, port: u16) -> Self {
320
350
        self.address.set_port(port);
321
350
        self
322
350
    }
323

            
324
    /// Sets the [`reuse_address`](Self::reuse_address) flag.
325
    #[must_use]
326
28
    pub const fn reuse_address(mut self, reuse_address: bool) -> Self {
327
28
        self.reuse_address = reuse_address;
328
28
        self
329
28
    }
330
}
331

            
332
impl From<u16> for BonsaiListenConfig {
333
350
    fn from(value: u16) -> Self {
334
350
        Self::default().port(value)
335
350
    }
336
}