From f56fd81d0ef8cbc5d8c6f0e947acab92ab047cdf Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Wed, 6 Nov 2024 16:18:11 +0100 Subject: [PATCH] simple refactoring --- .../methods/report/calendar_multiget.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/proppatch.rs | 6 ++--- crates/dav/src/resource/mod.rs | 21 ++++++++-------- crates/dav/src/xml/multistatus.rs | 25 ++++++++++++++++--- crates/dav/src/xml/tag_list.rs | 9 ++----- 8 files changed, 40 insertions(+), 29 deletions(-) diff --git a/crates/caldav/src/calendar/methods/report/calendar_multiget.rs b/crates/caldav/src/calendar/methods/report/calendar_multiget.rs index bcf750b..5747667 100644 --- a/crates/caldav/src/calendar/methods/report/calendar_multiget.rs +++ b/crates/caldav/src/calendar/methods/report/calendar_multiget.rs @@ -99,7 +99,7 @@ pub async fn handle_calendar_multiget( .into_iter() .map(|path| ResponseElement { href: path, - status: Some(format!("HTTP/1.1 {}", StatusCode::NOT_FOUND)), + status: Some(StatusCode::NOT_FOUND), ..Default::default() }) .collect(); diff --git a/crates/caldav/src/calendar/methods/report/sync_collection.rs b/crates/caldav/src/calendar/methods/report/sync_collection.rs index 3c60ccf..aaf5b8f 100644 --- a/crates/caldav/src/calendar/methods/report/sync_collection.rs +++ b/crates/caldav/src/calendar/methods/report/sync_collection.rs @@ -88,7 +88,7 @@ pub async fn handle_sync_collection( .unwrap(); responses.push(ResponseElement { href: path, - status: Some(format!("HTTP/1.1 {}", StatusCode::NOT_FOUND)), + status: Some(StatusCode::NOT_FOUND), ..Default::default() }); } diff --git a/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs b/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs index 2fc75c0..78c6416 100644 --- a/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs +++ b/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs @@ -104,7 +104,7 @@ pub async fn handle_addressbook_multiget( .into_iter() .map(|path| ResponseElement { href: path, - status: Some(format!("HTTP/1.1 {}", StatusCode::NOT_FOUND)), + status: Some(StatusCode::NOT_FOUND), ..Default::default() }) .collect(); diff --git a/crates/carddav/src/addressbook/methods/report/sync_collection.rs b/crates/carddav/src/addressbook/methods/report/sync_collection.rs index 138595b..e43c53c 100644 --- a/crates/carddav/src/addressbook/methods/report/sync_collection.rs +++ b/crates/carddav/src/addressbook/methods/report/sync_collection.rs @@ -86,7 +86,7 @@ pub async fn handle_sync_collection( .unwrap(); responses.push(ResponseElement { href: path, - status: Some(format!("HTTP/1.1 {}", StatusCode::NOT_FOUND)), + status: Some(StatusCode::NOT_FOUND), ..Default::default() }); } diff --git a/crates/dav/src/resource/methods/proppatch.rs b/crates/dav/src/resource/methods/proppatch.rs index d8c5f15..d60e0f3 100644 --- a/crates/dav/src/resource/methods/proppatch.rs +++ b/crates/dav/src/resource/methods/proppatch.rs @@ -135,15 +135,15 @@ pub(crate) async fn route_proppatch( propstat: vec![ PropstatWrapper::TagList(PropstatElement { prop: TagList::from(props_ok), - status: format!("HTTP/1.1 {}", StatusCode::OK), + status: StatusCode::OK, }), PropstatWrapper::TagList(PropstatElement { prop: TagList::from(props_not_found), - status: format!("HTTP/1.1 {}", StatusCode::NOT_FOUND), + status: StatusCode::NOT_FOUND, }), PropstatWrapper::TagList(PropstatElement { prop: TagList::from(props_conflict), - status: format!("HTTP/1.1 {}", StatusCode::CONFLICT), + status: StatusCode::CONFLICT, }), ], ..Default::default() diff --git a/crates/dav/src/resource/mod.rs b/crates/dav/src/resource/mod.rs index 6794212..08ac8fd 100644 --- a/crates/dav/src/resource/mod.rs +++ b/crates/dav/src/resource/mod.rs @@ -158,20 +158,21 @@ pub trait Resource: Clone + 'static { Error::BadRequest("propname MUST be the only queried prop".to_owned()).into(), ); } - let props: Vec = Self::list_props() - .iter() - .map(|&prop| prop.to_string()) - .collect(); + let props = Self::list_props() + .into_iter() + .map(str::to_owned) + .collect_vec(); return Ok(ResponseElement { href: path.to_owned(), propstat: vec![PropstatWrapper::TagList(PropstatElement { prop: TagList::from(props), - status: format!("HTTP/1.1 {}", StatusCode::OK), + status: StatusCode::OK, })], ..Default::default() }); } + if props.contains(&"allprop") { if props.len() != 1 { // allprop MUST be the only queried prop per spec @@ -198,10 +199,8 @@ pub trait Resource: Clone + 'static { let internal_prop_responses: Vec<_> = internal_props .into_iter() .map(|prop| self.get_internal_prop(rmap, user, &prop)) - .collect::, Self::Error>>()? - .into_iter() - .map(EitherProp::Right) - .collect(); + .map_ok(EitherProp::Right) + .collect::>()?; let mut prop_responses = valid_props .into_iter() @@ -211,14 +210,14 @@ pub trait Resource: Clone + 'static { prop_responses.extend(internal_prop_responses); let mut propstats = vec![PropstatWrapper::Normal(PropstatElement { - status: format!("HTTP/1.1 {}", StatusCode::OK), + status: StatusCode::OK, prop: PropTagWrapper { prop: prop_responses, }, })]; if !invalid_props.is_empty() { propstats.push(PropstatWrapper::TagList(PropstatElement { - status: format!("HTTP/1.1 {}", StatusCode::NOT_FOUND), + status: StatusCode::NOT_FOUND, prop: invalid_props .into_iter() .map(|s| s.to_owned()) diff --git a/crates/dav/src/xml/multistatus.rs b/crates/dav/src/xml/multistatus.rs index 0bf9ec8..655735d 100644 --- a/crates/dav/src/xml/multistatus.rs +++ b/crates/dav/src/xml/multistatus.rs @@ -1,8 +1,10 @@ use crate::{namespace::Namespace, xml::TagList}; use actix_web::{ - body::BoxBody, http::header::ContentType, HttpRequest, HttpResponse, Responder, ResponseError, + body::BoxBody, + http::{header::ContentType, StatusCode}, + HttpRequest, HttpResponse, Responder, ResponseError, }; -use serde::Serialize; +use serde::{Serialize, Serializer}; // Intermediate struct because of a serde limitation, see following article: // https://stackoverflow.com/questions/78444158/unsupportedcannot-serialize-enum-newtype-variant-exampledata @@ -18,7 +20,12 @@ pub struct PropTagWrapper { #[serde(rename_all = "kebab-case")] pub struct PropstatElement { pub prop: PropType, - pub status: String, + #[serde(serialize_with = "serialize_status")] + pub status: StatusCode, +} + +fn serialize_status(status: &StatusCode, serializer: S) -> Result { + format!("HTTP/1.1 {}", status).serialize(serializer) } #[derive(Serialize)] @@ -36,10 +43,20 @@ pub enum PropstatWrapper { pub struct ResponseElement { pub href: String, #[serde(skip_serializing_if = "Option::is_none")] - pub status: Option, + #[serde(serialize_with = "serialize_optional_status")] + pub status: Option, pub propstat: Vec>, } +fn serialize_optional_status( + status_option: &Option, + serializer: S, +) -> Result { + status_option + .map(|status| format!("HTTP/1.1 {}", status)) + .serialize(serializer) +} + impl Default for ResponseElement { fn default() -> Self { Self { diff --git a/crates/dav/src/xml/tag_list.rs b/crates/dav/src/xml/tag_list.rs index 422e8ae..6e64e66 100644 --- a/crates/dav/src/xml/tag_list.rs +++ b/crates/dav/src/xml/tag_list.rs @@ -1,3 +1,4 @@ +use derive_more::derive::From; use serde::ser::SerializeMap; use serde::{ @@ -5,7 +6,7 @@ use serde::{ Deserialize, Serialize, }; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, From)] pub struct TagList(Vec); struct TagListVisitor; @@ -59,9 +60,3 @@ impl TagList { self.0 } } - -impl From> for TagList { - fn from(value: Vec) -> Self { - Self(value) - } -}