diff --git a/crates/caldav/src/calendar/methods/mkcalendar.rs b/crates/caldav/src/calendar/methods/mkcalendar.rs index 4db713c..807183f 100644 --- a/crates/caldav/src/calendar/methods/mkcalendar.rs +++ b/crates/caldav/src/calendar/methods/mkcalendar.rs @@ -75,6 +75,7 @@ pub async fn route_mkcol_calendar>, prefix: Data, -) -> Result { +) -> Result { let (principal, cid) = path.into_inner(); if principal != auth.inner.user_id { return Err(Error::Unauthorized); @@ -188,20 +188,11 @@ pub async fn route_report_calendar\n".to_owned(); - let mut ser = quick_xml::se::Serializer::new(&mut output); - ser.indent(' ', 4); - MultistatusElement { + Ok(MultistatusElement { responses, member_responses: Vec::::new(), ns_dav: Namespace::Dav.as_str(), ns_caldav: Namespace::CalDAV.as_str(), ns_ical: Namespace::ICal.as_str(), - } - .serialize(ser) - .unwrap(); - - Ok(HttpResponse::MultiStatus() - .content_type(ContentType::xml()) - .body(output)) + }) } diff --git a/crates/dav/src/lib.rs b/crates/dav/src/lib.rs index b7311ee..08450a4 100644 --- a/crates/dav/src/lib.rs +++ b/crates/dav/src/lib.rs @@ -5,6 +5,5 @@ pub mod propfind; pub mod proppatch; pub mod resource; pub mod xml; -pub mod xml_snippets; pub use error::Error; diff --git a/crates/dav/src/propfind.rs b/crates/dav/src/propfind.rs index 30d90bb..6fbece6 100644 --- a/crates/dav/src/propfind.rs +++ b/crates/dav/src/propfind.rs @@ -2,15 +2,15 @@ use crate::depth_extractor::Depth; use crate::namespace::Namespace; use crate::resource::HandlePropfind; use crate::resource::ResourceService; -use crate::xml::tag_list::TagList; +use crate::xml::MultistatusElement; +use crate::xml::TagList; use crate::Error; -use actix_web::http::header::ContentType; use actix_web::web::{Data, Path}; -use actix_web::{HttpRequest, HttpResponse}; +use actix_web::HttpRequest; +use actix_web::Responder; use log::debug; use rustical_auth::{AuthInfoExtractor, CheckAuthentication}; use serde::Deserialize; -use serde::Serialize; // This is not the final place for this struct pub struct ServicePrefix(pub String); @@ -37,21 +37,6 @@ struct PropfindElement { prop: PropfindType, } -#[derive(Serialize)] -#[serde(rename = "multistatus")] -pub struct MultistatusElement { - #[serde(rename = "response")] - pub responses: Vec, - #[serde(rename = "response")] - pub member_responses: Vec, - #[serde(rename = "@xmlns")] - pub ns_dav: &'static str, - #[serde(rename = "@xmlns:C")] - pub ns_caldav: &'static str, - #[serde(rename = "@xmlns:IC")] - pub ns_ical: &'static str, -} - pub async fn route_propfind( path: Path, body: String, @@ -59,7 +44,7 @@ pub async fn route_propfind prefix: Data, auth: AuthInfoExtractor, depth: Depth, -) -> Result { +) -> Result { debug!("{body}"); let auth_info = auth.inner; let prefix = prefix.0.to_owned(); @@ -98,20 +83,11 @@ pub async fn route_propfind let resource = resource_service.get_file().await?; let response = resource.propfind(&prefix, props).await?; - let mut output = "\n".to_owned(); - let mut ser = quick_xml::se::Serializer::new(&mut output); - ser.indent(' ', 4); - MultistatusElement { + Ok(MultistatusElement { responses: vec![response], member_responses, ns_dav: Namespace::Dav.as_str(), ns_caldav: Namespace::CalDAV.as_str(), ns_ical: Namespace::ICal.as_str(), - } - .serialize(ser) - .unwrap(); - - Ok(HttpResponse::MultiStatus() - .content_type(ContentType::xml()) - .body(output)) + }) } diff --git a/crates/dav/src/proppatch.rs b/crates/dav/src/proppatch.rs index c4cfe29..dad7ddb 100644 --- a/crates/dav/src/proppatch.rs +++ b/crates/dav/src/proppatch.rs @@ -1,15 +1,15 @@ use crate::namespace::Namespace; -use crate::propfind::MultistatusElement; use crate::resource::InvalidProperty; use crate::resource::Resource; use crate::resource::ResourceService; use crate::resource::{PropstatElement, PropstatResponseElement, PropstatType}; -use crate::xml::tag_list::TagList; -use crate::xml::tag_name::TagName; +use crate::xml::MultistatusElement; +use crate::xml::TagList; +use crate::xml::TagName; use crate::Error; -use actix_web::http::header::ContentType; use actix_web::http::StatusCode; -use actix_web::{web::Path, HttpRequest, HttpResponse}; +use actix_web::Responder; +use actix_web::{web::Path, HttpRequest}; use log::debug; use rustical_auth::{AuthInfoExtractor, CheckAuthentication}; use serde::{Deserialize, Serialize}; @@ -49,7 +49,7 @@ pub async fn route_proppatch, -) -> Result { +) -> Result { let auth_info = auth.inner; let path_components = path.into_inner(); let href = req.path().to_owned(); @@ -132,10 +132,7 @@ pub async fn route_proppatch\n".to_owned(); - let mut ser = quick_xml::se::Serializer::new(&mut output); - ser.indent(' ', 4); - MultistatusElement { + Ok(MultistatusElement { responses: vec![PropstatResponseElement { href, propstat: vec![ @@ -158,12 +155,5 @@ pub async fn route_proppatch Self { + Self { href } + } +} diff --git a/crates/dav/src/xml/multistatus.rs b/crates/dav/src/xml/multistatus.rs new file mode 100644 index 0000000..2c465e6 --- /dev/null +++ b/crates/dav/src/xml/multistatus.rs @@ -0,0 +1,38 @@ +use actix_web::{ + body::BoxBody, http::header::ContentType, HttpRequest, HttpResponse, Responder, ResponseError, +}; +use log::debug; +use serde::Serialize; + +#[derive(Serialize)] +#[serde(rename = "multistatus")] +pub struct MultistatusElement { + #[serde(rename = "response")] + pub responses: Vec, + #[serde(rename = "response")] + pub member_responses: Vec, + #[serde(rename = "@xmlns")] + pub ns_dav: &'static str, + #[serde(rename = "@xmlns:C")] + pub ns_caldav: &'static str, + #[serde(rename = "@xmlns:IC")] + pub ns_ical: &'static str, +} + +impl Responder for MultistatusElement { + type Body = BoxBody; + + fn respond_to(self, _req: &HttpRequest) -> HttpResponse { + let mut output = "\n".to_owned(); + let mut ser = quick_xml::se::Serializer::new(&mut output); + ser.indent(' ', 4); + if let Err(err) = self.serialize(ser) { + return crate::Error::from(err).error_response(); + } + debug!("Return multistatus:\n{output}"); + + HttpResponse::MultiStatus() + .content_type(ContentType::xml()) + .body(output) + } +} diff --git a/crates/dav/src/xml/tag_name.rs b/crates/dav/src/xml/tag_name.rs index 4a122df..43df209 100644 --- a/crates/dav/src/xml/tag_name.rs +++ b/crates/dav/src/xml/tag_name.rs @@ -3,8 +3,8 @@ use serde::{ Deserialize, }; -#[derive(Debug, Clone)] -pub struct TagName(String); +#[derive(Debug, Clone, PartialEq)] +pub struct TagName(pub String); impl From for String { fn from(value: TagName) -> Self { diff --git a/crates/dav/src/xml_snippets.rs b/crates/dav/src/xml_snippets.rs deleted file mode 100644 index 58a2393..0000000 --- a/crates/dav/src/xml_snippets.rs +++ /dev/null @@ -1,12 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Clone, Deserialize, Serialize)] -pub struct HrefElement { - pub href: String, -} -impl HrefElement { - pub fn new(href: String) -> Self { - Self { href } - } -} - diff --git a/crates/dav/tests/tag_list.rs b/crates/dav/tests/tag_list.rs index aa04c44..4bb3a4a 100644 --- a/crates/dav/tests/tag_list.rs +++ b/crates/dav/tests/tag_list.rs @@ -1,4 +1,4 @@ -use rustical_dav::xml::tag_list::TagList; +use rustical_dav::xml::TagList; use serde::{Deserialize, Serialize}; const INPUT: &str = r#"