/* * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ use crate::utils::server::TestServerBuilder; use registry::schema::{ prelude::ObjectType, structs::{Account, Domain, EmailAlias}, }; use types::id::Id; pub async fn test() { let test = TestServerBuilder::new("directory_synchronization_test") .await .with_default_listeners() .await .disable_services() .build() .await; let admin = test.account("admin"); // Synchronizing an account with an unknown domain should fail assert!( test.server .synchronize_account(directory::Account { email: "john@unknown.org".to_string(), email_aliases: vec![], secret: "supersecret".to_string().into(), groups: vec![], description: "John Doe".to_string().into(), }) .await .is_err() ); // Initial account synchronization let mut account_in = directory::Account { email: "john@example.org".to_string(), email_aliases: vec![ "john.doe@example.org".to_string(), "j.doe@example.org".to_string(), ], secret: "supersecret".to_string().into(), groups: vec![ "corporate@example.org".to_string(), "sales@example.org".to_string(), ], description: "John Doe".to_string().into(), }; let result = test .server .synchronize_account(account_in.clone()) .await .unwrap(); let account_id = Id::from(result.id); let account_out = test .server .registry() .object::(account_id) .await .unwrap() .unwrap() .into_user() .unwrap(); let domain_id = account_out.domain_id; assert_eq!( admin.registry_get::(domain_id).await.name, "example.org" ); assert_eq!(account_out.name, "john"); assert_eq!(account_out.description.as_deref(), Some("John Doe")); assert_eq!( account_out .credentials .values() .next() .and_then(|v| v.as_main_credential()) .map(|c| c.secret.as_str()), Some("supersecret") ); assert_eq!(account_out.aliases.len(), 2); let aliases = account_out.aliases.iter().collect::>(); assert_eq!( aliases[0], &EmailAlias { description: None, domain_id, enabled: true, name: "john.doe".to_string(), } ); assert_eq!( aliases[1], &EmailAlias { description: None, domain_id, enabled: true, name: "j.doe".to_string(), } ); assert_eq!(account_out.member_group_ids.len(), 2); for (idx, group_id) in account_out.member_group_ids.iter().enumerate() { let group = admin .registry_get::(*group_id) .await .into_group() .unwrap(); assert_eq!(group.name, if idx == 0 { "corporate" } else { "sales" }); assert_eq!(group.domain_id, domain_id); } assert_eq!( test.server .registry() .count_object(ObjectType::Account) .await .unwrap(), 3 ); assert_eq!( test.server .registry() .count_object(ObjectType::Domain) .await .unwrap(), 1 ); // No changes should not cause any updates assert_eq!( test.server .synchronize_account(account_in.clone()) .await .unwrap() .id, account_id.document_id() ); assert_eq!( test.server .registry() .object::(account_id) .await .unwrap() .unwrap() .into_user() .unwrap(), account_out ); assert_eq!( test.server .registry() .count_object(ObjectType::Account) .await .unwrap(), 3 ); // Make some changes and synchronize again account_in.description = "Johnathan Doe".to_string().into(); account_in .email_aliases .push("johnny@example.org".to_string()); account_in.groups.pop(); account_in.groups.push("support@example.org".to_string()); account_in.secret = "evenmoresecret".to_string().into(); assert_eq!( test.server .synchronize_account(account_in.clone()) .await .unwrap() .id, account_id.document_id() ); let account_out = test .server .registry() .object::(account_id) .await .unwrap() .unwrap() .into_user() .unwrap(); assert_eq!( account_out .credentials .values() .next() .and_then(|v| v.as_main_credential()) .map(|c| c.secret.as_str()), Some("evenmoresecret") ); assert_eq!(account_out.description.as_deref(), Some("Johnathan Doe")); assert_eq!(account_out.aliases.len(), 3); let aliases = account_out.aliases.iter().collect::>(); assert_eq!( aliases[2], &EmailAlias { description: None, domain_id, enabled: true, name: "johnny".to_string(), } ); assert_eq!(account_out.member_group_ids.len(), 2); let account_groups = account_out .member_group_ids .iter() .copied() .collect::>(); for (idx, group_id) in account_groups.iter().enumerate() { let group = admin .registry_get::(*group_id) .await .into_group() .unwrap(); assert_eq!(group.name, if idx == 0 { "corporate" } else { "support" }); assert_eq!(group.domain_id, domain_id); } assert_eq!( test.server .registry() .count_object(ObjectType::Account) .await .unwrap(), 4 ); // Synchronize a group assert_eq!( test.server .synchronize_group(directory::Group { email: "corporate@example.org".to_string(), email_aliases: vec!["everyone@example.org".to_string()], description: "Corporate Group".to_string().into(), }) .await .unwrap(), account_groups[0].document_id() ); let group_out = test .server .registry() .object::(account_groups[0]) .await .unwrap() .unwrap() .into_group() .unwrap(); assert_eq!(group_out.name, "corporate"); assert_eq!(group_out.description.as_deref(), Some("Corporate Group")); assert_eq!(group_out.aliases.len(), 1); let aliases = group_out.aliases.iter().collect::>(); assert_eq!( aliases[0], &EmailAlias { description: None, domain_id, enabled: true, name: "everyone".to_string(), } ); assert_eq!( test.server .registry() .count_object(ObjectType::Account) .await .unwrap(), 4 ); }