643 lines
30 KiB
Rust
643 lines
30 KiB
Rust
/*
|
|
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
|
*/
|
|
|
|
use crate::{
|
|
addressbook::{get::AddressBookGet, set::AddressBookSet},
|
|
api::auth::JmapAuthorization,
|
|
blob::{copy::BlobCopy, get::BlobOperations, upload::BlobUpload},
|
|
calendar::{get::CalendarGet, set::CalendarSet},
|
|
calendar_event::{
|
|
copy::JmapCalendarEventCopy, get::CalendarEventGet, parse::CalendarEventParse,
|
|
query::CalendarEventQuery, set::CalendarEventSet,
|
|
},
|
|
calendar_event_notification::{
|
|
get::CalendarEventNotificationGet, query::CalendarEventNotificationQuery,
|
|
set::CalendarEventNotificationSet,
|
|
},
|
|
changes::{get::ChangesLookup, query::QueryChanges},
|
|
contact::{
|
|
copy::JmapContactCardCopy, get::ContactCardGet, parse::ContactCardParse,
|
|
query::ContactCardQuery, set::ContactCardSet,
|
|
},
|
|
email::{
|
|
copy::JmapEmailCopy, get::EmailGet, import::EmailImport, parse::EmailParse,
|
|
query::EmailQuery, set::EmailSet, snippet::EmailSearchSnippet,
|
|
},
|
|
file::{get::FileNodeGet, query::FileNodeQuery, set::FileNodeSet},
|
|
identity::{get::IdentityGet, set::IdentitySet},
|
|
mailbox::{get::MailboxGet, query::MailboxQuery, set::MailboxSet},
|
|
participant_identity::{get::ParticipantIdentityGet, set::ParticipantIdentitySet},
|
|
principal::{availability::PrincipalGetAvailability, get::PrincipalGet, query::PrincipalQuery},
|
|
push::{get::PushSubscriptionFetch, set::PushSubscriptionSet},
|
|
quota::{get::QuotaGet, query::QuotaQuery},
|
|
share_notification::{
|
|
get::ShareNotificationGet, query::ShareNotificationQuery, set::ShareNotificationSet,
|
|
},
|
|
sieve::{
|
|
get::SieveScriptGet, query::SieveScriptQuery, set::SieveScriptSet,
|
|
validate::SieveScriptValidate,
|
|
},
|
|
submission::{get::EmailSubmissionGet, query::EmailSubmissionQuery, set::EmailSubmissionSet},
|
|
thread::get::ThreadGet,
|
|
vacation::{get::VacationResponseGet, set::VacationResponseSet},
|
|
};
|
|
use common::{Server, auth::AccessToken};
|
|
use http_proto::HttpSessionData;
|
|
use jmap_proto::{
|
|
request::{
|
|
Call, CopyRequestMethod, GetRequestMethod, ParseRequestMethod, QueryRequestMethod, Request,
|
|
RequestMethod, SetRequestMethod, method::MethodName,
|
|
},
|
|
response::{Response, ResponseMethod, SetResponseMethod},
|
|
};
|
|
use std::future::Future;
|
|
use std::{sync::Arc, time::Instant};
|
|
use trc::JmapEvent;
|
|
use types::{collection::Collection, id::Id};
|
|
|
|
pub trait RequestHandler: Sync + Send {
|
|
fn handle_jmap_request<'x>(
|
|
&self,
|
|
request: Request<'x>,
|
|
access_token: Arc<AccessToken>,
|
|
session: &HttpSessionData,
|
|
) -> impl Future<Output = Response<'x>> + Send;
|
|
|
|
fn handle_method_call<'x>(
|
|
&self,
|
|
method: RequestMethod<'x>,
|
|
method_name: MethodName,
|
|
access_token: &AccessToken,
|
|
next_call: &mut Option<Call<RequestMethod<'x>>>,
|
|
session: &HttpSessionData,
|
|
) -> impl Future<Output = trc::Result<ResponseMethod<'x>>> + Send;
|
|
}
|
|
|
|
impl RequestHandler for Server {
|
|
#![allow(clippy::large_futures)]
|
|
async fn handle_jmap_request<'x>(
|
|
&self,
|
|
request: Request<'x>,
|
|
access_token: Arc<AccessToken>,
|
|
session: &HttpSessionData,
|
|
) -> Response<'x> {
|
|
let add_created_ids = request.created_ids.is_some();
|
|
let mut response = Response::new(
|
|
access_token.state(),
|
|
request.created_ids.unwrap_or_default(),
|
|
request.method_calls.len(),
|
|
);
|
|
|
|
for mut call in request.method_calls {
|
|
// Resolve result and id references
|
|
if let Err(error) = response.resolve_references(&mut call.method) {
|
|
let method_error = error.clone();
|
|
|
|
trc::error!(error.span_id(session.session_id));
|
|
|
|
response.push_response(call.id, MethodName::error(), method_error);
|
|
continue;
|
|
}
|
|
|
|
loop {
|
|
let mut next_call = None;
|
|
|
|
// Add response
|
|
let method_name = call.name.as_str();
|
|
match self
|
|
.handle_method_call(
|
|
call.method,
|
|
call.name,
|
|
&access_token,
|
|
&mut next_call,
|
|
session,
|
|
)
|
|
.await
|
|
{
|
|
Ok(mut method_response) => {
|
|
match &mut method_response {
|
|
ResponseMethod::Set(set_response) => {
|
|
// Add created ids
|
|
match set_response {
|
|
SetResponseMethod::Email(set_response) => {
|
|
set_response.update_created_ids(&mut response);
|
|
}
|
|
SetResponseMethod::Mailbox(set_response) => {
|
|
set_response.update_created_ids(&mut response);
|
|
}
|
|
SetResponseMethod::Identity(set_response) => {
|
|
set_response.update_created_ids(&mut response);
|
|
}
|
|
SetResponseMethod::EmailSubmission(set_response) => {
|
|
set_response.update_created_ids(&mut response);
|
|
}
|
|
SetResponseMethod::PushSubscription(set_response) => {
|
|
set_response.update_created_ids(&mut response);
|
|
}
|
|
SetResponseMethod::Sieve(set_response) => {
|
|
set_response.update_created_ids(&mut response);
|
|
}
|
|
SetResponseMethod::VacationResponse(set_response) => {
|
|
set_response.update_created_ids(&mut response);
|
|
}
|
|
SetResponseMethod::AddressBook(set_response) => {
|
|
set_response.update_created_ids(&mut response);
|
|
}
|
|
SetResponseMethod::ContactCard(set_response) => {
|
|
set_response.update_created_ids(&mut response);
|
|
}
|
|
SetResponseMethod::FileNode(set_response) => {
|
|
set_response.update_created_ids(&mut response);
|
|
}
|
|
SetResponseMethod::ShareNotification(set_response) => {
|
|
set_response.update_created_ids(&mut response);
|
|
}
|
|
SetResponseMethod::Calendar(set_response) => {
|
|
set_response.update_created_ids(&mut response);
|
|
}
|
|
SetResponseMethod::CalendarEvent(set_response) => {
|
|
set_response.update_created_ids(&mut response);
|
|
}
|
|
SetResponseMethod::ParticipantIdentity(set_response) => {
|
|
set_response.update_created_ids(&mut response);
|
|
}
|
|
SetResponseMethod::CalendarEventNotification(_) => {}
|
|
}
|
|
}
|
|
ResponseMethod::ImportEmail(import_response) => {
|
|
// Add created ids
|
|
import_response.update_created_ids(&mut response);
|
|
}
|
|
ResponseMethod::UploadBlob(upload_response) => {
|
|
// Add created blobIds
|
|
upload_response.update_created_ids(&mut response);
|
|
}
|
|
_ => {}
|
|
}
|
|
|
|
response.push_response(call.id, call.name, method_response);
|
|
}
|
|
Err(error) => {
|
|
let method_error = error.clone();
|
|
|
|
trc::error!(
|
|
error
|
|
.span_id(session.session_id)
|
|
.ctx_unique(trc::Key::AccountId, access_token.primary_id())
|
|
.caused_by(method_name)
|
|
);
|
|
|
|
response.push_error(call.id, method_error);
|
|
}
|
|
}
|
|
|
|
// Process next call
|
|
if let Some(next_call) = next_call {
|
|
call = next_call;
|
|
call.id
|
|
.clone_from(&response.method_responses.last().unwrap().id);
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if !add_created_ids {
|
|
response.created_ids.clear();
|
|
}
|
|
|
|
response
|
|
}
|
|
|
|
async fn handle_method_call<'x>(
|
|
&self,
|
|
method: RequestMethod<'x>,
|
|
method_name: MethodName,
|
|
access_token: &AccessToken,
|
|
next_call: &mut Option<Call<RequestMethod<'x>>>,
|
|
session: &HttpSessionData,
|
|
) -> trc::Result<ResponseMethod<'x>> {
|
|
let op_start = Instant::now();
|
|
|
|
// Check permissions
|
|
access_token.assert_has_jmap_permission(&method, method_name.obj)?;
|
|
|
|
// Handle method
|
|
let response = match method {
|
|
RequestMethod::Get(req) => match req {
|
|
GetRequestMethod::Email(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::Email)?;
|
|
|
|
self.email_get(req, access_token).await?.into()
|
|
}
|
|
GetRequestMethod::Mailbox(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::Mailbox)?;
|
|
|
|
self.mailbox_get(req, access_token).await?.into()
|
|
}
|
|
GetRequestMethod::Thread(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::Email)?;
|
|
|
|
self.thread_get(req).await?.into()
|
|
}
|
|
GetRequestMethod::Identity(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.identity_get(req).await?.into()
|
|
}
|
|
GetRequestMethod::EmailSubmission(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.email_submission_get(req).await?.into()
|
|
}
|
|
GetRequestMethod::PushSubscription(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
self.push_subscription_get(req, access_token).await?.into()
|
|
}
|
|
GetRequestMethod::Sieve(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.sieve_script_get(req).await?.into()
|
|
}
|
|
GetRequestMethod::VacationResponse(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.vacation_response_get(req).await?.into()
|
|
}
|
|
GetRequestMethod::Principal(req) => {
|
|
self.principal_get(req, access_token).await?.into()
|
|
}
|
|
GetRequestMethod::Quota(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.quota_get(req, access_token).await?.into()
|
|
}
|
|
GetRequestMethod::Blob(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.blob_get(req, access_token).await?.into()
|
|
}
|
|
GetRequestMethod::AddressBook(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::AddressBook)?;
|
|
|
|
self.address_book_get(req, access_token).await?.into()
|
|
}
|
|
GetRequestMethod::ContactCard(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::ContactCard)?;
|
|
|
|
self.contact_card_get(req, access_token).await?.into()
|
|
}
|
|
GetRequestMethod::FileNode(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::FileNode)?;
|
|
|
|
self.file_node_get(req, access_token).await?.into()
|
|
}
|
|
GetRequestMethod::PrincipalAvailability(req) => self
|
|
.principal_get_availability(req, access_token)
|
|
.await?
|
|
.into(),
|
|
GetRequestMethod::Calendar(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::Calendar)?;
|
|
|
|
self.calendar_get(req, access_token).await?.into()
|
|
}
|
|
GetRequestMethod::CalendarEvent(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::CalendarEvent)?;
|
|
|
|
self.calendar_event_get(req, access_token).await?.into()
|
|
}
|
|
GetRequestMethod::CalendarEventNotification(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.calendar_event_notification_get(req, access_token)
|
|
.await?
|
|
.into()
|
|
}
|
|
GetRequestMethod::ParticipantIdentity(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.participant_identity_get(req).await?.into()
|
|
}
|
|
GetRequestMethod::ShareNotification(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.share_notification_get(req).await?.into()
|
|
}
|
|
},
|
|
RequestMethod::Query(req) => match req {
|
|
QueryRequestMethod::Email(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::Email)?;
|
|
|
|
self.email_query(req, access_token).await?.into()
|
|
}
|
|
QueryRequestMethod::Mailbox(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::Mailbox)?;
|
|
|
|
self.mailbox_query(req, access_token).await?.into()
|
|
}
|
|
QueryRequestMethod::EmailSubmission(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.email_submission_query(req).await?.into()
|
|
}
|
|
QueryRequestMethod::Sieve(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.sieve_script_query(req).await?.into()
|
|
}
|
|
QueryRequestMethod::Principal(req) => self
|
|
.principal_query(req, access_token, session)
|
|
.await?
|
|
.into(),
|
|
QueryRequestMethod::Quota(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.quota_query(req, access_token).await?.into()
|
|
}
|
|
QueryRequestMethod::ContactCard(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::ContactCard)?;
|
|
|
|
self.contact_card_query(req, access_token).await?.into()
|
|
}
|
|
QueryRequestMethod::FileNode(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::FileNode)?;
|
|
|
|
self.file_node_query(req, access_token).await?.into()
|
|
}
|
|
QueryRequestMethod::CalendarEvent(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::CalendarEvent)?;
|
|
|
|
self.calendar_event_query(req, access_token).await?.into()
|
|
}
|
|
QueryRequestMethod::CalendarEventNotification(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.calendar_event_notification_query(req, access_token)
|
|
.await?
|
|
.into()
|
|
}
|
|
QueryRequestMethod::ShareNotification(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.share_notification_query(req).await?.into()
|
|
}
|
|
},
|
|
RequestMethod::Set(req) => match req {
|
|
SetRequestMethod::Email(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::Email)?;
|
|
|
|
self.email_set(req, access_token, session).await?.into()
|
|
}
|
|
SetRequestMethod::Mailbox(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::Mailbox)?;
|
|
|
|
self.mailbox_set(req, access_token).await?.into()
|
|
}
|
|
SetRequestMethod::Identity(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.identity_set(req, access_token).await?.into()
|
|
}
|
|
SetRequestMethod::EmailSubmission(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.email_submission_set(req, &session.instance, next_call)
|
|
.await?
|
|
.into()
|
|
}
|
|
SetRequestMethod::PushSubscription(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
self.push_subscription_set(req, access_token).await?.into()
|
|
}
|
|
SetRequestMethod::Sieve(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.sieve_script_set(req, access_token, session)
|
|
.await?
|
|
.into()
|
|
}
|
|
SetRequestMethod::VacationResponse(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.vacation_response_set(req, access_token).await?.into()
|
|
}
|
|
SetRequestMethod::AddressBook(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::AddressBook)?;
|
|
|
|
self.address_book_set(req, access_token, session)
|
|
.await?
|
|
.into()
|
|
}
|
|
SetRequestMethod::ContactCard(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::ContactCard)?;
|
|
|
|
self.contact_card_set(req, access_token, session)
|
|
.await?
|
|
.into()
|
|
}
|
|
SetRequestMethod::FileNode(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::FileNode)?;
|
|
|
|
self.file_node_set(req, access_token, session).await?.into()
|
|
}
|
|
SetRequestMethod::ShareNotification(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.share_notification_set(req).await?.into()
|
|
}
|
|
SetRequestMethod::Calendar(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::Calendar)?;
|
|
|
|
self.calendar_set(req, access_token, session).await?.into()
|
|
}
|
|
SetRequestMethod::CalendarEvent(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::CalendarEvent)?;
|
|
|
|
self.calendar_event_set(req, access_token, session)
|
|
.await?
|
|
.into()
|
|
}
|
|
SetRequestMethod::CalendarEventNotification(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.calendar_event_notification_set(req, access_token, session)
|
|
.await?
|
|
.into()
|
|
}
|
|
SetRequestMethod::ParticipantIdentity(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.participant_identity_set(req, access_token)
|
|
.await?
|
|
.into()
|
|
}
|
|
},
|
|
RequestMethod::Changes(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
|
|
self.changes(req, method_name.obj, access_token)
|
|
.await?
|
|
.into_method_response()
|
|
}
|
|
RequestMethod::Copy(req) => match req {
|
|
CopyRequestMethod::Email(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
set_account_id_if_missing(&mut req.from_account_id, access_token);
|
|
|
|
access_token
|
|
.assert_has_access(req.account_id, Collection::Email)?
|
|
.assert_has_access(req.from_account_id, Collection::Email)?;
|
|
|
|
self.email_copy(req, access_token, next_call, session)
|
|
.await?
|
|
.into()
|
|
}
|
|
CopyRequestMethod::Blob(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.blob_copy(req, access_token).await?.into()
|
|
}
|
|
CopyRequestMethod::ContactCard(mut req) => {
|
|
set_account_id_if_missing(&mut req.from_account_id, access_token);
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
|
|
access_token
|
|
.assert_has_access(req.account_id, Collection::ContactCard)?
|
|
.assert_has_access(req.from_account_id, Collection::ContactCard)?;
|
|
|
|
self.contact_card_copy(req, access_token, next_call, session)
|
|
.await?
|
|
.into()
|
|
}
|
|
CopyRequestMethod::CalendarEvent(mut req) => {
|
|
set_account_id_if_missing(&mut req.from_account_id, access_token);
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
|
|
access_token
|
|
.assert_has_access(req.account_id, Collection::CalendarEvent)?
|
|
.assert_has_access(req.from_account_id, Collection::CalendarEvent)?;
|
|
|
|
self.calendar_event_copy(req, access_token, next_call, session)
|
|
.await?
|
|
.into()
|
|
}
|
|
},
|
|
RequestMethod::ImportEmail(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::Email)?;
|
|
|
|
self.email_import(req, access_token, session).await?.into()
|
|
}
|
|
RequestMethod::Parse(req) => match req {
|
|
ParseRequestMethod::Email(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::Email)?;
|
|
|
|
self.email_parse(req, access_token).await?.into()
|
|
}
|
|
ParseRequestMethod::ContactCard(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::ContactCard)?;
|
|
|
|
self.contact_card_parse(req, access_token).await?.into()
|
|
}
|
|
ParseRequestMethod::CalendarEvent(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::CalendarEvent)?;
|
|
|
|
self.calendar_event_parse(req, access_token).await?.into()
|
|
}
|
|
},
|
|
RequestMethod::QueryChanges(req) => self.query_changes(req, access_token).await?.into(),
|
|
RequestMethod::SearchSnippet(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_has_access(req.account_id, Collection::Email)?;
|
|
|
|
self.email_search_snippet(req, access_token).await?.into()
|
|
}
|
|
RequestMethod::ValidateScript(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.sieve_script_validate(req, access_token).await?.into()
|
|
}
|
|
RequestMethod::LookupBlob(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.blob_lookup(req).await?.into()
|
|
}
|
|
RequestMethod::UploadBlob(mut req) => {
|
|
set_account_id_if_missing(&mut req.account_id, access_token);
|
|
access_token.assert_is_member(req.account_id)?;
|
|
|
|
self.blob_upload_many(req, access_token).await?.into()
|
|
}
|
|
RequestMethod::Echo(req) => req.into(),
|
|
RequestMethod::Error(error) => return Err(error),
|
|
};
|
|
|
|
trc::event!(
|
|
Jmap(JmapEvent::MethodCall),
|
|
Id = method_name.as_str(),
|
|
SpanId = session.session_id,
|
|
AccountId = access_token.primary_id(),
|
|
Elapsed = op_start.elapsed(),
|
|
);
|
|
|
|
Ok(response)
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub(crate) fn set_account_id_if_missing(account_id: &mut Id, access_token: &AccessToken) {
|
|
if !account_id.is_valid() {
|
|
*account_id = Id::from(access_token.primary_id());
|
|
}
|
|
}
|