calendar collection: timezone-id validation

This commit is contained in:
Lennart
2025-01-15 20:11:47 +01:00
parent 97d7a260dc
commit 89572e28d1

View File

@@ -50,6 +50,8 @@ pub enum CalendarProp {
#[xml(ns = "rustical_dav::namespace::NS_CALDAV")] #[xml(ns = "rustical_dav::namespace::NS_CALDAV")]
CalendarTimezone(Option<String>), CalendarTimezone(Option<String>),
// https://datatracker.ietf.org/doc/html/rfc7809 // https://datatracker.ietf.org/doc/html/rfc7809
#[xml(ns = "rustical_dav::namespace::NS_CALDAV", skip_deserializing)]
TimezoneServiceSet(HrefElement),
#[xml(ns = "rustical_dav::namespace::NS_CALDAV")] #[xml(ns = "rustical_dav::namespace::NS_CALDAV")]
CalendarTimezoneId(Option<String>), CalendarTimezoneId(Option<String>),
#[xml(ns = "rustical_dav::namespace::NS_ICAL")] #[xml(ns = "rustical_dav::namespace::NS_ICAL")]
@@ -124,6 +126,10 @@ impl Resource for CalendarResource {
CalendarPropName::CalendarTimezone => { CalendarPropName::CalendarTimezone => {
CalendarProp::CalendarTimezone(self.cal.timezone.clone()) CalendarProp::CalendarTimezone(self.cal.timezone.clone())
} }
// chrono_tz uses the IANA database
CalendarPropName::TimezoneServiceSet => CalendarProp::TimezoneServiceSet(
"https://www.iana.org/time-zones".to_owned().into(),
),
CalendarPropName::CalendarTimezoneId => { CalendarPropName::CalendarTimezoneId => {
CalendarProp::CalendarTimezoneId(self.cal.timezone_id.clone()) CalendarProp::CalendarTimezoneId(self.cal.timezone_id.clone())
} }
@@ -169,11 +175,19 @@ impl Resource for CalendarResource {
Ok(()) Ok(())
} }
CalendarProp::CalendarTimezone(timezone) => { CalendarProp::CalendarTimezone(timezone) => {
// TODO: Ensure that timezone-id is also updated
self.cal.timezone = timezone; self.cal.timezone = timezone;
Ok(()) Ok(())
} }
CalendarProp::TimezoneServiceSet(_) => Err(rustical_dav::Error::PropReadOnly),
CalendarProp::CalendarTimezoneId(timezone_id) => { CalendarProp::CalendarTimezoneId(timezone_id) => {
// TODO: Set or remove timezone accordingly if let Some(tzid) = &timezone_id {
// Validate timezone id
chrono_tz::Tz::from_str(tzid).map_err(|_| {
rustical_dav::Error::BadRequest(format!("Invalid timezone-id: {}", tzid))
})?;
// TODO: Ensure that timezone is also updated (For now hope that clients play nice)
}
self.cal.timezone_id = timezone_id; self.cal.timezone_id = timezone_id;
Ok(()) Ok(())
} }
@@ -218,6 +232,7 @@ impl Resource for CalendarResource {
self.cal.timezone = None; self.cal.timezone = None;
Ok(()) Ok(())
} }
CalendarPropName::TimezoneServiceSet => Err(rustical_dav::Error::PropReadOnly),
CalendarPropName::CalendarTimezoneId => { CalendarPropName::CalendarTimezoneId => {
self.cal.timezone_id = None; self.cal.timezone_id = None;
Ok(()) Ok(())
@@ -270,9 +285,7 @@ impl<C: CalendarStore, S: SubscriptionStore> CalendarResourceService<C, S> {
} }
#[async_trait(?Send)] #[async_trait(?Send)]
impl<C: CalendarStore, S: SubscriptionStore> ResourceService impl<C: CalendarStore, S: SubscriptionStore> ResourceService for CalendarResourceService<C, S> {
for CalendarResourceService<C, S>
{
type MemberType = CalendarObjectResource; type MemberType = CalendarObjectResource;
type PathComponents = (String, String); // principal, calendar_id type PathComponents = (String, String); // principal, calendar_id
type Resource = CalendarResource; type Resource = CalendarResource;