simple refactoring

This commit is contained in:
Lennart
2024-11-06 16:18:11 +01:00
parent c21993ab15
commit f56fd81d0e
8 changed files with 40 additions and 29 deletions

View File

@@ -99,7 +99,7 @@ pub async fn handle_calendar_multiget<C: CalendarStore + ?Sized>(
.into_iter() .into_iter()
.map(|path| ResponseElement { .map(|path| ResponseElement {
href: path, href: path,
status: Some(format!("HTTP/1.1 {}", StatusCode::NOT_FOUND)), status: Some(StatusCode::NOT_FOUND),
..Default::default() ..Default::default()
}) })
.collect(); .collect();

View File

@@ -88,7 +88,7 @@ pub async fn handle_sync_collection<C: CalendarStore + ?Sized>(
.unwrap(); .unwrap();
responses.push(ResponseElement { responses.push(ResponseElement {
href: path, href: path,
status: Some(format!("HTTP/1.1 {}", StatusCode::NOT_FOUND)), status: Some(StatusCode::NOT_FOUND),
..Default::default() ..Default::default()
}); });
} }

View File

@@ -104,7 +104,7 @@ pub async fn handle_addressbook_multiget<AS: AddressbookStore + ?Sized>(
.into_iter() .into_iter()
.map(|path| ResponseElement { .map(|path| ResponseElement {
href: path, href: path,
status: Some(format!("HTTP/1.1 {}", StatusCode::NOT_FOUND)), status: Some(StatusCode::NOT_FOUND),
..Default::default() ..Default::default()
}) })
.collect(); .collect();

View File

@@ -86,7 +86,7 @@ pub async fn handle_sync_collection<AS: AddressbookStore + ?Sized>(
.unwrap(); .unwrap();
responses.push(ResponseElement { responses.push(ResponseElement {
href: path, href: path,
status: Some(format!("HTTP/1.1 {}", StatusCode::NOT_FOUND)), status: Some(StatusCode::NOT_FOUND),
..Default::default() ..Default::default()
}); });
} }

View File

