1
use std::{collections::HashMap, marker::PhantomData, path::Path, sync::Arc};
2

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

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

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

            
43
    pub(crate) custom_apis: HashMap<ApiName, Arc<dyn AnyHandler<B>>>,
44
}
45

            
46
impl<B: Backend> ServerConfiguration<B> {
47
    /// Sets [`Self::server_name`](Self#structfield.server_name) to `server_name` and returns self.
48
33
    pub fn server_name(mut self, server_name: impl Into<String>) -> Self {
49
33
        self.server_name = server_name.into();
50
33
        self
51
33
    }
52

            
53
    /// Sets [`Self::client_simultaneous_request_limit`](Self#structfield.client_simultaneous_request_limit) to `request_limit` and returns self.
54
    pub fn client_simultaneous_request_limit(mut self, request_limit: usize) -> Self {
55
        self.client_simultaneous_request_limit = request_limit;
56
        self
57
    }
58

            
59
    /// Sets [`Self::request_workers`](Self#structfield.request_workers) to `workers` and returns self.
60
    pub fn request_workers(mut self, workers: usize) -> Self {
61
        self.request_workers = workers;
62
        self
63
    }
64

            
65
    /// Sets [`Self::default_permissions`](Self#structfield.default_permissions) to `default_permissions` and returns self.
66
82
    pub fn default_permissions<P: Into<DefaultPermissions>>(
67
82
        mut self,
68
82
        default_permissions: P,
69
82
    ) -> Self {
70
82
        self.default_permissions = default_permissions.into();
71
82
        self
72
82
    }
73

            
74
    /// Sets [`AcmeConfiguration::contact_email`] to `contact_email` and returns self.
75
    #[cfg(feature = "acme")]
76
    pub fn acme_contact_email(mut self, contact_email: impl Into<String>) -> Self {
77
        self.acme.contact_email = Some(contact_email.into());
78
        self
79
    }
80

            
81
    /// Sets [`AcmeConfiguration::directory`] to `directory` and returns self.
82
    #[cfg(feature = "acme")]
83
    pub fn acme_directory(mut self, directory: impl Into<String>) -> Self {
84
        self.acme.directory = directory.into();
85
        self
86
    }
87

            
88
    /// Registers a `handler` for a [`Api`][api::Api]. When an [`Api`][api::Api] is
89
    /// received by the server, the handler will be invoked
90
2873
    pub fn register_custom_api<Dispatcher: Handler<B, Api> + 'static, Api: api::Api>(
91
2873
        &mut self,
92
2873
    ) -> Result<(), Error> {
93
2873
        // TODO this should error on duplicate registration.
94
2873
        self.custom_apis.insert(
95
2873
            Api::name(),
96
2873
            Arc::new(AnyWrapper::<Dispatcher, B, Api>(PhantomData)),
97
2873
        );
98
2873
        Ok(())
99
2873
    }
100

            
101
    /// Registers the custom api dispatcher and returns self.
102
    pub fn with_api<Dispatcher: Handler<B, Api> + 'static, Api: api::Api>(
103
        mut self,
104
    ) -> Result<Self, Error> {
105
2873
        self.register_custom_api::<Dispatcher, Api>()?;
106
2873
        Ok(self)
107
2873
    }
