caldav, carddav: Generate Propname enums with strum

This commit is contained in:
Lennart
2024-11-12 15:28:22 +01:00
parent 6747fde623
commit 7dfa0c9062
7 changed files with 65 additions and 82 deletions

View File

@@ -13,8 +13,6 @@ use actix_web::http::Method;
use actix_web::web; use actix_web::web;
use actix_web::{web::Data, HttpRequest}; use actix_web::{web::Data, HttpRequest};
use async_trait::async_trait; use async_trait::async_trait;
use base64::prelude::{BASE64_STANDARD, BASE64_URL_SAFE};
use base64::Engine;
use derive_more::derive::{From, Into}; use derive_more::derive::{From, Into};
use rustical_dav::privileges::UserPrivilegeSet; use rustical_dav::privileges::UserPrivilegeSet;
use rustical_dav::resource::{Resource, ResourceService}; use rustical_dav::resource::{Resource, ResourceService};
@@ -25,7 +23,7 @@ use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use strum::{EnumString, VariantNames}; use strum::{EnumDiscriminants, EnumString, VariantNames};
pub struct CalendarResourceService<C: CalendarStore + ?Sized> { pub struct CalendarResourceService<C: CalendarStore + ?Sized> {
cal_store: Arc<C>, cal_store: Arc<C>,
@@ -33,27 +31,12 @@ pub struct CalendarResourceService<C: CalendarStore + ?Sized> {
calendar_id: String, calendar_id: String,
} }
#[derive(EnumString, VariantNames, Clone)] #[derive(Default, Deserialize, Serialize, PartialEq, EnumDiscriminants)]
#[strum(serialize_all = "kebab-case")] #[strum_discriminants(
pub enum CalendarPropName { name(CalendarPropName),
Displayname, derive(EnumString, VariantNames),
Getcontenttype, strum(serialize_all = "kebab-case")
Transports, )]
Topic,
CalendarColor,
CalendarDescription,
CalendarTimezone,
CalendarOrder,
SupportedCalendarComponentSet,
SupportedCalendarData,
MaxResourceSize,
SupportedReportSet,
SyncToken,
Getctag,
Source,
}
#[derive(Default, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum CalendarProp { pub enum CalendarProp {
// WebDAV (RFC 2518) // WebDAV (RFC 2518)
@@ -178,6 +161,9 @@ impl Resource for CalendarResource {
CalendarPropName::Source => { CalendarPropName::Source => {
CalendarProp::Source(self.0.subscription_url.to_owned().map(HrefElement::from)) CalendarProp::Source(self.0.subscription_url.to_owned().map(HrefElement::from))
} }
CalendarPropName::Invalid => {
return Err(rustical_dav::Error::BadRequest("invalid prop name".to_owned()).into())
}
}) })
} }
@@ -255,6 +241,7 @@ impl Resource for CalendarResource {
CalendarPropName::Getctag => Err(rustical_dav::Error::PropReadOnly), CalendarPropName::Getctag => Err(rustical_dav::Error::PropReadOnly),
// Converting a calendar subscription calendar into a normal one would be weird // Converting a calendar subscription calendar into a normal one would be weird
CalendarPropName::Source => Err(rustical_dav::Error::PropReadOnly), CalendarPropName::Source => Err(rustical_dav::Error::PropReadOnly),
CalendarPropName::Invalid => Err(rustical_dav::Error::PropReadOnly),
} }
} }

View File

@@ -10,7 +10,7 @@ use rustical_dav::{
use rustical_store::{auth::User, CalendarObject, CalendarStore}; use rustical_store::{auth::User, CalendarObject, CalendarStore};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::sync::Arc; use std::sync::Arc;
use strum::{EnumString, VariantNames}; use strum::{EnumDiscriminants, EnumString, VariantNames};
pub struct CalendarObjectResourceService<C: CalendarStore + ?Sized> { pub struct CalendarObjectResourceService<C: CalendarStore + ?Sized> {
cal_store: Arc<C>, cal_store: Arc<C>,
@@ -19,15 +19,12 @@ pub struct CalendarObjectResourceService<C: CalendarStore + ?Sized> {
object_id: String, object_id: String,
} }
#[derive(EnumString, VariantNames, Clone)] #[derive(Default, Deserialize, Serialize, PartialEq, EnumDiscriminants)]
#[strum(serialize_all = "kebab-case")] #[strum_discriminants(
pub enum CalendarObjectPropName { name(CalendarObjectPropName),
Getetag, derive(EnumString, VariantNames),
CalendarData, strum(serialize_all = "kebab-case")
Getcontenttype, )]
}
#[derive(Default, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum CalendarObjectProp { pub enum CalendarObjectProp {
// WebDAV (RFC 2518) // WebDAV (RFC 2518)
@@ -73,6 +70,9 @@ impl Resource for CalendarObjectResource {
CalendarObjectPropName::Getcontenttype => { CalendarObjectPropName::Getcontenttype => {
CalendarObjectProp::Getcontenttype("text/calendar;charset=utf-8".to_owned()) CalendarObjectProp::Getcontenttype("text/calendar;charset=utf-8".to_owned())
} }
CalendarObjectPropName::Invalid => {
return Err(rustical_dav::Error::BadRequest("invalid prop name".to_owned()).into())
}
}) })
} }

