JMAP for Contacts implementation (part 1)
This commit is contained in:
29
crates/jmap/src/addressbook/get.rs
Normal file
29
crates/jmap/src/addressbook/get.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use common::{Server, auth::AccessToken};
|
||||
use jmap_proto::{
|
||||
method::get::{GetRequest, GetResponse},
|
||||
object::addressbook::AddressBook,
|
||||
};
|
||||
|
||||
pub trait AddressBookGet: Sync + Send {
|
||||
fn address_book_get(
|
||||
&self,
|
||||
request: GetRequest<AddressBook>,
|
||||
access_token: &AccessToken,
|
||||
) -> impl Future<Output = trc::Result<GetResponse<AddressBook>>> + Send;
|
||||
}
|
||||
|
||||
impl AddressBookGet for Server {
|
||||
async fn address_book_get(
|
||||
&self,
|
||||
mut request: GetRequest<AddressBook>,
|
||||
access_token: &AccessToken,
|
||||
) -> trc::Result<GetResponse<AddressBook>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
8
crates/jmap/src/addressbook/mod.rs
Normal file
8
crates/jmap/src/addressbook/mod.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
pub mod get;
|
||||
pub mod set;
|
||||
32
crates/jmap/src/addressbook/set.rs
Normal file
32
crates/jmap/src/addressbook/set.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use common::{Server, auth::AccessToken};
|
||||
use http_proto::HttpSessionData;
|
||||
use jmap_proto::{
|
||||
method::set::{SetRequest, SetResponse},
|
||||
object::addressbook::AddressBook,
|
||||
};
|
||||
|
||||
pub trait AddressBookSet: Sync + Send {
|
||||
fn address_book_set(
|
||||
&self,
|
||||
request: SetRequest<'_, AddressBook>,
|
||||
access_token: &AccessToken,
|
||||
session: &HttpSessionData,
|
||||
) -> impl Future<Output = trc::Result<SetResponse<AddressBook>>> + Send;
|
||||
}
|
||||
|
||||
impl AddressBookSet for Server {
|
||||
async fn address_book_set(
|
||||
&self,
|
||||
mut request: SetRequest<'_, AddressBook>,
|
||||
access_token: &AccessToken,
|
||||
session: &HttpSessionData,
|
||||
) -> trc::Result<SetResponse<AddressBook>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,8 @@
|
||||
use common::auth::AccessToken;
|
||||
use directory::Permission;
|
||||
use jmap_proto::request::{
|
||||
CopyRequestMethod, GetRequestMethod, QueryChangesRequestMethod, QueryRequestMethod,
|
||||
RequestMethod, SetRequestMethod, method::MethodObject,
|
||||
CopyRequestMethod, GetRequestMethod, ParseRequestMethod, QueryChangesRequestMethod,
|
||||
QueryRequestMethod, RequestMethod, SetRequestMethod, method::MethodObject,
|
||||
};
|
||||
use types::{collection::Collection, id::Id};
|
||||
|
||||
@@ -67,6 +67,8 @@ impl JmapAuthorization for AccessToken {
|
||||
GetRequestMethod::Principal(_) => Permission::JmapPrincipalGet,
|
||||
GetRequestMethod::Quota(_) => Permission::JmapQuotaGet,
|
||||
GetRequestMethod::Blob(_) => Permission::JmapBlobGet,
|
||||
GetRequestMethod::AddressBook(_) => Permission::JmapAddressBookGet,
|
||||
GetRequestMethod::ContactCard(_) => Permission::JmapContactCardGet,
|
||||
},
|
||||
RequestMethod::Set(m) => match &m {
|
||||
SetRequestMethod::Email(_) => Permission::JmapEmailSet,
|
||||
@@ -76,6 +78,8 @@ impl JmapAuthorization for AccessToken {
|
||||
SetRequestMethod::PushSubscription(_) => Permission::JmapPushSubscriptionSet,
|
||||
SetRequestMethod::Sieve(_) => Permission::JmapSieveScriptSet,
|
||||
SetRequestMethod::VacationResponse(_) => Permission::JmapVacationResponseSet,
|
||||
SetRequestMethod::AddressBook(_) => Permission::JmapAddressBookSet,
|
||||
SetRequestMethod::ContactCard(_) => Permission::JmapContactCardSet,
|
||||
},
|
||||
RequestMethod::Changes(_) => match object {
|
||||
MethodObject::Email => Permission::JmapEmailChanges,
|
||||
@@ -84,20 +88,26 @@ impl JmapAuthorization for AccessToken {
|
||||
MethodObject::Identity => Permission::JmapIdentityChanges,
|
||||
MethodObject::EmailSubmission => Permission::JmapEmailSubmissionChanges,
|
||||
MethodObject::Quota => Permission::JmapQuotaChanges,
|
||||
MethodObject::ContactCard => Permission::JmapContactCardChanges,
|
||||
MethodObject::Core
|
||||
| MethodObject::Blob
|
||||
| MethodObject::PushSubscription
|
||||
| MethodObject::SearchSnippet
|
||||
| MethodObject::VacationResponse
|
||||
| MethodObject::SieveScript
|
||||
| MethodObject::Principal => Permission::JmapEmailChanges, // Unimplemented
|
||||
| MethodObject::Principal
|
||||
| MethodObject::AddressBook => Permission::JmapEmailChanges,
|
||||
},
|
||||
RequestMethod::Copy(m) => match &m {
|
||||
CopyRequestMethod::Email(_) => Permission::JmapEmailCopy,
|
||||
CopyRequestMethod::Blob(_) => Permission::JmapBlobCopy,
|
||||
CopyRequestMethod::ContactCard(_) => Permission::JmapContactCardCopy,
|
||||
},
|
||||
RequestMethod::ImportEmail(_) => Permission::JmapEmailImport,
|
||||
RequestMethod::ParseEmail(_) => Permission::JmapEmailParse,
|
||||
RequestMethod::Parse(m) => match &m {
|
||||
ParseRequestMethod::Email(_) => Permission::JmapEmailParse,
|
||||
ParseRequestMethod::ContactCard(_) => Permission::JmapContactCardParse,
|
||||
},
|
||||
RequestMethod::QueryChanges(m) => match m {
|
||||
QueryChangesRequestMethod::Email(_) => Permission::JmapEmailQueryChanges,
|
||||
QueryChangesRequestMethod::Mailbox(_) => Permission::JmapMailboxQueryChanges,
|
||||
@@ -107,6 +117,9 @@ impl JmapAuthorization for AccessToken {
|
||||
QueryChangesRequestMethod::Sieve(_) => Permission::JmapSieveScriptQueryChanges,
|
||||
QueryChangesRequestMethod::Principal(_) => Permission::JmapPrincipalQueryChanges,
|
||||
QueryChangesRequestMethod::Quota(_) => Permission::JmapQuotaQueryChanges,
|
||||
QueryChangesRequestMethod::ContactCard(_) => {
|
||||
Permission::JmapContactCardQueryChanges
|
||||
}
|
||||
},
|
||||
RequestMethod::Query(m) => match m {
|
||||
QueryRequestMethod::Email(_) => Permission::JmapEmailQuery,
|
||||
@@ -115,6 +128,7 @@ impl JmapAuthorization for AccessToken {
|
||||
QueryRequestMethod::Sieve(_) => Permission::JmapSieveScriptQuery,
|
||||
QueryRequestMethod::Principal(_) => Permission::JmapPrincipalQuery,
|
||||
QueryRequestMethod::Quota(_) => Permission::JmapQuotaQuery,
|
||||
QueryRequestMethod::ContactCard(_) => Permission::JmapContactCardQuery,
|
||||
},
|
||||
RequestMethod::SearchSnippet(_) => Permission::JmapSearchSnippet,
|
||||
RequestMethod::ValidateScript(_) => Permission::JmapSieveScriptValidate,
|
||||
|
||||
@@ -4,12 +4,15 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use std::{sync::Arc, time::Instant};
|
||||
|
||||
use crate::{
|
||||
addressbook::{get::AddressBookGet, set::AddressBookSet},
|
||||
api::auth::JmapAuthorization,
|
||||
blob::{copy::BlobCopy, get::BlobOperations, upload::BlobUpload},
|
||||
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,
|
||||
@@ -31,16 +34,16 @@ use common::{Server, auth::AccessToken};
|
||||
use http_proto::HttpSessionData;
|
||||
use jmap_proto::{
|
||||
request::{
|
||||
Call, CopyRequestMethod, GetRequestMethod, QueryRequestMethod, Request, RequestMethod,
|
||||
SetRequestMethod, method::MethodName,
|
||||
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};
|
||||
|
||||
use std::future::Future;
|
||||
|
||||
pub trait RequestHandler: Sync + Send {
|
||||
fn handle_jmap_request<'x>(
|
||||
&self,
|
||||
@@ -126,6 +129,12 @@ impl RequestHandler for Server {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
ResponseMethod::ImportEmail(import_response) => {
|
||||
@@ -248,6 +257,18 @@ impl RequestHandler for Server {
|
||||
|
||||
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()
|
||||
}
|
||||
},
|
||||
RequestMethod::Query(req) => match req {
|
||||
QueryRequestMethod::Email(mut req) => {
|
||||
@@ -284,6 +305,12 @@ impl RequestHandler for Server {
|
||||
|
||||
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()
|
||||
}
|
||||
},
|
||||
RequestMethod::Set(req) => match req {
|
||||
SetRequestMethod::Email(mut req) => {
|
||||
@@ -330,6 +357,22 @@ impl RequestHandler for Server {
|
||||
|
||||
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()
|
||||
}
|
||||
},
|
||||
RequestMethod::Changes(mut req) => {
|
||||
set_account_id_if_missing(&mut req.account_id, access_token);
|
||||
@@ -356,6 +399,16 @@ impl RequestHandler for Server {
|
||||
|
||||
self.blob_copy(req, access_token).await?.into()
|
||||
}
|
||||
CopyRequestMethod::ContactCard(mut req) => {
|
||||
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()
|
||||
}
|
||||
},
|
||||
RequestMethod::ImportEmail(mut req) => {
|
||||
set_account_id_if_missing(&mut req.account_id, access_token);
|
||||
@@ -363,12 +416,20 @@ impl RequestHandler for Server {
|
||||
|
||||
self.email_import(req, access_token, session).await?.into()
|
||||
}
|
||||
RequestMethod::ParseEmail(mut req) => {
|
||||
set_account_id_if_missing(&mut req.account_id, access_token);
|
||||
access_token.assert_has_access(req.account_id, Collection::Email)?;
|
||||
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()
|
||||
}
|
||||
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()
|
||||
}
|
||||
},
|
||||
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);
|
||||
|
||||
@@ -230,6 +230,9 @@ impl IntermediateChangesResponse {
|
||||
MethodObject::EmailSubmission => {
|
||||
ChangesResponseMethod::EmailSubmission(transmute_response(self.response))
|
||||
}
|
||||
MethodObject::ContactCard => {
|
||||
ChangesResponseMethod::ContactCard(transmute_response(self.response))
|
||||
}
|
||||
MethodObject::Core
|
||||
| MethodObject::Blob
|
||||
| MethodObject::PushSubscription
|
||||
@@ -237,7 +240,8 @@ impl IntermediateChangesResponse {
|
||||
| MethodObject::VacationResponse
|
||||
| MethodObject::SieveScript
|
||||
| MethodObject::Principal
|
||||
| MethodObject::Quota => unreachable!(),
|
||||
| MethodObject::Quota
|
||||
| MethodObject::AddressBook => unreachable!(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
use super::get::ChangesLookup;
|
||||
use crate::{
|
||||
api::request::set_account_id_if_missing, email::query::EmailQuery,
|
||||
mailbox::query::MailboxQuery, sieve::query::SieveScriptQuery,
|
||||
api::request::set_account_id_if_missing, contact::query::ContactCardQuery,
|
||||
email::query::EmailQuery, mailbox::query::MailboxQuery, sieve::query::SieveScriptQuery,
|
||||
submission::query::EmailSubmissionQuery,
|
||||
};
|
||||
use common::{Server, auth::AccessToken};
|
||||
@@ -137,6 +137,30 @@ impl QueryChanges for Server {
|
||||
up_to_id = request.up_to_id;
|
||||
results = self.sieve_script_query(request.into()).await?;
|
||||
}
|
||||
QueryChangesRequestMethod::ContactCard(mut request) => {
|
||||
// Query changes
|
||||
set_account_id_if_missing(&mut request.account_id, access_token);
|
||||
changes = self
|
||||
.changes(
|
||||
build_changes_request(&request),
|
||||
MethodObject::ContactCard,
|
||||
access_token,
|
||||
)
|
||||
.await?
|
||||
.response;
|
||||
let calculate_total = request.calculate_total.unwrap_or(false);
|
||||
has_changes = changes.has_changes();
|
||||
response = build_query_changes_response(&request, &changes);
|
||||
|
||||
if !has_changes && !calculate_total {
|
||||
return Ok(response);
|
||||
}
|
||||
|
||||
up_to_id = request.up_to_id;
|
||||
results = self
|
||||
.contact_card_query(request.into(), access_token)
|
||||
.await?;
|
||||
}
|
||||
QueryChangesRequestMethod::Principal(_) => {
|
||||
return Err(trc::JmapEvent::CannotCalculateChanges.into_err());
|
||||
}
|
||||
|
||||
35
crates/jmap/src/contact/copy.rs
Normal file
35
crates/jmap/src/contact/copy.rs
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use common::{Server, auth::AccessToken};
|
||||
use http_proto::HttpSessionData;
|
||||
use jmap_proto::{
|
||||
method::copy::{CopyRequest, CopyResponse},
|
||||
object::contact::ContactCard,
|
||||
request::{Call, RequestMethod},
|
||||
};
|
||||
|
||||
pub trait JmapContactCardCopy: Sync + Send {
|
||||
fn contact_card_copy<'x>(
|
||||
&self,
|
||||
request: CopyRequest<'x, ContactCard>,
|
||||
access_token: &AccessToken,
|
||||
next_call: &mut Option<Call<RequestMethod<'x>>>,
|
||||
session: &HttpSessionData,
|
||||
) -> impl Future<Output = trc::Result<CopyResponse<ContactCard>>> + Send;
|
||||
}
|
||||
|
||||
impl JmapContactCardCopy for Server {
|
||||
async fn contact_card_copy<'x>(
|
||||
&self,
|
||||
request: CopyRequest<'x, ContactCard>,
|
||||
access_token: &AccessToken,
|
||||
next_call: &mut Option<Call<RequestMethod<'x>>>,
|
||||
session: &HttpSessionData,
|
||||
) -> trc::Result<CopyResponse<ContactCard>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
29
crates/jmap/src/contact/get.rs
Normal file
29
crates/jmap/src/contact/get.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use common::{Server, auth::AccessToken};
|
||||
use jmap_proto::{
|
||||
method::get::{GetRequest, GetResponse},
|
||||
object::contact::ContactCard,
|
||||
};
|
||||
|
||||
pub trait ContactCardGet: Sync + Send {
|
||||
fn contact_card_get(
|
||||
&self,
|
||||
request: GetRequest<ContactCard>,
|
||||
access_token: &AccessToken,
|
||||
) -> impl Future<Output = trc::Result<GetResponse<ContactCard>>> + Send;
|
||||
}
|
||||
|
||||
impl ContactCardGet for Server {
|
||||
async fn contact_card_get(
|
||||
&self,
|
||||
mut request: GetRequest<ContactCard>,
|
||||
access_token: &AccessToken,
|
||||
) -> trc::Result<GetResponse<ContactCard>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
11
crates/jmap/src/contact/mod.rs
Normal file
11
crates/jmap/src/contact/mod.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
pub mod copy;
|
||||
pub mod get;
|
||||
pub mod parse;
|
||||
pub mod query;
|
||||
pub mod set;
|
||||
29
crates/jmap/src/contact/parse.rs
Normal file
29
crates/jmap/src/contact/parse.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use common::{Server, auth::AccessToken};
|
||||
use jmap_proto::{
|
||||
method::parse::{ParseRequest, ParseResponse},
|
||||
object::contact::ContactCard,
|
||||
};
|
||||
|
||||
pub trait ContactCardParse: Sync + Send {
|
||||
fn contact_card_parse(
|
||||
&self,
|
||||
request: ParseRequest<ContactCard>,
|
||||
access_token: &AccessToken,
|
||||
) -> impl Future<Output = trc::Result<ParseResponse<ContactCard>>> + Send;
|
||||
}
|
||||
|
||||
impl ContactCardParse for Server {
|
||||
async fn contact_card_parse(
|
||||
&self,
|
||||
request: ParseRequest<ContactCard>,
|
||||
access_token: &AccessToken,
|
||||
) -> trc::Result<ParseResponse<ContactCard>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
29
crates/jmap/src/contact/query.rs
Normal file
29
crates/jmap/src/contact/query.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use common::{Server, auth::AccessToken};
|
||||
use jmap_proto::{
|
||||
method::query::{QueryRequest, QueryResponse},
|
||||
object::contact::ContactCard,
|
||||
};
|
||||
|
||||
pub trait ContactCardQuery: Sync + Send {
|
||||
fn contact_card_query(
|
||||
&self,
|
||||
request: QueryRequest<ContactCard>,
|
||||
access_token: &AccessToken,
|
||||
) -> impl Future<Output = trc::Result<QueryResponse>> + Send;
|
||||
}
|
||||
|
||||
impl ContactCardQuery for Server {
|
||||
async fn contact_card_query(
|
||||
&self,
|
||||
mut request: QueryRequest<ContactCard>,
|
||||
access_token: &AccessToken,
|
||||
) -> trc::Result<QueryResponse> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
32
crates/jmap/src/contact/set.rs
Normal file
32
crates/jmap/src/contact/set.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <hello@stalw.art>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use common::{Server, auth::AccessToken};
|
||||
use http_proto::HttpSessionData;
|
||||
use jmap_proto::{
|
||||
method::set::{SetRequest, SetResponse},
|
||||
object::contact::ContactCard,
|
||||
};
|
||||
|
||||
pub trait ContactCardSet: Sync + Send {
|
||||
fn contact_card_set(
|
||||
&self,
|
||||
request: SetRequest<'_, ContactCard>,
|
||||
access_token: &AccessToken,
|
||||
session: &HttpSessionData,
|
||||
) -> impl Future<Output = trc::Result<SetResponse<ContactCard>>> + Send;
|
||||
}
|
||||
|
||||
impl ContactCardSet for Server {
|
||||
async fn contact_card_set(
|
||||
&self,
|
||||
mut request: SetRequest<'_, ContactCard>,
|
||||
access_token: &AccessToken,
|
||||
session: &HttpSessionData,
|
||||
) -> trc::Result<SetResponse<ContactCard>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,16 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use super::{
|
||||
body::{ToBodyPart, TruncateBody},
|
||||
headers::HeaderToValue,
|
||||
};
|
||||
use crate::blob::download::BlobDownload;
|
||||
use common::{Server, auth::AccessToken};
|
||||
use email::message::index::PREVIEW_LENGTH;
|
||||
use jmap_proto::{
|
||||
method::parse::{ParseEmailRequest, ParseEmailResponse},
|
||||
object::email::EmailProperty,
|
||||
method::parse::{ParseRequest, ParseResponse},
|
||||
object::email::{Email, EmailProperty},
|
||||
request::IntoValid,
|
||||
};
|
||||
use jmap_tools::{Key, Map, Value};
|
||||
@@ -18,27 +23,20 @@ use mail_parser::{
|
||||
use std::future::Future;
|
||||
use utils::map::vec_map::VecMap;
|
||||
|
||||
use crate::blob::download::BlobDownload;
|
||||
|
||||
use super::{
|
||||
body::{ToBodyPart, TruncateBody},
|
||||
headers::HeaderToValue,
|
||||
};
|
||||
|
||||
pub trait EmailParse: Sync + Send {
|
||||
fn email_parse(
|
||||
&self,
|
||||
request: ParseEmailRequest,
|
||||
request: ParseRequest<Email>,
|
||||
access_token: &AccessToken,
|
||||
) -> impl Future<Output = trc::Result<ParseEmailResponse>> + Send;
|
||||
) -> impl Future<Output = trc::Result<ParseResponse<Email>>> + Send;
|
||||
}
|
||||
|
||||
impl EmailParse for Server {
|
||||
async fn email_parse(
|
||||
&self,
|
||||
request: ParseEmailRequest,
|
||||
request: ParseRequest<Email>,
|
||||
access_token: &AccessToken,
|
||||
) -> trc::Result<ParseEmailResponse> {
|
||||
) -> trc::Result<ParseResponse<Email>> {
|
||||
if request.blob_ids.len() > self.core.jmap.mail_parse_max_items {
|
||||
return Err(trc::JmapEvent::RequestTooLarge.into_err());
|
||||
}
|
||||
@@ -70,6 +68,7 @@ impl EmailParse for Server {
|
||||
]
|
||||
});
|
||||
let body_properties = request
|
||||
.arguments
|
||||
.body_properties
|
||||
.map(|v| v.into_valid().collect())
|
||||
.unwrap_or_else(|| {
|
||||
@@ -86,12 +85,12 @@ impl EmailParse for Server {
|
||||
EmailProperty::Location,
|
||||
]
|
||||
});
|
||||
let fetch_text_body_values = request.fetch_text_body_values.unwrap_or(false);
|
||||
let fetch_html_body_values = request.fetch_html_body_values.unwrap_or(false);
|
||||
let fetch_all_body_values = request.fetch_all_body_values.unwrap_or(false);
|
||||
let max_body_value_bytes = request.max_body_value_bytes.unwrap_or(0);
|
||||
let fetch_text_body_values = request.arguments.fetch_text_body_values.unwrap_or(false);
|
||||
let fetch_html_body_values = request.arguments.fetch_html_body_values.unwrap_or(false);
|
||||
let fetch_all_body_values = request.arguments.fetch_all_body_values.unwrap_or(false);
|
||||
let max_body_value_bytes = request.arguments.max_body_value_bytes.unwrap_or(0);
|
||||
|
||||
let mut response = ParseEmailResponse {
|
||||
let mut response = ParseResponse {
|
||||
account_id: request.account_id,
|
||||
parsed: VecMap::with_capacity(request.blob_ids.len()),
|
||||
not_parsable: vec![],
|
||||
|
||||
@@ -24,9 +24,11 @@ use store::{
|
||||
use trc::AddContext;
|
||||
use types::collection::Collection;
|
||||
|
||||
pub mod addressbook;
|
||||
pub mod api;
|
||||
pub mod blob;
|
||||
pub mod changes;
|
||||
pub mod contact;
|
||||
pub mod email;
|
||||
pub mod identity;
|
||||
pub mod mailbox;
|
||||
|
||||
Reference in New Issue
Block a user