From 2774d092ac8fb5e12d77a9f59ca9c4a920ee923e Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Thu, 10 Jul 2025 15:45:54 +0200 Subject: [PATCH] propfind: Implement Implements #95 --- .../caldav/src/calendar/methods/report/mod.rs | 2 +- .../methods/report/sync_collection.rs | 2 +- .../methods/report/addressbook_multiget.rs | 2 +- .../methods/report/sync_collection.rs | 2 +- crates/dav/src/resource/methods/propfind.rs | 11 +++- crates/dav/src/resource/mod.rs | 63 ++++++++++--------- crates/dav/src/xml/propfind.rs | 3 +- 7 files changed, 50 insertions(+), 35 deletions(-) diff --git a/crates/caldav/src/calendar/methods/report/mod.rs b/crates/caldav/src/calendar/methods/report/mod.rs index f6de9b0..9af5cba 100644 --- a/crates/caldav/src/calendar/methods/report/mod.rs +++ b/crates/caldav/src/calendar/methods/report/mod.rs @@ -67,7 +67,7 @@ fn objects_response( object, principal: principal.to_owned(), } - .propfind(&path, prop, puri, user)?, + .propfind(&path, prop, None, puri, user)?, ); } diff --git a/crates/caldav/src/calendar/methods/report/sync_collection.rs b/crates/caldav/src/calendar/methods/report/sync_collection.rs index fa0479f..7b70f20 100644 --- a/crates/caldav/src/calendar/methods/report/sync_collection.rs +++ b/crates/caldav/src/calendar/methods/report/sync_collection.rs @@ -39,7 +39,7 @@ pub async fn handle_sync_collection( object, principal: principal.to_owned(), } - .propfind(&path, &sync_collection.prop, puri, user)?, + .propfind(&path, &sync_collection.prop, None, puri, user)?, ); } diff --git a/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs b/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs index d156b4f..a3bf595 100644 --- a/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs +++ b/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs @@ -81,7 +81,7 @@ pub async fn handle_addressbook_multiget( object, principal: principal.to_owned(), } - .propfind(&path, prop, puri, user)?, + .propfind(&path, prop, None, puri, user)?, ); } diff --git a/crates/carddav/src/addressbook/methods/report/sync_collection.rs b/crates/carddav/src/addressbook/methods/report/sync_collection.rs index b4dfd33..f27837b 100644 --- a/crates/carddav/src/addressbook/methods/report/sync_collection.rs +++ b/crates/carddav/src/addressbook/methods/report/sync_collection.rs @@ -39,7 +39,7 @@ pub async fn handle_sync_collection( object, principal: principal.to_owned(), } - .propfind(&path, &sync_collection.prop, puri, user)?, + .propfind(&path, &sync_collection.prop, None, puri, user)?, ); } diff --git a/crates/dav/src/resource/methods/propfind.rs b/crates/dav/src/resource/methods/propfind.rs index e8c610f..daed710 100644 --- a/crates/dav/src/resource/methods/propfind.rs +++ b/crates/dav/src/resource/methods/propfind.rs @@ -64,6 +64,7 @@ pub(crate) async fn route_propfind( } else { PropfindElement { prop: PropfindType::Allprop, + include: None, } }; let propfind_member: PropfindElement<<::Prop as PropName>::Names> = @@ -72,6 +73,7 @@ pub(crate) async fn route_propfind( } else { PropfindElement { prop: PropfindType::Allprop, + include: None, } }; @@ -82,13 +84,20 @@ pub(crate) async fn route_propfind( member_responses.push(member.propfind( &format!("{}/{}", path.trim_end_matches('/'), member.get_name()), &propfind_member.prop, + propfind_member.include.as_ref(), puri, principal, )?); } } - let response = resource.propfind(path, &propfind_self.prop, puri, principal)?; + let response = resource.propfind( + path, + &propfind_self.prop, + propfind_self.include.as_ref(), + puri, + principal, + )?; Ok(MultistatusElement { responses: vec![response], diff --git a/crates/dav/src/resource/mod.rs b/crates/dav/src/resource/mod.rs index c5afa79..79b39c9 100644 --- a/crates/dav/src/resource/mod.rs +++ b/crates/dav/src/resource/mod.rs @@ -106,6 +106,7 @@ pub trait Resource: Clone + Send + 'static { &self, path: &str, prop: &PropfindType<::Names>, + include: Option<&PropElement<::Names>>, principal_uri: &impl PrincipalUri, principal: &Self::Principal, ) -> Result, Self::Error> { @@ -115,36 +116,40 @@ pub trait Resource: Clone + Send + 'static { path.push('/'); } - // TODO: Support include element - let (props, invalid_props): (HashSet<::Names>, Vec<_>) = match prop - { - PropfindType::Propname => { - let props = Self::list_props() - .into_iter() - .map(|(ns, tag)| (ns.map(NamespaceOwned::from), tag.to_string())) - .collect_vec(); + let (mut props, mut invalid_props): (HashSet<::Names>, Vec<_>) = + match prop { + PropfindType::Propname => { + let props = Self::list_props() + .into_iter() + .map(|(ns, tag)| (ns.map(NamespaceOwned::from), tag.to_string())) + .collect_vec(); - return Ok(ResponseElement { - href: path.to_owned(), - propstat: vec![PropstatWrapper::TagList(PropstatElement { - prop: TagList::from(props), - status: StatusCode::OK, - })], - ..Default::default() - }); - } - PropfindType::Allprop => ( - Self::list_props() - .iter() - .map(|(_ns, name)| ::Names::from_str(name).unwrap()) - .collect(), - vec![], - ), - PropfindType::Prop(PropElement(valid_tags, invalid_tags)) => ( - valid_tags.iter().cloned().collect(), - invalid_tags.to_owned(), - ), - }; + return Ok(ResponseElement { + href: path.to_owned(), + propstat: vec![PropstatWrapper::TagList(PropstatElement { + prop: TagList::from(props), + status: StatusCode::OK, + })], + ..Default::default() + }); + } + PropfindType::Allprop => ( + Self::list_props() + .iter() + .map(|(_ns, name)| ::Names::from_str(name).unwrap()) + .collect(), + vec![], + ), + PropfindType::Prop(PropElement(valid_tags, invalid_tags)) => ( + valid_tags.iter().cloned().collect(), + invalid_tags.to_owned(), + ), + }; + + if let Some(PropElement(valid_tags, invalid_tags)) = include { + props.extend(valid_tags.clone()); + invalid_props.extend(invalid_tags.to_owned()); + } let prop_responses = props .into_iter() diff --git a/crates/dav/src/xml/propfind.rs b/crates/dav/src/xml/propfind.rs index c8232c9..587bbc3 100644 --- a/crates/dav/src/xml/propfind.rs +++ b/crates/dav/src/xml/propfind.rs @@ -11,10 +11,11 @@ use rustical_xml::XmlRootTag; pub struct PropfindElement { #[xml(ty = "untagged")] pub prop: PropfindType, + #[xml(ns = "crate::namespace::NS_DAV")] + pub include: Option>, } #[derive(Debug, Clone, PartialEq)] -// pub struct PropElement(#[xml(ty = "untagged", flatten)] pub Vec); pub struct PropElement( // valid pub Vec,