Settings hot reloading - Part 4
This commit is contained in:
@@ -42,6 +42,7 @@ async fn ldap_directory() {
|
||||
let mut config = DirectoryTest::new("sqlite".into()).await;
|
||||
let handle = config.directories.directories.remove("ldap").unwrap();
|
||||
let base_store = config.stores.stores.get("sqlite").unwrap();
|
||||
let core = config.core;
|
||||
|
||||
// Test authentication
|
||||
assert_eq!(
|
||||
@@ -150,27 +151,39 @@ async fn ldap_directory() {
|
||||
|
||||
// Ids by email
|
||||
compare_sorted(
|
||||
handle.email_to_ids("jane@example.org").await.unwrap(),
|
||||
core.email_to_ids(&handle, "jane@example.org")
|
||||
.await
|
||||
.unwrap(),
|
||||
map_account_ids(base_store, vec!["jane"]).await,
|
||||
);
|
||||
compare_sorted(
|
||||
handle.email_to_ids("jane+alias@example.org").await.unwrap(),
|
||||
core.email_to_ids(&handle, "jane+alias@example.org")
|
||||
.await
|
||||
.unwrap(),
|
||||
map_account_ids(base_store, vec!["jane"]).await,
|
||||
);
|
||||
compare_sorted(
|
||||
handle.email_to_ids("info@example.org").await.unwrap(),
|
||||
core.email_to_ids(&handle, "info@example.org")
|
||||
.await
|
||||
.unwrap(),
|
||||
map_account_ids(base_store, vec!["bill", "jane", "john"]).await,
|
||||
);
|
||||
compare_sorted(
|
||||
handle.email_to_ids("info+alias@example.org").await.unwrap(),
|
||||
core.email_to_ids(&handle, "info+alias@example.org")
|
||||
.await
|
||||
.unwrap(),
|
||||
map_account_ids(base_store, vec!["bill", "jane", "john"]).await,
|
||||
);
|
||||
compare_sorted(
|
||||
handle.email_to_ids("unknown@example.org").await.unwrap(),
|
||||
core.email_to_ids(&handle, "unknown@example.org")
|
||||
.await
|
||||
.unwrap(),
|
||||
Vec::<u32>::new(),
|
||||
);
|
||||
assert_eq!(
|
||||
handle.email_to_ids("anything@catchall.org").await.unwrap(),
|
||||
core.email_to_ids(&handle, "anything@catchall.org")
|
||||
.await
|
||||
.unwrap(),
|
||||
map_account_ids(base_store, vec!["robert"]).await
|
||||
);
|
||||
|
||||
@@ -179,32 +192,41 @@ async fn ldap_directory() {
|
||||
assert!(!handle.is_local_domain("other.org").await.unwrap());
|
||||
|
||||
// RCPT TO
|
||||
assert!(handle.rcpt("jane@example.org").await.unwrap());
|
||||
assert!(handle.rcpt("info@example.org").await.unwrap());
|
||||
assert!(handle.rcpt("jane+alias@example.org").await.unwrap());
|
||||
assert!(handle.rcpt("info+alias@example.org").await.unwrap());
|
||||
assert!(handle.rcpt("random_user@catchall.org").await.unwrap());
|
||||
assert!(!handle.rcpt("invalid@example.org").await.unwrap());
|
||||
assert!(core.rcpt(&handle, "jane@example.org").await.unwrap());
|
||||
assert!(core.rcpt(&handle, "info@example.org").await.unwrap());
|
||||
assert!(core.rcpt(&handle, "jane+alias@example.org").await.unwrap());
|
||||
assert!(core.rcpt(&handle, "info+alias@example.org").await.unwrap());
|
||||
assert!(core
|
||||
.rcpt(&handle, "random_user@catchall.org")
|
||||
.await
|
||||
.unwrap());
|
||||
assert!(!core.rcpt(&handle, "invalid@example.org").await.unwrap());
|
||||
|
||||
// VRFY
|
||||
compare_sorted(
|
||||
handle.vrfy("jane").await.unwrap(),
|
||||
core.vrfy(&handle, "jane").await.unwrap(),
|
||||
vec!["jane@example.org".to_string()],
|
||||
);
|
||||
compare_sorted(
|
||||
handle.vrfy("john").await.unwrap(),
|
||||
core.vrfy(&handle, "john").await.unwrap(),
|
||||
vec!["john@example.org".to_string()],
|
||||
);
|
||||
compare_sorted(
|
||||
handle.vrfy("jane+alias@example").await.unwrap(),
|
||||
core.vrfy(&handle, "jane+alias@example").await.unwrap(),
|
||||
vec!["jane@example.org".to_string()],
|
||||
);
|
||||
compare_sorted(handle.vrfy("info").await.unwrap(), Vec::<String>::new());
|
||||
compare_sorted(handle.vrfy("invalid").await.unwrap(), Vec::<String>::new());
|
||||
compare_sorted(
|
||||
core.vrfy(&handle, "info").await.unwrap(),
|
||||
Vec::<String>::new(),
|
||||
);
|
||||
compare_sorted(
|
||||
core.vrfy(&handle, "invalid").await.unwrap(),
|
||||
Vec::<String>::new(),
|
||||
);
|
||||
|
||||
// EXPN
|
||||
compare_sorted(
|
||||
handle.expn("info@example.org").await.unwrap(),
|
||||
core.expn(&handle, "info@example.org").await.unwrap(),
|
||||
vec![
|
||||
"bill@example.org".to_string(),
|
||||
"jane@example.org".to_string(),
|
||||
@@ -212,7 +234,7 @@ async fn ldap_directory() {
|
||||
],
|
||||
);
|
||||
compare_sorted(
|
||||
handle.expn("john@example.org").await.unwrap(),
|
||||
core.expn(&handle, "john@example.org").await.unwrap(),
|
||||
Vec::<String>::new(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -27,53 +27,38 @@ pub mod ldap;
|
||||
pub mod smtp;
|
||||
pub mod sql;
|
||||
|
||||
use common::config::smtp::session::AddressMapping;
|
||||
use directory::{
|
||||
backend::internal::manage::ManageDirectory, core::config::ConfigDirectory, Directories,
|
||||
Principal,
|
||||
};
|
||||
use common::{config::smtp::session::AddressMapping, Core};
|
||||
use directory::{backend::internal::manage::ManageDirectory, Directories, Principal};
|
||||
use mail_send::Credentials;
|
||||
use rustls::ServerConfig;
|
||||
use rustls_pemfile::{certs, pkcs8_private_keys};
|
||||
use rustls_pki_types::PrivateKeyDer;
|
||||
use std::{borrow::Cow, io::BufReader, path::PathBuf, sync::Arc};
|
||||
use std::{borrow::Cow, io::BufReader, sync::Arc};
|
||||
use store::{LookupStore, Store, Stores};
|
||||
use tokio_rustls::TlsAcceptor;
|
||||
|
||||
use crate::store::TempDir;
|
||||
use crate::{store::TempDir, AssertConfig};
|
||||
|
||||
const CONFIG: &str = r#"
|
||||
[directory."rocksdb"]
|
||||
type = "internal"
|
||||
store = "rocksdb"
|
||||
|
||||
[directory."rocksdb".options]
|
||||
catch-all = true
|
||||
subaddressing = true
|
||||
|
||||
[directory."foundationdb"]
|
||||
type = "internal"
|
||||
store = "foundationdb"
|
||||
|
||||
[directory."foundationdb".options]
|
||||
catch-all = true
|
||||
subaddressing = true
|
||||
|
||||
[directory."sqlite"]
|
||||
type = "sql"
|
||||
store = "sqlite"
|
||||
|
||||
[directory."sqlite".options]
|
||||
catch-all = true
|
||||
subaddressing = true
|
||||
|
||||
[directory."sqlite".columns]
|
||||
name = "name"
|
||||
description = "description"
|
||||
secret = "secret"
|
||||
email = "address"
|
||||
quota = "quota"
|
||||
type = "type"
|
||||
class = "type"
|
||||
|
||||
[store."rocksdb"]
|
||||
type = "rocksdb"
|
||||
@@ -104,17 +89,13 @@ lookup = "sqlite"
|
||||
type = "sql"
|
||||
store = "postgresql"
|
||||
|
||||
[directory."postgresql".options]
|
||||
catch-all = true
|
||||
subaddressing = true
|
||||
|
||||
[directory."postgresql".columns]
|
||||
name = "name"
|
||||
description = "description"
|
||||
secret = "secret"
|
||||
email = "address"
|
||||
quota = "quota"
|
||||
type = "type"
|
||||
class = "type"
|
||||
|
||||
[store."postgresql"]
|
||||
type = "postgresql"
|
||||
@@ -139,17 +120,13 @@ domains = "SELECT 1 FROM emails WHERE address LIKE '%@' || $1 LIMIT 1"
|
||||
type = "sql"
|
||||
store = "mysql"
|
||||
|
||||
[directory."mysql".options]
|
||||
catch-all = true
|
||||
subaddressing = true
|
||||
|
||||
[directory."mysql".columns]
|
||||
name = "name"
|
||||
description = "description"
|
||||
secret = "secret"
|
||||
email = "address"
|
||||
quota = "quota"
|
||||
type = "type"
|
||||
class = "type"
|
||||
|
||||
[store."mysql"]
|
||||
type = "mysql"
|
||||
@@ -172,7 +149,7 @@ domains = "SELECT 1 FROM emails WHERE address LIKE CONCAT('%@', ?) LIMIT 1"
|
||||
|
||||
[directory."ldap"]
|
||||
type = "ldap"
|
||||
address = "ldap://localhost:3893"
|
||||
url = "ldap://localhost:3893"
|
||||
base-dn = "dc=example,dc=org"
|
||||
|
||||
[directory."ldap".bind]
|
||||
@@ -183,10 +160,6 @@ secret = "mysecret"
|
||||
enable = false
|
||||
dn = "cn=?,ou=svcaccts,dc=example,dc=org"
|
||||
|
||||
[directory."ldap".options]
|
||||
catch-all = true
|
||||
subaddressing = true
|
||||
|
||||
[directory."ldap".filter]
|
||||
name = "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(uid=?))"
|
||||
email = "(&(|(objectClass=posixAccount)(objectClass=posixGroup))(|(mail=?)(givenName=?)(sn=?)))"
|
||||
@@ -205,27 +178,27 @@ groups = ["memberOf", "otherGroups"]
|
||||
email = "mail"
|
||||
email-alias = "givenName"
|
||||
quota = "diskQuota"
|
||||
type = "objectClass"
|
||||
class = "objectClass"
|
||||
|
||||
##############################################################################
|
||||
|
||||
[directory."imap"]
|
||||
type = "imap"
|
||||
address = "127.0.0.1"
|
||||
host = "127.0.0.1"
|
||||
port = 9198
|
||||
|
||||
[directory."imap".pool]
|
||||
max-connections = 5
|
||||
|
||||
[directory."imap".tls]
|
||||
implicit = true
|
||||
enable = true
|
||||
allow-invalid-certs = true
|
||||
|
||||
##############################################################################
|
||||
|
||||
[directory."smtp"]
|
||||
type = "lmtp"
|
||||
address = "127.0.0.1"
|
||||
host = "127.0.0.1"
|
||||
port = 9199
|
||||
|
||||
[directory."smtp".limits]
|
||||
@@ -236,7 +209,7 @@ rcpt = 5
|
||||
max-connections = 5
|
||||
|
||||
[directory."smtp".tls]
|
||||
implicit = true
|
||||
enable = true
|
||||
allow-invalid-certs = true
|
||||
|
||||
[directory."smtp".cache]
|
||||
@@ -248,13 +221,9 @@ ttl = {positive = '10s', negative = '5s'}
|
||||
[directory."local"]
|
||||
type = "memory"
|
||||
|
||||
[directory."local".options]
|
||||
catch-all = true
|
||||
subaddressing = true
|
||||
|
||||
[[directory."local".principals]]
|
||||
name = "john"
|
||||
type = "individual"
|
||||
class = "individual"
|
||||
description = "John Doe"
|
||||
secret = "12345"
|
||||
email = ["john@example.org", "jdoe@example.org", "john.doe@example.org"]
|
||||
@@ -263,7 +232,7 @@ member-of = ["sales"]
|
||||
|
||||
[[directory."local".principals]]
|
||||
name = "jane"
|
||||
type = "individual"
|
||||
class = "individual"
|
||||
description = "Jane Doe"
|
||||
secret = "abcde"
|
||||
email = "jane@example.org"
|
||||
@@ -272,7 +241,7 @@ member-of = ["sales", "support"]
|
||||
|
||||
[[directory."local".principals]]
|
||||
name = "bill"
|
||||
type = "individual"
|
||||
class = "individual"
|
||||
description = "Bill Foobar"
|
||||
secret = "$2y$05$bvIG6Nmid91Mu9RcmmWZfO5HJIMCT8riNW0hEp8f6/FuA2/mHZFpe"
|
||||
quota = 500000
|
||||
@@ -281,12 +250,12 @@ email-list = ["info@example.org"]
|
||||
|
||||
[[directory."local".principals]]
|
||||
name = "sales"
|
||||
type = "group"
|
||||
class = "group"
|
||||
description = "Sales Team"
|
||||
|
||||
[[directory."local".principals]]
|
||||
name = "support"
|
||||
type = "group"
|
||||
class = "group"
|
||||
description = "Support Team"
|
||||
|
||||
"#;
|
||||
@@ -299,6 +268,7 @@ pub struct DirectoryTest {
|
||||
pub directories: Directories,
|
||||
pub stores: Stores,
|
||||
pub temp_dir: TempDir,
|
||||
pub core: Core,
|
||||
}
|
||||
|
||||
impl DirectoryTest {
|
||||
@@ -308,24 +278,41 @@ impl DirectoryTest {
|
||||
if id_store.is_some() {
|
||||
// Disable foundationdb store for SQL tests (the fdb select api version can only be run once per process)
|
||||
config_file = config_file
|
||||
.replace("type = \"foundationdb\"", "type = \"ignore\"")
|
||||
.replace("store = \"foundationdb\"", "disable = true");
|
||||
.replace(
|
||||
"type = \"foundationdb\"",
|
||||
"type = \"foundationdb\"\ndisable = true",
|
||||
)
|
||||
.replace(
|
||||
"store = \"foundationdb\"",
|
||||
"store = \"foundationdb\"\ndisable = true",
|
||||
)
|
||||
} else {
|
||||
// Disable internal store
|
||||
config_file =
|
||||
config_file.replace("type = \"memory\"", "type = \"memory\"\ndisable = true")
|
||||
}
|
||||
let config = utils::config::Config::new(&config_file).unwrap();
|
||||
let stores = config.parse_stores().await.unwrap();
|
||||
let mut config = utils::config::Config::new(&config_file).unwrap();
|
||||
let stores = Stores::parse(&mut config).await;
|
||||
let directories = Directories::parse(
|
||||
&mut config,
|
||||
&stores,
|
||||
id_store
|
||||
.map(|id| stores.stores.get(id).unwrap().clone())
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
.await;
|
||||
config.assert_no_errors();
|
||||
|
||||
// Enable catch-all and subaddressing
|
||||
let mut core = Core::default();
|
||||
core.smtp.session.rcpt.catch_all = AddressMapping::Enable;
|
||||
core.smtp.session.rcpt.subaddressing = AddressMapping::Enable;
|
||||
|
||||
DirectoryTest {
|
||||
directories: config
|
||||
.parse_directory(
|
||||
&stores,
|
||||
id_store
|
||||
.map(|id| stores.stores.get(id).unwrap().clone())
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
.await
|
||||
.unwrap(),
|
||||
directories,
|
||||
stores,
|
||||
temp_dir,
|
||||
core,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -530,6 +517,9 @@ impl core::fmt::Debug for Item {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
// DEPRECATED - TODO: Remove
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
#[ignore]
|
||||
async fn lookup_local() {
|
||||
@@ -539,12 +529,12 @@ async fn lookup_local() {
|
||||
format = "regex"
|
||||
values = ["^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$",
|
||||
"^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"]
|
||||
|
||||
|
||||
[store."local/glob"]
|
||||
type = "memory"
|
||||
format = "glob"
|
||||
values = ["*@example.org", "test@*", "localhost", "*+*@*.domain.net"]
|
||||
|
||||
|
||||
[store."local/list"]
|
||||
type = "memory"
|
||||
format = "list"
|
||||
@@ -564,7 +554,7 @@ async fn lookup_local() {
|
||||
)
|
||||
.unwrap();*/
|
||||
|
||||
let lookups = utils::config::Config::new(
|
||||
let mut config = utils::config::Config::new(
|
||||
&LOOKUP_CONFIG.replace(
|
||||
"%PATH%",
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
@@ -578,11 +568,9 @@ async fn lookup_local() {
|
||||
.unwrap(),
|
||||
),
|
||||
)
|
||||
.unwrap()
|
||||
.parse_stores()
|
||||
.await
|
||||
.unwrap()
|
||||
.lookup_stores;
|
||||
.unwrap();
|
||||
|
||||
let lookups = Stores::parse(&mut config).await.lookup_stores;
|
||||
|
||||
for (lookup, item, expect) in [
|
||||
("glob", "user@example.org", true),
|
||||
@@ -613,6 +601,7 @@ async fn lookup_local() {
|
||||
);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[tokio::test]
|
||||
async fn address_mappings() {
|
||||
@@ -639,22 +628,23 @@ async fn address_mappings() {
|
||||
expected-catch = "info@example.org"
|
||||
"#;
|
||||
|
||||
let config = utils::config::Config::new(MAPPINGS).unwrap();
|
||||
let mut config = utils::config::Config::new(MAPPINGS).unwrap();
|
||||
const ADDR: &str = "john.doe+alias@example.org";
|
||||
const ADDR_NO_MATCH: &str = "jane@example.org";
|
||||
let core = Core::default();
|
||||
|
||||
for test in ["enable", "disable", "custom"] {
|
||||
let catch_all = AddressMapping::from_config(&config, (test, "catch-all")).unwrap();
|
||||
let subaddressing = AddressMapping::from_config(&config, (test, "subaddressing")).unwrap();
|
||||
let catch_all = AddressMapping::parse(&mut config, (test, "catch-all"));
|
||||
let subaddressing = AddressMapping::parse(&mut config, (test, "subaddressing"));
|
||||
|
||||
assert_eq!(
|
||||
subaddressing.to_subaddress(ADDR).await,
|
||||
subaddressing.to_subaddress(&core, ADDR).await,
|
||||
config.value_require((test, "expected-sub")).unwrap(),
|
||||
"failed subaddress for {test:?}"
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
subaddressing.to_subaddress(ADDR_NO_MATCH).await,
|
||||
subaddressing.to_subaddress(&core, ADDR_NO_MATCH).await,
|
||||
config
|
||||
.value_require((test, "expected-sub-nomatch"))
|
||||
.unwrap(),
|
||||
@@ -662,7 +652,7 @@ async fn address_mappings() {
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
catch_all.to_catch_all(ADDR).await,
|
||||
catch_all.to_catch_all(&core, ADDR).await,
|
||||
config
|
||||
.property_require::<Option<String>>((test, "expected-catch"))
|
||||
.unwrap()
|
||||
|
||||
@@ -39,7 +39,7 @@ use crate::directory::{DirectoryTest, Item, LookupResult};
|
||||
use super::dummy_tls_acceptor;
|
||||
|
||||
#[tokio::test]
|
||||
async fn smtp_directory() {
|
||||
async fn lmtp_directory() {
|
||||
// Spawn mock LMTP server
|
||||
let shutdown = spawn_mock_lmtp_server(5);
|
||||
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
|
||||
@@ -47,6 +47,7 @@ async fn smtp_directory() {
|
||||
// Obtain directory handle
|
||||
let mut config = DirectoryTest::new(None).await;
|
||||
let handle = config.directories.directories.remove("smtp").unwrap();
|
||||
let core = config.core;
|
||||
|
||||
// Basic lookup
|
||||
let tests = vec![
|
||||
@@ -94,19 +95,19 @@ async fn smtp_directory() {
|
||||
|
||||
for (item, expected) in &tests {
|
||||
let result: LookupResult = match item {
|
||||
Item::IsAccount(v) => handle.rcpt(v).await.unwrap().into(),
|
||||
Item::IsAccount(v) => core.rcpt(&handle, v).await.unwrap().into(),
|
||||
Item::Authenticate(v) => handle
|
||||
.query(QueryBy::Credentials(v), true)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_some()
|
||||
.into(),
|
||||
Item::Verify(v) => match handle.vrfy(v).await {
|
||||
Item::Verify(v) => match core.vrfy(&handle, v).await {
|
||||
Ok(v) => v.into(),
|
||||
Err(DirectoryError::Unsupported) => LookupResult::False,
|
||||
Err(e) => panic!("Unexpected error: {e:?}"),
|
||||
},
|
||||
Item::Expand(v) => match handle.expn(v).await {
|
||||
Item::Expand(v) => match core.expn(&handle, v).await {
|
||||
Ok(v) => v.into(),
|
||||
Err(DirectoryError::Unsupported) => LookupResult::False,
|
||||
Err(e) => panic!("Unexpected error: {e:?}"),
|
||||
@@ -118,27 +119,29 @@ async fn smtp_directory() {
|
||||
|
||||
// Concurrent requests
|
||||
let mut requests = Vec::new();
|
||||
let core = Arc::new(core);
|
||||
for n in 0..100 {
|
||||
let (item, expected) = &tests[n % tests.len()];
|
||||
let item = item.append(n);
|
||||
let item_clone = item.clone();
|
||||
let handle = handle.clone();
|
||||
let core = core.clone();
|
||||
requests.push((
|
||||
tokio::spawn(async move {
|
||||
let result: LookupResult = match &item {
|
||||
Item::IsAccount(v) => handle.rcpt(v).await.unwrap().into(),
|
||||
Item::IsAccount(v) => core.rcpt(&handle, v).await.unwrap().into(),
|
||||
Item::Authenticate(v) => handle
|
||||
.query(QueryBy::Credentials(v), true)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_some()
|
||||
.into(),
|
||||
Item::Verify(v) => match handle.vrfy(v).await {
|
||||
Item::Verify(v) => match core.vrfy(&handle, v).await {
|
||||
Ok(v) => v.into(),
|
||||
Err(DirectoryError::Unsupported) => LookupResult::False,
|
||||
Err(e) => panic!("Unexpected error: {e:?}"),
|
||||
},
|
||||
Item::Expand(v) => match handle.expn(v).await {
|
||||
Item::Expand(v) => match core.expn(&handle, v).await {
|
||||
Ok(v) => v.into(),
|
||||
Err(DirectoryError::Unsupported) => LookupResult::False,
|
||||
Err(e) => panic!("Unexpected error: {e:?}"),
|
||||
@@ -172,10 +175,11 @@ async fn smtp_directory() {
|
||||
let item = item.append(n);
|
||||
let item_clone = item.clone();
|
||||
let handle = handle.clone();
|
||||
let core = core.clone();
|
||||
requests.push((
|
||||
tokio::spawn(async move {
|
||||
let result: LookupResult = match &item {
|
||||
Item::IsAccount(v) => handle.rcpt(v).await.unwrap().into(),
|
||||
Item::IsAccount(v) => core.rcpt(&handle, v).await.unwrap().into(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ async fn sql_directory() {
|
||||
store: config.stores.lookup_stores.remove(directory_id).unwrap(),
|
||||
};
|
||||
let base_store = config.stores.stores.get(directory_id).unwrap();
|
||||
let core = config.core;
|
||||
|
||||
// Create tables
|
||||
store.create_test_directory().await;
|
||||
@@ -216,27 +217,39 @@ async fn sql_directory() {
|
||||
|
||||
// Ids by email
|
||||
assert_eq!(
|
||||
handle.email_to_ids("jane@example.org").await.unwrap(),
|
||||
core.email_to_ids(&handle, "jane@example.org")
|
||||
.await
|
||||
.unwrap(),
|
||||
map_account_ids(base_store, vec!["jane"]).await
|
||||
);
|
||||
assert_eq!(
|
||||
handle.email_to_ids("info@example.org").await.unwrap(),
|
||||
core.email_to_ids(&handle, "info@example.org")
|
||||
.await
|
||||
.unwrap(),
|
||||
map_account_ids(base_store, vec!["bill", "jane", "john"]).await
|
||||
);
|
||||
assert_eq!(
|
||||
handle.email_to_ids("jane+alias@example.org").await.unwrap(),
|
||||
core.email_to_ids(&handle, "jane+alias@example.org")
|
||||
.await
|
||||
.unwrap(),
|
||||
map_account_ids(base_store, vec!["jane"]).await
|
||||
);
|
||||
assert_eq!(
|
||||
handle.email_to_ids("info+alias@example.org").await.unwrap(),
|
||||
core.email_to_ids(&handle, "info+alias@example.org")
|
||||
.await
|
||||
.unwrap(),
|
||||
map_account_ids(base_store, vec!["bill", "jane", "john"]).await
|
||||
);
|
||||
assert_eq!(
|
||||
handle.email_to_ids("unknown@example.org").await.unwrap(),
|
||||
core.email_to_ids(&handle, "unknown@example.org")
|
||||
.await
|
||||
.unwrap(),
|
||||
Vec::<u32>::new()
|
||||
);
|
||||
assert_eq!(
|
||||
handle.email_to_ids("anything@catchall.org").await.unwrap(),
|
||||
core.email_to_ids(&handle, "anything@catchall.org")
|
||||
.await
|
||||
.unwrap(),
|
||||
map_account_ids(base_store, vec!["robert"]).await
|
||||
);
|
||||
|
||||
@@ -245,32 +258,41 @@ async fn sql_directory() {
|
||||
assert!(!handle.is_local_domain("other.org").await.unwrap());
|
||||
|
||||
// RCPT TO
|
||||
assert!(handle.rcpt("jane@example.org").await.unwrap());
|
||||
assert!(handle.rcpt("info@example.org").await.unwrap());
|
||||
assert!(handle.rcpt("jane+alias@example.org").await.unwrap());
|
||||
assert!(handle.rcpt("info+alias@example.org").await.unwrap());
|
||||
assert!(handle.rcpt("random_user@catchall.org").await.unwrap());
|
||||
assert!(!handle.rcpt("invalid@example.org").await.unwrap());
|
||||
assert!(core.rcpt(&handle, "jane@example.org").await.unwrap());
|
||||
assert!(core.rcpt(&handle, "info@example.org").await.unwrap());
|
||||
assert!(core.rcpt(&handle, "jane+alias@example.org").await.unwrap());
|
||||
assert!(core.rcpt(&handle, "info+alias@example.org").await.unwrap());
|
||||
assert!(core
|
||||
.rcpt(&handle, "random_user@catchall.org")
|
||||
.await
|
||||
.unwrap());
|
||||
assert!(!core.rcpt(&handle, "invalid@example.org").await.unwrap());
|
||||
|
||||
// VRFY
|
||||
assert_eq!(
|
||||
handle.vrfy("jane").await.unwrap(),
|
||||
core.vrfy(&handle, "jane").await.unwrap(),
|
||||
vec!["jane@example.org".to_string()]
|
||||
);
|
||||
assert_eq!(
|
||||
handle.vrfy("john").await.unwrap(),
|
||||
core.vrfy(&handle, "john").await.unwrap(),
|
||||
vec!["john@example.org".to_string()]
|
||||
);
|
||||
assert_eq!(
|
||||
handle.vrfy("jane+alias@example").await.unwrap(),
|
||||
core.vrfy(&handle, "jane+alias@example").await.unwrap(),
|
||||
vec!["jane@example.org".to_string()]
|
||||
);
|
||||
assert_eq!(handle.vrfy("info").await.unwrap(), Vec::<String>::new());
|
||||
assert_eq!(handle.vrfy("invalid").await.unwrap(), Vec::<String>::new());
|
||||
assert_eq!(
|
||||
core.vrfy(&handle, "info").await.unwrap(),
|
||||
Vec::<String>::new()
|
||||
);
|
||||
assert_eq!(
|
||||
core.vrfy(&handle, "invalid").await.unwrap(),
|
||||
Vec::<String>::new()
|
||||
);
|
||||
|
||||
// EXPN
|
||||
assert_eq!(
|
||||
handle.expn("info@example.org").await.unwrap(),
|
||||
core.expn(&handle, "info@example.org").await.unwrap(),
|
||||
vec![
|
||||
"bill@example.org".to_string(),
|
||||
"jane@example.org".to_string(),
|
||||
@@ -278,7 +300,7 @@ async fn sql_directory() {
|
||||
]
|
||||
);
|
||||
assert_eq!(
|
||||
handle.expn("john@example.org").await.unwrap(),
|
||||
core.expn(&handle, "john@example.org").await.unwrap(),
|
||||
Vec::<String>::new()
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user