@@ -135,15 +135,15 @@ pub(crate) async fn route_proppatch<R: ResourceService>(
propstat: vec![ propstat: vec![
PropstatWrapper::TagList(PropstatElement { PropstatWrapper::TagList(PropstatElement {
prop: TagList::from(props_ok), prop: TagList::from(props_ok),
status: format!("HTTP/1.1 {}", StatusCode::OK), status: StatusCode::OK,
}), }),
PropstatWrapper::TagList(PropstatElement { PropstatWrapper::TagList(PropstatElement {
prop: TagList::from(props_not_found), prop: TagList::from(props_not_found),
status: format!("HTTP/1.1 {}", StatusCode::NOT_FOUND), status: StatusCode::NOT_FOUND,
}), }),
PropstatWrapper::TagList(PropstatElement { PropstatWrapper::TagList(PropstatElement {
prop: TagList::from(props_conflict), prop: TagList::from(props_conflict),
status: format!("HTTP/1.1 {}", StatusCode::CONFLICT), status: StatusCode::CONFLICT,
}), }),
], ],
..Default::default() ..Default::default()

View File

@@ -158,20 +158,21 @@ pub trait Resource: Clone + 'static {
Error::BadRequest("propname MUST be the only queried prop".to_owned()).into(), Error::BadRequest("propname MUST be the only queried prop".to_owned()).into(),
); );
} }
let props: Vec<String> = Self::list_props() let props = Self::list_props()
.iter() .into_iter()
.map(|&prop| prop.to_string()) .map(str::to_owned)
.collect(); .collect_vec();
return Ok(ResponseElement { return Ok(ResponseElement {
href: path.to_owned(), href: path.to_owned(),
propstat: vec![PropstatWrapper::TagList(PropstatElement { propstat: vec![PropstatWrapper::TagList(PropstatElement {
prop: TagList::from(props), prop: TagList::from(props),
status: format!("HTTP/1.1 {}", StatusCode::OK), status: StatusCode::OK,
})], })],
..Default::default() ..Default::default()
}); });
} }
if props.contains(&"allprop") { if props.contains(&"allprop") {
if props.len() != 1 { if props.len() != 1 {
// allprop MUST be the only queried prop per spec // 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 let internal_prop_responses: Vec<_> = internal_props
.into_iter() .into_iter()
.map(|prop| self.get_internal_prop(rmap, user, &prop)) .map(|prop| self.get_internal_prop(rmap, user, &prop))
.collect::<Result<Vec<CommonPropertiesProp>, Self::Error>>()? .map_ok(EitherProp::Right)
.into_iter() .collect::<Result<_, Self::Error>>()?;
.map(EitherProp::Right)
.collect();
let mut prop_responses = valid_props let mut prop_responses = valid_props
.into_iter() .into_iter()
@@ -211,14 +210,14 @@ pub trait Resource: Clone + 'static {
prop_responses.extend(internal_prop_responses); prop_responses.extend(internal_prop_responses);
let mut propstats = vec![PropstatWrapper::Normal(PropstatElement { let mut propstats = vec![PropstatWrapper::Normal(PropstatElement {
status: format!("HTTP/1.1 {}", StatusCode::OK), status: StatusCode::OK,
prop: PropTagWrapper { prop: PropTagWrapper {
prop: prop_responses, prop: prop_responses,
}, },
})]; })];
if !invalid_props.is_empty() { if !invalid_props.is_empty() {
propstats.push(PropstatWrapper::TagList(PropstatElement { propstats.push(PropstatWrapper::TagList(PropstatElement {
status: format!("HTTP/1.1 {}", StatusCode::NOT_FOUND), status: StatusCode::NOT_FOUND,
prop: invalid_props prop: invalid_props
.into_iter() .into_iter()
.map(|s| s.to_owned()) .map(|s| s.to_owned())

View File

@@ -1,8 +1,10 @@
use crate::{namespace::Namespace, xml::TagList}; use crate::{namespace::Namespace, xml::TagList};
use actix_web::{ 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: // Intermediate struct because of a serde limitation, see following article:
// https://stackoverflow.com/questions/78444158/unsupportedcannot-serialize-enum-newtype-variant-exampledata // https://stackoverflow.com/questions/78444158/unsupportedcannot-serialize-enum-newtype-variant-exampledata
@@ -18,7 +20,12 @@ pub struct PropTagWrapper<T: Serialize> {
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub struct PropstatElement<PropType: Serialize> { pub struct PropstatElement<PropType: Serialize> {
pub prop: PropType, pub prop: PropType,
pub status: String, #[serde(serialize_with = "serialize_status")]
pub status: StatusCode,
}
fn serialize_status<S: Serializer>(status: &StatusCode, serializer: S) -> Result<S::Ok, S::Error> {
format!("HTTP/1.1 {}", status).serialize(serializer)
} }
#[derive(Serialize)] #[derive(Serialize)]
@@ -36,10 +43,20 @@ pub enum PropstatWrapper<T: Serialize> {
pub struct ResponseElement<PropstatType: Serialize> { pub struct ResponseElement<PropstatType: Serialize> {
pub href: String, pub href: String,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>, #[serde(serialize_with = "serialize_optional_status")]
pub status: Option<StatusCode>,
pub propstat: Vec<PropstatWrapper<PropstatType>>, pub propstat: Vec<PropstatWrapper<PropstatType>>,
} }
fn serialize_optional_status<S: Serializer>(
status_option: &Option<StatusCode>,
serializer: S,
) -> Result<S::Ok, S::Error> {
status_option
.map(|status| format!("HTTP/1.1 {}", status))
.serialize(serializer)
}
impl<PT: Serialize> Default for ResponseElement<PT> { impl<PT: Serialize> Default for ResponseElement<PT> {
fn default() -> Self { fn default() -> Self {
Self { Self {

View File

@@ -1,3 +1,4 @@
use derive_more::derive::From;
use serde::ser::SerializeMap; use serde::ser::SerializeMap;
use serde::{ use serde::{
@@ -5,7 +6,7 @@ use serde::{
Deserialize, Serialize, Deserialize, Serialize,
}; };
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq, From)]
pub struct TagList(Vec<String>); pub struct TagList(Vec<String>);
struct TagListVisitor; struct TagListVisitor;
@@ -59,9 +60,3 @@ impl TagList {
self.0 self.0
} }
} }
impl From<Vec<String>> for TagList {
fn from(value: Vec<String>) -> Self {
Self(value)
}
}