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:
2026-09-18 10:21:56 -07:00
commit 7dae9b29fd
1650 changed files with 485521 additions and 0 deletions
+266
View File
@@ -0,0 +1,266 @@
/*
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
use crate::{
jmap::calendar::event::*,
utils::{
jmap::{IntoJmapSet, JmapUtils},
server::TestServer,
},
};
use calcard::jscalendar::JSCalendarProperty;
use jmap_proto::request::method::MethodObject;
use serde_json::json;
use types::id::Id;
pub async fn test(test: &TestServer) {
println!("Running Principal Availability 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 calendars
let response = john
.jmap_create(
MethodObject::Calendar,
[json!({
"name": "Test Calendar",
"includeInAvailability": "all"
})],
Vec::<(&str, &str)>::new(),
)
.await;
let calendar1_id = response.created(0).id().to_string();
// Create test events
let event_1 = test_jscalendar_1().with_property(
JSCalendarProperty::<Id>::CalendarIds,
[calendar1_id.as_str()].into_jmap_set(),
);
let event_2 = test_jscalendar_2().with_property(
JSCalendarProperty::<Id>::CalendarIds,
[calendar1_id.as_str()].into_jmap_set(),
);
let event_3 = test_jscalendar_3()
.with_property(
JSCalendarProperty::<Id>::CalendarIds,
[calendar1_id.as_str()].into_jmap_set(),
)
.with_property(
JSCalendarProperty::<Id>::Participants,
json!({
"3f5bc8c0-c722-5345-b7d9-5a899db08a30": {
"calendarAddress": "mailto:[email protected]",
"@type": "Participant",
"roles": {
"attendee": true,
"chair": true
},
"participationStatus": "accepted"
}
}),
);
let response = john
.jmap_create(
MethodObject::CalendarEvent,
[event_1, event_2, event_3],
Vec::<(&str, &str)>::new(),
)
.await;
let _event_1_id = response.created(0).id().to_string();
let _event_2_id = response.created(1).id().to_string();
let event_3_id = response.created(2).id().to_string();
// Jane should not have access to John's availability
let response = jane
.jmap_method_calls(json!([[
"Principal/getAvailability",
{
"accountId": &jane_id,
"id": &john_id,
"utcStart": "2006-01-01T00:00:00Z",
"utcEnd": "2006-01-08T00:00:00Z",
},
"0"
]]))
.await;
response.list_array().assert_is_equal(json!([]));
// Grant Jane free/busy access
john.jmap_update(
MethodObject::Calendar,
[(
&calendar1_id,
json!({
"shareWith": {
&jane_id : {
"mayReadFreeBusy": true,
}
}
}),
)],
Vec::<(&str, &str)>::new(),
)
.await
.updated(&calendar1_id);
// Jane should see John's availability now
let response = jane
.jmap_method_calls(json!([[
"Principal/getAvailability",
{
"accountId": &jane_id,
"id": &john_id,
"utcStart": "2006-01-01T00:00:00Z",
"utcEnd": "2006-01-08T00:00:00Z",
},
"0"
]]))
.await;
response.list_array().assert_is_equal(json!([
{
"utcStart": "2006-01-02T15:00:00Z",
"utcEnd": "2006-01-02T16:00:00Z",
"busyStatus": "confirmed",
"event": null
},
{
"utcStart": "2006-01-02T17:00:00Z",
"utcEnd": "2006-01-02T18:00:00Z",
"busyStatus": "confirmed",
"event": null
},
{
"utcStart": "2006-01-03T17:00:00Z",
"utcEnd": "2006-01-03T18:00:00Z",
"busyStatus": "confirmed",
"event": null
},
{
"utcStart": "2006-01-04T15:00:00Z",
"utcEnd": "2006-01-04T16:00:00Z",
"busyStatus": "confirmed",
"event": null
},
{
"utcStart": "2006-01-04T19:00:00Z",
"utcEnd": "2006-01-04T20:00:00Z",
"busyStatus": "confirmed",
"event": null
},
{
"utcStart": "2006-01-05T17:00:00Z",
"utcEnd": "2006-01-05T18:00:00Z",
"busyStatus": "confirmed",
"event": null
},
{
"utcStart": "2006-01-06T19:00:00Z",
"utcEnd": "2006-01-06T20:00:00Z",
"busyStatus": "confirmed",
"event": null
}
]));
// Update availability to none
john.jmap_update(
MethodObject::Calendar,
[(
&calendar1_id,
json!({
"includeInAvailability": "none"
}),
)],
Vec::<(&str, &str)>::new(),
)
.await
.updated(&calendar1_id);
// Jane should not see any events now
let response = jane
.jmap_method_calls(json!([[
"Principal/getAvailability",
{
"accountId": &jane_id,
"id": &john_id,
"utcStart": "2006-01-01T00:00:00Z",
"utcEnd": "2006-01-08T00:00:00Z",
},
"0"
]]))
.await;
response.list_array().assert_is_equal(json!([]));
// Update availability to attending
john.jmap_update(
MethodObject::Calendar,
[(
&calendar1_id,
json!({
"includeInAvailability": "attending"
}),
)],
Vec::<(&str, &str)>::new(),
)
.await
.updated(&calendar1_id);
// Jane should only see events where John is attending
let response = jane
.jmap_method_calls(json!([[
"Principal/getAvailability",
{
"accountId": &jane_id,
"id": &john_id,
"utcStart": "2006-01-01T00:00:00Z",
"utcEnd": "2006-01-08T00:00:00Z",
},
"0"
]]))
.await;
response.list_array().assert_is_equal(json!([
{
"utcStart": "2006-01-04T15:00:00Z",
"utcEnd": "2006-01-04T16:00:00Z",
"busyStatus": "confirmed",
"event": null
}
]));
// Update attending event to not attending
john.jmap_update(
MethodObject::CalendarEvent,
[(
&event_3_id,
json!({
"participants/3f5bc8c0-c722-5345-b7d9-5a899db08a30/participationStatus": "declined"
}),
)],
Vec::<(&str, &str)>::new(),
)
.await
.updated(&event_3_id);
// Jane should not see any events now
let response = jane
.jmap_method_calls(json!([[
"Principal/getAvailability",
{
"accountId": &jane_id,
"id": &john_id,
"utcStart": "2006-01-01T00:00:00Z",
"utcEnd": "2006-01-08T00:00:00Z",
},
"0"
]]))
.await;
response.list_array().assert_is_equal(json!([]));
// Cleanup
john.destroy_all_calendars().await;
test.assert_is_empty().await;
}
+471
View File
@@ -0,0 +1,471 @@
/*
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
use jmap_proto::{object::principal::PrincipalProperty, request::method::MethodObject};
use serde_json::json;
use crate::utils::{jmap::JmapUtils, server::TestServer};
pub async fn test(test: &TestServer) {
println!("Running Principal get/query tests...");
let john = test.account("[email protected]");
let jane = test.account("[email protected]");
let bill = test.account("[email protected]");
let sales = test.account("[email protected]");
let john_id = john.id_string();
let jane_id = jane.id_string();
let bill_id = bill.id_string();
let sales_id = sales.id_string();
// Validate session object capabilities
let response = john.jmap_session_object().await.into_inner();
let application_server_key =
response["capabilities"]["urn:ietf:params:jmap:webpush-vapid"]["applicationServerKey"]
.clone();
response.assert_is_equal(json!({
"capabilities": {
"urn:ietf:params:jmap:core": {
"maxSizeUpload": 50000000,
"maxConcurrentUpload": 4,
"maxSizeRequest": 10000000,
"maxConcurrentRequests": 4,
"maxCallsInRequest": 16,
"maxObjectsInGet": 100000,
"maxObjectsInSet": 100000,
"collationAlgorithms": [
"i;ascii-numeric",
"i;ascii-casemap",
"i;unicode-casemap"
]
},
"urn:ietf:params:jmap:mail": {},
"urn:ietf:params:jmap:calendars": {},
"urn:ietf:params:jmap:calendars:parse": {},
"urn:ietf:params:jmap:contacts": {},
"urn:ietf:params:jmap:contacts:parse": {},
"urn:ietf:params:jmap:emailpush": {},
"urn:ietf:params:jmap:filenode": {},
"urn:ietf:params:jmap:principals": {},
"urn:ietf:params:jmap:principals:availability": {},
"urn:ietf:params:jmap:submission": {},
"urn:ietf:params:jmap:vacationresponse": {},
"urn:ietf:params:jmap:sieve": {
"implementation": "Stalwart v1.0.0"
},
"urn:ietf:params:jmap:blob": {},
"urn:ietf:params:jmap:quota": {},
"urn:ietf:params:jmap:webpush-vapid": {
"applicationServerKey": application_server_key
},
"urn:ietf:params:jmap:websocket": {
"url": "wss://127.0.0.1:8899/jmap/ws",
"supportsPush": true
}
},
"accounts": {
john_id: {
"name": "[email protected]",
"isPersonal": true,
"isReadOnly": false,
"accountCapabilities": {
"urn:ietf:params:jmap:mail": {
"maxMailboxesPerEmail": null,
"maxMailboxDepth": 10,
"maxSizeMailboxName": 255,
"maxSizeAttachmentsPerEmail": 50000000,
"emailQuerySortOptions": [
"receivedAt",
"size",
"from",
"to",
"subject",
"sentAt",
"hasKeyword",
"allInThreadHaveKeyword",
"someInThreadHaveKeyword"
],
"mayCreateTopLevelMailbox": true
},
"urn:ietf:params:jmap:submission": {
"maxDelayedSend": 2592000,
"submissionExtensions": {
"FUTURERELEASE": [],
"SIZE": [],
"DSN": [],
"DELIVERYBY": [],
"MT-PRIORITY": [
"MIXER"
],
"REQUIRETLS": []
}
},
"urn:ietf:params:jmap:vacationresponse": {},
"urn:ietf:params:jmap:contacts": {
"maxAddressBooksPerCard": null,
"mayCreateAddressBook": true
},
"urn:ietf:params:jmap:contacts:parse": {},
"urn:ietf:params:jmap:emailpush": {},
"urn:ietf:params:jmap:calendars": {
"maxCalendarsPerEvent": null,
"minDateTime": "0001-01-01T00:00:00Z",
"maxDateTime": "9999-12-31T23:59:59Z",
"maxExpandedQueryDuration": "P52W1D",
"maxParticipantsPerEvent": 20,
"mayCreateCalendar": true
},
"urn:ietf:params:jmap:calendars:parse": {},
"urn:ietf:params:jmap:websocket": {},
"urn:ietf:params:jmap:sieve": {
"maxSizeScriptName": 512,
"maxSizeScript": 102400,
"maxNumberScripts": 100,
"maxNumberRedirects": 1,
"sieveExtensions": [
"body",
"comparator-elbonia",
"comparator-i;ascii-casemap",
"comparator-i;ascii-numeric",
"comparator-i;octet",
"convert",
"copy",
"date",
"duplicate",
"editheader",
"enclose",
"encoded-character",
"enotify",
"envelope",
"envelope-deliverby",
"envelope-dsn",
"environment",
"ereject",
"extlists",
"extracttext",
"fcc",
"fileinto",
"foreverypart",
"ihave",
"imap4flags",
"imapsieve",
"include",
"index",
"mailbox",
"mailboxid",
"mboxmetadata",
"mime",
"redirect-deliverby",
"redirect-dsn",
"regex",
"reject",
"relational",
"replace",
"servermetadata",
"spamtest",
"spamtestplus",
"special-use",
"subaddress",
"vacation",
"vacation-seconds",
"variables",
"virustest"
],
"notificationMethods": [
"mailto"
],
"externalLists": null
},
"urn:ietf:params:jmap:blob": {
"maxSizeBlobSet": 7499488,
"maxDataSources": 16,
"supportedTypeNames": [
"Email",
"Thread",
"SieveScript"
],
"supportedDigestAlgorithms": [
"sha",
"sha-256",
"sha-512"
]
},
"urn:ietf:params:jmap:quota": {},
"urn:ietf:params:jmap:principals": {
"currentUserPrincipalId": john_id
},
"urn:ietf:params:jmap:principals:availability": {
"maxAvailabilityDuration": "P52W1D",
},
"urn:ietf:params:jmap:filenode": {
"maxFileNodeDepth": null,
"maxSizeFileNodeName": 255,
"forbiddenNameChars": "/<>:\"\\|?*",
"forbiddenNodeNames": [
".",
"..",
"CON",
"PRN",
"AUX",
"NUL",
"COM0",
"COM1",
"COM2",
"COM3",
"COM4",
"COM5",
"COM6",
"COM7",
"COM8",
"COM9",
"LPT0",
"LPT1",
"LPT2",
"LPT3",
"LPT4",
"LPT5",
"LPT6",
"LPT7",
"LPT8",
"LPT9"
],
"fileNodeQuerySortOptions": [
"name",
"size",
"nodeType"
],
"mayCreateTopLevelFileNode": true,
"caseInsensitiveNames": false,
"webTrashUrl": null,
"webUrlTemplate": null,
"webWriteUrlTemplate": null
},
"urn:ietf:params:jmap:mail:share": {},
"urn:stalwart:jmap": {}
}
}
},
"primaryAccounts": {
"urn:ietf:params:jmap:mail": john_id,
"urn:ietf:params:jmap:submission": john_id,
"urn:ietf:params:jmap:vacationresponse": john_id,
"urn:ietf:params:jmap:contacts": john_id,
"urn:ietf:params:jmap:contacts:parse": john_id,
"urn:ietf:params:jmap:emailpush": john_id,
"urn:ietf:params:jmap:calendars": john_id,
"urn:ietf:params:jmap:calendars:parse": john_id,
"urn:ietf:params:jmap:websocket": john_id,
"urn:ietf:params:jmap:sieve": john_id,
"urn:ietf:params:jmap:blob": john_id,
"urn:ietf:params:jmap:quota": john_id,
"urn:ietf:params:jmap:principals": john_id,
"urn:ietf:params:jmap:principals:availability": john_id,
"urn:ietf:params:jmap:filenode": john_id,
"urn:ietf:params:jmap:mail:share": john_id,
"urn:stalwart:jmap": john_id
},
"username": "[email protected]",
"apiUrl": "https://127.0.0.1:8899/jmap/",
"downloadUrl":
"https://127.0.0.1:8899/jmap/download/{accountId}/{blobId}/{name}?accept={type}",
"uploadUrl":
"https://127.0.0.1:8899/jmap/upload/{accountId}/",
"eventSourceUrl":
"https://127.0.0.1:8899/jmap/eventsource/?types={types}&closeafter={closeafter}&ping={ping}",
"state": response.text_field("state")
}));
// Obtain principal ids for Jane, Bill and the sales group
let response = john
.jmap_query(
MethodObject::Principal,
[("email", "[email protected]")],
["name"],
Vec::<(&str, &str)>::new(),
)
.await;
assert_eq!(response.ids().collect::<Vec<_>>(), [john_id]);
let response = john
.jmap_query(
MethodObject::Principal,
[("name", "[email protected]")],
["name"],
Vec::<(&str, &str)>::new(),
)
.await;
assert_eq!(response.ids().collect::<Vec<_>>(), [bill_id]);
let response = john
.jmap_query(
MethodObject::Principal,
[("accountIds", [jane_id])],
["name"],
Vec::<(&str, &str)>::new(),
)
.await;
assert_eq!(response.ids().collect::<Vec<_>>(), [jane_id]);
let response = john
.jmap_query(
MethodObject::Principal,
[("text", "sales group")],
["name"],
Vec::<(&str, &str)>::new(),
)
.await;
assert_eq!(response.ids().collect::<Vec<_>>(), [sales_id]);
// Validate principal contents
let response = john
.jmap_get(
MethodObject::Principal,
[
PrincipalProperty::Id,
PrincipalProperty::Type,
PrincipalProperty::Email,
PrincipalProperty::Description,
PrincipalProperty::Name,
PrincipalProperty::Timezone,
PrincipalProperty::Capabilities,
PrincipalProperty::Accounts,
],
[john_id, jane_id, bill_id, sales_id],
)
.await;
let list = response.list();
assert_eq!(list.len(), 4);
list[0].assert_is_equal(json!({
"id": john_id,
"type": "individual",
"email": "[email protected]",
"description": "John Doe",
"name": "[email protected]",
"timezone": null,
"capabilities": {
"urn:ietf:params:jmap:mail": {},
"urn:ietf:params:jmap:contacts": {},
"urn:ietf:params:jmap:calendars": {},
"urn:ietf:params:jmap:filenode": {},
"urn:ietf:params:jmap:principals": {}
},
"accounts": {
john_id: {
"urn:ietf:params:jmap:mail": {},
"urn:ietf:params:jmap:contacts": {},
"urn:ietf:params:jmap:calendars": {
"accountId": john_id,
"mayGetAvailability": true,
"mayShareWith": true,
"calendarAddress": "mailto:[email protected]"
},
"urn:ietf:params:jmap:filenode": {},
"urn:ietf:params:jmap:principals": {},
"urn:ietf:params:jmap:principals:owner": {
"accountIdForPrincipal": john_id,
"principalId": john_id
}
}
}
}));
list[1].assert_is_equal(json!({
"id": jane_id,
"type": "individual",
"email": "[email protected]",
"description": "Jane Smith",
"name": "[email protected]",
"timezone": null,
"capabilities": {
"urn:ietf:params:jmap:mail": {},
"urn:ietf:params:jmap:contacts": {},
"urn:ietf:params:jmap:calendars": {},
"urn:ietf:params:jmap:filenode": {},
"urn:ietf:params:jmap:principals": {}
},
"accounts": {
jane_id: {
"urn:ietf:params:jmap:mail": {},
"urn:ietf:params:jmap:contacts": {},
"urn:ietf:params:jmap:calendars": {
"accountId": jane_id,
"mayGetAvailability": true,
"mayShareWith": true,
"calendarAddress": "mailto:[email protected]"
},
"urn:ietf:params:jmap:filenode": {},
"urn:ietf:params:jmap:principals": {},
"urn:ietf:params:jmap:principals:owner": {
"accountIdForPrincipal": jane_id,
"principalId": jane_id
}
}
}
}));
list[2].assert_is_equal(json!({
"id": bill_id,
"type": "individual",
"email": "[email protected]",
"description": "Bill Foobar",
"name": "[email protected]",
"timezone": null,
"capabilities": {
"urn:ietf:params:jmap:mail": {},
"urn:ietf:params:jmap:contacts": {},
"urn:ietf:params:jmap:calendars": {},
"urn:ietf:params:jmap:filenode": {},
"urn:ietf:params:jmap:principals": {}
},
"accounts": {
bill_id: {
"urn:ietf:params:jmap:mail": {},
"urn:ietf:params:jmap:contacts": {},
"urn:ietf:params:jmap:calendars": {
"accountId": bill_id,
"mayGetAvailability": true,
"mayShareWith": true,
"calendarAddress": "mailto:[email protected]"
},
"urn:ietf:params:jmap:filenode": {},
"urn:ietf:params:jmap:principals": {},
"urn:ietf:params:jmap:principals:owner": {
"accountIdForPrincipal": bill_id,
"principalId": bill_id
}
}
}
}));
list[3].assert_is_equal(json!({
"id": sales_id,
"type": "group",
"email": "[email protected]",
"description": "Sales Group",
"name": "[email protected]",
"timezone": null,
"capabilities": {
"urn:ietf:params:jmap:mail": {},
"urn:ietf:params:jmap:contacts": {},
"urn:ietf:params:jmap:calendars": {},
"urn:ietf:params:jmap:filenode": {},
"urn:ietf:params:jmap:principals": {}
},
"accounts": {
sales_id: {
"urn:ietf:params:jmap:mail": {},
"urn:ietf:params:jmap:contacts": {},
"urn:ietf:params:jmap:calendars": {
"accountId": sales_id,
"mayGetAvailability": true,
"mayShareWith": true,
"calendarAddress": "mailto:[email protected]"
},
"urn:ietf:params:jmap:filenode": {},
"urn:ietf:params:jmap:principals": {},
"urn:ietf:params:jmap:principals:owner": {
"accountIdForPrincipal": sales_id,
"principalId": sales_id
}
}
}
}));
}
+8
View File
@@ -0,0 +1,8 @@
/*
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
pub mod availability;
pub mod get;