Files
inbuxa-server/tests/src/directory/integration.rs
T
jcoffey-dev 7dae9b29fd Import upstream v0.16.22, stripped
Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f
Enterprise-only files removed or emptied: 63
Enterprise-only snippets removed: 117 in 50 files
Dangling module declarations removed: 5
Cargo edits turning enterprise off: 14
Verification: clean
Enterprise feature gates left for rebuilt features: 19 in 18 files

Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
2026-09-18 10:21:56 -07:00

233 lines
6.6 KiB
Rust

/*
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
use crate::{
directory::ldap::ldap_test_directory,
utils::{server::TestServerBuilder, smtp::SmtpConnection},
};
use ahash::AHashMap;
use common::auth::{AuthRequest, RECOVERY_ADMIN_ID};
use email::cache::MessageCacheFetch;
use registry::schema::structs::{Account, AccountSettings, Directory};
use std::net::IpAddr;
use types::id::Id;
pub async fn test() {
println!("Running directory integration tests...");
crate::utils::containers::ensure_openldap().await;
let test = TestServerBuilder::new("directory_integration_test")
.await
.with_default_listeners()
.await
.with_object(Directory::Ldap(ldap_test_directory()))
.await
.build()
.await;
let admin = test.account("admin");
admin.mta_no_auth().await;
admin.mta_disable_spam_filter().await;
admin.reload_settings().await;
// Test account creation by login
let account = crate::utils::account::Account::new(
"[email protected]",
"this is John's LDAP password",
&[],
"",
Id::from(u32::MAX),
);
assert_eq!(
account
.registry_get::<AccountSettings>(Id::singleton())
.await
.description
.as_deref(),
Some("John Doe")
);
// Test account creation by rcpt
let mut lmtp = SmtpConnection::connect().await;
for rcpt in [
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
"[email protected]",
] {
lmtp.ingest(
"[email protected]",
&[rcpt],
&TEST_EMAIL.replace("$RCPT", rcpt),
)
.await;
}
// Fetch all accounts
let mut accounts = admin
.registry_get_all::<Account>()
.await
.into_iter()
.map(|(id, account)| {
(
match &account {
Account::User(user_account) => user_account.name.clone(),
Account::Group(group_account) => group_account.name.clone(),
},
(account, id),
)
})
.collect::<AHashMap<_, _>>();
assert_eq!(accounts.len(), 5, "Got: {accounts:#?}");
// Validate accounts
for (name, description, secret, groups, aliases) in [
(
"john.doe",
"John Doe",
"$app$8958830913002348890$",
&["sales"][..],
&["john"][..],
),
(
"jane.smith",
"Jane Smith",
"$app$4096614298472586996$",
&["sales", "corporate"][..],
&[][..],
),
(
"bill.foobar",
"Bill Foobar",
"",
&["corporate"][..],
&["bill"][..],
),
] {
let (account, id) = accounts
.remove(name)
.map(|(account, id)| (account.into_user().unwrap(), id))
.unwrap();
assert_eq!(account.description.as_deref(), Some(description));
if !secret.is_empty() {
assert_eq!(
test.server
.registry()
.object::<Account>(id)
.await
.unwrap()
.unwrap()
.into_user()
.unwrap()
.credentials
.values()
.next()
.and_then(|v| v.as_main_credential())
.map(|v| v.secret.as_str()),
Some(secret)
);
}
for group in groups {
let id = accounts.get(*group).unwrap().1;
assert!(
account
.member_group_ids
.iter()
.any(|group_id| group_id == &id),
"Account {name} is not a member of group {group}"
);
}
for alias in aliases {
assert!(
account
.aliases
.iter()
.any(|account_alias| account_alias.name == *alias),
"Account {name} does not have alias {alias}"
);
}
assert_eq!(
test.server
.get_cached_messages(id.document_id())
.await
.unwrap()
.emails
.index
.len(),
1
);
}
// Validate groups
for (name, description, aliases) in [
("sales", "sales", &[][..]),
("corporate", "corporate", &["everyone"][..]),
] {
let (account, id) = accounts
.remove(name)
.map(|(account, id)| (account.into_group().unwrap(), id))
.unwrap();
assert_eq!(account.description.as_deref(), Some(description));
for alias in aliases {
assert!(
account
.aliases
.iter()
.any(|account_alias| account_alias.name == *alias),
"Group {name} does not have alias {alias}"
);
}
assert_eq!(
test.server
.get_cached_messages(id.document_id())
.await
.unwrap()
.emails
.index
.len(),
1
);
}
// Test recovery admin impersonation of an account that has not logged in before
assert!(
test.server
.account_id_from_email("[email protected]", false)
.await
.unwrap()
.is_none(),
"Account [email protected] exists before impersonation"
);
let access_token = test
.server
.authenticate(&AuthRequest::from_plain(
"[email protected]%admin",
admin.secret(),
0,
IpAddr::from([127, 0, 0, 1]),
))
.await
.unwrap_or_else(|err| panic!("Failed to impersonate [email protected]: {err:?}"));
assert_ne!(access_token.account_id(), RECOVERY_ADMIN_ID);
assert_eq!(
test.server
.registry()
.object::<Account>(access_token.account_id().into())
.await
.unwrap()
.and_then(|account| account.into_user())
.map(|account| account.name),
Some("multi.mail".to_string())
);
}
const TEST_EMAIL: &str = r#"From: [email protected]
To: $RCPT
Subject: TPS Report for $RCPT
I'm going to need those TPS reports ASAP. So, if you could do that, that'd be great.
"#;