View File

@@ -11,7 +11,7 @@ use rustical_store::auth::User;
use rustical_store::CalendarStore; use rustical_store::CalendarStore;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::sync::Arc; use std::sync::Arc;
use strum::{EnumString, VariantNames}; use strum::{EnumDiscriminants, EnumString, VariantNames};
pub struct PrincipalResourceService<C: CalendarStore + ?Sized> { pub struct PrincipalResourceService<C: CalendarStore + ?Sized> {
principal: String, principal: String,
@@ -23,11 +23,17 @@ pub struct PrincipalResource {
principal: String, principal: String,
} }
#[derive(Default, Deserialize, Serialize, PartialEq)] #[derive(Default, Deserialize, Serialize, PartialEq, EnumDiscriminants)]
#[strum_discriminants(
name(PrincipalPropName),
derive(EnumString, VariantNames),
strum(serialize_all = "kebab-case")
)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum PrincipalProp { pub enum PrincipalProp {
// WebDAV Access Control (RFC 3744) // WebDAV Access Control (RFC 3744)
#[serde(rename = "principal-URL")] #[serde(rename = "principal-URL")]
#[strum_discriminants(strum(serialize = "principal-URL"))]
PrincipalUrl(HrefElement), PrincipalUrl(HrefElement),
// CalDAV (RFC 4791) // CalDAV (RFC 4791)
@@ -41,15 +47,6 @@ pub enum PrincipalProp {
Invalid, Invalid,
} }
#[derive(EnumString, VariantNames, Clone)]
#[strum(serialize_all = "kebab-case")]
pub enum PrincipalPropName {
#[strum(serialize = "principal-URL")]
PrincipalUrl,
CalendarHomeSet,
CalendarUserAddressSet,
}
impl PrincipalResource { impl PrincipalResource {
pub fn get_principal_url(rmap: &ResourceMap, principal: &str) -> String { pub fn get_principal_url(rmap: &ResourceMap, principal: &str) -> String {
Self::get_url(rmap, vec![principal]).unwrap() Self::get_url(rmap, vec![principal]).unwrap()
@@ -80,6 +77,9 @@ impl Resource for PrincipalResource {
PrincipalPropName::CalendarUserAddressSet => { PrincipalPropName::CalendarUserAddressSet => {
PrincipalProp::CalendarUserAddressSet(principal_href) PrincipalProp::CalendarUserAddressSet(principal_href)
} }
PrincipalPropName::Invalid => {
return Err(rustical_dav::Error::BadRequest("invalid prop name".to_owned()).into())
}
}) })
} }

View File

@@ -9,7 +9,7 @@ use rustical_dav::{
use rustical_store::{auth::User, AddressObject, AddressbookStore}; use rustical_store::{auth::User, AddressObject, AddressbookStore};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::sync::Arc; use std::sync::Arc;
use strum::{EnumString, VariantNames}; use strum::{EnumDiscriminants, EnumString, VariantNames};
use super::methods::{get_object, put_object}; use super::methods::{get_object, put_object};
@@ -20,15 +20,12 @@ pub struct AddressObjectResourceService<AS: AddressbookStore + ?Sized> {
object_id: String, object_id: String,
} }
#[derive(EnumString, VariantNames, Clone)] #[derive(Default, Deserialize, Serialize, PartialEq, EnumDiscriminants)]
#[strum(serialize_all = "kebab-case")] #[strum_discriminants(
pub enum AddressObjectPropName { name(AddressObjectPropName),
Getetag, derive(EnumString, VariantNames),
AddressData, strum(serialize_all = "kebab-case")
Getcontenttype, )]
}
#[derive(Default, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum AddressObjectProp { pub enum AddressObjectProp {
// WebDAV (RFC 2518) // WebDAV (RFC 2518)
@@ -74,6 +71,9 @@ impl Resource for AddressObjectResource {
AddressObjectPropName::Getcontenttype => { AddressObjectPropName::Getcontenttype => {
AddressObjectProp::Getcontenttype("text/vcard;charset=utf-8".to_owned()) AddressObjectProp::Getcontenttype("text/vcard;charset=utf-8".to_owned())
} }
AddressObjectPropName::Invalid => {
return Err(rustical_dav::Error::BadRequest("invalid prop name".to_owned()).into())
}
}) })
} }

View File

