From 2143bc850c4bc4a9f140ac9662acc1c429c650a9 Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Mon, 4 Nov 2024 20:46:16 +0100 Subject: [PATCH] simplify resourcetype --- crates/caldav/src/calendar/prop.rs | 8 ---- crates/caldav/src/calendar/resource.rs | 9 ++-- crates/caldav/src/calendar_object/resource.rs | 11 ++--- crates/caldav/src/principal/mod.rs | 14 ++---- crates/carddav/src/address_object/resource.rs | 11 ++--- crates/carddav/src/addressbook/prop.rs | 8 ---- crates/carddav/src/addressbook/resource.rs | 9 ++-- crates/carddav/src/principal/mod.rs | 14 ++---- crates/dav/src/extensions/mod.rs | 16 +++---- crates/dav/src/resource/mod.rs | 7 +-- crates/dav/src/resources/root.rs | 14 ++---- crates/dav/src/xml/mod.rs | 3 ++ crates/dav/src/xml/resourcetype.rs | 46 +++++++++++++++++++ 13 files changed, 98 insertions(+), 72 deletions(-) create mode 100644 crates/dav/src/xml/resourcetype.rs diff --git a/crates/caldav/src/calendar/prop.rs b/crates/caldav/src/calendar/prop.rs index b4e8488..074e2b6 100644 --- a/crates/caldav/src/calendar/prop.rs +++ b/crates/caldav/src/calendar/prop.rs @@ -39,14 +39,6 @@ pub struct SupportedCalendarData { calendar_data: CalendarData, } -#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq)] -#[serde(rename_all = "kebab-case")] -pub struct Resourcetype { - #[serde(rename = "C:calendar", alias = "calendar")] - calendar: (), - collection: (), -} - #[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] #[serde(rename_all = "kebab-case")] pub enum ReportMethod { diff --git a/crates/caldav/src/calendar/resource.rs b/crates/caldav/src/calendar/resource.rs index 14eeb7a..336e0a4 100644 --- a/crates/caldav/src/calendar/resource.rs +++ b/crates/caldav/src/calendar/resource.rs @@ -1,7 +1,7 @@ use super::methods::mkcalendar::route_mkcalendar; use super::methods::report::route_report_calendar; use super::prop::{ - Resourcetype, SupportedCalendarComponent, SupportedCalendarComponentSet, SupportedCalendarData, + SupportedCalendarComponent, SupportedCalendarComponentSet, SupportedCalendarData, SupportedReportSet, }; use crate::calendar_object::resource::CalendarObjectResource; @@ -83,7 +83,7 @@ pub enum CalendarProp { #[serde(skip_deserializing, untagged)] #[from] - ExtCommonProperties(CommonPropertiesProp), + ExtCommonProperties(CommonPropertiesProp), #[serde(untagged)] #[default] @@ -97,9 +97,12 @@ impl Resource for CalendarResource { type PropName = CalendarPropName; type Prop = CalendarProp; type Error = Error; - type ResourceType = Resourcetype; type PrincipalResource = PrincipalResource; + fn get_resourcetype() -> &'static [&'static str] { + &["collection", "C:calendar"] + } + fn get_prop( &self, _rmap: &ResourceMap, diff --git a/crates/caldav/src/calendar_object/resource.rs b/crates/caldav/src/calendar_object/resource.rs index f9700d6..e45ac53 100644 --- a/crates/caldav/src/calendar_object/resource.rs +++ b/crates/caldav/src/calendar_object/resource.rs @@ -41,7 +41,7 @@ pub enum CalendarObjectProp { #[serde(skip_deserializing, untagged)] #[from] - ExtCommonProperties(CommonPropertiesProp), + ExtCommonProperties(CommonPropertiesProp), #[serde(untagged)] #[default] @@ -54,16 +54,15 @@ pub struct CalendarObjectResource { pub principal: String, } -#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq)] -#[serde(rename_all = "kebab-case")] -pub struct Resourcetype {} - impl Resource for CalendarObjectResource { type PropName = CalendarObjectPropName; type Prop = CalendarObjectProp; type Error = Error; type PrincipalResource = PrincipalResource; - type ResourceType = Resourcetype; + + fn get_resourcetype() -> &'static [&'static str] { + &[] + } fn get_prop( &self, diff --git a/crates/caldav/src/principal/mod.rs b/crates/caldav/src/principal/mod.rs index 4dffdce..be1af1c 100644 --- a/crates/caldav/src/principal/mod.rs +++ b/crates/caldav/src/principal/mod.rs @@ -25,13 +25,6 @@ pub struct PrincipalResource { principal: String, } -#[derive(Deserialize, Serialize, Default, Debug, PartialEq)] -#[serde(rename_all = "kebab-case")] -pub struct Resourcetype { - principal: (), - collection: (), -} - #[derive(Default, Deserialize, Serialize, From, PartialEq)] #[serde(rename_all = "kebab-case")] pub enum PrincipalProp { @@ -47,7 +40,7 @@ pub enum PrincipalProp { #[serde(skip_deserializing, untagged)] #[from] - ExtCommonProperties(CommonPropertiesProp), + ExtCommonProperties(CommonPropertiesProp), #[serde(untagged)] #[default] @@ -73,9 +66,12 @@ impl Resource for PrincipalResource { type PropName = PrincipalPropName; type Prop = PrincipalProp; type Error = Error; - type ResourceType = Resourcetype; type PrincipalResource = PrincipalResource; + fn get_resourcetype() -> &'static [&'static str] { + &["collection", "principal"] + } + fn get_prop( &self, rmap: &ResourceMap, diff --git a/crates/carddav/src/address_object/resource.rs b/crates/carddav/src/address_object/resource.rs index 3367c72..4c291fe 100644 --- a/crates/carddav/src/address_object/resource.rs +++ b/crates/carddav/src/address_object/resource.rs @@ -42,7 +42,7 @@ pub enum AddressObjectProp { #[serde(skip_deserializing, untagged)] #[from] - ExtCommonProperties(CommonPropertiesProp), + ExtCommonProperties(CommonPropertiesProp), #[serde(untagged)] #[default] @@ -55,17 +55,16 @@ pub struct AddressObjectResource { pub principal: String, } -#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq)] -#[serde(rename_all = "kebab-case")] -pub struct Resourcetype {} - impl Resource for AddressObjectResource { type PropName = AddressObjectPropName; type Prop = AddressObjectProp; type Error = Error; - type ResourceType = Resourcetype; type PrincipalResource = PrincipalResource; + fn get_resourcetype() -> &'static [&'static str] { + &[] + } + fn get_prop( &self, _rmap: &ResourceMap, diff --git a/crates/carddav/src/addressbook/prop.rs b/crates/carddav/src/addressbook/prop.rs index 3b6c1f8..b1e36ee 100644 --- a/crates/carddav/src/addressbook/prop.rs +++ b/crates/carddav/src/addressbook/prop.rs @@ -33,14 +33,6 @@ impl Default for SupportedAddressData { } } -#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq)] -#[serde(rename_all = "kebab-case")] -pub struct Resourcetype { - #[serde(rename = "CARD:addressbook", alias = "addressbook")] - addressbook: (), - collection: (), -} - #[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] #[serde(rename_all = "kebab-case")] pub enum ReportMethod { diff --git a/crates/carddav/src/addressbook/resource.rs b/crates/carddav/src/addressbook/resource.rs index 9401f30..08b43c5 100644 --- a/crates/carddav/src/addressbook/resource.rs +++ b/crates/carddav/src/addressbook/resource.rs @@ -1,6 +1,6 @@ use super::methods::mkcol::route_mkcol; use super::methods::report::route_report_addressbook; -use super::prop::{Resourcetype, SupportedAddressData, SupportedReportSet}; +use super::prop::{SupportedAddressData, SupportedReportSet}; use crate::address_object::resource::AddressObjectResource; use crate::principal::PrincipalResource; use crate::Error; @@ -68,7 +68,7 @@ pub enum AddressbookProp { #[serde(skip_deserializing, untagged)] #[from] - ExtCommonProperties(CommonPropertiesProp), + ExtCommonProperties(CommonPropertiesProp), #[serde(untagged)] #[default] @@ -82,9 +82,12 @@ impl Resource for AddressbookResource { type PropName = AddressbookPropName; type Prop = AddressbookProp; type Error = Error; - type ResourceType = Resourcetype; type PrincipalResource = PrincipalResource; + fn get_resourcetype() -> &'static [&'static str] { + &["collection", "CARD:addressbook"] + } + fn get_prop( &self, _rmap: &ResourceMap, diff --git a/crates/carddav/src/principal/mod.rs b/crates/carddav/src/principal/mod.rs index 3bed1f3..ee80388 100644 --- a/crates/carddav/src/principal/mod.rs +++ b/crates/carddav/src/principal/mod.rs @@ -25,13 +25,6 @@ pub struct PrincipalResource { principal: String, } -#[derive(Deserialize, Serialize, Default, Debug, PartialEq)] -#[serde(rename_all = "kebab-case")] -pub struct Resourcetype { - principal: (), - collection: (), -} - #[derive(Default, Deserialize, Serialize, From, PartialEq)] #[serde(rename_all = "kebab-case")] pub enum PrincipalProp { @@ -47,7 +40,7 @@ pub enum PrincipalProp { #[serde(skip_deserializing, untagged)] #[from] - ExtCommonProperties(CommonPropertiesProp), + ExtCommonProperties(CommonPropertiesProp), #[serde(untagged)] #[default] @@ -73,9 +66,12 @@ impl Resource for PrincipalResource { type PropName = PrincipalPropName; type Prop = PrincipalProp; type Error = Error; - type ResourceType = Resourcetype; type PrincipalResource = PrincipalResource; + fn get_resourcetype() -> &'static [&'static str] { + &["collection", "principal"] + } + fn get_prop( &self, rmap: &ResourceMap, diff --git a/crates/dav/src/extensions/mod.rs b/crates/dav/src/extensions/mod.rs index cc3ab68..86482a0 100644 --- a/crates/dav/src/extensions/mod.rs +++ b/crates/dav/src/extensions/mod.rs @@ -1,8 +1,8 @@ use crate::{ extension::ResourceExtension, privileges::UserPrivilegeSet, - resource::{InvalidProperty, Resource, ResourceType}, - xml::HrefElement, + resource::{InvalidProperty, Resource}, + xml::{HrefElement, Resourcetype}, }; use actix_web::dev::ResourceMap; use rustical_store::auth::User; @@ -21,10 +21,10 @@ impl Default for CommonPropertiesExtension { #[derive(Deserialize, Serialize, PartialEq)] #[serde(rename_all = "kebab-case")] -pub enum CommonPropertiesProp { +pub enum CommonPropertiesProp { // WebDAV (RFC 2518) #[serde(skip_deserializing)] - Resourcetype(RT), + Resourcetype(Resourcetype), // WebDAV Current Principal Extension (RFC 5397) CurrentUserPrincipal(HrefElement), @@ -37,7 +37,7 @@ pub enum CommonPropertiesProp { Invalid, } -impl InvalidProperty for CommonPropertiesProp { +impl InvalidProperty for CommonPropertiesProp { fn invalid_property(&self) -> bool { matches!(self, Self::Invalid) } @@ -54,9 +54,9 @@ pub enum CommonPropertiesPropName { impl ResourceExtension for CommonPropertiesExtension where - R::Prop: From>, + R::Prop: From, { - type Prop = CommonPropertiesProp; + type Prop = CommonPropertiesProp; type PropName = CommonPropertiesPropName; type Error = R::Error; @@ -69,7 +69,7 @@ where ) -> Result { Ok(match prop { CommonPropertiesPropName::Resourcetype => { - CommonPropertiesProp::Resourcetype(R::ResourceType::default()) + CommonPropertiesProp::Resourcetype(Resourcetype(R::get_resourcetype())) } CommonPropertiesPropName::CurrentUserPrincipal => { CommonPropertiesProp::CurrentUserPrincipal( diff --git a/crates/dav/src/resource/mod.rs b/crates/dav/src/resource/mod.rs index 2e71878..45b1a05 100644 --- a/crates/dav/src/resource/mod.rs +++ b/crates/dav/src/resource/mod.rs @@ -29,10 +29,11 @@ impl Deserialize<'de>> ResourceType for T {} pub trait Resource: Clone + 'static { type PropName: ResourcePropName; - type Prop: ResourceProp + From> + PartialEq; + type Prop: ResourceProp + From + PartialEq; type Error: ResponseError + From; type PrincipalResource: Resource; - type ResourceType: Default + Serialize + for<'de> Deserialize<'de>; + + fn get_resourcetype() -> &'static [&'static str]; fn list_extensions() -> Vec> { vec![CommonPropertiesExtension::default()] @@ -122,7 +123,7 @@ pub trait Resource: Clone + 'static { Error::BadRequest("allprop MUST be the only queried prop".to_owned()).into(), ); } - props = Self::list_props(); + props = Self::list_props().to_vec(); for extension in Self::list_extensions() { let ext_props: Vec<&str> = extension.list_props().into(); props.extend(ext_props); diff --git a/crates/dav/src/resources/root.rs b/crates/dav/src/resources/root.rs index 0a514f2..5bd234c 100644 --- a/crates/dav/src/resources/root.rs +++ b/crates/dav/src/resources/root.rs @@ -5,17 +5,10 @@ use actix_web::dev::ResourceMap; use actix_web::HttpRequest; use async_trait::async_trait; use rustical_store::auth::User; -use serde::{Deserialize, Serialize}; use std::any::type_name; use std::marker::PhantomData; use strum::{EnumString, VariantNames}; -#[derive(Deserialize, Serialize, Default, Debug, PartialEq)] -#[serde(rename_all = "kebab-case")] -pub struct Resourcetype { - collection: (), -} - #[derive(Clone)] pub struct RootResource(PhantomData); @@ -31,11 +24,14 @@ pub enum RootResourcePropName {} impl Resource for RootResource { type PropName = RootResourcePropName; - type Prop = CommonPropertiesProp; + type Prop = CommonPropertiesProp; type Error = PR::Error; - type ResourceType = Resourcetype; type PrincipalResource = PR; + fn get_resourcetype() -> &'static [&'static str] { + &["collection"] + } + fn get_prop( &self, _rmap: &ResourceMap, diff --git a/crates/dav/src/xml/mod.rs b/crates/dav/src/xml/mod.rs index b4a5fb5..122a253 100644 --- a/crates/dav/src/xml/mod.rs +++ b/crates/dav/src/xml/mod.rs @@ -1,4 +1,5 @@ pub mod multistatus; +mod resourcetype; pub mod tag_list; pub mod tag_name; @@ -7,6 +8,8 @@ pub use multistatus::MultistatusElement; pub use tag_list::TagList; pub use tag_name::TagName; +pub use resourcetype::Resourcetype; + use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Deserialize, Serialize, From, PartialEq)] diff --git a/crates/dav/src/xml/resourcetype.rs b/crates/dav/src/xml/resourcetype.rs new file mode 100644 index 0000000..61da53f --- /dev/null +++ b/crates/dav/src/xml/resourcetype.rs @@ -0,0 +1,46 @@ +use serde::de::{MapAccess, Visitor}; +use serde::ser::SerializeMap; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq)] +pub struct Resourcetype(pub &'static [&'static str]); + +struct ResourcetypeVisitor; + +impl<'de> Visitor<'de> for ResourcetypeVisitor { + type Value = Resourcetype; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("TagList") + } + + fn visit_map(self, mut map: A) -> Result + where + A: MapAccess<'de>, + { + while map.next_key::()?.is_some() {} + Ok(Resourcetype(&[])) + } +} + +impl<'de> Deserialize<'de> for Resourcetype { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + deserializer.deserialize_map(ResourcetypeVisitor) + } +} + +impl Serialize for Resourcetype { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut map = serializer.serialize_map(Some(self.0.len()))?; + for entry in self.0 { + map.serialize_entry(entry, &())?; + } + map.end() + } +}