mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-13 19:22:26 +00:00
Make MultistatusElement responder, other refactoring
This commit is contained in:
@@ -75,6 +75,7 @@ pub async fn route_mkcol_calendar<A: CheckAuthentication, C: CalendarStore + ?Si
|
|||||||
timezone: request.calendar_timezone,
|
timezone: request.calendar_timezone,
|
||||||
color: request.calendar_color,
|
color: request.calendar_color,
|
||||||
description: request.calendar_description,
|
description: request.calendar_description,
|
||||||
|
deleted: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
match context.store.read().await.get_calendar(&cid).await {
|
match context.store.read().await.get_calendar(&cid).await {
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
use crate::{event::resource::EventFile, Error};
|
use crate::{event::resource::EventFile, Error};
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
http::header::ContentType,
|
|
||||||
web::{Data, Path},
|
web::{Data, Path},
|
||||||
HttpRequest, HttpResponse,
|
HttpRequest, Responder,
|
||||||
};
|
};
|
||||||
use rustical_auth::{AuthInfoExtractor, CheckAuthentication};
|
use rustical_auth::{AuthInfoExtractor, CheckAuthentication};
|
||||||
use rustical_dav::{
|
use rustical_dav::{
|
||||||
namespace::Namespace,
|
namespace::Namespace,
|
||||||
propfind::{MultistatusElement, PropElement, PropfindType, ServicePrefix},
|
propfind::{PropElement, PropfindType, ServicePrefix},
|
||||||
resource::HandlePropfind,
|
resource::HandlePropfind,
|
||||||
|
xml::MultistatusElement,
|
||||||
};
|
};
|
||||||
use rustical_store::event::Event;
|
use rustical_store::event::Event;
|
||||||
use rustical_store::CalendarStore;
|
use rustical_store::CalendarStore;
|
||||||
@@ -143,7 +143,7 @@ pub async fn route_report_calendar<A: CheckAuthentication, C: CalendarStore + ?S
|
|||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
cal_store: Data<RwLock<C>>,
|
cal_store: Data<RwLock<C>>,
|
||||||
prefix: Data<ServicePrefix>,
|
prefix: Data<ServicePrefix>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<impl Responder, Error> {
|
||||||
let (principal, cid) = path.into_inner();
|
let (principal, cid) = path.into_inner();
|
||||||
if principal != auth.inner.user_id {
|
if principal != auth.inner.user_id {
|
||||||
return Err(Error::Unauthorized);
|
return Err(Error::Unauthorized);
|
||||||
@@ -188,20 +188,11 @@ pub async fn route_report_calendar<A: CheckAuthentication, C: CalendarStore + ?S
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut output = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".to_owned();
|
Ok(MultistatusElement {
|
||||||
let mut ser = quick_xml::se::Serializer::new(&mut output);
|
|
||||||
ser.indent(' ', 4);
|
|
||||||
MultistatusElement {
|
|
||||||
responses,
|
responses,
|
||||||
member_responses: Vec::<String>::new(),
|
member_responses: Vec::<String>::new(),
|
||||||
ns_dav: Namespace::Dav.as_str(),
|
ns_dav: Namespace::Dav.as_str(),
|
||||||
ns_caldav: Namespace::CalDAV.as_str(),
|
ns_caldav: Namespace::CalDAV.as_str(),
|
||||||
ns_ical: Namespace::ICal.as_str(),
|
ns_ical: Namespace::ICal.as_str(),
|
||||||
}
|
})
|
||||||
.serialize(ser)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
Ok(HttpResponse::MultiStatus()
|
|
||||||
.content_type(ContentType::xml())
|
|
||||||
.body(output))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,5 @@ pub mod propfind;
|
|||||||
pub mod proppatch;
|
pub mod proppatch;
|
||||||
pub mod resource;
|
pub mod resource;
|
||||||
pub mod xml;
|
pub mod xml;
|
||||||
pub mod xml_snippets;
|
|
||||||
|
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
|
|||||||
@@ -2,15 +2,15 @@ use crate::depth_extractor::Depth;
|
|||||||
use crate::namespace::Namespace;
|
use crate::namespace::Namespace;
|
||||||
use crate::resource::HandlePropfind;
|
use crate::resource::HandlePropfind;
|
||||||
use crate::resource::ResourceService;
|
use crate::resource::ResourceService;
|
||||||
use crate::xml::tag_list::TagList;
|
use crate::xml::MultistatusElement;
|
||||||
|
use crate::xml::TagList;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
use actix_web::http::header::ContentType;
|
|
||||||
use actix_web::web::{Data, Path};
|
use actix_web::web::{Data, Path};
|
||||||
use actix_web::{HttpRequest, HttpResponse};
|
use actix_web::HttpRequest;
|
||||||
|
use actix_web::Responder;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use rustical_auth::{AuthInfoExtractor, CheckAuthentication};
|
use rustical_auth::{AuthInfoExtractor, CheckAuthentication};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
|
||||||
|
|
||||||
// This is not the final place for this struct
|
// This is not the final place for this struct
|
||||||
pub struct ServicePrefix(pub String);
|
pub struct ServicePrefix(pub String);
|
||||||
@@ -37,21 +37,6 @@ struct PropfindElement {
|
|||||||
prop: PropfindType,
|
prop: PropfindType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
|
||||||
#[serde(rename = "multistatus")]
|
|
||||||
pub struct MultistatusElement<T1: Serialize, T2: Serialize> {
|
|
||||||
#[serde(rename = "response")]
|
|
||||||
pub responses: Vec<T1>,
|
|
||||||
#[serde(rename = "response")]
|
|
||||||
pub member_responses: Vec<T2>,
|
|
||||||
#[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<A: CheckAuthentication, R: ResourceService + ?Sized>(
|
pub async fn route_propfind<A: CheckAuthentication, R: ResourceService + ?Sized>(
|
||||||
path: Path<R::PathComponents>,
|
path: Path<R::PathComponents>,
|
||||||
body: String,
|
body: String,
|
||||||
@@ -59,7 +44,7 @@ pub async fn route_propfind<A: CheckAuthentication, R: ResourceService + ?Sized>
|
|||||||
prefix: Data<ServicePrefix>,
|
prefix: Data<ServicePrefix>,
|
||||||
auth: AuthInfoExtractor<A>,
|
auth: AuthInfoExtractor<A>,
|
||||||
depth: Depth,
|
depth: Depth,
|
||||||
) -> Result<HttpResponse, R::Error> {
|
) -> Result<impl Responder, R::Error> {
|
||||||
debug!("{body}");
|
debug!("{body}");
|
||||||
let auth_info = auth.inner;
|
let auth_info = auth.inner;
|
||||||
let prefix = prefix.0.to_owned();
|
let prefix = prefix.0.to_owned();
|
||||||
@@ -98,20 +83,11 @@ pub async fn route_propfind<A: CheckAuthentication, R: ResourceService + ?Sized>
|
|||||||
let resource = resource_service.get_file().await?;
|
let resource = resource_service.get_file().await?;
|
||||||
let response = resource.propfind(&prefix, props).await?;
|
let response = resource.propfind(&prefix, props).await?;
|
||||||
|
|
||||||
let mut output = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".to_owned();
|
Ok(MultistatusElement {
|
||||||
let mut ser = quick_xml::se::Serializer::new(&mut output);
|
|
||||||
ser.indent(' ', 4);
|
|
||||||
MultistatusElement {
|
|
||||||
responses: vec![response],
|
responses: vec![response],
|
||||||
member_responses,
|
member_responses,
|
||||||
ns_dav: Namespace::Dav.as_str(),
|
ns_dav: Namespace::Dav.as_str(),
|
||||||
ns_caldav: Namespace::CalDAV.as_str(),
|
ns_caldav: Namespace::CalDAV.as_str(),
|
||||||
ns_ical: Namespace::ICal.as_str(),
|
ns_ical: Namespace::ICal.as_str(),
|
||||||
}
|
})
|
||||||
.serialize(ser)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
Ok(HttpResponse::MultiStatus()
|
|
||||||
.content_type(ContentType::xml())
|
|
||||||
.body(output))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
use crate::namespace::Namespace;
|
use crate::namespace::Namespace;
|
||||||
use crate::propfind::MultistatusElement;
|
|
||||||
use crate::resource::InvalidProperty;
|
use crate::resource::InvalidProperty;
|
||||||
use crate::resource::Resource;
|
use crate::resource::Resource;
|
||||||
use crate::resource::ResourceService;
|
use crate::resource::ResourceService;
|
||||||
use crate::resource::{PropstatElement, PropstatResponseElement, PropstatType};
|
use crate::resource::{PropstatElement, PropstatResponseElement, PropstatType};
|
||||||
use crate::xml::tag_list::TagList;
|
use crate::xml::MultistatusElement;
|
||||||
use crate::xml::tag_name::TagName;
|
use crate::xml::TagList;
|
||||||
|
use crate::xml::TagName;
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
use actix_web::http::header::ContentType;
|
|
||||||
use actix_web::http::StatusCode;
|
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 log::debug;
|
||||||
use rustical_auth::{AuthInfoExtractor, CheckAuthentication};
|
use rustical_auth::{AuthInfoExtractor, CheckAuthentication};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -49,7 +49,7 @@ pub async fn route_proppatch<A: CheckAuthentication, R: ResourceService + ?Sized
|
|||||||
body: String,
|
body: String,
|
||||||
req: HttpRequest,
|
req: HttpRequest,
|
||||||
auth: AuthInfoExtractor<A>,
|
auth: AuthInfoExtractor<A>,
|
||||||
) -> Result<HttpResponse, R::Error> {
|
) -> Result<impl Responder, R::Error> {
|
||||||
let auth_info = auth.inner;
|
let auth_info = auth.inner;
|
||||||
let path_components = path.into_inner();
|
let path_components = path.into_inner();
|
||||||
let href = req.path().to_owned();
|
let href = req.path().to_owned();
|
||||||
@@ -132,10 +132,7 @@ pub async fn route_proppatch<A: CheckAuthentication, R: ResourceService + ?Sized
|
|||||||
resource_service.save_file(resource).await?;
|
resource_service.save_file(resource).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut output = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".to_owned();
|
Ok(MultistatusElement {
|
||||||
let mut ser = quick_xml::se::Serializer::new(&mut output);
|
|
||||||
ser.indent(' ', 4);
|
|
||||||
MultistatusElement {
|
|
||||||
responses: vec![PropstatResponseElement {
|
responses: vec![PropstatResponseElement {
|
||||||
href,
|
href,
|
||||||
propstat: vec![
|
propstat: vec![
|
||||||
@@ -158,12 +155,5 @@ pub async fn route_proppatch<A: CheckAuthentication, R: ResourceService + ?Sized
|
|||||||
ns_dav: Namespace::Dav.as_str(),
|
ns_dav: Namespace::Dav.as_str(),
|
||||||
ns_caldav: Namespace::CalDAV.as_str(),
|
ns_caldav: Namespace::CalDAV.as_str(),
|
||||||
ns_ical: Namespace::ICal.as_str(),
|
ns_ical: Namespace::ICal.as_str(),
|
||||||
}
|
})
|
||||||
.serialize(ser)
|
|
||||||
.unwrap();
|
|
||||||
debug!("{output}");
|
|
||||||
|
|
||||||
Ok(HttpResponse::MultiStatus()
|
|
||||||
.content_type(ContentType::xml())
|
|
||||||
.body(output))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +1,20 @@
|
|||||||
|
pub mod multistatus;
|
||||||
pub mod tag_list;
|
pub mod tag_list;
|
||||||
pub mod tag_name;
|
pub mod tag_name;
|
||||||
|
|
||||||
|
pub use multistatus::MultistatusElement;
|
||||||
|
pub use tag_list::TagList;
|
||||||
|
pub use tag_name::TagName;
|
||||||
|
|
||||||
|
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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
38
crates/dav/src/xml/multistatus.rs
Normal file
38
crates/dav/src/xml/multistatus.rs
Normal file
@@ -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<T1: Serialize, T2: Serialize> {
|
||||||
|
#[serde(rename = "response")]
|
||||||
|
pub responses: Vec<T1>,
|
||||||
|
#[serde(rename = "response")]
|
||||||
|
pub member_responses: Vec<T2>,
|
||||||
|
#[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<T1: Serialize, T2: Serialize> Responder for MultistatusElement<T1, T2> {
|
||||||
|
type Body = BoxBody;
|
||||||
|
|
||||||
|
fn respond_to(self, _req: &HttpRequest) -> HttpResponse<Self::Body> {
|
||||||
|
let mut output = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,8 +3,8 @@ use serde::{
|
|||||||
Deserialize,
|
Deserialize,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct TagName(String);
|
pub struct TagName(pub String);
|
||||||
|
|
||||||
impl From<TagName> for String {
|
impl From<TagName> for String {
|
||||||
fn from(value: TagName) -> Self {
|
fn from(value: TagName) -> Self {
|
||||||
|
|||||||
@@ -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 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use rustical_dav::xml::tag_list::TagList;
|
use rustical_dav::xml::TagList;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
const INPUT: &str = r#"<Document>
|
const INPUT: &str = r#"<Document>
|
||||||
|
|||||||
Reference in New Issue
Block a user