108
}
109

            
110
impl<B: Backend> Default for ServerConfiguration<B> {
111
492
    fn default() -> Self {
112
492
        Self {
113
492
            server_name: String::from("bonsaidb"),
114
492
            client_simultaneous_request_limit: 16,
115
492
            // TODO this was arbitrarily picked, it probably should be higher,
116
492
            // but it also should probably be based on the cpu's capabilities
117
492
            request_workers: 16,
118
492
            storage: bonsaidb_local::config::StorageConfiguration::default(),
119
492
            default_permissions: DefaultPermissions::Permissions(Permissions::default()),
120
492
            custom_apis: HashMap::default(),
121
492
            #[cfg(feature = "acme")]
122
492
            acme: AcmeConfiguration::default(),
123
492
        }
124
492
    }
125
}
126

            
127
#[cfg(feature = "acme")]
128
mod acme {
129
    /// The Automated Certificate Management Environment (ACME) configuration.
130
    #[derive(Debug, Clone)]
131
    pub struct AcmeConfiguration {
132
        /// The contact email to register with the ACME directory for the account.
133
        pub contact_email: Option<String>,
134
        /// The ACME directory to use for registration. The default is
135
        /// [`LETS_ENCRYPT_PRODUCTION_DIRECTORY`].
136
        pub directory: String,
137
    }
138

            
139
    impl Default for AcmeConfiguration {
140
670
        fn default() -> Self {
141
670
            Self {
142
670
                contact_email: None,
143
670
                directory: LETS_ENCRYPT_PRODUCTION_DIRECTORY.to_string(),
144
670
            }
145
670
        }
146
    }
147

            
148
    pub use async_acme::acme::{LETS_ENCRYPT_PRODUCTION_DIRECTORY, LETS_ENCRYPT_STAGING_DIRECTORY};
149
}
150

            
151
#[cfg(feature = "acme")]
152
pub use acme::*;
153

            
154
/// The default permissions to use for all connections to the server.
155
#[derive(Debug, Clone)]
156
pub enum DefaultPermissions {
157
    /// Allow all permissions. Do not use outside of completely trusted environments.
158
    AllowAll,
159
    /// A defined set of permissions.
160
    Permissions(Permissions),
161
}
162

            
163
impl From<DefaultPermissions> for Permissions {
164
683
    fn from(permissions: DefaultPermissions) -> Self {
165
683
        match permissions {
166
52
            DefaultPermissions::Permissions(permissions) => permissions,
167
631
            DefaultPermissions::AllowAll => Self::allow_all(),
168
        }
169
683
    }
170
}
171

            
172
impl From<Permissions> for DefaultPermissions {
173
52
    fn from(permissions: Permissions) -> Self {
174
52
        Self::Permissions(permissions)
175
52
    }
176
}
177

            
178
impl<B: Backend> Builder for ServerConfiguration<B> {
179
    fn with_schema<S: Schema>(mut self) -> Result<Self, bonsaidb_local::Error> {
180
81
        self.storage.register_schema::<S>()?;
181
81
        Ok(self)
182
81
    }
183

            
184
    fn memory_only(mut self) -> Self {
185
        self.storage.memory_only = true;
186
        self
187
    }
188

            
189
82
    fn path<P: AsRef<Path>>(mut self, path: P) -> Self {
190
82
        self.storage.path = Some(path.as_ref().to_owned());
191
82
        self
192
82
    }
193

            
194
    fn unique_id(mut self, unique_id: u64) -> Self {
195
        self.storage.unique_id = Some(unique_id);
196
        self
197
    }
198

            
199
    #[cfg(feature = "encryption")]
200
    fn vault_key_storage<VaultKeyStorage: AnyVaultKeyStorage>(
201
        mut self,
202
        key_storage: VaultKeyStorage,
203
    ) -> Self {
204
        self.storage.vault_key_storage = Some(std::sync::Arc::new(key_storage));
205
        self
206
    }
207

            
208
    #[cfg(feature = "encryption")]
209
    fn default_encryption_key(mut self, key: KeyId) -> Self {
210
        self.storage.default_encryption_key = Some(key);
211
        self
212
    }
213

            
214
    fn tasks_worker_count(mut self, worker_count: usize) -> Self {
215
        self.storage.workers.worker_count = worker_count;
216
        self
217
    }
218

            
219
    fn tasks_parallelization(mut self, parallelization: usize) -> Self {
220
        self.storage.workers.parallelization = parallelization;
221
        self
222
    }
223

            
224
    fn check_view_integrity_on_open(mut self, check: bool) -> Self {
225
        self.storage.views.check_integrity_on_open = check;
226
        self
227
    }
228

            
229
    #[cfg(feature = "compression")]
230
38
    fn default_compression(mut self, compression: Compression) -> Self {
231
38
        self.storage.default_compression = Some(compression);
232
38
        self
233
38
    }
234

            
235
18
    fn key_value_persistence(mut self, persistence: KeyValuePersistence) -> Self {
236
18
        self.storage.key_value_persistence = persistence;
237
18
        self
238
18
    }
239

            
240
2
    fn authenticated_permissions<P: Into<Permissions>>(
241
2
        mut self,
242
2
        authenticated_permissions: P,
243
2
    ) -> Self {
244
2
        self.storage.authenticated_permissions = authenticated_permissions.into();
245
2
        self
246
2
    }
247

            
248
    #[cfg(feature = "password-hashing")]
249
    fn argon(mut self, argon: bonsaidb_local::config::ArgonConfiguration) -> Self {
250
        self.storage.argon = argon;
251
        self
252
    }
253
}