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,164 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use common::{Server, auth::AccessToken, sharing::EffectiveAcl};
|
||||
use email::cache::{MessageCacheFetch, email::MessageCacheAccess, mailbox::MailboxCacheAccess};
|
||||
use jmap_proto::{
|
||||
method::get::{GetRequest, GetResponse},
|
||||
object::mailbox::{Mailbox, MailboxProperty, MailboxValue},
|
||||
};
|
||||
use jmap_tools::{Map, Value};
|
||||
use std::future::Future;
|
||||
use store::ahash::AHashSet;
|
||||
use types::{acl::Acl, collection::Collection, keyword::Keyword, special_use::SpecialUse};
|
||||
|
||||
use crate::{api::acl::JmapRights, changes::state::JmapCacheState};
|
||||
|
||||
pub trait MailboxGet: Sync + Send {
|
||||
fn mailbox_get(
|
||||
&self,
|
||||
request: GetRequest<Mailbox>,
|
||||
access_token: &AccessToken,
|
||||
) -> impl Future<Output = trc::Result<GetResponse<Mailbox>>> + Send;
|
||||
}
|
||||
|
||||
impl MailboxGet for Server {
|
||||
async fn mailbox_get(
|
||||
&self,
|
||||
mut request: GetRequest<Mailbox>,
|
||||
access_token: &AccessToken,
|
||||
) -> trc::Result<GetResponse<Mailbox>> {
|
||||
let (ids, not_found_ids) = request.unwrap_ids(self.core.jmap.get_max_objects)?;
|
||||
let properties = request.unwrap_properties(&[
|
||||
MailboxProperty::Id,
|
||||
MailboxProperty::Name,
|
||||
MailboxProperty::ParentId,
|
||||
MailboxProperty::Role,
|
||||
MailboxProperty::SortOrder,
|
||||
MailboxProperty::IsSubscribed,
|
||||
MailboxProperty::TotalEmails,
|
||||
MailboxProperty::UnreadEmails,
|
||||
MailboxProperty::TotalThreads,
|
||||
MailboxProperty::UnreadThreads,
|
||||
MailboxProperty::MyRights,
|
||||
]);
|
||||
let account_id = request.account_id.document_id();
|
||||
let personal_id = access_token.personal_id(account_id, Collection::Mailbox);
|
||||
let cache = self.get_cached_messages(account_id).await?;
|
||||
let shared_ids = if access_token.is_shared(account_id) {
|
||||
cache.shared_mailboxes(access_token, Acl::Read).into()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let ids = if let Some(ids) = ids {
|
||||
ids
|
||||
} else {
|
||||
cache
|
||||
.mailboxes
|
||||
.index
|
||||
.keys()
|
||||
.filter(|id| shared_ids.as_ref().is_none_or(|ids| ids.contains(**id)))
|
||||
.copied()
|
||||
.take(self.core.jmap.get_max_objects)
|
||||
.map(Into::into)
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
let mut response = GetResponse {
|
||||
account_id: request.account_id.into(),
|
||||
state: Some(cache.get_state(true)),
|
||||
list: Vec::with_capacity(ids.len()),
|
||||
not_found: not_found_ids,
|
||||
};
|
||||
|
||||
for id in ids {
|
||||
// Obtain the mailbox object
|
||||
let document_id = id.document_id();
|
||||
let cached_mailbox = if let Some(mailbox) =
|
||||
cache.mailbox_by_id(&document_id).filter(|_| {
|
||||
shared_ids
|
||||
.as_ref()
|
||||
.is_none_or(|ids| ids.contains(document_id))
|
||||
}) {
|
||||
mailbox
|
||||
} else {
|
||||
response.push_not_found(id);
|
||||
continue;
|
||||
};
|
||||
|
||||
let mut mailbox = Map::with_capacity(properties.len());
|
||||
|
||||
for property in &properties {
|
||||
let value = match property {
|
||||
MailboxProperty::Id => Value::Element(MailboxValue::Id(id)),
|
||||
MailboxProperty::Name => Value::Str(cached_mailbox.name.to_string().into()),
|
||||
MailboxProperty::Role => match cached_mailbox.role {
|
||||
SpecialUse::None => Value::Null,
|
||||
role => Value::Element(MailboxValue::Role(role)),
|
||||
},
|
||||
MailboxProperty::SortOrder => {
|
||||
Value::Number(cached_mailbox.sort_order().unwrap_or_default().into())
|
||||
}
|
||||
MailboxProperty::ParentId => {
|
||||
if let Some(parent_id) = cached_mailbox.parent_id() {
|
||||
Value::Element(MailboxValue::Id(parent_id.into()))
|
||||
} else {
|
||||
Value::Null
|
||||
}
|
||||
}
|
||||
MailboxProperty::TotalEmails => {
|
||||
Value::Number(cache.in_mailbox(document_id).count().into())
|
||||
}
|
||||
MailboxProperty::UnreadEmails => Value::Number(
|
||||
cache
|
||||
.in_mailbox_without_keyword(document_id, &Keyword::Seen)
|
||||
.count()
|
||||
.into(),
|
||||
),
|
||||
MailboxProperty::TotalThreads => Value::Number(
|
||||
cache
|
||||
.in_mailbox(document_id)
|
||||
.map(|m| m.thread_id)
|
||||
.collect::<AHashSet<_>>()
|
||||
.len()
|
||||
.into(),
|
||||
),
|
||||
MailboxProperty::UnreadThreads => Value::Number(
|
||||
cache
|
||||
.in_mailbox_without_keyword(document_id, &Keyword::Seen)
|
||||
.map(|m| m.thread_id)
|
||||
.collect::<AHashSet<_>>()
|
||||
.len()
|
||||
.into(),
|
||||
),
|
||||
MailboxProperty::MyRights => {
|
||||
if access_token.is_shared(account_id) {
|
||||
JmapRights::rights::<Mailbox>(
|
||||
cached_mailbox.acls.as_slice().effective_acl(access_token),
|
||||
)
|
||||
} else {
|
||||
JmapRights::all_rights::<Mailbox>()
|
||||
}
|
||||
}
|
||||
MailboxProperty::IsSubscribed => {
|
||||
Value::Bool(cached_mailbox.subscribers.contains(&personal_id))
|
||||
}
|
||||
MailboxProperty::ShareWith => JmapRights::share_with::<Mailbox>(
|
||||
account_id,
|
||||
access_token,
|
||||
&cached_mailbox.acls,
|
||||
),
|
||||
_ => Value::Null,
|
||||
};
|
||||
|
||||
mailbox.insert_unchecked(property.clone(), value);
|
||||
}
|
||||
|
||||
// Add result to response
|
||||
response.list.push(mailbox.into());
|
||||
}
|
||||
Ok(response)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user