mirror of
https://github.com/stalwartlabs/mail-server.git
synced 2025-09-06 12:04:17 +08:00
148 lines
5.2 KiB
Rust
148 lines
5.2 KiB
Rust
/*
|
|
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
|
*/
|
|
|
|
use deadpool::{
|
|
Runtime,
|
|
managed::{Manager, Pool},
|
|
};
|
|
use std::{sync::Arc, time::Duration};
|
|
use store::{Store, Stores};
|
|
use utils::config::Config;
|
|
|
|
use ahash::AHashMap;
|
|
|
|
use crate::{
|
|
Directories, Directory, DirectoryInner,
|
|
backend::{
|
|
imap::ImapDirectory, ldap::LdapDirectory, memory::MemoryDirectory, oidc::OpenIdDirectory,
|
|
smtp::SmtpDirectory, sql::SqlDirectory,
|
|
},
|
|
};
|
|
|
|
use super::cache::CachedDirectory;
|
|
|
|
impl Directories {
|
|
pub async fn parse(
|
|
config: &mut Config,
|
|
stores: &Stores,
|
|
data_store: Store,
|
|
is_enterprise: bool,
|
|
) -> Self {
|
|
let mut directories = AHashMap::new();
|
|
|
|
for id in config.sub_keys("directory", ".type") {
|
|
// Parse directory
|
|
let id = id.as_str();
|
|
#[cfg(feature = "test_mode")]
|
|
{
|
|
if config
|
|
.property_or_default::<bool>(("directory", id, "disable"), "false")
|
|
.unwrap_or(false)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
let protocol = config
|
|
.value_require(("directory", id, "type"))
|
|
.unwrap()
|
|
.to_string();
|
|
let prefix = ("directory", id);
|
|
let store = match protocol.as_str() {
|
|
"internal" => Some(DirectoryInner::Internal(
|
|
if let Some(store_id) = config.value_require(("directory", id, "store")) {
|
|
if let Some(data) = stores.stores.get(store_id) {
|
|
data.clone()
|
|
} else {
|
|
config.new_parse_error(
|
|
("directory", id, "store"),
|
|
"Store does not exist",
|
|
);
|
|
continue;
|
|
}
|
|
} else {
|
|
continue;
|
|
},
|
|
)),
|
|
"ldap" => LdapDirectory::from_config(config, prefix, data_store.clone())
|
|
.map(DirectoryInner::Ldap),
|
|
"sql" => SqlDirectory::from_config(config, prefix, stores, data_store.clone())
|
|
.map(DirectoryInner::Sql),
|
|
"imap" => ImapDirectory::from_config(config, prefix).map(DirectoryInner::Imap),
|
|
"smtp" => {
|
|
SmtpDirectory::from_config(config, prefix, false).map(DirectoryInner::Smtp)
|
|
}
|
|
"lmtp" => {
|
|
SmtpDirectory::from_config(config, prefix, true).map(DirectoryInner::Smtp)
|
|
}
|
|
"memory" => MemoryDirectory::from_config(config, prefix, data_store.clone())
|
|
.await
|
|
.map(DirectoryInner::Memory),
|
|
"oidc" => OpenIdDirectory::from_config(config, prefix, data_store.clone())
|
|
.map(DirectoryInner::OpenId),
|
|
unknown => {
|
|
let err = format!("Unknown directory type: {unknown:?}");
|
|
config.new_parse_error(("directory", id, "type"), err);
|
|
continue;
|
|
}
|
|
};
|
|
|
|
// Build directory
|
|
if let Some(store) = store {
|
|
// SPDX-SnippetBegin
|
|
// SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
|
// SPDX-License-Identifier: LicenseRef-SEL
|
|
#[cfg(feature = "enterprise")]
|
|
if store.is_enterprise_directory() && !is_enterprise {
|
|
let message =
|
|
format!("Directory {protocol:?} is an Enterprise Edition feature");
|
|
config.new_parse_error(("directory", id, "type"), message);
|
|
continue;
|
|
}
|
|
// SPDX-SnippetEnd
|
|
|
|
let directory = Arc::new(Directory {
|
|
store,
|
|
cache: CachedDirectory::try_from_config(config, ("directory", id)),
|
|
});
|
|
|
|
// Add directory
|
|
directories.insert(id.to_string(), directory);
|
|
}
|
|
}
|
|
|
|
Directories { directories }
|
|
}
|
|
}
|
|
|
|
pub(crate) fn build_pool<M: Manager>(
|
|
config: &mut Config,
|
|
prefix: &str,
|
|
manager: M,
|
|
) -> Result<Pool<M>, String> {
|
|
Pool::builder(manager)
|
|
.runtime(Runtime::Tokio1)
|
|
.max_size(
|
|
config
|
|
.property_or_default((prefix, "pool.max-connections"), "10")
|
|
.unwrap_or(10),
|
|
)
|
|
.create_timeout(
|
|
config
|
|
.property_or_default::<Duration>((prefix, "pool.timeout.create"), "30s")
|
|
.unwrap_or_else(|| Duration::from_secs(30))
|
|
.into(),
|
|
)
|
|
.wait_timeout(config.property_or_default((prefix, "pool.timeout.wait"), "30s"))
|
|
.recycle_timeout(config.property_or_default((prefix, "pool.timeout.recycle"), "30s"))
|
|
.build()
|
|
.map_err(|err| {
|
|
format!(
|
|
"Failed to build pool for {prefix:?}: {err}",
|
|
prefix = prefix,
|
|
err = err
|
|
)
|
|
})
|
|
}
|