DAV file management delete
This commit is contained in:
@@ -101,7 +101,7 @@ impl MailboxDestroy for Server {
|
||||
// otherwise delete it.
|
||||
let mut destroy_ids = RoaringBitmap::new();
|
||||
for (message_id, mailbox_ids) in self
|
||||
.get_properties::<HashedValue<Archive>, _, _>(
|
||||
.get_properties::<HashedValue<Archive>, _>(
|
||||
account_id,
|
||||
Collection::Email,
|
||||
&message_ids,
|
||||
@@ -190,7 +190,7 @@ impl MailboxDestroy for Server {
|
||||
}
|
||||
|
||||
// Obtain mailbox
|
||||
if let Some(mailbox) = self
|
||||
if let Some(mailbox_) = self
|
||||
.get_property::<HashedValue<Archive>>(
|
||||
account_id,
|
||||
Collection::Mailbox,
|
||||
@@ -200,8 +200,8 @@ impl MailboxDestroy for Server {
|
||||
.await
|
||||
.caused_by(trc::location!())?
|
||||
{
|
||||
let mailbox = mailbox
|
||||
.into_deserialized::<Mailbox>()
|
||||
let mailbox = mailbox_
|
||||
.to_unarchived::<Mailbox>()
|
||||
.caused_by(trc::location!())?;
|
||||
// Validate ACLs
|
||||
if access_token.is_shared(account_id) {
|
||||
@@ -224,7 +224,7 @@ impl MailboxDestroy for Server {
|
||||
.with_collection(Collection::Mailbox)
|
||||
.delete_document(document_id)
|
||||
.clear(Property::EmailIds)
|
||||
.custom(ObjectIndexBuilder::new().with_current(mailbox))
|
||||
.custom(ObjectIndexBuilder::<_, ()>::new().with_current(mailbox))
|
||||
.caused_by(trc::location!())?;
|
||||
|
||||
match self.core.storage.data.write(batch.build()).await {
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
*/
|
||||
|
||||
use common::{
|
||||
config::jmap::settings::SpecialUse,
|
||||
config::jmap::settings::{ArchivedSpecialUse, SpecialUse},
|
||||
storage::{
|
||||
folder::FolderHierarchy,
|
||||
index::{IndexValue, IndexableObject},
|
||||
index::{IndexValue, IndexableAndSerializableObject, IndexableObject},
|
||||
},
|
||||
};
|
||||
use jmap_proto::types::property::Property;
|
||||
use jmap_proto::types::{property::Property, value::AclGrant};
|
||||
use store::write::{MaybeDynamicId, TagValue};
|
||||
|
||||
use super::{ArchivedMailbox, ArchivedUidMailbox, Mailbox, UidMailbox};
|
||||
@@ -41,14 +41,63 @@ impl IndexableObject for Mailbox {
|
||||
},
|
||||
IndexValue::U32List {
|
||||
field: Property::IsSubscribed.into(),
|
||||
value: &self.subscribers,
|
||||
value: (&self.subscribers).into(),
|
||||
},
|
||||
IndexValue::Acl {
|
||||
value: (&self.acls).into(),
|
||||
},
|
||||
IndexValue::Acl { value: &self.acls },
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexableObject for &ArchivedMailbox {
|
||||
fn index_values(&self) -> impl Iterator<Item = IndexValue<'_>> {
|
||||
[
|
||||
IndexValue::Text {
|
||||
field: Property::Name.into(),
|
||||
value: self.name.to_lowercase().into(),
|
||||
},
|
||||
IndexValue::Text {
|
||||
field: Property::Role.into(),
|
||||
value: self.role.as_str().unwrap_or_default().into(),
|
||||
},
|
||||
IndexValue::Tag {
|
||||
field: Property::Role.into(),
|
||||
is_set: !matches!(self.role, ArchivedSpecialUse::None),
|
||||
},
|
||||
IndexValue::U32 {
|
||||
field: Property::ParentId.into(),
|
||||
value: u32::from(self.parent_id).into(),
|
||||
},
|
||||
IndexValue::U32 {
|
||||
field: Property::SortOrder.into(),
|
||||
value: self.sort_order.as_ref().map(u32::from),
|
||||
},
|
||||
IndexValue::U32List {
|
||||
field: Property::IsSubscribed.into(),
|
||||
value: self
|
||||
.subscribers
|
||||
.iter()
|
||||
.map(u32::from)
|
||||
.collect::<Vec<_>>()
|
||||
.into(),
|
||||
},
|
||||
IndexValue::Acl {
|
||||
value: self
|
||||
.acls
|
||||
.iter()
|
||||
.map(AclGrant::from)
|
||||
.collect::<Vec<_>>()
|
||||
.into(),
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexableAndSerializableObject for Mailbox {}
|
||||
|
||||
impl FolderHierarchy for ArchivedMailbox {
|
||||
fn name(&self) -> String {
|
||||
self.name.to_string()
|
||||
@@ -57,6 +106,10 @@ impl FolderHierarchy for ArchivedMailbox {
|
||||
fn parent_id(&self) -> u32 {
|
||||
u32::from(self.parent_id)
|
||||
}
|
||||
|
||||
fn is_container(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&UidMailbox> for TagValue<MaybeDynamicId> {
|
||||
|
||||
@@ -102,7 +102,7 @@ impl MailboxFnc for Server {
|
||||
}
|
||||
batch
|
||||
.create_document_with_id(document_id)
|
||||
.custom(ObjectIndexBuilder::new().with_changes(object))
|
||||
.custom(ObjectIndexBuilder::<(), _>::new().with_changes(object))
|
||||
.caused_by(trc::location!())?;
|
||||
mailbox_ids.insert(document_id);
|
||||
}
|
||||
@@ -133,7 +133,7 @@ impl MailboxFnc for Server {
|
||||
}
|
||||
})
|
||||
.into_iterator()
|
||||
.map(|(document_id, name)| (name, document_id))
|
||||
.map(|e| (e.name, e.document_id))
|
||||
.collect::<AHashMap<String, u32>>();
|
||||
|
||||
let mut next_parent_id = 0;
|
||||
@@ -177,7 +177,7 @@ impl MailboxFnc for Server {
|
||||
.with_collection(Collection::Mailbox)
|
||||
.create_document()
|
||||
.custom(
|
||||
ObjectIndexBuilder::new()
|
||||
ObjectIndexBuilder::<(), _>::new()
|
||||
.with_changes(Mailbox::new(name).with_parent_id(next_parent_id)),
|
||||
)
|
||||
.caused_by(trc::location!())?;
|
||||
@@ -275,8 +275,8 @@ impl MailboxFnc for Server {
|
||||
folders
|
||||
.format(|mailbox_id, _| (mailbox_id == INBOX_ID).then(|| "INBOX".to_string()))
|
||||
.into_iterator()
|
||||
.find(|(_, folder_name)| folder_name.eq_ignore_ascii_case(path))
|
||||
.map(|(document_id, _)| document_id)
|
||||
.find(|e| e.name.eq_ignore_ascii_case(path))
|
||||
.map(|e| e.document_id)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ pub const ARCHIVE_ID: u32 = 5;
|
||||
pub const TOMBSTONE_ID: u32 = u32::MAX - 1;
|
||||
|
||||
#[derive(rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[rkyv(derive(Debug))]
|
||||
pub struct Mailbox {
|
||||
pub name: String,
|
||||
pub role: SpecialUse,
|
||||
|
||||
@@ -64,7 +64,7 @@ impl EmailDeletion for Server {
|
||||
// Fetch mailboxes and threadIds
|
||||
let mut thread_ids: AHashMap<u32, i32> = AHashMap::new();
|
||||
for (document_id, mailboxes) in self
|
||||
.get_properties::<Archive, _, _>(
|
||||
.get_properties::<Archive, _>(
|
||||
account_id,
|
||||
Collection::Email,
|
||||
&document_ids,
|
||||
@@ -86,7 +86,7 @@ impl EmailDeletion for Server {
|
||||
);
|
||||
}
|
||||
for (document_id, thread_id) in self
|
||||
.get_properties::<u32, _, _>(
|
||||
.get_properties::<u32, _>(
|
||||
account_id,
|
||||
Collection::Email,
|
||||
&document_ids,
|
||||
@@ -343,7 +343,7 @@ impl EmailDeletion for Server {
|
||||
// Find messages to destroy
|
||||
let mut destroy_ids = RoaringBitmap::new();
|
||||
for (document_id, cid) in self
|
||||
.get_properties::<u64, _, _>(
|
||||
.get_properties::<u64, _>(
|
||||
account_id,
|
||||
Collection::Email,
|
||||
&deletion_candidates,
|
||||
|
||||
@@ -29,7 +29,7 @@ impl SieveScriptDelete for Server {
|
||||
) -> trc::Result<bool> {
|
||||
// Fetch record
|
||||
let account_id = resource_token.account_id;
|
||||
let obj = self
|
||||
let obj_ = self
|
||||
.get_property::<HashedValue<Archive>>(
|
||||
account_id,
|
||||
Collection::SieveScript,
|
||||
@@ -42,8 +42,9 @@ impl SieveScriptDelete for Server {
|
||||
.into_err()
|
||||
.caused_by(trc::location!())
|
||||
.document_id(document_id)
|
||||
})?
|
||||
.into_deserialized::<SieveScript>()
|
||||
})?;
|
||||
let obj = obj_
|
||||
.to_unarchived::<SieveScript>()
|
||||
.caused_by(trc::location!())?;
|
||||
|
||||
// Make sure the script is not active
|
||||
@@ -59,7 +60,7 @@ impl SieveScriptDelete for Server {
|
||||
.delete_document(document_id)
|
||||
.clear(Property::EmailIds)
|
||||
.custom(
|
||||
ObjectIndexBuilder::new()
|
||||
ObjectIndexBuilder::<_, ()>::new()
|
||||
.with_current(obj)
|
||||
.with_tenant_id(resource_token),
|
||||
)
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use common::storage::index::{IndexValue, IndexableObject};
|
||||
use common::storage::index::{IndexValue, IndexableAndSerializableObject, IndexableObject};
|
||||
use jmap_proto::types::property::Property;
|
||||
|
||||
use super::SieveScript;
|
||||
use super::{ArchivedSieveScript, SieveScript};
|
||||
|
||||
impl IndexableObject for SieveScript {
|
||||
fn index_values(&self) -> impl Iterator<Item = IndexValue<'_>> {
|
||||
@@ -28,3 +28,27 @@ impl IndexableObject for SieveScript {
|
||||
.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexableAndSerializableObject for SieveScript {}
|
||||
|
||||
impl IndexableObject for &ArchivedSieveScript {
|
||||
fn index_values(&self) -> impl Iterator<Item = IndexValue<'_>> {
|
||||
[
|
||||
IndexValue::Text {
|
||||
field: Property::Name.into(),
|
||||
value: self.name.to_lowercase().into(),
|
||||
},
|
||||
IndexValue::U32 {
|
||||
field: Property::IsActive.into(),
|
||||
value: Some(self.is_active as u32),
|
||||
},
|
||||
IndexValue::Blob {
|
||||
value: (&self.blob_hash).into(),
|
||||
},
|
||||
IndexValue::Quota {
|
||||
used: u32::from(self.size),
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ pub struct SeenIds {
|
||||
#[derive(
|
||||
rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, Debug, Default, Clone, PartialEq, Eq,
|
||||
)]
|
||||
#[rkyv(derive(Debug))]
|
||||
pub struct SieveScript {
|
||||
pub name: String,
|
||||
pub is_active: bool,
|
||||
@@ -51,6 +52,7 @@ pub struct SieveScript {
|
||||
#[derive(
|
||||
rkyv::Archive, rkyv::Deserialize, rkyv::Serialize, Debug, Default, Clone, PartialEq, Eq,
|
||||
)]
|
||||
#[rkyv(derive(Debug))]
|
||||
pub struct VacationResponse {
|
||||
pub from_date: Option<u64>,
|
||||
pub to_date: Option<u64>,
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use common::storage::index::{IndexValue, IndexableObject};
|
||||
use common::storage::index::{IndexValue, IndexableAndSerializableObject, IndexableObject};
|
||||
use jmap_proto::types::property::Property;
|
||||
|
||||
use super::EmailSubmission;
|
||||
use super::{ArchivedEmailSubmission, EmailSubmission};
|
||||
|
||||
impl IndexableObject for EmailSubmission {
|
||||
fn index_values(&self) -> impl Iterator<Item = IndexValue<'_>> {
|
||||
@@ -36,3 +36,33 @@ impl IndexableObject for EmailSubmission {
|
||||
.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexableObject for &ArchivedEmailSubmission {
|
||||
fn index_values(&self) -> impl Iterator<Item = IndexValue<'_>> {
|
||||
[
|
||||
IndexValue::Text {
|
||||
field: Property::UndoStatus.into(),
|
||||
value: self.undo_status.as_index().into(),
|
||||
},
|
||||
IndexValue::U32 {
|
||||
field: Property::EmailId.into(),
|
||||
value: Some(u32::from(self.email_id)),
|
||||
},
|
||||
IndexValue::U32 {
|
||||
field: Property::ThreadId.into(),
|
||||
value: Some(u32::from(self.thread_id)),
|
||||
},
|
||||
IndexValue::U32 {
|
||||
field: Property::IdentityId.into(),
|
||||
value: Some(u32::from(self.identity_id)),
|
||||
},
|
||||
IndexValue::U64 {
|
||||
field: Property::SendAt.into(),
|
||||
value: Some(u64::from(self.send_at)),
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexableAndSerializableObject for EmailSubmission {}
|
||||
|
||||
@@ -47,7 +47,7 @@ impl ThreadCache for Server {
|
||||
} else {
|
||||
let thread_cache = Arc::new(Threads {
|
||||
threads: self
|
||||
.get_properties::<u32, _, _>(
|
||||
.get_properties::<u32, _>(
|
||||
account_id,
|
||||
Collection::Email,
|
||||
&(),
|
||||
|
||||
Reference in New Issue
Block a user