diff --git a/crates/caldav/src/calendar/methods/mkcalendar.rs b/crates/caldav/src/calendar/methods/mkcalendar.rs index d065231..0dcc4e0 100644 --- a/crates/caldav/src/calendar/methods/mkcalendar.rs +++ b/crates/caldav/src/calendar/methods/mkcalendar.rs @@ -1,10 +1,14 @@ +use std::str::FromStr; + use crate::Error; use crate::calendar::CalendarResourceService; use crate::calendar::prop::SupportedCalendarComponentSet; +use crate::error::Precondition; use axum::extract::{Path, State}; use axum::response::{IntoResponse, Response}; use http::{Method, StatusCode}; use ical::IcalParser; +use ical::types::get_proprietary_tzid; use rustical_dav::xml::HrefElement; use rustical_ical::CalendarObjectType; use rustical_store::auth::Principal; @@ -84,21 +88,33 @@ pub async fn route_mkcalendar( } let timezone_id = if let Some(tzid) = request.calendar_timezone_id { + if chrono_tz::Tz::from_str(&tzid).is_err() { + return Err(Error::PreconditionFailed(Precondition::CalendarTimezone( + "Invalid timezone ID in calendar-timezone-id", + ))); + } Some(tzid) } else if let Some(tz) = request.calendar_timezone { - // TODO: Proper error (calendar-timezone precondition) let calendar = IcalParser::from_slice(tz.as_bytes()) .next() - .ok_or_else(|| rustical_dav::Error::BadRequest("No timezone data provided".to_owned()))? - .map_err(|_| rustical_dav::Error::BadRequest("Error parsing timezone".to_owned()))?; + .ok_or(Error::PreconditionFailed(Precondition::CalendarTimezone( + "No timezone data provided", + )))? + .map_err(|_| { + Error::PreconditionFailed(Precondition::CalendarTimezone("Error parsing timezone")) + })?; - let timezone = calendar.vtimezones.values().next().ok_or_else(|| { - rustical_dav::Error::BadRequest("No timezone data provided".to_owned()) - })?; + let timezone = calendar + .vtimezones + .values() + .next() + .ok_or(Error::PreconditionFailed(Precondition::CalendarTimezone( + "No timezone data provided", + )))?; let timezone: Option = timezone.into(); - let timezone = timezone.ok_or_else(|| { - rustical_dav::Error::BadRequest("Cannot translate VTIMEZONE into IANA TZID".to_owned()) - })?; + let timezone = timezone.ok_or(Error::PreconditionFailed( + Precondition::CalendarTimezone("No timezone data provided"), + ))?; Some(timezone.name().to_owned()) } else { diff --git a/crates/caldav/src/error.rs b/crates/caldav/src/error.rs index 8ec67eb..2f5837d 100644 --- a/crates/caldav/src/error.rs +++ b/crates/caldav/src/error.rs @@ -12,6 +12,9 @@ pub enum Precondition { #[error("valid-calendar-data")] #[xml(ns = "rustical_dav::namespace::NS_CALDAV")] ValidCalendarData, + #[error("calendar-timezone")] + #[xml(ns = "rustical_dav::namespace::NS_CALDAV")] + CalendarTimezone(&'static str), } impl IntoResponse for Precondition {