PROPFIND: Implement propname, altough in an ugly way

This commit is contained in:
Lennart
2024-06-21 22:19:03 +02:00
parent b32968e942
commit 326aa9a895

View File

@@ -55,11 +55,18 @@ pub trait ResourceService: Sized {
} }
#[derive(Serialize)] #[derive(Serialize)]
pub struct PropWrapper<T: Serialize> { pub struct PropTagWrapper<T: Serialize> {
#[serde(rename = "$value")] #[serde(rename = "$value")]
prop: T, prop: T,
} }
#[derive(Serialize)]
#[serde(untagged)]
pub enum PropWrapper<T: Serialize> {
Prop(PropTagWrapper<T>),
TagList(TagList),
}
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub struct PropstatElement<T: Serialize> { pub struct PropstatElement<T: Serialize> {
@@ -104,11 +111,20 @@ impl<R: Resource> HandlePropfind for R {
if props.len() != 1 { if props.len() != 1 {
// propname MUST be the only queried prop per spec // propname MUST be the only queried prop per spec
return Err( 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 let props: Vec<String> = R::list_props()
props = R::list_props().into(); .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.contains(&"allprop") {
if props.len() != 1 { if props.len() != 1 {
@@ -120,22 +136,29 @@ impl<R: Resource> HandlePropfind for R {
props = R::list_props().into(); props = R::list_props().into();
} }
let mut invalid_props = Vec::new(); let (valid_props, invalid_props): (Vec<Option<R::PropName>>, Vec<Option<&str>>) = props
let mut prop_responses = Vec::new(); .into_iter()
for prop in props { .map(|prop| {
if let Ok(valid_prop) = R::PropName::from_str(prop) { if let Ok(valid_prop) = R::PropName::from_str(prop) {
let response = self.get_prop(prefix, valid_prop.clone())?; (Some(valid_prop), None)
prop_responses.push(response);
} else { } else {
invalid_props.push(prop); (None, Some(prop))
}
} }
})
.unzip();
let valid_props: Vec<R::PropName> = 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::<Result<Vec<R::Prop>, R::Error>>()?;
let mut propstats = vec![PropstatType::Normal(PropstatElement { let mut propstats = vec![PropstatType::Normal(PropstatElement {
status: format!("HTTP/1.1 {}", StatusCode::OK), status: format!("HTTP/1.1 {}", StatusCode::OK),
prop: PropWrapper { prop: PropWrapper::Prop(PropTagWrapper {
prop: prop_responses, prop: prop_responses,
}, }),
})]; })];
if !invalid_props.is_empty() { if !invalid_props.is_empty() {
propstats.push(PropstatType::NotFound(PropstatElement { propstats.push(PropstatType::NotFound(PropstatElement {