propfind: Implement <include/>

Implements #95
This commit is contained in:
Lennart
2025-07-10 15:45:54 +02:00
parent 32b616fd75
commit 2774d092ac
7 changed files with 50 additions and 35 deletions

View File

@@ -67,7 +67,7 @@ fn objects_response(
object,
principal: principal.to_owned(),
}
.propfind(&path, prop, puri, user)?,
.propfind(&path, prop, None, puri, user)?,
);
}

View File

@@ -39,7 +39,7 @@ pub async fn handle_sync_collection<C: CalendarStore>(
object,
principal: principal.to_owned(),
}
.propfind(&path, &sync_collection.prop, puri, user)?,
.propfind(&path, &sync_collection.prop, None, puri, user)?,
);
}

View File

@@ -81,7 +81,7 @@ pub async fn handle_addressbook_multiget<AS: AddressbookStore>(
object,
principal: principal.to_owned(),
}
.propfind(&path, prop, puri, user)?,
.propfind(&path, prop, None, puri, user)?,
);
}

View File

@@ -39,7 +39,7 @@ pub async fn handle_sync_collection<AS: AddressbookStore>(
object,
principal: principal.to_owned(),
}
.propfind(&path, &sync_collection.prop, puri, user)?,
.propfind(&path, &sync_collection.prop, None, puri, user)?,
);
}

View File

@@ -64,6 +64,7 @@ pub(crate) async fn route_propfind<R: ResourceService>(
} else {
PropfindElement {
prop: PropfindType::Allprop,
include: None,
}
};
let propfind_member: PropfindElement<<<R::MemberType as Resource>::Prop as PropName>::Names> =
@@ -72,6 +73,7 @@ pub(crate) async fn route_propfind<R: ResourceService>(
} else {
PropfindElement {
prop: PropfindType::Allprop,
include: None,
}
};
@@ -82,13 +84,20 @@ pub(crate) async fn route_propfind<R: ResourceService>(
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],

View File

@@ -106,6 +106,7 @@ pub trait Resource: Clone + Send + 'static {
&self,
path: &str,
prop: &PropfindType<<Self::Prop as PropName>::Names>,
include: Option<&PropElement<<Self::Prop as PropName>::Names>>,
principal_uri: &impl PrincipalUri,
principal: &Self::Principal,
) -> Result<ResponseElement<Self::Prop>, Self::Error> {
@@ -115,36 +116,40 @@ pub trait Resource: Clone + Send + 'static {
path.push('/');
}
// TODO: Support include element
let (props, invalid_props): (HashSet<<Self::Prop as PropName>::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<<Self::Prop as PropName>::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)| <Self::Prop as PropName>::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)| <Self::Prop as PropName>::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()

View File

@@ -11,10 +11,11 @@ use rustical_xml::XmlRootTag;
pub struct PropfindElement<PN: XmlDeserialize> {
#[xml(ty = "untagged")]
pub prop: PropfindType<PN>,
#[xml(ns = "crate::namespace::NS_DAV")]
pub include: Option<PropElement<PN>>,
}
#[derive(Debug, Clone, PartialEq)]
// pub struct PropElement<PN: XmlDeserialize = Propname>(#[xml(ty = "untagged", flatten)] pub Vec<PN>);
pub struct PropElement<PN: XmlDeserialize>(
// valid
pub Vec<PN>,