Files
Stalwart/tests/src/directory/synchronization.rs

306 lines
8.2 KiB
Rust

/*
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
*
* 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() {
println!("Running directory synchronization tests...");
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: Some(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: Some(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>(account_id)
.await
.unwrap()
.unwrap()
.into_user()
.unwrap();
let domain_id = account_out.domain_id;
assert_eq!(
admin.registry_get::<Domain>(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::<Vec<_>>();
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::<Account>(*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>(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());
let groups = account_in.groups.get_or_insert_default();
groups.pop();
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>(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::<Vec<_>>();
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::<Vec<_>>();
for (idx, group_id) in account_groups.iter().enumerate() {
let group = admin
.registry_get::<Account>(*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
);
account_in.groups = None;
test.server
.synchronize_account(account_in.clone())
.await
.unwrap();
let account_out = test
.server
.registry()
.object::<Account>(account_id)
.await
.unwrap()
.unwrap()
.into_user()
.unwrap();
assert_eq!(account_out.member_group_ids.len(), 2);
account_in.groups = Some(vec![]);
test.server
.synchronize_account(account_in.clone())
.await
.unwrap();
let account_out = test
.server
.registry()
.object::<Account>(account_id)
.await
.unwrap()
.unwrap()
.into_user()
.unwrap();
assert_eq!(account_out.member_group_ids.len(), 0);
// 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>(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::<Vec<_>>();
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
);
}