JMAP for Contacts implementation (part 2)

This commit is contained in:
mdecimus
2025-10-02 19:03:17 +02:00
parent 98deb17482
commit 3da4619d43
26 changed files with 1293 additions and 86 deletions

View File

@@ -402,6 +402,7 @@ impl AccessToken {
s.finish() as u32
}
#[inline(always)]
pub fn primary_id(&self) -> u32 {
self.primary_id
}

View File

@@ -40,6 +40,8 @@ pub struct JmapConfig {
pub mail_max_size: usize,
pub mail_autoexpunge_after: Option<u64>,
pub contact_parse_max_items: usize,
pub sieve_max_script_name: usize,
pub sieve_max_scripts: usize,
@@ -337,6 +339,9 @@ impl JmapConfig {
.value("authentication.master.secret")
.map(|p| (u.to_string(), p.to_string()))
}),
contact_parse_max_items: config
.property("jmap.contact.parse.max-items")
.unwrap_or(100),
default_folders,
shared_folder,
};

View File

@@ -37,6 +37,7 @@ use std::{
sync::{Arc, atomic::AtomicBool},
time::{Duration, Instant},
};
use store::rand::{Rng, distr::Alphanumeric};
use tinyvec::TinyVec;
use tokio::sync::{Notify, Semaphore, mpsc};
use tokio_rustls::TlsConnector;
@@ -575,6 +576,19 @@ impl DavResources {
.find(|res| res.document_id == id && res.is_container())
}
pub fn container_resource_path_by_id(&self, id: u32) -> Option<DavResourcePath<'_>> {
self.resources
.iter()
.enumerate()
.find(|(_, resource)| resource.document_id == id && resource.is_container())
.and_then(|(idx, resource)| {
self.paths
.iter()
.find(|path| path.resource_idx == idx)
.map(|path| DavResourcePath { path, resource })
})
}
pub fn subtree(&self, search_path: &str) -> impl Iterator<Item = DavResourcePath<'_>> {
let prefix = format!("{search_path}/");
self.paths.iter().filter_map(move |path| {
@@ -635,6 +649,13 @@ impl DavResources {
})
}
pub fn children_ids(&self, parent_id: u32) -> impl Iterator<Item = u32> {
self.paths
.iter()
.filter(move |item| item.parent_id.is_some_and(|id| id == parent_id))
.map(|path| self.resources[path.resource_idx].document_id)
}
pub fn format_resource(&self, resource: DavResourcePath<'_>) -> String {
if resource.resource.is_container() {
format!("{}{}/", self.base_path, resource.path.path)
@@ -822,6 +843,17 @@ impl DavName {
pub fn new(name: String, parent_id: u32) -> Self {
Self { name, parent_id }
}
pub fn new_with_rand_name(parent_id: u32) -> Self {
Self {
name: store::rand::rng()
.sample_iter(Alphanumeric)
.take(10)
.map(char::from)
.collect::<String>(),
parent_id,
}
}
}
impl<T> CacheSwap<T> {

View File

@@ -90,4 +90,16 @@ impl DavResources {
}
})
}
pub fn has_container_id(&self, id: &u32) -> bool {
self.resources
.iter()
.any(|r| r.document_id == *id && r.is_container())
}
pub fn has_item_id(&self, id: &u32) -> bool {
self.resources
.iter()
.any(|r| r.document_id == *id && !r.is_container())
}
}