From 326aa9a8953155452e951d83d95229e48a182314 Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Fri, 21 Jun 2024 22:19:03 +0200 Subject: [PATCH] PROPFIND: Implement propname, altough in an ugly way --- crates/dav/src/resource.rs | 55 +++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/crates/dav/src/resource.rs b/crates/dav/src/resource.rs index e4014a8..d73eb6a 100644 --- a/crates/dav/src/resource.rs +++ b/crates/dav/src/resource.rs @@ -55,11 +55,18 @@ pub trait ResourceService: Sized { } #[derive(Serialize)] -pub struct PropWrapper { +pub struct PropTagWrapper { #[serde(rename = "$value")] prop: T, } +#[derive(Serialize)] +#[serde(untagged)] +pub enum PropWrapper { + Prop(PropTagWrapper), + TagList(TagList), +} + #[derive(Serialize)] #[serde(rename_all = "kebab-case")] pub struct PropstatElement { @@ -104,11 +111,20 @@ impl HandlePropfind for R { if props.len() != 1 { // propname MUST be the only queried prop per spec return Err( - Error::BadRequest("allprop MUST be the only queried prop".to_owned()).into(), + Error::BadRequest("propname MUST be the only queried prop".to_owned()).into(), ); } - // TODO: implement propname - props = R::list_props().into(); + let props: Vec = R::list_props() + .iter() + .map(|&prop| prop.to_string()) + .collect(); + return Ok(PropstatResponseElement { + href: self.get_path().to_owned(), + propstat: vec![PropstatType::Normal(PropstatElement { + prop: PropWrapper::TagList(TagList::from(props)), + status: format!("HTTP/1.1 {}", StatusCode::OK), + })], + }); } if props.contains(&"allprop") { if props.len() != 1 { @@ -120,22 +136,29 @@ impl HandlePropfind for R { props = R::list_props().into(); } - let mut invalid_props = Vec::new(); - let mut prop_responses = Vec::new(); - for prop in props { - if let Ok(valid_prop) = R::PropName::from_str(prop) { - let response = self.get_prop(prefix, valid_prop.clone())?; - prop_responses.push(response); - } else { - invalid_props.push(prop); - } - } + let (valid_props, invalid_props): (Vec>, Vec>) = props + .into_iter() + .map(|prop| { + if let Ok(valid_prop) = R::PropName::from_str(prop) { + (Some(valid_prop), None) + } else { + (None, Some(prop)) + } + }) + .unzip(); + let valid_props: Vec = valid_props.into_iter().flatten().collect(); + let invalid_props: Vec<&str> = invalid_props.into_iter().flatten().collect(); + + let prop_responses = valid_props + .into_iter() + .map(|prop| self.get_prop(prefix, prop)) + .collect::, R::Error>>()?; let mut propstats = vec![PropstatType::Normal(PropstatElement { status: format!("HTTP/1.1 {}", StatusCode::OK), - prop: PropWrapper { + prop: PropWrapper::Prop(PropTagWrapper { prop: prop_responses, - }, + }), })]; if !invalid_props.is_empty() { propstats.push(PropstatType::NotFound(PropstatElement {