From d69c0dcd4537057a7d27dfecfbfc9388f39b0e7c Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Wed, 13 Sep 2023 19:31:14 +0200 Subject: [PATCH] Move route_propfind to its own file --- crates/dav/src/lib.rs | 91 ++++------------------------ crates/dav/src/propfind.rs | 31 +--------- crates/dav/src/routes/mod.rs | 1 + crates/dav/src/routes/propfind.rs | 99 +++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 111 deletions(-) create mode 100644 crates/dav/src/routes/propfind.rs diff --git a/crates/dav/src/lib.rs b/crates/dav/src/lib.rs index cd94ede..7696099 100644 --- a/crates/dav/src/lib.rs +++ b/crates/dav/src/lib.rs @@ -1,19 +1,14 @@ -use actix_web::http::header::ContentType; use actix_web::http::Method; -use actix_web::web::{self, Data, Path}; -use actix_web::{guard, HttpRequest, HttpResponse, Responder}; -use depth_extractor::Depth; +use actix_web::web::{self, Data}; +use actix_web::{guard, HttpResponse, Responder}; use error::Error; -use namespace::Namespace; -use propfind::{generate_multistatus, parse_propfind}; -use quick_xml::events::BytesText; -use resource::{HandlePropfind, Resource}; use resources::calendar::CalendarResource; use resources::event::EventResource; use resources::principal::PrincipalCalendarsResource; use resources::root::RootResource; +use routes::propfind::route_propfind; use routes::{calendar, event}; -use rustical_auth::{AuthInfoExtractor, CheckAuthentication}; +use rustical_auth::CheckAuthentication; use rustical_store::calendar::CalendarStore; use std::str::FromStr; use std::sync::Arc; @@ -60,96 +55,30 @@ pub fn configure_dav( .to(options_handler), ) .service( - web::resource("").route(web::method(propfind_method()).to(route_new_propfind::< + web::resource("").route(web::method(propfind_method()).to(route_propfind::< A, RootResource, C, >)), ) - .service( - web::resource("/{principal}").route( - web::method(propfind_method()).to(route_new_propfind::< - A, - PrincipalCalendarsResource, - C, - >), - ), - ) + .service(web::resource("/{principal}").route( + web::method(propfind_method()).to(route_propfind::, C>), + )) .service( web::resource("/{principal}/{calendar}") .route(web::method(report_method()).to(calendar::route_report_calendar::)) - .route( - web::method(propfind_method()).to(route_new_propfind::, C>), - ) + .route(web::method(propfind_method()).to(route_propfind::, C>)) .route(web::method(mkcol_method()).to(calendar::route_mkcol_calendar::)), ) .service( web::resource("/{principal}/{calendar}/{event}") - .route(web::method(propfind_method()).to(route_new_propfind::)) - .route(web::method(propfind_method()).to(route_new_propfind::, C>)) + .route(web::method(propfind_method()).to(route_propfind::, C>)) .route(web::method(Method::DELETE).to(event::delete_event::)) .route(web::method(Method::GET).to(event::get_event::)) .route(web::method(Method::PUT).to(event::put_event::)), ); } -async fn route_new_propfind( - path: Path, - body: String, - req: HttpRequest, - context: Data>, - auth: AuthInfoExtractor, - depth: Depth, -) -> Result { - let props = parse_propfind(&body).map_err(|_e| Error::BadRequest)?; - let req_path = req.path().to_string(); - let auth_info = auth.inner; - - let resource = R::acquire_from_request( - req, - auth_info, - path.into_inner(), - context.prefix.to_string(), - ) - .await - .map_err(|_e| Error::InternalError)?; - - let mut responses = vec![resource - .propfind(props.clone()) - .map_err(|_e| Error::InternalError)?]; - - if depth != Depth::Zero { - for member in resource - .get_members() - .await - .map_err(|_e| Error::InternalError)? - { - responses.push( - member - .propfind(props.clone()) - .map_err(|_e| Error::InternalError)?, - ); - } - } - - let output = generate_multistatus( - vec![Namespace::Dav, Namespace::CalDAV, Namespace::ICal], - |writer| { - for response in responses { - writer.write_event(quick_xml::events::Event::Text(BytesText::from_escaped( - response, - )))?; - } - Ok(()) - }, - ) - .map_err(|_e| Error::InternalError)?; - - Ok(HttpResponse::MultiStatus() - .content_type(ContentType::xml()) - .body(output)) -} - async fn options_handler() -> impl Responder { HttpResponse::Ok() .insert_header(( diff --git a/crates/dav/src/propfind.rs b/crates/dav/src/propfind.rs index c10e84a..20eb497 100644 --- a/crates/dav/src/propfind.rs +++ b/crates/dav/src/propfind.rs @@ -1,41 +1,12 @@ use std::io::Write; use actix_web::http::StatusCode; -use anyhow::{anyhow, Result}; +use anyhow::Result; use quick_xml::{ events::{attributes::Attribute, BytesText}, Writer, }; -pub fn parse_propfind(body: &str) -> Result> { - if body.is_empty() { - // if body is empty, allprops must be returned (RFC 4918) - return Ok(vec!["allprops"]); - } - let doc = roxmltree::Document::parse(body)?; - - let propfind_node = doc.root_element(); - if propfind_node.tag_name().name() != "propfind" { - return Err(anyhow!("invalid tag")); - } - - let prop_node = if let Some(el) = propfind_node.first_element_child() { - el - } else { - return Ok(Vec::new()); - }; - - let props = match prop_node.tag_name().name() { - "prop" => Ok(prop_node - .children() - .map(|node| node.tag_name().name()) - .collect()), - _ => Err(anyhow!("invalid prop tag")), - }; - dbg!(body, &props); - props -} - pub fn write_resourcetype( writer: &mut Writer, types: Vec<&str>, diff --git a/crates/dav/src/routes/mod.rs b/crates/dav/src/routes/mod.rs index ec0aeac..538e825 100644 --- a/crates/dav/src/routes/mod.rs +++ b/crates/dav/src/routes/mod.rs @@ -1,2 +1,3 @@ pub mod calendar; pub mod event; +pub mod propfind; diff --git a/crates/dav/src/routes/propfind.rs b/crates/dav/src/routes/propfind.rs new file mode 100644 index 0000000..4eae43e --- /dev/null +++ b/crates/dav/src/routes/propfind.rs @@ -0,0 +1,99 @@ +use crate::depth_extractor::Depth; +use crate::error::Error; +use crate::namespace::Namespace; +use crate::propfind::generate_multistatus; +use crate::resource::{HandlePropfind, Resource}; +use crate::CalDavContext; +use actix_web::http::header::ContentType; +use actix_web::web::{Data, Path}; +use actix_web::{HttpRequest, HttpResponse}; +use anyhow::{anyhow, Result}; +use quick_xml::events::BytesText; +use rustical_auth::{AuthInfoExtractor, CheckAuthentication}; +use rustical_store::calendar::CalendarStore; + +fn parse_propfind(body: &str) -> Result> { + if body.is_empty() { + // if body is empty, allprops must be returned (RFC 4918) + return Ok(vec!["allprops"]); + } + let doc = roxmltree::Document::parse(body)?; + + let propfind_node = doc.root_element(); + if propfind_node.tag_name().name() != "propfind" { + return Err(anyhow!("invalid tag")); + } + + let prop_node = if let Some(el) = propfind_node.first_element_child() { + el + } else { + return Ok(Vec::new()); + }; + + let props = match prop_node.tag_name().name() { + "prop" => Ok(prop_node + .children() + .map(|node| node.tag_name().name()) + .collect()), + _ => Err(anyhow!("invalid prop tag")), + }; + dbg!(body, &props); + props +} + +pub async fn route_propfind( + path: Path, + body: String, + req: HttpRequest, + context: Data>, + auth: AuthInfoExtractor, + depth: Depth, +) -> Result { + let props = parse_propfind(&body).map_err(|_e| Error::BadRequest)?; + // let req_path = req.path().to_string(); + let auth_info = auth.inner; + + let resource = R::acquire_from_request( + req, + auth_info, + path.into_inner(), + context.prefix.to_string(), + ) + .await + .map_err(|_e| Error::InternalError)?; + + let mut responses = vec![resource + .propfind(props.clone()) + .map_err(|_e| Error::InternalError)?]; + + if depth != Depth::Zero { + for member in resource + .get_members() + .await + .map_err(|_e| Error::InternalError)? + { + responses.push( + member + .propfind(props.clone()) + .map_err(|_e| Error::InternalError)?, + ); + } + } + + let output = generate_multistatus( + vec![Namespace::Dav, Namespace::CalDAV, Namespace::ICal], + |writer| { + for response in responses { + writer.write_event(quick_xml::events::Event::Text(BytesText::from_escaped( + response, + )))?; + } + Ok(()) + }, + ) + .map_err(|_e| Error::InternalError)?; + + Ok(HttpResponse::MultiStatus() + .content_type(ContentType::xml()) + .body(output)) +}