@@ -17,7 +17,7 @@ use rustical_store::{Addressbook, AddressbookStore};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use strum::{EnumString, VariantNames}; use strum::{EnumDiscriminants, EnumString, VariantNames};
pub struct AddressbookResourceService<AS: AddressbookStore + ?Sized> { pub struct AddressbookResourceService<AS: AddressbookStore + ?Sized> {
addr_store: Arc<AS>, addr_store: Arc<AS>,
@@ -25,21 +25,13 @@ pub struct AddressbookResourceService<AS: AddressbookStore + ?Sized> {
addressbook_id: String, addressbook_id: String,
} }
#[derive(EnumString, VariantNames, Clone)] #[derive(Default, Deserialize, Serialize, PartialEq, EnumDiscriminants)]
#[strum(serialize_all = "kebab-case")]
pub enum AddressbookPropName {
Displayname,
Getcontenttype,
AddressbookDescription,
SupportedAddressData,
SupportedReportSet,
MaxResourceSize,
SyncToken,
Getctag,
}
#[derive(Default, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
#[strum_discriminants(
name(AddressbookPropName),
derive(EnumString, VariantNames),
strum(serialize_all = "kebab-case")
)]
pub enum AddressbookProp { pub enum AddressbookProp {
// WebDAV (RFC 2518) // WebDAV (RFC 2518)
Displayname(Option<String>), Displayname(Option<String>),
@@ -110,6 +102,9 @@ impl Resource for AddressbookResource {
} }
AddressbookPropName::SyncToken => AddressbookProp::SyncToken(self.0.format_synctoken()), AddressbookPropName::SyncToken => AddressbookProp::SyncToken(self.0.format_synctoken()),
AddressbookPropName::Getctag => AddressbookProp::Getctag(self.0.format_synctoken()), AddressbookPropName::Getctag => AddressbookProp::Getctag(self.0.format_synctoken()),
AddressbookPropName::Invalid => {
return Err(rustical_dav::Error::BadRequest("invalid prop name".to_owned()).into())
}
}) })
} }
@@ -149,6 +144,7 @@ impl Resource for AddressbookResource {
AddressbookPropName::SupportedAddressData => Err(rustical_dav::Error::PropReadOnly), AddressbookPropName::SupportedAddressData => Err(rustical_dav::Error::PropReadOnly),
AddressbookPropName::SyncToken => Err(rustical_dav::Error::PropReadOnly), AddressbookPropName::SyncToken => Err(rustical_dav::Error::PropReadOnly),
AddressbookPropName::Getctag => Err(rustical_dav::Error::PropReadOnly), AddressbookPropName::Getctag => Err(rustical_dav::Error::PropReadOnly),
AddressbookPropName::Invalid => Err(rustical_dav::Error::PropReadOnly),
} }
} }

View File

@@ -11,7 +11,7 @@ use rustical_store::auth::User;
use rustical_store::AddressbookStore; use rustical_store::AddressbookStore;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::sync::Arc; use std::sync::Arc;
use strum::{EnumString, VariantNames}; use strum::{EnumDiscriminants, EnumString, VariantNames};
pub struct PrincipalResourceService<A: AddressbookStore + ?Sized> { pub struct PrincipalResourceService<A: AddressbookStore + ?Sized> {
principal: String, principal: String,
@@ -23,11 +23,17 @@ pub struct PrincipalResource {
principal: String, principal: String,
} }
#[derive(Default, Deserialize, Serialize, PartialEq)] #[derive(Default, Deserialize, Serialize, PartialEq, EnumDiscriminants)]
#[strum_discriminants(
name(PrincipalPropName),
derive(EnumString, VariantNames),
strum(serialize_all = "kebab-case")
)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum PrincipalProp { pub enum PrincipalProp {
// WebDAV Access Control (RFC 3744) // WebDAV Access Control (RFC 3744)
#[serde(rename = "principal-URL")] #[serde(rename = "principal-URL")]
#[strum_discriminants(strum(serialize = "principal-URL"))]
PrincipalUrl(HrefElement), PrincipalUrl(HrefElement),
// CardDAV (RFC 6352) // CardDAV (RFC 6352)
@@ -41,15 +47,6 @@ pub enum PrincipalProp {
Invalid, Invalid,
} }
#[derive(EnumString, VariantNames, Clone)]
#[strum(serialize_all = "kebab-case")]
pub enum PrincipalPropName {
#[strum(serialize = "principal-URL")]
PrincipalUrl,
AddressbookHomeSet,
PrincipalAddress,
}
impl PrincipalResource { impl PrincipalResource {
pub fn get_principal_url(rmap: &ResourceMap, principal: &str) -> String { pub fn get_principal_url(rmap: &ResourceMap, principal: &str) -> String {
Self::get_url(rmap, vec![principal]).unwrap() Self::get_url(rmap, vec![principal]).unwrap()
@@ -80,6 +77,9 @@ impl Resource for PrincipalResource {
PrincipalProp::AddressbookHomeSet(principal_href) PrincipalProp::AddressbookHomeSet(principal_href)
} }
PrincipalPropName::PrincipalAddress => PrincipalProp::PrincipalAddress(None), PrincipalPropName::PrincipalAddress => PrincipalProp::PrincipalAddress(None),
PrincipalPropName::Invalid => {
return Err(rustical_dav::Error::BadRequest("invalid prop name".to_owned()).into())
}
}) })
} }

View File

@@ -45,7 +45,7 @@ impl<PR: Resource> Resource for RootResource<PR> {
_user: &User, _user: &User,
_prop: &Self::PropName, _prop: &Self::PropName,
) -> Result<Self::Prop, Self::Error> { ) -> Result<Self::Prop, Self::Error> {
panic!("we shouldn't end up here") unreachable!("we shouldn't end up here")
} }
#[inline] #[inline]