diff options
author | mdecimus <mauro@stalw.art> | 2024-09-18 11:18:43 +0200 |
---|---|---|
committer | mdecimus <mauro@stalw.art> | 2024-09-18 11:18:43 +0200 |
commit | d0303aefa8f5c0e8700326f979af17669cb8d325 (patch) | |
tree | 1173424ac8828f63737fe11af0151088cd5d8999 | |
parent | 6b7dac0fcbeb3b2a2a6e0a734c18d2b44c41f594 (diff) |
Test fixes - part 3
-rw-r--r-- | crates/directory/src/backend/internal/lookup.rs | 41 | ||||
-rw-r--r-- | crates/directory/src/backend/internal/manage.rs | 78 | ||||
-rw-r--r-- | crates/store/src/dispatch/store.rs | 18 | ||||
-rw-r--r-- | tests/src/directory/internal.rs | 196 | ||||
-rw-r--r-- | tests/src/imap/mod.rs | 97 | ||||
-rw-r--r-- | tests/src/jmap/auth_acl.rs | 61 | ||||
-rw-r--r-- | tests/src/jmap/auth_limits.rs | 20 | ||||
-rw-r--r-- | tests/src/jmap/auth_oauth.rs | 20 | ||||
-rw-r--r-- | tests/src/jmap/blob.rs | 21 | ||||
-rw-r--r-- | tests/src/jmap/crypto.rs | 20 | ||||
-rw-r--r-- | tests/src/jmap/delivery.rs | 116 | ||||
-rw-r--r-- | tests/src/jmap/email_submission.rs | 24 | ||||
-rw-r--r-- | tests/src/jmap/enterprise.rs | 51 | ||||
-rw-r--r-- | tests/src/jmap/event_source.rs | 24 | ||||
-rw-r--r-- | tests/src/jmap/mod.rs | 63 | ||||
-rw-r--r-- | tests/src/jmap/purge.rs | 33 | ||||
-rw-r--r-- | tests/src/jmap/push_subscription.rs | 17 | ||||
-rw-r--r-- | tests/src/jmap/quota.rs | 75 | ||||
-rw-r--r-- | tests/src/jmap/sieve_script.rs | 28 | ||||
-rw-r--r-- | tests/src/jmap/vacation_response.rs | 30 | ||||
-rw-r--r-- | tests/src/jmap/websocket.rs | 20 |
21 files changed, 670 insertions, 383 deletions
diff --git a/crates/directory/src/backend/internal/lookup.rs b/crates/directory/src/backend/internal/lookup.rs index 7517357f..e1852476 100644 --- a/crates/directory/src/backend/internal/lookup.rs +++ b/crates/directory/src/backend/internal/lookup.rs @@ -7,8 +7,9 @@ use mail_send::Credentials; use store::{ write::{DirectoryClass, ValueClass}, - IterateParams, Store, ValueKey, + Deserialize, IterateParams, Store, ValueKey, }; +use trc::AddContext; use crate::{Principal, QueryBy, Type}; @@ -124,12 +125,16 @@ impl DirectoryStore for Store { ValueKey::from(ValueClass::Directory(DirectoryClass::EmailToId( vec![u8::MAX; 10], ))), - ) - .no_values(), - |key, _| { + ), + |key, value| { let key = std::str::from_utf8(key.get(1..).unwrap_or_default()).unwrap_or_default(); - if key.split('@').next().unwrap_or(key).contains(address) { + if key.split('@').next().unwrap_or(key).contains(address) + && PrincipalInfo::deserialize(value) + .caused_by(trc::location!())? + .typ + != Type::List + { results.push(key.to_string()); } Ok(true) @@ -143,15 +148,23 @@ impl DirectoryStore for Store { async fn expn(&self, address: &str) -> trc::Result<Vec<String>> { let mut results = Vec::new(); - for account_id in self.email_to_ids(address).await? { - if let Some(email) = self - .get_value::<Principal>(ValueKey::from(ValueClass::Directory( - DirectoryClass::Principal(account_id), - ))) - .await? - .and_then(|mut p| p.take_str(PrincipalField::Emails)) - { - results.push(email); + if let Some(ptype) = self + .get_value::<PrincipalInfo>(ValueKey::from(ValueClass::Directory( + DirectoryClass::EmailToId(address.as_bytes().to_vec()), + ))) + .await? + .filter(|p| p.typ == Type::List) + { + for account_id in self.get_members(ptype.id).await? { + if let Some(email) = self + .get_value::<Principal>(ValueKey::from(ValueClass::Directory( + DirectoryClass::Principal(account_id), + ))) + .await? + .and_then(|mut p| p.take_str(PrincipalField::Emails)) + { + results.push(email); + } } } diff --git a/crates/directory/src/backend/internal/manage.rs b/crates/directory/src/backend/internal/manage.rs index 84f4686f..6b92cc30 100644 --- a/crates/directory/src/backend/internal/manage.rs +++ b/crates/directory/src/backend/internal/manage.rs @@ -942,23 +942,12 @@ impl ManageDirectory for Store { .or_else(|| change.field.map_internal_roles(&member)) .ok_or_else(|| not_found(member.clone()))?; - let expected_type = match change.field { - PrincipalField::MemberOf => Type::Group, - PrincipalField::Lists => Type::List, - PrincipalField::Roles => Type::Role, - _ => unreachable!(), - }; - - if member_info.typ != expected_type { - return Err(error( - format!("Invalid {} value", change.field.as_str()), - format!( - "Principal {member:?} is not a {}.", - expected_type.as_str() - ) - .into(), - )); - } + validate_member_of( + change.field, + principal.inner.typ, + member_info.typ, + &member, + )?; if !member_of.contains(&member_info.id) { batch.set( @@ -1009,23 +998,12 @@ impl ManageDirectory for Store { .ok_or_else(|| not_found(member.clone()))?; if !member_of.contains(&member_info.id) { - let expected_type = match change.field { - PrincipalField::MemberOf => Type::Group, - PrincipalField::Lists => Type::List, - PrincipalField::Roles => Type::Role, - _ => unreachable!(), - }; - - if member_info.typ != expected_type { - return Err(error( - format!("Invalid {} value", change.field.as_str()), - format!( - "Principal {member:?} is not a {}.", - expected_type.as_str() - ) - .into(), - )); - } + validate_member_of( + change.field, + principal.inner.typ, + member_info.typ, + &member, + )?; batch.set( ValueClass::Directory(DirectoryClass::MemberOf { @@ -1664,6 +1642,38 @@ impl From<Principal> for MaybeDynamicValue { } } +fn validate_member_of( + field: PrincipalField, + typ: Type, + member_type: Type, + member_name: &str, +) -> trc::Result<()> { + let expected_types = match (field, typ) { + (PrincipalField::MemberOf, Type::Individual) => &[Type::Group, Type::Individual][..], + (PrincipalField::MemberOf, Type::Group) => &[Type::Group][..], + (PrincipalField::Lists, Type::Individual | Type::Group) => &[Type::List][..], + (PrincipalField::Roles, Type::Individual | Type::Tenant | Type::Role) => &[Type::Role][..], + _ => &[][..], + }; + + if expected_types.is_empty() || !expected_types.contains(&member_type) { + Err(error( + format!("Invalid {} value", field.as_str()), + format!( + "Principal {member_name:?} is not a {}.", + expected_types + .iter() + .map(|t| t.as_str().to_string()) + .collect::<Vec<_>>() + .join(", ") + ) + .into(), + )) + } else { + Ok(()) + } +} + #[derive(Clone, Copy)] struct DynamicPrincipalInfo { typ: Type, diff --git a/crates/store/src/dispatch/store.rs b/crates/store/src/dispatch/store.rs index 9a938120..4fc95197 100644 --- a/crates/store/src/dispatch/store.rs +++ b/crates/store/src/dispatch/store.rs @@ -474,6 +474,24 @@ impl Store { .caused_by(trc::location!())?; } + // Delete property counters (TODO: make this more elegant) + self.delete_range( + ValueKey { + account_id, + collection: 1, + document_id: 0, + class: ValueClass::Property(84), + }, + ValueKey { + account_id, + collection: 1, + document_id: u32::MAX, + class: ValueClass::Property(84), + }, + ) + .await + .caused_by(trc::location!())?; + Ok(()) } diff --git a/tests/src/directory/internal.rs b/tests/src/directory/internal.rs index 32b9bf90..3cde6c15 100644 --- a/tests/src/directory/internal.rs +++ b/tests/src/directory/internal.rs @@ -18,7 +18,7 @@ use mail_send::Credentials; use store::{ roaring::RoaringBitmap, write::{BatchBuilder, BitmapClass, ValueClass}, - BitmapKey, ValueKey, + BitmapKey, Store, ValueKey, }; use crate::directory::{DirectoryTest, IntoTestPrincipal, TestPrincipal}; @@ -718,3 +718,197 @@ async fn internal_directory() { ); } } + +#[allow(async_fn_in_trait)] +pub trait TestInternalDirectory { + async fn create_test_user(&self, login: &str, secret: &str, name: &str, emails: &[&str]) + -> u32; + async fn create_test_group(&self, login: &str, name: &str, emails: &[&str]) -> u32; + async fn create_test_list(&self, login: &str, name: &str, emails: &[&str]) -> u32; + async fn set_test_quota(&self, login: &str, quota: u32); + async fn add_to_group(&self, login: &str, group: &str); + async fn remove_from_group(&self, login: &str, group: &str); + async fn remove_test_alias(&self, login: &str, alias: &str); + async fn create_test_domains(&self, domains: &[&str]); +} + +impl TestInternalDirectory for Store { + async fn create_test_user( + &self, + login: &str, + secret: &str, + name: &str, + emails: &[&str], + ) -> u32 { + let role = if login == "admin" { "admin" } else { "user" }; + self.create_test_domains(emails).await; + if let Some(principal) = self.query(QueryBy::Name(login), false).await.unwrap() { + self.update_principal( + QueryBy::Id(principal.id()), + vec![ + PrincipalUpdate::set( + PrincipalField::Secrets, + PrincipalValue::StringList(vec![secret.to_string()]), + ), + PrincipalUpdate::set( + PrincipalField::Description, + PrincipalValue::String(name.to_string()), + ), + PrincipalUpdate::set( + PrincipalField::Emails, + PrincipalValue::StringList(emails.iter().map(|s| s.to_string()).collect()), + ), + PrincipalUpdate::add_item( + PrincipalField::Roles, + PrincipalValue::String(role.to_string()), + ), + ], + None, + ) + .await + .unwrap(); + principal.id() + } else { + self.create_principal( + Principal::new(0, Type::Individual) + .with_field(PrincipalField::Name, login.to_string()) + .with_field(PrincipalField::Description, name.to_string()) + .with_field( + PrincipalField::Secrets, + PrincipalValue::StringList(vec![secret.to_string()]), + ) + .with_field( + PrincipalField::Emails, + PrincipalValue::StringList(emails.iter().map(|s| s.to_string()).collect()), + ) + .with_field( + PrincipalField::Roles, + PrincipalValue::StringList(vec![role.to_string()]), + ), + None, + ) + .await + .unwrap() + } + } + + async fn create_test_group(&self, login: &str, name: &str, emails: &[&str]) -> u32 { + self.create_test_domains(emails).await; + if let Some(principal) = self.query(QueryBy::Name(login), false).await.unwrap() { + principal.id() + } else { + self.create_principal( + Principal::new(0, Type::Group) + .with_field(PrincipalField::Name, login.to_string()) + .with_field(PrincipalField::Description, name.to_string()) + .with_field( + PrincipalField::Emails, + PrincipalValue::StringList(emails.iter().map(|s| s.to_string()).collect()), + ) + .with_field( + PrincipalField::Roles, + PrincipalValue::StringList(vec!["user".to_string()]), + ), + None, + ) + .await + .unwrap() + } + } + + async fn create_test_list(&self, login: &str, name: &str, members: &[&str]) -> u32 { + if let Some(principal) = self.query(QueryBy::Name(login), false).await.unwrap() { + principal.id() + } else { + self.create_test_domains(&[login]).await; + self.create_principal( + Principal::new(0, Type::List) + .with_field(PrincipalField::Name, login.to_string()) + .with_field(PrincipalField::Description, name.to_string()) + .with_field( + PrincipalField::Members, + PrincipalValue::StringList(members.iter().map(|s| s.to_string()).collect()), + ) + .with_field( + PrincipalField::Emails, + PrincipalValue::StringList(vec![login.to_string()]), + ), + None, + ) + .await + .unwrap() + } + } + + async fn set_test_quota(&self, login: &str, quota: u32) { + self.update_principal( + QueryBy::Name(login), + vec![PrincipalUpdate::set( + PrincipalField::Quota, + PrincipalValue::Integer(quota as u64), + )], + None, + ) + .await + .unwrap(); + } + + async fn add_to_group(&self, login: &str, group: &str) { + self.update_principal( + QueryBy::Name(login), + vec![PrincipalUpdate::add_item( + PrincipalField::MemberOf, + PrincipalValue::String(group.to_string()), + )], + None, + ) + .await + .unwrap(); + } + + async fn remove_from_group(&self, login: &str, group: &str) { + self.update_principal( + QueryBy::Name(login), + vec![PrincipalUpdate::remove_item( + PrincipalField::MemberOf, + PrincipalValue::String(group.to_string()), + )], + None, + ) + .await + .unwrap(); + } + + async fn remove_test_alias(&self, login: &str, alias: &str) { + self.update_principal( + QueryBy::Name(login), + vec![PrincipalUpdate::remove_item( + PrincipalField::Emails, + PrincipalValue::String(alias.to_string()), + )], + None, + ) + .await + .unwrap(); + } + + async fn create_test_domains(&self, domains: &[&str]) { + for domain in domains { + let domain = domain.rsplit_once('@').map_or(*domain, |(_, d)| d); + if self + .query(QueryBy::Name(domain), false) + .await + .unwrap() + .is_none() + { + self.create_principal( + Principal::new(0, Type::Domain) + .with_field(PrincipalField::Name, domain.to_string()), + None, + ) + .await + .unwrap(); + } + } + } +} diff --git a/tests/src/imap/mod.rs b/tests/src/imap/mod.rs index 82ca7bc0..0dcfe9b3 100644 --- a/tests/src/imap/mod.rs +++ b/tests/src/imap/mod.rs @@ -36,7 +36,6 @@ use common::{ use ::store::Stores; use ahash::AHashSet; -use directory::backend::internal::manage::ManageDirectory; use imap::core::{ImapSessionManager, Inner, IMAP}; use imap_proto::ResponseType; use jmap::{api::JmapSessionManager, JMAP}; @@ -49,7 +48,9 @@ use tokio::{ }; use utils::config::Config; -use crate::{add_test_certs, directory::DirectoryStore, store::TempDir, AssertConfig}; +use crate::{ + add_test_certs, directory::internal::TestInternalDirectory, store::TempDir, AssertConfig, +}; const SERVER: &str = r#" [lookup.default] @@ -98,7 +99,7 @@ reject-non-fqdn = false [session.rcpt] relay = [ { if = "!is_empty(authenticated_as)", then = true }, { else = false } ] -directory = "'auth'" +directory = "'{STORE}'" [session.rcpt.errors] total = 5 @@ -187,7 +188,7 @@ data = "{STORE}" fts = "{STORE}" blob = "{STORE}" lookup = "{STORE}" -directory = "auth" +directory = "{STORE}" [jmap.protocol] set.max-objects = 100000 @@ -252,17 +253,9 @@ verify = "SELECT address FROM emails WHERE address LIKE '%' || ? || '%' AND type expand = "SELECT p.address FROM emails AS p JOIN emails AS l ON p.name = l.name WHERE p.type = 'primary' AND l.address = ? AND l.type = 'list' ORDER BY p.address LIMIT 50" domains = "SELECT 1 FROM emails WHERE address LIKE '%@' || ? LIMIT 1" -[directory."auth"] -type = "sql" -store = "auth" - -[directory."auth".columns] -name = "name" -description = "description" -secret = "secret" -email = "address" -quota = "quota" -class = "type" +[directory."{STORE}"] +type = "internal" +store = "{STORE}" [oauth] key = "parerga_und_paralipomena" @@ -386,49 +379,57 @@ async fn init_imap_tests(store_id: &str, delete_if_exists: bool) -> IMAPTest { }; }); + if delete_if_exists { + store.destroy().await; + } + // Create tables and test accounts - let lookup = DirectoryStore { - store: shared_core - .load() - .storage - .lookups - .get("auth") - .unwrap() - .clone(), - }; - lookup.create_test_directory().await; - lookup - .create_test_user("admin", "secret", "Superuser") + store + .create_test_user("admin", "secret", "Superuser", &[]) .await; - lookup - .create_test_user_with_email("jdoe@example.com", "secret", "John Doe") + store + .create_test_user( + "jdoe@example.com", + "secret", + "John Doe", + &["jdoe@example.com"], + ) .await; - lookup - .create_test_user_with_email("jane.smith@example.com", "secret", "Jane Smith") + store + .create_test_user( + "jane.smith@example.com", + "secret", + "Jane Smith", + &["jane.smith@example.com"], + ) .await; - lookup - .create_test_user_with_email("foobar@example.com", "secret", "Bill Foobar") + store + .create_test_user( + "foobar@example.com", + "secret", + "Bill Foobar", + &["foobar@example.com"], + ) .await; - lookup - .create_test_user_with_email("popper@example.com", "secret", "Karl Popper") + store + .create_test_user( + "popper@example.com", + "secret", + "Karl Popper", + &["popper@example.com"], + ) .await; - lookup - .create_test_group_with_email("support@example.com", "Support Group") + store + .create_test_group( + "support@example.com", + "Support Group", + &["support@example.com"], + ) .await; - lookup + store .add_to_group("jane.smith@example.com", "support@example.com") .await; - if delete_if_exists { - store.destroy().await; - } - - // Assign Id 0 to admin (required for some tests) - store - .get_or_create_principal_id("admin", directory::Type::Individual) - .await - .unwrap(); - IMAPTest { jmap: JMAP::from(jmap.clone()).into(), imap: imap.imap_inner, diff --git a/tests/src/jmap/auth_acl.rs b/tests/src/jmap/auth_acl.rs index d3ab2917..23a7d977 100644 --- a/tests/src/jmap/auth_acl.rs +++ b/tests/src/jmap/auth_acl.rs @@ -4,7 +4,6 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use directory::backend::internal::manage::ManageDirectory; use jmap::mailbox::{INBOX_ID, TRASH_ID}; use jmap_client::{ core::{ @@ -19,7 +18,10 @@ use jmap_proto::types::id::Id; use std::fmt::Debug; use store::ahash::AHashMap; -use crate::jmap::{assert_is_empty, mailbox::destroy_all_mailboxes, test_account_login}; +use crate::{ + directory::internal::TestInternalDirectory, + jmap::{assert_is_empty, mailbox::destroy_all_mailboxes, test_account_login}, +}; use super::JMAPTest; @@ -31,53 +33,48 @@ pub async fn test(params: &mut JMAPTest) { let inbox_id = Id::new(INBOX_ID as u64).to_string(); let trash_id = Id::new(TRASH_ID as u64).to_string(); - params - .directory - .create_test_user_with_email("jdoe@example.com", "12345", "John Doe") - .await; - params - .directory - .create_test_user_with_email("jane.smith@example.com", "abcde", "Jane Smith") - .await; - params - .directory - .create_test_user_with_email("bill@example.com", "098765", "Bill Foobar") - .await; - params - .directory - .create_test_group_with_email("sales@example.com", "Sales Group") - .await; let john_id: Id = server .core .storage .data - .get_or_create_principal_id("jdoe@example.com", directory::Type::Individual) + .create_test_user( + "jdoe@example.com", + "12345", + "John Doe", + &["jdoe@example.com"], + ) .await - .unwrap() .into(); let jane_id: Id = server .core .storage .data - .get_or_create_principal_id("jane.smith@example.com", directory::Type::Individual) + .create_test_user( + "jane.smith@example.com", + "abcde", + "Jane Smith", + &["jane.smith@example.com"], + ) .await - .unwrap() .into(); let bill_id: Id = server .core .storage .data - .get_or_create_principal_id("bill@example.com", directory::Type::Individual) + .create_test_user( + "bill@example.com", + "098765", + "Bill Foobar", + &["bill@example.com"], + ) .await - .unwrap() .into(); let sales_id: Id = server .core .storage .data - .get_or_create_principal_id("sales@example.com", directory::Type::Individual) + .create_test_group("sales@example.com", "Sales Group", &["sales@example.com"]) .await - .unwrap() .into(); // Authenticate all accounts @@ -666,8 +663,10 @@ pub async fn test(params: &mut JMAPTest) { // Add John and Jane to the Sales group for name in ["jdoe@example.com", "jane.smith@example.com"] { - params - .directory + server + .core + .storage + .data .add_to_group(name, "sales@example.com") .await; } @@ -765,8 +764,10 @@ pub async fn test(params: &mut JMAPTest) { ); // Remove John from the sales group - params - .directory + server + .core + .storage + .data .remove_from_group("jdoe@example.com", "sales@example.com") .await; server.inner.sessions.clear(); diff --git a/tests/src/jmap/auth_limits.rs b/tests/src/jmap/auth_limits.rs index f492463e..a9b5ad3c 100644 --- a/tests/src/jmap/auth_limits.rs +++ b/tests/src/jmap/auth_limits.rs @@ -11,7 +11,6 @@ use std::{ }; use common::listener::blocked::BLOCKED_IP_KEY; -use directory::backend::internal::manage::ManageDirectory; use imap_proto::ResponseType; use jmap_client::{ client::{Client, Credentials}, @@ -22,6 +21,7 @@ use jmap_proto::types::id::Id; use store::write::now; use crate::{ + directory::internal::TestInternalDirectory, imap::{ImapConnection, Type}, jmap::{assert_is_empty, mailbox::destroy_all_mailboxes}, }; @@ -33,24 +33,20 @@ pub async fn test(params: &mut JMAPTest) { // Create test account let server = params.server.clone(); - params - .directory - .create_test_user_with_email("jdoe@example.com", "12345", "John Doe") - .await; let account_id = Id::from( server .core .storage .data - .get_or_create_principal_id("jdoe@example.com", directory::Type::Individual) - .await - .unwrap(), + .create_test_user( + "jdoe@example.com", + "12345", + "John Doe", + &["jdoe@example.com", "john.doe@example.com"], + ) + .await, ) .to_string(); - params - .directory - .link_test_address("jdoe@example.com", "john.doe@example.com", "alias") - .await; // Reset rate limiters server.inner.concurrency_limiter.clear(); diff --git a/tests/src/jmap/auth_oauth.rs b/tests/src/jmap/auth_oauth.rs index 8248f289..4977c01e 100644 --- a/tests/src/jmap/auth_oauth.rs +++ b/tests/src/jmap/auth_oauth.rs @@ -7,7 +7,6 @@ use std::time::{Duration, Instant}; use bytes::Bytes; -use directory::backend::internal::manage::ManageDirectory; use jmap::auth::oauth::{ DeviceAuthResponse, ErrorType, OAuthCodeRequest, OAuthMetadata, TokenResponse, }; @@ -19,7 +18,10 @@ use jmap_proto::types::id::Id; use serde::de::DeserializeOwned; use store::ahash::AHashMap; -use crate::jmap::{assert_is_empty, mailbox::destroy_all_mailboxes, ManagementApi}; +use crate::{ + directory::internal::TestInternalDirectory, + jmap::{assert_is_empty, mailbox::destroy_all_mailboxes, ManagementApi}, +}; use super::JMAPTest; @@ -36,18 +38,18 @@ pub async fn test(params: &mut JMAPTest) { // Create test account let server = params.server.clone(); - params - .directory - .create_test_user_with_email("jdoe@example.com", "12345", "John Doe") - .await; let john_id = Id::from( server .core .storage .data - .get_or_create_principal_id("jdoe@example.com", directory::Type::Individual) - .await - .unwrap(), + .create_test_user( + "jdoe@example.com", + "12345", + "John Doe", + &["jdoe@example.com"], + ) + .await, ) .to_string(); diff --git a/tests/src/jmap/blob.rs b/tests/src/jmap/blob.rs index 6ffd9e65..423a8363 100644 --- a/tests/src/jmap/blob.rs +++ b/tests/src/jmap/blob.rs @@ -4,32 +4,33 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use directory::backend::internal::manage::ManageDirectory; use jmap::mailbox::INBOX_ID; use jmap_proto::types::id::Id; use serde_json::Value; -use crate::jmap::{assert_is_empty, jmap_json_request, mailbox::destroy_all_mailboxes}; +use crate::{ + directory::internal::TestInternalDirectory, + jmap::{assert_is_empty, jmap_json_request, mailbox::destroy_all_mailboxes}, +}; use super::JMAPTest; pub async fn test(params: &mut JMAPTest) { println!("Running blob tests..."); let server = params.server.clone(); - params - .directory - .create_test_user_with_email("jdoe@example.com", "12345", "John Doe") - .await; let account_id = Id::from( server .core .storage .data - .get_or_create_principal_id("jdoe@example.com", directory::Type::Individual) - .await - .unwrap(), + .create_test_user( + "jdoe@example.com", + "12345", + "John Doe", + &["jdoe@example.com"], + ) + .await, ); - server.core.storage.data.blob_expire_all().await; // Blob/set simple test diff --git a/tests/src/jmap/crypto.rs b/tests/src/jmap/crypto.rs index 61367ed4..18aeb577 100644 --- a/tests/src/jmap/crypto.rs +++ b/tests/src/jmap/crypto.rs @@ -6,14 +6,16 @@ use std::path::PathBuf; -use directory::backend::internal::manage::ManageDirectory; use jmap::email::crypto::{ try_parse_certs, Algorithm, EncryptMessage, EncryptionMethod, EncryptionParams, EncryptionType, }; use jmap_proto::types::id::Id; use mail_parser::{MessageParser, MimeHeaders}; -use crate::jmap::{delivery::SmtpConnection, ManagementApi}; +use crate::{ + directory::internal::TestInternalDirectory, + jmap::{delivery::SmtpConnection, ManagementApi}, +}; use super::JMAPTest; @@ -23,18 +25,18 @@ pub async fn test(params: &mut JMAPTest) { // Create test account let server = params.server.clone(); let client = &mut params.client; - params - .directory - .create_test_user_with_email("jdoe@example.com", "12345", "John Doe") - .await; let account_id = Id::from( server .core .storage .data - .get_or_create_principal_id("jdoe@example.com", directory::Type::Individual) - .await - .unwrap(), + .create_test_user( + "jdoe@example.com", + "12345", + "John Doe", + &["jdoe@example.com"], + ) + .await, ) .to_string(); diff --git a/tests/src/jmap/delivery.rs b/tests/src/jmap/delivery.rs index 2cc6bd56..1b238170 100644 --- a/tests/src/jmap/delivery.rs +++ b/tests/src/jmap/delivery.rs @@ -6,7 +6,6 @@ use std::time::Duration; -use directory::backend::internal::manage::ManageDirectory; use jmap::mailbox::{INBOX_ID, JUNK_ID}; use jmap_proto::types::{collection::Collection, id::Id, property::Property}; @@ -15,7 +14,10 @@ use tokio::{ net::TcpStream, }; -use crate::jmap::{assert_is_empty, mailbox::destroy_all_mailboxes}; +use crate::{ + directory::internal::TestInternalDirectory, + jmap::{assert_is_empty, mailbox::destroy_all_mailboxes}, +}; use super::JMAPTest; @@ -24,65 +26,54 @@ pub async fn test(params: &mut JMAPTest) { // Create a domain name and a test account let server = params.server.clone(); - params - .directory - .create_test_user_with_email("jdoe@example.com", "12345", "John Doe") - .await; - params - .directory - .create_test_user_with_email("jane@example.com", "abcdef", "Jane Smith") - .await; - params - .directory - .create_test_user_with_email("bill@example.com", "098765", "Bill Foobar") - .await; - let account_id_1 = Id::from( - server - .core - .storage - .data - .get_or_create_principal_id("jdoe@example.com", directory::Type::Individual) - .await - .unwrap(), - ) - .to_string(); - let account_id_2 = Id::from( - server - .core - .storage - .data - .get_or_create_principal_id("jane@example.com", directory::Type::Individual) - .await - .unwrap(), - ) - .to_string(); - let account_id_3 = Id::from( - server - .core - .storage - .data - .get_or_create_principal_id("bill@example.com", directory::Type::Individual) - .await - .unwrap(), - ) - .to_string(); - params - .directory - .link_test_address("jdoe@example.com", "john.doe@example.com", "alias") - .await; + let mut account_id_1 = String::new(); + let mut account_id_2 = String::new(); + let mut account_id_3 = String::new(); + + for (id, email, password, name, aliases) in [ + ( + &mut account_id_1, + "jdoe@example.com", + "12345", + "John Doe", + Some(&["jdoe@example.com", "john.doe@example.com"][..]), + ), + ( + &mut account_id_2, + "jane@example.com", + "abcdef", + "Jane Smith", + None, + ), + ( + &mut account_id_3, + "bill@example.com", + "098765", + "Bill Foobar", + None, + ), + ] { + *id = Id::from( + server + .core + .storage + .data + .create_test_user(email, password, name, aliases.unwrap_or(&[email][..])) + .await, + ) + .to_string(); + } // Create a mailing list - params - .directory - .link_test_address("jdoe@example.com", "members@example.com", "list") - .await; - params - .directory - .link_test_address("jane@example.com", "members@example.com", "list") - .await; - params - .directory - .link_test_address("bill@example.com", "members@example.com", "list") + server + .core + .storage + .data + .create_test_list( + "members@example.com", + "Mailing List", + &["jdoe@example.com", "jane@example.com", "bill@example.com"], + ) .await; // Delivering to individuals @@ -225,8 +216,11 @@ pub async fn test(params: &mut JMAPTest) { // Removing members from the mailing list and chunked ingest params - .directory - .remove_test_alias("jdoe@example.com", "members@example.com") + .server + .core + .storage + .data + .remove_from_group("jdoe@example.com", "members@example.com") .await; lmtp.ingest_chunked( "bill@example.com", diff --git a/tests/src/jmap/email_submission.rs b/tests/src/jmap/email_submission.rs index b4bdb4ff..0f1e996c 100644 --- a/tests/src/jmap/email_submission.rs +++ b/tests/src/jmap/email_submission.rs @@ -5,7 +5,6 @@ */ use ahash::AHashMap; -use directory::backend::internal::manage::ManageDirectory; use jmap_client::{ core::set::{SetError, SetErrorType, SetObject}, email_submission::{query::Filter, Address, Delivered, DeliveryStatus, Displayed, UndoStatus}, @@ -26,8 +25,9 @@ use tokio::{ sync::mpsc, }; -use crate::jmap::{ - assert_is_empty, email_set::assert_email_properties, mailbox::destroy_all_mailboxes, +use crate::{ + directory::internal::TestInternalDirectory, + jmap::{assert_is_empty, email_set::assert_email_properties, mailbox::destroy_all_mailboxes}, }; use super::JMAPTest; @@ -76,22 +76,18 @@ pub async fn test(params: &mut JMAPTest) { // Create a test account let server = params.server.clone(); - params - .directory - .create_test_user_with_email("jdoe@example.com", "12345", "John Doe") - .await; - params - .directory - .link_test_address("jdoe@example.com", "john.doe@example.com", "alias") - .await; let account_id = Id::from( server .core .storage .data - .get_or_create_principal_id("jdoe@example.com", directory::Type::Individual) - .await - .unwrap(), + .create_test_user( + "jdoe@example.com", + "12345", + "John Doe", + &["jdoe@example.com", "john.doe@example.com"], + ) + .await, ) .to_string(); diff --git a/tests/src/jmap/enterprise.rs b/tests/src/jmap/enterprise.rs index 2135a84e..fc6fc491 100644 --- a/tests/src/jmap/enterprise.rs +++ b/tests/src/jmap/enterprise.rs @@ -35,6 +35,7 @@ use trc::{ use utils::config::{cron::SimpleCron, Config}; use crate::{ + directory::internal::TestInternalDirectory, imap::{ImapConnection, Type}, jmap::delivery::SmtpConnection, AssertConfig, @@ -112,8 +113,17 @@ pub async fn test(params: &mut JMAPTest) { // Create test account params - .directory - .create_test_user_with_email("jdoe@example.com", "secret", "John Doe") + .server + .shared_core + .load() + .storage + .data + .create_test_user( + "jdoe@example.com", + "secret", + "John Doe", + &["jdoe@example.com"], + ) .await; alerts(¶ms.server.shared_core.load()).await; @@ -121,10 +131,39 @@ pub async fn test(params: &mut JMAPTest) { tracing(params).await; metrics(params).await; - // Disable Enterprise - let mut core = params.server.shared_core.load_full().as_ref().clone(); - core.enterprise = None; - params.server.shared_core.store(core.into()); + params.server.shared_core.store( + params + .server + .shared_core + .load_full() + .as_ref() + .clone() + .enable_enterprise() + .into(), + ); +} + +pub trait EnterpriseCore { + fn enable_enterprise(self) -> Self; +} + +impl EnterpriseCore for Core { + fn enable_enterprise(mut self) -> Self { + self.enterprise = Enterprise { + license: LicenseKey { + valid_to: now() + 3600, + valid_from: now() - 3600, + hostname: String::new(), + accounts: 100, + }, + undelete: None, + trace_store: None, + metrics_store: None, + metrics_alerts: vec![], + } + .into(); + self + } } async fn alerts(core: &Core) { diff --git a/tests/src/jmap/event_source.rs b/tests/src/jmap/event_source.rs index ed221172..a74e755f 100644 --- a/tests/src/jmap/event_source.rs +++ b/tests/src/jmap/event_source.rs @@ -6,10 +6,13 @@ use std::time::Duration; -use crate::jmap::{ - assert_is_empty, delivery::SmtpConnection, mailbox::destroy_all_mailboxes, test_account_login, +use crate::{ + directory::internal::TestInternalDirectory, + jmap::{ + assert_is_empty, delivery::SmtpConnection, mailbox::destroy_all_mailboxes, + test_account_login, + }, }; -use directory::backend::internal::manage::ManageDirectory; use futures::StreamExt; use jmap::mailbox::INBOX_ID; use jmap_client::{event_source::Changes, mailbox::Role, TypeState}; @@ -25,20 +28,21 @@ pub async fn test(params: &mut JMAPTest) { // Create test account let server = params.server.clone(); - params - .directory - .create_test_user_with_email("jdoe@example.com", "12345", "John Doe") - .await; let account_id = Id::from( server .core .storage .data - .get_or_create_principal_id("jdoe@example.com", directory::Type::Individual) - .await - .unwrap(), + .create_test_user( + "jdoe@example.com", + "12345", + "John Doe", + &["jdoe@example.com"], + ) + .await, ) .to_string(); + let client = test_account_login("jdoe@example.com", "12345").await; let mut changes = client diff --git a/tests/src/jmap/mod.rs b/tests/src/jmap/mod.rs index 12b50154..1978cec5 100644 --- a/tests/src/jmap/mod.rs +++ b/tests/src/jmap/mod.rs @@ -23,7 +23,7 @@ use common::{ manager::config::{ConfigManager, Patterns}, Core, Ipc, IPC_CHANNEL_BUFFER, }; -use enterprise::insert_test_metrics; +use enterprise::{insert_test_metrics, EnterpriseCore}; use hyper::{header::AUTHORIZATION, Method}; use imap::core::{ImapSessionManager, IMAP}; use jmap::{api::JmapSessionManager, JMAP}; @@ -44,7 +44,9 @@ use tokio::sync::{mpsc, watch}; use utils::{config::Config, map::ttl_dashmap::TtlMap, BlobHash}; use webhooks::{spawn_mock_webhook_endpoint, MockWebhookEndpoint}; -use crate::{add_test_certs, directory::DirectoryStore, store::TempDir, AssertConfig}; +use crate::{ + add_test_certs, directory::internal::TestInternalDirectory, store::TempDir, AssertConfig, +}; pub mod auth_acl; pub mod auth_limits; @@ -117,7 +119,7 @@ reject-non-fqdn = false [session.rcpt] relay = [ { if = "!is_empty(authenticated_as)", then = true }, { else = false } ] -directory = "'auth'" +directory = "'{STORE}'" [session.rcpt.errors] total = 5 @@ -196,7 +198,7 @@ data = "{STORE}" fts = "{STORE}" blob = "{STORE}" lookup = "{STORE}" -directory = "auth" +directory = "{STORE}" [spam.header] is-spam = "X-Spam-Status: Yes" @@ -252,17 +254,9 @@ verify = "SELECT address FROM emails WHERE address LIKE '%' || ? || '%' AND type expand = "SELECT p.address FROM emails AS p JOIN emails AS l ON p.name = l.name WHERE p.type = 'primary' AND l.address = ? AND l.type = 'list' ORDER BY p.address LIMIT 50" domains = "SELECT 1 FROM emails WHERE address LIKE '%@' || ? LIMIT 1" -[directory."auth"] -type = "sql" -store = "auth" - -[directory."auth".columns] -name = "name" -description = "description" -secret = "secret" -email = "address" -quota = "quota" -class = "type" +[directory."{STORE}"] +type = "internal" +store = "{STORE}" [imap.auth] allow-plain-text = true @@ -316,7 +310,7 @@ pub async fn jmap_tests() { .await; webhooks::test(&mut params).await; - /*email_query::test(&mut params, delete).await; + /* //email_query::test(&mut params, delete).await; email_get::test(&mut params).await; email_set::test(&mut params).await; email_parse::test(&mut params).await; @@ -324,12 +318,12 @@ pub async fn jmap_tests() { email_changes::test(&mut params).await; email_query_changes::test(&mut params).await; email_copy::test(&mut params).await; - thread_get::test(&mut params).await; - thread_merge::test(&mut params).await; + //thread_get::test(&mut params).await; + //thread_merge::test(&mut params).await; mailbox::test(&mut params).await; delivery::test(&mut params).await; auth_acl::test(&mut params).await; - auth_limits::test(&mut params).await;*/ + auth_limits::test(&mut params).await; auth_oauth::test(&mut params).await; event_source::test(&mut params).await; push_subscription::test(&mut params).await; @@ -339,7 +333,7 @@ pub async fn jmap_tests() { websocket::test(&mut params).await; quota::test(&mut params).await; crypto::test(&mut params).await; - blob::test(&mut params).await; + blob::test(&mut params).await;*/ purge::test(&mut params).await; enterprise::test(&mut params).await; @@ -378,7 +372,6 @@ pub async fn jmap_metric_tests() { pub struct JMAPTest { server: Arc<JMAP>, client: Client, - directory: DirectoryStore, temp_dir: TempDir, webhook: Arc<MockWebhookEndpoint>, shutdown_tx: watch::Sender<bool>, @@ -531,7 +524,9 @@ async fn init_jmap_tests(store_id: &str, delete_if_exists: bool) -> JMAPTest { .unwrap_or_default(), }; let tracers = Telemetry::parse(&mut config, &stores); - let core = Core::parse(&mut config, stores, config_manager).await; + let core = Core::parse(&mut config, stores, config_manager) + .await + .enable_enterprise(); let store = core.storage.data.clone(); let shared_core = core.into_shared(); @@ -599,25 +594,18 @@ async fn init_jmap_tests(store_id: &str, delete_if_exists: bool) -> JMAPTest { }; }); - // Create tables - let directory = DirectoryStore { - store: shared_core - .load() - .storage - .lookups - .get("auth") - .unwrap() - .clone(), - }; - directory.create_test_directory().await; - directory - .create_test_user("admin", "secret", "Superuser") - .await; - if delete_if_exists { store.destroy().await; } + // Create tables + shared_core + .load() + .storage + .data + .create_test_user("admin", "secret", "Superuser", &[]) + .await; + // Create client let mut client = Client::new() .credentials(Credentials::basic("admin", "secret")) @@ -632,7 +620,6 @@ async fn init_jmap_tests(store_id: &str, delete_if_exists: bool) -> JMAPTest { server: JMAP::from(jmap).into(), temp_dir, client, - directory, shutdown_tx, webhook: spawn_mock_webhook_endpoint(), } diff --git a/tests/src/jmap/purge.rs b/tests/src/jmap/purge.rs index c979b8f6..3849ee73 100644 --- a/tests/src/jmap/purge.rs +++ b/tests/src/jmap/purge.rs @@ -5,7 +5,7 @@ */ use ahash::AHashSet; -use directory::backend::internal::manage::ManageDirectory; +use directory::{backend::internal::manage::ManageDirectory, QueryBy}; use imap_proto::ResponseType; use jmap::{ mailbox::{INBOX_ID, JUNK_ID, TRASH_ID}, @@ -17,7 +17,11 @@ use store::{ IterateParams, LogKey, U32_LEN, U64_LEN, }; -use crate::imap::{AssertResult, ImapConnection, Type}; +use crate::{ + directory::internal::TestInternalDirectory, + imap::{AssertResult, ImapConnection, Type}, + jmap::assert_is_empty, +}; use super::JMAPTest; @@ -30,17 +34,18 @@ pub async fn test(params: &mut JMAPTest) { let junk_id = Id::from(JUNK_ID).to_string(); // Connect to IMAP - params - .directory - .create_test_user_with_email("jdoe@example.com", "12345", "John Doe") - .await; let account_id = server .core .storage .data - .get_or_create_principal_id("jdoe@example.com", directory::Type::Individual) - .await - .unwrap(); + .create_test_user( + "jdoe@example.com", + "12345", + "John Doe", + &["jdoe@example.com"], + ) + .await; + let mut imap = ImapConnection::connect(b"_x ").await; imap.assert_read(Type::Untagged, ResponseType::Ok).await; imap.send("LOGIN \"jdoe@example.com\" \"12345\"").await; @@ -188,6 +193,16 @@ pub async fn test(params: &mut JMAPTest) { change ); } + + // Delete account + server + .core + .storage + .data + .delete_principal(QueryBy::Id(account_id)) + .await + .unwrap(); + assert_is_empty(server).await; } async fn get_changes(server: &JMAP) -> AHashSet<(u64, u8)> { diff --git a/tests/src/jmap/push_subscription.rs b/tests/src/jmap/push_subscription.rs index 5bce030b..442e9172 100644 --- a/tests/src/jmap/push_subscription.rs +++ b/tests/src/jmap/push_subscription.rs @@ -14,7 +14,6 @@ use std::{ use base64::{engine::general_purpose, Engine}; use common::{config::server::Servers, listener::SessionData, Core}; -use directory::backend::internal::manage::ManageDirectory; use ece::EcKeyComponents; use hyper::{body, header::CONTENT_ENCODING, server::conn::http1, service::service_fn, StatusCode}; use hyper_util::rt::TokioIo; @@ -34,6 +33,7 @@ use utils::config::Config; use crate::{ add_test_certs, + directory::internal::TestInternalDirectory, jmap::{assert_is_empty, mailbox::destroy_all_mailboxes, test_account_login}, AssertConfig, }; @@ -64,19 +64,20 @@ pub async fn test(params: &mut JMAPTest) { // Create test account let server = params.server.clone(); - params - .directory - .create_test_user_with_email("jdoe@example.com", "12345", "John Doe") - .await; let account_id = Id::from( server .core .storage .data - .get_or_create_principal_id("jdoe@example.com", directory::Type::Individual) - .await - .unwrap(), + .create_test_user( + "jdoe@example.com", + "12345", + "John Doe", + &["jdoe@example.com"], + ) + .await, ); + params.client.set_default_account_id(account_id); let client = test_account_login("jdoe@example.com", "12345").await; diff --git a/tests/src/jmap/quota.rs b/tests/src/jmap/quota.rs index c20e9bd1..c186c90f 100644 --- a/tests/src/jmap/quota.rs +++ b/tests/src/jmap/quota.rs @@ -4,11 +4,13 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use crate::jmap::{ - assert_is_empty, delivery::SmtpConnection, emails_purge_tombstoned, jmap_raw_request, - mailbox::destroy_all_mailboxes, test_account_login, +use crate::{ + directory::internal::TestInternalDirectory, + jmap::{ + assert_is_empty, delivery::SmtpConnection, emails_purge_tombstoned, jmap_raw_request, + mailbox::destroy_all_mailboxes, test_account_login, + }, }; -use directory::backend::internal::manage::ManageDirectory; use jmap::{blob::upload::DISABLE_UPLOAD_QUOTA, mailbox::INBOX_ID}; use jmap_client::{ core::set::{SetErrorType, SetObject}, @@ -21,38 +23,43 @@ use super::JMAPTest; pub async fn test(params: &mut JMAPTest) { println!("Running quota tests..."); let server = params.server.clone(); - params - .directory - .create_test_user_with_email("jdoe@example.com", "12345", "John Doe") - .await; - params - .directory - .create_test_user_with_email("robert@example.com", "aabbcc", "Robert Foobar") - .await; - let other_account_id = Id::from( - server - .core - .storage - .data - .get_or_create_principal_id("jdoe@example.com", directory::Type::Individual) - .await - .unwrap(), - ); - let account_id = Id::from( - server - .core - .storage - .data - .get_or_create_principal_id("robert@example.com", directory::Type::Individual) - .await - .unwrap(), - ); - params - .directory + let mut account_id = Id::from(0u64); + let mut other_account_id = Id::from(0u64); + + for (id, email, password, name) in [ + ( + &mut other_account_id, + "jdoe@example.com", + "12345", + "John Doe", + ), + ( + &mut account_id, + "robert@example.com", + "aabbcc", + "Robert Foobar", + ), + ] { + *id = Id::from( + server + .core + .storage + .data + .create_test_user(email, password, name, &[email][..]) + .await, + ); + } + + server + .core + .storage + .data .set_test_quota("robert@example.com", 1024) .await; - params - .directory + server + .core + .storage + .data .add_to_group("robert@example.com", "jdoe@example.com") .await; diff --git a/tests/src/jmap/sieve_script.rs b/tests/src/jmap/sieve_script.rs index 455fda11..683dbe8a 100644 --- a/tests/src/jmap/sieve_script.rs +++ b/tests/src/jmap/sieve_script.rs @@ -4,7 +4,6 @@ * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ -use directory::backend::internal::manage::ManageDirectory; use jmap_client::{ core::set::{SetError, SetErrorType}, email, mailbox, @@ -18,11 +17,14 @@ use std::{ time::{Duration, Instant}, }; -use crate::jmap::{ - assert_is_empty, - delivery::SmtpConnection, - email_submission::{assert_message_delivery, spawn_mock_smtp_server, MockMessage}, - mailbox::destroy_all_mailboxes, +use crate::{ + directory::internal::TestInternalDirectory, + jmap::{ + assert_is_empty, + delivery::SmtpConnection, + email_submission::{assert_message_delivery, spawn_mock_smtp_server, MockMessage}, + mailbox::destroy_all_mailboxes, + }, }; use super::JMAPTest; @@ -33,18 +35,18 @@ pub async fn test(params: &mut JMAPTest) { let client = &mut params.client; // Create test account - params - .directory - .create_test_user_with_email("jdoe@example.com", "12345", "John Doe") - .await; let account_id = Id::from( server .core .storage .data - .get_or_create_principal_id("jdoe@example.com", directory::Type::Individual) - .await - .unwrap(), + .create_test_user( + "jdoe@example.com", + "12345", + "John Doe", + &["jdoe@example.com"], + ) + .await, ) .to_string(); client.set_default_account_id(&account_id); diff --git a/tests/src/jmap/vacation_response.rs b/tests/src/jmap/vacation_response.rs index f1c58998..72520939 100644 --- a/tests/src/jmap/vacation_response.rs +++ b/tests/src/jmap/vacation_response.rs @@ -6,17 +6,19 @@ use chrono::{TimeDelta, Utc}; -use directory::backend::internal::manage::ManageDirectory; use jmap_proto::types::id::Id; use std::time::Instant; -use crate::jmap::{ - assert_is_empty, - delivery::SmtpConnection, - email_submission::{ - assert_message_delivery, expect_nothing, spawn_mock_smtp_server, MockMessage, +use crate::{ + directory::internal::TestInternalDirectory, + jmap::{ + assert_is_empty, + delivery::SmtpConnection, + email_submission::{ + assert_message_delivery, expect_nothing, spawn_mock_smtp_server, MockMessage, + }, + mailbox::destroy_all_mailboxes, }, - mailbox::destroy_all_mailboxes, }; use super::JMAPTest; @@ -27,18 +29,18 @@ pub async fn test(params: &mut JMAPTest) { // Create test account let server = params.server.clone(); let client = &mut params.client; - params - .directory - .create_test_user_with_email("jdoe@example.com", "12345", "John Doe") - .await; let account_id = Id::from( server .core .storage .data - .get_or_create_principal_id("jdoe@example.com", directory::Type::Individual) - .await - .unwrap(), + .create_test_user( + "jdoe@example.com", + "12345", + "John Doe", + &["jdoe@example.com"], + ) + .await, ) .to_string(); client.set_default_account_id(&account_id); diff --git a/tests/src/jmap/websocket.rs b/tests/src/jmap/websocket.rs index ad9fcc1c..36745164 100644 --- a/tests/src/jmap/websocket.rs +++ b/tests/src/jmap/websocket.rs @@ -5,7 +5,6 @@ */ use ahash::AHashSet; -use directory::backend::internal::manage::ManageDirectory; use futures::StreamExt; use jmap_client::{ client_ws::WebSocketMessage, @@ -20,7 +19,10 @@ use std::time::Duration; use tokio::sync::mpsc; -use crate::jmap::{assert_is_empty, mailbox::destroy_all_mailboxes, test_account_login}; +use crate::{ + directory::internal::TestInternalDirectory, + jmap::{assert_is_empty, mailbox::destroy_all_mailboxes, test_account_login}, +}; use super::JMAPTest; @@ -29,18 +31,18 @@ pub async fn test(params: &mut JMAPTest) { let server = params.server.clone(); // Authenticate all accounts - params - .directory - .create_test_user_with_email("jdoe@example.com", "12345", "John Doe") - .await; let account_id = Id::from( server .core .storage .data - .get_or_create_principal_id("jdoe@example.com", directory::Type::Individual) - .await - .unwrap(), + .create_test_user( + "jdoe@example.com", + "12345", + "John Doe", + &["jdoe@example.com"], + ) + .await, ) .to_string(); let client = test_account_login("jdoe@example.com", "12345").await; |