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.
This commit is contained in:
@@ -0,0 +1,674 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use crate::utils::{jmap::JmapUtils, server::TestServer};
|
||||
use calcard::jscontact::JSContactProperty;
|
||||
use jmap_proto::{
|
||||
object::{addressbook::AddressBookProperty, share_notification::ShareNotificationProperty},
|
||||
request::method::MethodObject,
|
||||
};
|
||||
use serde_json::json;
|
||||
use types::id::Id;
|
||||
|
||||
pub async fn test(test: &TestServer) {
|
||||
println!("Running Contacts ACL tests...");
|
||||
let john = test.account("[email protected]");
|
||||
let jane = test.account("[email protected]");
|
||||
let john_id = john.id_string().to_string();
|
||||
let jane_id = jane.id_string().to_string();
|
||||
|
||||
// Create test address books
|
||||
let response = john
|
||||
.jmap_create(
|
||||
MethodObject::AddressBook,
|
||||
[json!({
|
||||
"name": "Test #1",
|
||||
})],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await;
|
||||
let john_book_id = response.created(0).id().to_string();
|
||||
let john_contact_id = john
|
||||
.jmap_create(
|
||||
MethodObject::ContactCard,
|
||||
[json!({
|
||||
"uid": "abc123",
|
||||
"name": {
|
||||
"full": "John's Simple Contact",
|
||||
},
|
||||
"addressBookIds": {
|
||||
&john_book_id: true
|
||||
},
|
||||
})],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await
|
||||
.created(0)
|
||||
.id()
|
||||
.to_string();
|
||||
let response = jane
|
||||
.jmap_create(
|
||||
MethodObject::AddressBook,
|
||||
[json!({
|
||||
"name": "Test #1",
|
||||
})],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await;
|
||||
let jane_book_id = response.created(0).id().to_string();
|
||||
let jane_contact_id = jane
|
||||
.jmap_create(
|
||||
MethodObject::ContactCard,
|
||||
[json!({
|
||||
"uid": "abc456",
|
||||
"name": {
|
||||
"full": "Jane's Simple Contact",
|
||||
},
|
||||
"addressBookIds": {
|
||||
&jane_book_id: true
|
||||
},
|
||||
})],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await
|
||||
.created(0)
|
||||
.id()
|
||||
.to_string();
|
||||
|
||||
// Verify myRights
|
||||
john.jmap_get(
|
||||
MethodObject::AddressBook,
|
||||
[
|
||||
AddressBookProperty::Id,
|
||||
AddressBookProperty::Name,
|
||||
AddressBookProperty::MyRights,
|
||||
AddressBookProperty::ShareWith,
|
||||
],
|
||||
[john_book_id.as_str()],
|
||||
)
|
||||
.await
|
||||
.list()[0]
|
||||
.assert_is_equal(json!({
|
||||
"id": john_book_id,
|
||||
"name": "Test #1",
|
||||
"myRights": {
|
||||
"mayRead": true,
|
||||
"mayWrite": true,
|
||||
"mayDelete": true,
|
||||
"mayShare": true
|
||||
},
|
||||
"shareWith": {}
|
||||
}));
|
||||
|
||||
// Obtain share notifications
|
||||
let mut jane_share_change_id = jane
|
||||
.jmap_get(
|
||||
MethodObject::ShareNotification,
|
||||
Vec::<&str>::new(),
|
||||
Vec::<&str>::new(),
|
||||
)
|
||||
.await
|
||||
.state()
|
||||
.to_string();
|
||||
|
||||
// Make sure Jane has no access
|
||||
assert_eq!(
|
||||
jane.jmap_get_account(
|
||||
john,
|
||||
MethodObject::AddressBook,
|
||||
Vec::<&str>::new(),
|
||||
[john_book_id.as_str()],
|
||||
)
|
||||
.await
|
||||
.method_response()
|
||||
.typ(),
|
||||
"forbidden"
|
||||
);
|
||||
|
||||
// Share address book with Jane
|
||||
john.jmap_update(
|
||||
MethodObject::AddressBook,
|
||||
[(
|
||||
&john_book_id,
|
||||
json!({
|
||||
"shareWith": {
|
||||
&jane_id : {
|
||||
"mayRead": true,
|
||||
}
|
||||
}
|
||||
}),
|
||||
)],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await
|
||||
.updated(&john_book_id);
|
||||
john.jmap_get(
|
||||
MethodObject::AddressBook,
|
||||
[
|
||||
AddressBookProperty::Id,
|
||||
AddressBookProperty::Name,
|
||||
AddressBookProperty::ShareWith,
|
||||
],
|
||||
[john_book_id.as_str()],
|
||||
)
|
||||
.await
|
||||
.list()[0]
|
||||
.assert_is_equal(json!({
|
||||
"id": john_book_id,
|
||||
"name": "Test #1",
|
||||
"shareWith": {
|
||||
&jane_id : {
|
||||
"mayRead": true,
|
||||
"mayWrite": false,
|
||||
"mayDelete": false,
|
||||
"mayShare": false
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
// Verify Jane can access the contact
|
||||
jane.jmap_get_account(
|
||||
john,
|
||||
MethodObject::AddressBook,
|
||||
[
|
||||
AddressBookProperty::Id,
|
||||
AddressBookProperty::Name,
|
||||
AddressBookProperty::MyRights,
|
||||
],
|
||||
[john_book_id.as_str()],
|
||||
)
|
||||
.await
|
||||
.list()[0]
|
||||
.assert_is_equal(json!({
|
||||
"id": john_book_id,
|
||||
"name": "Test #1",
|
||||
"myRights": {
|
||||
"mayRead": true,
|
||||
"mayWrite": false,
|
||||
"mayDelete": false,
|
||||
"mayShare": false
|
||||
}
|
||||
}));
|
||||
jane.jmap_get_account(
|
||||
john,
|
||||
MethodObject::ContactCard,
|
||||
[AddressBookProperty::Id, AddressBookProperty::Name],
|
||||
[john_contact_id.as_str()],
|
||||
)
|
||||
.await
|
||||
.list()[0]
|
||||
.assert_is_equal(json!({
|
||||
"id": john_contact_id,
|
||||
"name": {
|
||||
"full": "John's Simple Contact"
|
||||
},
|
||||
}));
|
||||
|
||||
// Verify Jane received a share notification
|
||||
let response = jane
|
||||
.jmap_changes(MethodObject::ShareNotification, &jane_share_change_id)
|
||||
.await;
|
||||
jane_share_change_id = response.new_state().to_string();
|
||||
let changes = response.changes().collect::<Vec<_>>();
|
||||
assert_eq!(changes.len(), 1);
|
||||
let share_id = changes[0].as_created();
|
||||
jane.jmap_get(
|
||||
MethodObject::ShareNotification,
|
||||
[
|
||||
ShareNotificationProperty::Id,
|
||||
ShareNotificationProperty::ChangedBy,
|
||||
ShareNotificationProperty::ObjectType,
|
||||
ShareNotificationProperty::ObjectAccountId,
|
||||
ShareNotificationProperty::ObjectId,
|
||||
ShareNotificationProperty::OldRights,
|
||||
ShareNotificationProperty::NewRights,
|
||||
ShareNotificationProperty::Name,
|
||||
],
|
||||
[share_id],
|
||||
)
|
||||
.await
|
||||
.list()[0]
|
||||
.assert_is_equal(json!({
|
||||
"id": &share_id,
|
||||
"changedBy": {
|
||||
"principalId": &john_id,
|
||||
"name": "John Doe",
|
||||
"email": "[email protected]"
|
||||
},
|
||||
"objectType": "AddressBook",
|
||||
"objectAccountId": &john_id,
|
||||
"objectId": &john_book_id,
|
||||
"oldRights": {
|
||||
"mayRead": false,
|
||||
"mayWrite": false,
|
||||
"mayDelete": false,
|
||||
"mayShare": false
|
||||
},
|
||||
"newRights": {
|
||||
"mayRead": true,
|
||||
"mayWrite": false,
|
||||
"mayDelete": false,
|
||||
"mayShare": false
|
||||
},
|
||||
"name": null
|
||||
}));
|
||||
|
||||
// Updating and deleting should fail
|
||||
assert_eq!(
|
||||
jane.jmap_update_account(
|
||||
john,
|
||||
MethodObject::AddressBook,
|
||||
[(&john_book_id, json!({}))],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await
|
||||
.not_updated(&john_book_id)
|
||||
.description(),
|
||||
"You are not allowed to modify this address book."
|
||||
);
|
||||
assert_eq!(
|
||||
jane.jmap_destroy_account(
|
||||
john,
|
||||
MethodObject::AddressBook,
|
||||
[&john_book_id],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await
|
||||
.not_destroyed(&john_book_id)
|
||||
.description(),
|
||||
"You are not allowed to delete this address book."
|
||||
);
|
||||
assert!(
|
||||
jane.jmap_update_account(
|
||||
john,
|
||||
MethodObject::ContactCard,
|
||||
[(&john_contact_id, json!({}))],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await
|
||||
.not_updated(&john_contact_id)
|
||||
.description()
|
||||
.contains("You are not allowed to modify address book"),
|
||||
);
|
||||
assert!(
|
||||
jane.jmap_destroy_account(
|
||||
john,
|
||||
MethodObject::ContactCard,
|
||||
[&john_contact_id],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await
|
||||
.not_destroyed(&john_contact_id)
|
||||
.description()
|
||||
.contains("You are not allowed to remove contacts from address book"),
|
||||
);
|
||||
|
||||
// Grant Jane write access
|
||||
john.jmap_update(
|
||||
MethodObject::AddressBook,
|
||||
[(
|
||||
&john_book_id,
|
||||
json!({
|
||||
format!("shareWith/{jane_id}/mayWrite"): true,
|
||||
format!("shareWith/{jane_id}/mayDelete"): true,
|
||||
}),
|
||||
)],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await
|
||||
.updated(&john_book_id);
|
||||
jane.jmap_get_account(
|
||||
john,
|
||||
MethodObject::AddressBook,
|
||||
[
|
||||
AddressBookProperty::Id,
|
||||
AddressBookProperty::Name,
|
||||
AddressBookProperty::MyRights,
|
||||
],
|
||||
[john_book_id.as_str()],
|
||||
)
|
||||
.await
|
||||
.list()[0]
|
||||
.assert_is_equal(json!({
|
||||
"id": john_book_id,
|
||||
"name": "Test #1",
|
||||
"myRights": {
|
||||
"mayRead": true,
|
||||
"mayWrite": true,
|
||||
"mayDelete": true,
|
||||
"mayShare": false
|
||||
}
|
||||
}));
|
||||
|
||||
// Verify Jane received a share notification with the updated rights
|
||||
let response = jane
|
||||
.jmap_changes(MethodObject::ShareNotification, &jane_share_change_id)
|
||||
.await;
|
||||
jane_share_change_id = response.new_state().to_string();
|
||||
let changes = response.changes().collect::<Vec<_>>();
|
||||
assert_eq!(changes.len(), 1);
|
||||
let share_id = changes[0].as_created();
|
||||
jane.jmap_get(
|
||||
MethodObject::ShareNotification,
|
||||
[
|
||||
ShareNotificationProperty::Id,
|
||||
ShareNotificationProperty::ChangedBy,
|
||||
ShareNotificationProperty::ObjectType,
|
||||
ShareNotificationProperty::ObjectAccountId,
|
||||
ShareNotificationProperty::ObjectId,
|
||||
ShareNotificationProperty::OldRights,
|
||||
ShareNotificationProperty::NewRights,
|
||||
ShareNotificationProperty::Name,
|
||||
],
|
||||
[share_id],
|
||||
)
|
||||
.await
|
||||
.list()[0]
|
||||
.assert_is_equal(json!({
|
||||
"id": &share_id,
|
||||
"changedBy": {
|
||||
"principalId": &john_id,
|
||||
"name": "John Doe",
|
||||
"email": "[email protected]"
|
||||
},
|
||||
"objectType": "AddressBook",
|
||||
"objectAccountId": &john_id,
|
||||
"objectId": &john_book_id,
|
||||
"oldRights": {
|
||||
"mayRead": true,
|
||||
"mayWrite": false,
|
||||
"mayDelete": false,
|
||||
"mayShare": false
|
||||
},
|
||||
"newRights": {
|
||||
"mayRead": true,
|
||||
"mayWrite": true,
|
||||
"mayDelete": true,
|
||||
"mayShare": false
|
||||
},
|
||||
"name": null
|
||||
}));
|
||||
|
||||
// Creating a root folder should fail
|
||||
assert_eq!(
|
||||
jane.jmap_create_account(
|
||||
john,
|
||||
MethodObject::AddressBook,
|
||||
[json!({
|
||||
"name": "A new shared address book",
|
||||
})],
|
||||
Vec::<(&str, &str)>::new()
|
||||
)
|
||||
.await
|
||||
.not_created(0)
|
||||
.description(),
|
||||
"Cannot create address books in a shared account."
|
||||
);
|
||||
|
||||
// Copy Jane's contact into John's address book
|
||||
let john_copied_contact_id = jane
|
||||
.jmap_copy(
|
||||
jane,
|
||||
john,
|
||||
MethodObject::ContactCard,
|
||||
[(
|
||||
&jane_contact_id,
|
||||
json!({
|
||||
"addressBookIds": {
|
||||
&john_book_id: true
|
||||
}
|
||||
}),
|
||||
)],
|
||||
false,
|
||||
)
|
||||
.await
|
||||
.copied(&jane_contact_id)
|
||||
.id()
|
||||
.to_string();
|
||||
jane.jmap_get_account(
|
||||
john,
|
||||
MethodObject::ContactCard,
|
||||
[
|
||||
JSContactProperty::<Id>::Id,
|
||||
JSContactProperty::AddressBookIds,
|
||||
JSContactProperty::Name,
|
||||
],
|
||||
[john_copied_contact_id.as_str()],
|
||||
)
|
||||
.await
|
||||
.list()[0]
|
||||
.assert_is_equal(json!({
|
||||
"id": john_copied_contact_id,
|
||||
"name": {
|
||||
"full": "Jane's Simple Contact"
|
||||
},
|
||||
"addressBookIds": {
|
||||
&john_book_id: true
|
||||
}
|
||||
}));
|
||||
|
||||
// Destroy the copied contact
|
||||
assert_eq!(
|
||||
jane.jmap_destroy_account(
|
||||
john,
|
||||
MethodObject::ContactCard,
|
||||
[john_copied_contact_id.as_str()],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await
|
||||
.destroyed()
|
||||
.collect::<Vec<_>>(),
|
||||
[&john_copied_contact_id]
|
||||
);
|
||||
|
||||
// Update John's contact
|
||||
jane.jmap_update_account(
|
||||
john,
|
||||
MethodObject::ContactCard,
|
||||
[(
|
||||
&john_contact_id,
|
||||
json!({
|
||||
"name": {
|
||||
"full": "John's Updated Contact",
|
||||
}
|
||||
}),
|
||||
)],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await
|
||||
.updated(&john_contact_id);
|
||||
jane.jmap_get_account(
|
||||
john,
|
||||
MethodObject::ContactCard,
|
||||
[JSContactProperty::<Id>::Id, JSContactProperty::Name],
|
||||
[john_contact_id.as_str()],
|
||||
)
|
||||
.await
|
||||
.list()[0]
|
||||
.assert_is_equal(json!({
|
||||
"id": john_contact_id,
|
||||
"name": {
|
||||
"full": "John's Updated Contact"
|
||||
},
|
||||
}));
|
||||
|
||||
// Update John's address book name
|
||||
jane.jmap_update_account(
|
||||
john,
|
||||
MethodObject::AddressBook,
|
||||
[(
|
||||
&john_book_id,
|
||||
json!({
|
||||
"name": "Jane's version of John's Address Book",
|
||||
"description": "This is John's address book, but Jane can edit it now"
|
||||
}),
|
||||
)],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await
|
||||
.updated(&john_book_id);
|
||||
jane.jmap_get_account(
|
||||
john,
|
||||
MethodObject::AddressBook,
|
||||
[
|
||||
AddressBookProperty::Id,
|
||||
AddressBookProperty::Name,
|
||||
AddressBookProperty::Description,
|
||||
],
|
||||
[john_book_id.as_str()],
|
||||
)
|
||||
.await
|
||||
.list()[0]
|
||||
.assert_is_equal(json!({
|
||||
"id": john_book_id,
|
||||
"name": "Jane's version of John's Address Book",
|
||||
"description": "This is John's address book, but Jane can edit it now"
|
||||
}));
|
||||
|
||||
// John should still see the old name
|
||||
john.jmap_get(
|
||||
MethodObject::AddressBook,
|
||||
[
|
||||
AddressBookProperty::Id,
|
||||
AddressBookProperty::Name,
|
||||
AddressBookProperty::Description,
|
||||
],
|
||||
[john_book_id.as_str()],
|
||||
)
|
||||
.await
|
||||
.list()[0]
|
||||
.assert_is_equal(json!({
|
||||
"id": john_book_id,
|
||||
"name": "Test #1",
|
||||
"description": null
|
||||
}));
|
||||
|
||||
// Revoke Jane's access
|
||||
john.jmap_update(
|
||||
MethodObject::AddressBook,
|
||||
[(
|
||||
&john_book_id,
|
||||
json!({
|
||||
format!("shareWith/{jane_id}"): ()
|
||||
}),
|
||||
)],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await
|
||||
.updated(&john_book_id);
|
||||
john.jmap_get(
|
||||
MethodObject::AddressBook,
|
||||
[
|
||||
AddressBookProperty::Id,
|
||||
AddressBookProperty::Name,
|
||||
AddressBookProperty::ShareWith,
|
||||
],
|
||||
[john_book_id.as_str()],
|
||||
)
|
||||
.await
|
||||
.list()[0]
|
||||
.assert_is_equal(json!({
|
||||
"id": john_book_id,
|
||||
"name": "Test #1",
|
||||
"shareWith": {}
|
||||
}));
|
||||
|
||||
// Verify Jane can no longer access the address book or its contacts
|
||||
assert_eq!(
|
||||
jane.jmap_get_account(
|
||||
john,
|
||||
MethodObject::AddressBook,
|
||||
Vec::<&str>::new(),
|
||||
[john_book_id.as_str()],
|
||||
)
|
||||
.await
|
||||
.method_response()
|
||||
.typ(),
|
||||
"forbidden"
|
||||
);
|
||||
|
||||
// Verify Jane received a share notification with the updated rights
|
||||
let response = jane
|
||||
.jmap_changes(MethodObject::ShareNotification, &jane_share_change_id)
|
||||
.await;
|
||||
let changes = response.changes().collect::<Vec<_>>();
|
||||
assert_eq!(changes.len(), 1);
|
||||
let share_id = changes[0].as_created();
|
||||
jane.jmap_get(
|
||||
MethodObject::ShareNotification,
|
||||
[
|
||||
ShareNotificationProperty::Id,
|
||||
ShareNotificationProperty::ChangedBy,
|
||||
ShareNotificationProperty::ObjectType,
|
||||
ShareNotificationProperty::ObjectAccountId,
|
||||
ShareNotificationProperty::ObjectId,
|
||||
ShareNotificationProperty::OldRights,
|
||||
ShareNotificationProperty::NewRights,
|
||||
ShareNotificationProperty::Name,
|
||||
],
|
||||
[share_id],
|
||||
)
|
||||
.await
|
||||
.list()[0]
|
||||
.assert_is_equal(json!({
|
||||
"id": &share_id,
|
||||
"changedBy": {
|
||||
"principalId": &john_id,
|
||||
"name": "John Doe",
|
||||
"email": "[email protected]"
|
||||
},
|
||||
"objectType": "AddressBook",
|
||||
"objectAccountId": &john_id,
|
||||
"objectId": &john_book_id,
|
||||
"oldRights": {
|
||||
"mayRead": true,
|
||||
"mayWrite": true,
|
||||
"mayDelete": true,
|
||||
"mayShare": false
|
||||
},
|
||||
"newRights": {
|
||||
"mayRead": false,
|
||||
"mayWrite": false,
|
||||
"mayDelete": false,
|
||||
"mayShare": false
|
||||
},
|
||||
"name": null
|
||||
}));
|
||||
|
||||
// Grant Jane delete access once again
|
||||
john.jmap_update(
|
||||
MethodObject::AddressBook,
|
||||
[(
|
||||
&john_book_id,
|
||||
json!({
|
||||
format!("shareWith/{jane_id}/mayRead"): true,
|
||||
format!("shareWith/{jane_id}/mayDelete"): true,
|
||||
}),
|
||||
)],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await
|
||||
.updated(&john_book_id);
|
||||
|
||||
// Verify Jane can delete the address book
|
||||
assert_eq!(
|
||||
jane.jmap_destroy_account(
|
||||
john,
|
||||
MethodObject::AddressBook,
|
||||
[john_book_id.as_str()],
|
||||
[("onDestroyRemoveContents", true)],
|
||||
)
|
||||
.await
|
||||
.destroyed()
|
||||
.collect::<Vec<_>>(),
|
||||
[john_book_id.as_str()]
|
||||
);
|
||||
|
||||
// Destroy all mailboxes
|
||||
john.destroy_all_addressbooks().await;
|
||||
jane.destroy_all_addressbooks().await;
|
||||
test.assert_is_empty().await;
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use crate::utils::{
|
||||
jmap::{ChangeType, JmapUtils},
|
||||
server::TestServer,
|
||||
};
|
||||
use jmap_proto::{object::addressbook::AddressBookProperty, request::method::MethodObject};
|
||||
use serde_json::json;
|
||||
|
||||
pub async fn test(test: &TestServer) {
|
||||
println!("Running AddressBook tests...");
|
||||
let account = test.account("[email protected]");
|
||||
|
||||
// Make sure the default address book exists
|
||||
let response = account
|
||||
.jmap_get(
|
||||
MethodObject::AddressBook,
|
||||
[
|
||||
AddressBookProperty::Id,
|
||||
AddressBookProperty::Name,
|
||||
AddressBookProperty::Description,
|
||||
AddressBookProperty::SortOrder,
|
||||
AddressBookProperty::IsSubscribed,
|
||||
AddressBookProperty::IsDefault,
|
||||
],
|
||||
Vec::<&str>::new(),
|
||||
)
|
||||
.await;
|
||||
let list = response.list();
|
||||
assert_eq!(list.len(), 1);
|
||||
let default_addressbook_id = list[0].id().to_string();
|
||||
assert_eq!(
|
||||
list[0],
|
||||
json!({
|
||||
"name": "Stalwart Address Book ([email protected])",
|
||||
"description": (),
|
||||
"sortOrder": 0,
|
||||
"isSubscribed": true,
|
||||
"isDefault": true,
|
||||
"id": default_addressbook_id,
|
||||
})
|
||||
);
|
||||
let change_id = response.state();
|
||||
|
||||
// Create Address Book
|
||||
let addressbook_id = account
|
||||
.jmap_create(
|
||||
MethodObject::AddressBook,
|
||||
[json!({
|
||||
"name": "Test address book",
|
||||
"description": "My personal address book",
|
||||
"sortOrder": 1,
|
||||
"isSubscribed": true
|
||||
|
||||
})],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await
|
||||
.created(0)
|
||||
.id()
|
||||
.to_string();
|
||||
|
||||
// Validate changes
|
||||
assert_eq!(
|
||||
account
|
||||
.jmap_changes(MethodObject::AddressBook, change_id)
|
||||
.await
|
||||
.changes()
|
||||
.collect::<Vec<_>>(),
|
||||
[ChangeType::Created(&addressbook_id)]
|
||||
);
|
||||
|
||||
// Get Address Book
|
||||
let response = account
|
||||
.jmap_get(
|
||||
MethodObject::AddressBook,
|
||||
[
|
||||
AddressBookProperty::Id,
|
||||
AddressBookProperty::Name,
|
||||
AddressBookProperty::Description,
|
||||
AddressBookProperty::SortOrder,
|
||||
AddressBookProperty::IsSubscribed,
|
||||
AddressBookProperty::IsDefault,
|
||||
],
|
||||
[&addressbook_id],
|
||||
)
|
||||
.await;
|
||||
assert_eq!(
|
||||
response.list()[0],
|
||||
json!({
|
||||
"name": "Test address book",
|
||||
"description": "My personal address book",
|
||||
"sortOrder": 1,
|
||||
"isSubscribed": true,
|
||||
"isDefault": false,
|
||||
"id": addressbook_id,
|
||||
})
|
||||
);
|
||||
|
||||
// Update Address Book and set it as default
|
||||
account
|
||||
.jmap_update(
|
||||
MethodObject::AddressBook,
|
||||
[(
|
||||
addressbook_id.as_str(),
|
||||
json!({
|
||||
"name": "Updated address book",
|
||||
"description": "My updated personal address book",
|
||||
"sortOrder": 2,
|
||||
"isSubscribed": false
|
||||
}),
|
||||
)],
|
||||
[("onSuccessSetIsDefault", addressbook_id.as_str())],
|
||||
)
|
||||
.await
|
||||
.updated(&addressbook_id);
|
||||
|
||||
// Validate changes
|
||||
assert_eq!(
|
||||
account
|
||||
.jmap_get(
|
||||
MethodObject::AddressBook,
|
||||
[
|
||||
AddressBookProperty::Id,
|
||||
AddressBookProperty::Name,
|
||||
AddressBookProperty::Description,
|
||||
AddressBookProperty::SortOrder,
|
||||
AddressBookProperty::IsSubscribed,
|
||||
AddressBookProperty::IsDefault,
|
||||
],
|
||||
[&addressbook_id, &default_addressbook_id],
|
||||
)
|
||||
.await
|
||||
.list(),
|
||||
vec![
|
||||
json!({
|
||||
"name": "Updated address book",
|
||||
"description": "My updated personal address book",
|
||||
"sortOrder": 2,
|
||||
"isSubscribed": false,
|
||||
"isDefault": true,
|
||||
"id": addressbook_id,
|
||||
}),
|
||||
json!({
|
||||
"name": "Stalwart Address Book ([email protected])",
|
||||
"description": (),
|
||||
"sortOrder": 0,
|
||||
"isSubscribed": true,
|
||||
"isDefault": false,
|
||||
"id": default_addressbook_id,
|
||||
})
|
||||
]
|
||||
);
|
||||
|
||||
// Create a contact
|
||||
let _ = account
|
||||
.jmap_create(
|
||||
MethodObject::ContactCard,
|
||||
[json!({
|
||||
"addressBookIds": {
|
||||
&addressbook_id: true
|
||||
},
|
||||
"name": {
|
||||
"components": [
|
||||
{ "kind": "given", "value": "Joe" },
|
||||
{ "kind": "surname", "value": "Bloggs" }
|
||||
]
|
||||
},
|
||||
"emails": {
|
||||
"0": {
|
||||
"address": "[email protected]"
|
||||
}
|
||||
}
|
||||
})],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await
|
||||
.created(0)
|
||||
.id();
|
||||
|
||||
// Try destroying the address book (should fail)
|
||||
assert_eq!(
|
||||
account
|
||||
.jmap_destroy(
|
||||
MethodObject::AddressBook,
|
||||
[&addressbook_id],
|
||||
Vec::<(&str, &str)>::new(),
|
||||
)
|
||||
.await
|
||||
.not_destroyed(&addressbook_id)
|
||||
.typ(),
|
||||
"addressBookHasContents"
|
||||
);
|
||||
|
||||
// Destroy using force
|
||||
assert_eq!(
|
||||
account
|
||||
.jmap_destroy(
|
||||
MethodObject::AddressBook,
|
||||
[&addressbook_id],
|
||||
[("onDestroyRemoveContents", true)],
|
||||
)
|
||||
.await
|
||||
.destroyed()
|
||||
.collect::<Vec<_>>(),
|
||||
vec![&addressbook_id]
|
||||
);
|
||||
|
||||
// Destroy all mailboxes
|
||||
account.destroy_all_addressbooks().await;
|
||||
test.assert_is_empty().await;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
pub mod acl;
|
||||
pub mod addressbook;
|
||||
pub mod contact;
|
||||
Reference in New Issue
Block a user