diff --git a/crates/common/src/config/dav.rs b/crates/common/src/config/dav.rs
index bd655371..9518fcf3 100644
--- a/crates/common/src/config/dav.rs
+++ b/crates/common/src/config/dav.rs
@@ -14,6 +14,7 @@ pub struct DavConfig {
pub max_lock_timeout: u64,
pub max_locks_per_user: usize,
pub max_changes: usize,
+ pub max_match_results: usize,
}
impl DavConfig {
@@ -33,6 +34,9 @@ impl DavConfig {
.property("dav.limits.max-locks-per-user")
.unwrap_or(10),
max_changes: config.property("dav.limits.max-changes").unwrap_or(1000),
+ max_match_results: config
+ .property("dav.limits.max-match-results")
+ .unwrap_or(1000),
}
}
}
diff --git a/crates/dav-proto/src/responses/property.rs b/crates/dav-proto/src/responses/property.rs
index c097d3ba..e529c469 100644
--- a/crates/dav-proto/src/responses/property.rs
+++ b/crates/dav-proto/src/responses/property.rs
@@ -170,6 +170,18 @@ impl Display for ReportSet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ReportSet::SyncCollection => write!(f, ""),
+ ReportSet::ExpandProperty => write!(f, ""),
+ ReportSet::AddressbookQuery => write!(f, ""),
+ ReportSet::AddressbookMultiGet => write!(f, ""),
+ ReportSet::CalendarQuery => write!(f, ""),
+ ReportSet::CalendarMultiGet => write!(f, ""),
+ ReportSet::FreeBusyQuery => write!(f, ""),
+ ReportSet::AclPrincipalPropSet => write!(f, ""),
+ ReportSet::PrincipalMatch => write!(f, ""),
+ ReportSet::PrincipalPropertySearch => write!(f, ""),
+ ReportSet::PrincipalSearchPropertySet => {
+ write!(f, "")
+ }
}
}
}
diff --git a/crates/dav-proto/src/schema/property.rs b/crates/dav-proto/src/schema/property.rs
index e3531369..ada74ee5 100644
--- a/crates/dav-proto/src/schema/property.rs
+++ b/crates/dav-proto/src/schema/property.rs
@@ -160,6 +160,16 @@ pub enum DavValue {
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
pub enum ReportSet {
SyncCollection,
+ ExpandProperty,
+ AddressbookQuery,
+ AddressbookMultiGet,
+ CalendarQuery,
+ CalendarMultiGet,
+ FreeBusyQuery,
+ AclPrincipalPropSet,
+ PrincipalMatch,
+ PrincipalPropertySearch,
+ PrincipalSearchPropertySet,
}
#[derive(Debug, Clone, PartialEq, Eq)]
diff --git a/crates/dav-proto/src/schema/request.rs b/crates/dav-proto/src/schema/request.rs
index ed12bf8c..7bb63b7a 100644
--- a/crates/dav-proto/src/schema/request.rs
+++ b/crates/dav-proto/src/schema/request.rs
@@ -338,3 +338,9 @@ impl ArchivedDeadProperty {
}
}
}
+
+impl PropertyUpdate {
+ pub fn has_changes(&self) -> bool {
+ !self.set.is_empty() || !self.remove.is_empty()
+ }
+}
diff --git a/crates/dav-proto/src/schema/response.rs b/crates/dav-proto/src/schema/response.rs
index c8f4af5b..3ebb9ea6 100644
--- a/crates/dav-proto/src/schema/response.rs
+++ b/crates/dav-proto/src/schema/response.rs
@@ -55,7 +55,7 @@ pub struct SyncToken(pub String);
#[repr(transparent)]
pub struct Href(pub String);
-#[derive(Debug, Clone, PartialEq, Eq)]
+#[derive(Debug, Default, Clone, PartialEq, Eq)]
#[cfg_attr(test, derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct List(pub Vec);
diff --git a/crates/dav/src/common/acl.rs b/crates/dav/src/common/acl.rs
index d7fba69d..494a7c7e 100644
--- a/crates/dav/src/common/acl.rs
+++ b/crates/dav/src/common/acl.rs
@@ -5,21 +5,53 @@
*/
use common::{Server, auth::AccessToken, sharing::EffectiveAcl};
-use dav_proto::schema::{
- property::Privilege,
- response::{Ace, GrantDeny, Href, Principal},
+use dav_proto::{
+ RequestHeaders,
+ schema::{
+ property::{DavProperty, Privilege, WebDavProperty},
+ request::{AclPrincipalPropSet, PropFind},
+ response::{Ace, BaseCondition, GrantDeny, Href, MultiStatus, Principal},
+ },
};
-use directory::{QueryBy, backend::internal::PrincipalField};
+use directory::{QueryBy, Type, backend::internal::PrincipalField};
+use groupware::{calendar::Calendar, contact::AddressBook, file::FileNode};
+use http_proto::HttpResponse;
use hyper::StatusCode;
-use jmap_proto::types::{acl::Acl, collection::Collection, value::ArchivedAclGrant};
+use jmap_proto::types::{
+ acl::Acl,
+ collection::Collection,
+ property::Property,
+ value::{AclGrant, ArchivedAclGrant},
+};
use rkyv::vec::ArchivedVec;
-use store::ahash::AHashSet;
+use store::{
+ ahash::AHashSet,
+ roaring::RoaringBitmap,
+ write::{AlignedBytes, Archive},
+};
use trc::AddContext;
use utils::map::bitmap::Bitmap;
-use crate::{DavError, DavResource};
+use crate::{
+ DavError, DavErrorCondition, DavResource, common::uri::DavUriResource,
+ principal::propfind::PrincipalPropFind,
+};
pub(crate) trait DavAclHandler: Sync + Send {
+ fn handle_acl_prop_set(
+ &self,
+ access_token: &AccessToken,
+ headers: RequestHeaders<'_>,
+ request: AclPrincipalPropSet,
+ ) -> impl Future