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,323 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use crate::config::mailstore::jmap::JmapConfig;
|
||||
use ahash::AHashSet;
|
||||
use calcard::icalendar::ICalendarDuration;
|
||||
use jmap_proto::{
|
||||
object::{email::EmailComparator, file_node::FileNodeComparator},
|
||||
request::capability::{
|
||||
BlobCapabilities, CalendarCapabilities, Capabilities, Capability, ContactsCapabilities,
|
||||
CoreCapabilities, EmptyCapabilities, FileNodeCapabilities, MailCapabilities,
|
||||
PrincipalAvailabilityCapabilities, PrincipalCapabilities, SieveAccountCapabilities,
|
||||
SieveSessionCapabilities, SubmissionCapabilities, WebPushCapabilities,
|
||||
},
|
||||
types::date::UTCDate,
|
||||
};
|
||||
use registry::{
|
||||
schema::structs::{Calendar, Email, SieveUserInterpreter},
|
||||
types::EnumImpl,
|
||||
};
|
||||
use store::registry::bootstrap::Bootstrap;
|
||||
use types::type_state::DataType;
|
||||
use utils::map::vec_map::VecMap;
|
||||
|
||||
impl JmapConfig {
|
||||
pub async fn add_capabilities(&mut self, bp: &mut Bootstrap) {
|
||||
// Add core capabilities
|
||||
self.capabilities.session.append(
|
||||
Capability::Core,
|
||||
Capabilities::Core(CoreCapabilities {
|
||||
max_size_upload: self.upload_max_size as u64,
|
||||
max_concurrent_upload: self.upload_max_concurrent.unwrap_or(u32::MAX as u64),
|
||||
max_size_request: self.request_max_size as u64,
|
||||
max_concurrent_requests: self.request_max_concurrent.unwrap_or(u32::MAX as u64),
|
||||
max_calls_in_request: self.request_max_calls as u64,
|
||||
max_objects_in_get: self.get_max_objects as u64,
|
||||
max_objects_in_set: self.set_max_objects as u64,
|
||||
collation_algorithms: vec![
|
||||
"i;ascii-numeric".to_string(),
|
||||
"i;ascii-casemap".to_string(),
|
||||
"i;unicode-casemap".to_string(),
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
// Add email capabilities
|
||||
let email = bp.setting_infallible::<Email>().await;
|
||||
self.capabilities.session.append(
|
||||
Capability::Mail,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
self.capabilities.account.insert(
|
||||
Capability::Mail,
|
||||
Capabilities::Mail(MailCapabilities {
|
||||
max_mailboxes_per_email: None,
|
||||
max_mailbox_depth: email.max_mailbox_depth,
|
||||
max_size_mailbox_name: email.max_mailbox_name_length,
|
||||
max_size_attachments_per_email: email.max_attachment_size,
|
||||
email_query_sort_options: vec![
|
||||
EmailComparator::ReceivedAt,
|
||||
EmailComparator::Size,
|
||||
EmailComparator::From,
|
||||
EmailComparator::To,
|
||||
EmailComparator::Subject,
|
||||
EmailComparator::SentAt,
|
||||
EmailComparator::HasKeyword(Default::default()),
|
||||
EmailComparator::AllInThreadHaveKeyword(Default::default()),
|
||||
EmailComparator::SomeInThreadHaveKeyword(Default::default()),
|
||||
],
|
||||
may_create_top_level_mailbox: true,
|
||||
}),
|
||||
);
|
||||
|
||||
// Add calendar capabilities
|
||||
self.capabilities.session.append(
|
||||
Capability::Calendars,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
self.capabilities.account.insert(
|
||||
Capability::Calendars,
|
||||
Capabilities::Calendar(CalendarCapabilities {
|
||||
max_calendars_per_event: None,
|
||||
min_date_time: UTCDate {
|
||||
year: 1,
|
||||
month: 1,
|
||||
day: 1,
|
||||
hour: 0,
|
||||
minute: 0,
|
||||
second: 0,
|
||||
tz_before_gmt: false,
|
||||
tz_hour: 0,
|
||||
tz_minute: 0,
|
||||
},
|
||||
max_date_time: UTCDate {
|
||||
year: 9999,
|
||||
month: 12,
|
||||
day: 31,
|
||||
hour: 23,
|
||||
minute: 59,
|
||||
second: 59,
|
||||
tz_before_gmt: false,
|
||||
tz_hour: 0,
|
||||
tz_minute: 0,
|
||||
},
|
||||
max_expanded_query_duration: ICalendarDuration::from_seconds(86400 * 365)
|
||||
.to_string(),
|
||||
max_participants_per_event: bp
|
||||
.setting_infallible::<Calendar>()
|
||||
.await
|
||||
.max_attendees
|
||||
.into(),
|
||||
may_create_calendar: true,
|
||||
}),
|
||||
);
|
||||
|
||||
self.capabilities.session.append(
|
||||
Capability::CalendarsParse,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
self.capabilities.account.insert(
|
||||
Capability::CalendarsParse,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
|
||||
// Add contacts capabilities
|
||||
self.capabilities.session.append(
|
||||
Capability::Contacts,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
self.capabilities.account.insert(
|
||||
Capability::Contacts,
|
||||
Capabilities::Contacts(ContactsCapabilities {
|
||||
max_address_books_per_card: None,
|
||||
may_create_address_book: true,
|
||||
}),
|
||||
);
|
||||
self.capabilities.session.append(
|
||||
Capability::ContactsParse,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
self.capabilities.account.insert(
|
||||
Capability::ContactsParse,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
|
||||
// Add file node capabilities
|
||||
self.capabilities.session.append(
|
||||
Capability::FileNode,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
self.capabilities.account.insert(
|
||||
Capability::FileNode,
|
||||
Capabilities::FileNode(FileNodeCapabilities {
|
||||
max_file_node_depth: None,
|
||||
max_size_file_node_name: 255,
|
||||
forbidden_name_chars: Some("/<>:\"\\|?*".to_string()),
|
||||
forbidden_node_names: Some(
|
||||
[
|
||||
".", "..", "CON", "PRN", "AUX", "NUL", "COM0", "COM1", "COM2", "COM3",
|
||||
"COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT0", "LPT1", "LPT2",
|
||||
"LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
|
||||
]
|
||||
.into_iter()
|
||||
.map(str::to_string)
|
||||
.collect(),
|
||||
),
|
||||
file_node_query_sort_options: vec![
|
||||
FileNodeComparator::Name,
|
||||
FileNodeComparator::Size,
|
||||
FileNodeComparator::NodeType,
|
||||
],
|
||||
may_create_top_level_file_node: true,
|
||||
case_insensitive_names: false,
|
||||
web_trash_url: None,
|
||||
web_url_template: None,
|
||||
web_write_url_template: None,
|
||||
}),
|
||||
);
|
||||
|
||||
// Add principal capabilities
|
||||
self.capabilities.session.append(
|
||||
Capability::Principals,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
self.capabilities.account.insert(
|
||||
Capability::Principals,
|
||||
Capabilities::Principals(PrincipalCapabilities {
|
||||
current_user_principal_id: None,
|
||||
}),
|
||||
);
|
||||
self.capabilities.session.append(
|
||||
Capability::PrincipalsAvailability,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
self.capabilities.account.insert(
|
||||
Capability::PrincipalsAvailability,
|
||||
Capabilities::PrincipalsAvailability(PrincipalAvailabilityCapabilities {
|
||||
max_availability_duration: ICalendarDuration::from_seconds(86400 * 365).to_string(),
|
||||
}),
|
||||
);
|
||||
|
||||
// Add submission capabilities
|
||||
self.capabilities.session.append(
|
||||
Capability::Submission,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
self.capabilities.account.insert(
|
||||
Capability::Submission,
|
||||
Capabilities::Submission(SubmissionCapabilities {
|
||||
max_delayed_send: 86400 * 30,
|
||||
submission_extensions: VecMap::from_iter([
|
||||
("FUTURERELEASE".to_string(), Vec::new()),
|
||||
("SIZE".to_string(), Vec::new()),
|
||||
("DSN".to_string(), Vec::new()),
|
||||
("DELIVERYBY".to_string(), Vec::new()),
|
||||
("MT-PRIORITY".to_string(), vec!["MIXER".to_string()]),
|
||||
("REQUIRETLS".to_string(), vec![]),
|
||||
]),
|
||||
}),
|
||||
);
|
||||
|
||||
// Add vacation response capabilities
|
||||
self.capabilities.session.append(
|
||||
Capability::VacationResponse,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
self.capabilities.account.insert(
|
||||
Capability::VacationResponse,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
|
||||
// Add Sieve capabilities
|
||||
let sieve = bp.setting_infallible::<SieveUserInterpreter>().await;
|
||||
let disabled_capabilities = sieve
|
||||
.disable_capabilities
|
||||
.into_iter()
|
||||
.map(|v| v.as_str())
|
||||
.collect::<AHashSet<&str>>();
|
||||
let mut extensions = sieve::compiler::grammar::Capability::all()
|
||||
.iter()
|
||||
.map(|c| c.to_string())
|
||||
.filter(|c| !disabled_capabilities.contains(c.as_str()))
|
||||
.collect::<Vec<String>>();
|
||||
extensions.sort_unstable();
|
||||
|
||||
self.capabilities.session.append(
|
||||
Capability::Sieve,
|
||||
Capabilities::SieveSession(SieveSessionCapabilities::default()),
|
||||
);
|
||||
self.capabilities.account.insert(
|
||||
Capability::Sieve,
|
||||
Capabilities::SieveAccount(SieveAccountCapabilities {
|
||||
max_script_name: sieve.max_script_name_length as u64,
|
||||
max_script_size: sieve.max_script_size,
|
||||
max_scripts: sieve.max_scripts.unwrap_or(u32::MAX as u64),
|
||||
max_redirects: sieve.max_redirects,
|
||||
extensions,
|
||||
notification_methods: if !sieve.allowed_notify_uris.is_empty() {
|
||||
sieve.allowed_notify_uris.into_inner().into()
|
||||
} else {
|
||||
None
|
||||
},
|
||||
ext_lists: None,
|
||||
}),
|
||||
);
|
||||
|
||||
// Add Blob capabilities
|
||||
self.capabilities.session.append(
|
||||
Capability::Blob,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
self.capabilities.account.insert(
|
||||
Capability::Blob,
|
||||
Capabilities::Blob(BlobCapabilities {
|
||||
max_size_blob_set: (self.request_max_size as u64 * 3 / 4) - 512,
|
||||
max_data_sources: self.request_max_calls as u64,
|
||||
supported_type_names: vec![
|
||||
DataType::Email,
|
||||
DataType::Thread,
|
||||
DataType::SieveScript,
|
||||
],
|
||||
supported_digest_algorithms: vec!["sha", "sha-256", "sha-512"],
|
||||
}),
|
||||
);
|
||||
|
||||
// Add Quota capabilities
|
||||
self.capabilities.session.append(
|
||||
Capability::Quota,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
self.capabilities.account.insert(
|
||||
Capability::Quota,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
|
||||
// Add Email Delivery Push capabilities
|
||||
self.capabilities.session.append(
|
||||
Capability::EmailPush,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
self.capabilities.account.insert(
|
||||
Capability::EmailPush,
|
||||
Capabilities::Empty(EmptyCapabilities::default()),
|
||||
);
|
||||
|
||||
// Add Web Push VAPID capabilities
|
||||
if let Some(application_server_key) = self
|
||||
.vapid
|
||||
.as_ref()
|
||||
.map(|vapid| vapid.public_key().to_string())
|
||||
{
|
||||
self.capabilities.session.append(
|
||||
Capability::WebPushVapid,
|
||||
Capabilities::WebPush(WebPushCapabilities {
|
||||
application_server_key,
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user