From cd9e3ed8d651c4a2b73f08c9ddf189ff2f309547 Mon Sep 17 00:00:00 2001 From: Lennart K <18233294+lennart-k@users.noreply.github.com> Date: Fri, 16 Jan 2026 14:16:22 +0100 Subject: [PATCH] simplify handling of ical-related errors --- crates/caldav/src/calendar/methods/import.rs | 12 ++----- crates/caldav/src/error.rs | 3 +- crates/carddav/src/error.rs | 3 +- crates/ical/src/error.rs | 34 -------------------- crates/ical/src/lib.rs | 6 ++-- crates/store/src/error.rs | 5 +-- crates/store_sqlite/src/calendar_store.rs | 21 ++++++------ 7 files changed, 22 insertions(+), 62 deletions(-) delete mode 100644 crates/ical/src/error.rs diff --git a/crates/caldav/src/calendar/methods/import.rs b/crates/caldav/src/calendar/methods/import.rs index 94588c3..fd561e8 100644 --- a/crates/caldav/src/calendar/methods/import.rs +++ b/crates/caldav/src/calendar/methods/import.rs @@ -26,10 +26,7 @@ pub async fn route_import( } let parser = ical::IcalParser::from_slice(body.as_bytes()); - let mut cal = parser - .expect_one() - .map_err(rustical_ical::Error::ParserError)? - .mutable(); + let mut cal = parser.expect_one()?.mutable(); // Extract calendar metadata let displayname = cal @@ -70,12 +67,7 @@ pub async fn route_import( cal_components.push(CalendarObjectType::Todo); } - let objects = cal - .into_objects() - .map_err(rustical_ical::Error::ParserError)? - .into_iter() - .map(Into::into) - .collect(); + let objects = cal.into_objects()?.into_iter().map(Into::into).collect(); let new_cal = Calendar { principal, id: cal_id, diff --git a/crates/caldav/src/error.rs b/crates/caldav/src/error.rs index 833db6c..49161d7 100644 --- a/crates/caldav/src/error.rs +++ b/crates/caldav/src/error.rs @@ -75,7 +75,8 @@ impl Error { Self::XmlDecodeError(_) => StatusCode::BAD_REQUEST, Self::ChronoParseError(_) | Self::NotImplemented => StatusCode::INTERNAL_SERVER_ERROR, Self::NotFound => StatusCode::NOT_FOUND, - Self::IcalError(err) => err.status_code(), + // TODO: Can also be Bad Request, if it's used input + Self::IcalError(_err) => StatusCode::INTERNAL_SERVER_ERROR, Self::PreconditionFailed(_err) => StatusCode::PRECONDITION_FAILED, } } diff --git a/crates/carddav/src/error.rs b/crates/carddav/src/error.rs index 66409b5..dbdff71 100644 --- a/crates/carddav/src/error.rs +++ b/crates/carddav/src/error.rs @@ -43,7 +43,8 @@ impl Error { Self::XmlDecodeError(_) => StatusCode::BAD_REQUEST, Self::ChronoParseError(_) | Self::NotImplemented => StatusCode::INTERNAL_SERVER_ERROR, Self::NotFound => StatusCode::NOT_FOUND, - Self::IcalError(err) => err.status_code(), + // TODO: Can also be Bad Request, if it's used input + Self::IcalError(_err) => StatusCode::INTERNAL_SERVER_ERROR, } } } diff --git a/crates/ical/src/error.rs b/crates/ical/src/error.rs deleted file mode 100644 index 0054467..0000000 --- a/crates/ical/src/error.rs +++ /dev/null @@ -1,34 +0,0 @@ -use axum::{http::StatusCode, response::IntoResponse}; - -#[derive(Debug, thiserror::Error, PartialEq, Eq)] -pub enum Error { - #[error("Invalid ics/vcf input: {0}")] - InvalidData(String), - - #[error("Missing calendar")] - MissingCalendar, - - #[error("Missing contact")] - MissingContact, - - #[error(transparent)] - ParserError(#[from] ical::parser::ParserError), -} - -impl Error { - #[must_use] - pub const fn status_code(&self) -> StatusCode { - match self { - Self::InvalidData(_) | Self::MissingCalendar | Self::MissingContact => { - StatusCode::BAD_REQUEST - } - Self::ParserError(_) => StatusCode::INTERNAL_SERVER_ERROR, - } - } -} - -impl IntoResponse for Error { - fn into_response(self) -> axum::response::Response { - (self.status_code(), self.to_string()).into_response() - } -} diff --git a/crates/ical/src/lib.rs b/crates/ical/src/lib.rs index 7e1aa43..68782f3 100644 --- a/crates/ical/src/lib.rs +++ b/crates/ical/src/lib.rs @@ -1,13 +1,13 @@ #![warn(clippy::all, clippy::pedantic, clippy::nursery)] #![allow(clippy::missing_errors_doc, clippy::missing_panics_doc)] mod timestamp; +use ical::parser::ParserError; pub use timestamp::*; mod calendar_object; pub use calendar_object::*; -mod error; -pub use error::Error; - mod address_object; pub use address_object::AddressObject; + +pub type Error = ParserError; diff --git a/crates/store/src/error.rs b/crates/store/src/error.rs index 9ace70f..259a9fa 100644 --- a/crates/store/src/error.rs +++ b/crates/store/src/error.rs @@ -26,7 +26,7 @@ pub enum Error { Other(#[from] anyhow::Error), #[error(transparent)] - IcalError(#[from] rustical_ical::Error), + IcalError(#[from] ical::parser::ParserError), } impl Error { @@ -36,7 +36,8 @@ impl Error { Self::NotFound => StatusCode::NOT_FOUND, Self::AlreadyExists => StatusCode::CONFLICT, Self::ReadOnly => StatusCode::FORBIDDEN, - Self::IcalError(err) => err.status_code(), + // TODO: Can also be Bad Request, depending on when this is raised + Self::IcalError(_err) => StatusCode::INTERNAL_SERVER_ERROR, Self::InvalidPrincipalType(_) => StatusCode::BAD_REQUEST, _ => StatusCode::INTERNAL_SERVER_ERROR, } diff --git a/crates/store_sqlite/src/calendar_store.rs b/crates/store_sqlite/src/calendar_store.rs index 1aa301f..5e9ce84 100644 --- a/crates/store_sqlite/src/calendar_store.rs +++ b/crates/store_sqlite/src/calendar_store.rs @@ -24,18 +24,17 @@ struct CalendarObjectRow { impl TryFrom for (String, CalendarObject) { type Error = rustical_store::Error; - fn try_from(value: CalendarObjectRow) -> Result { - let object = CalendarObject::from_ics(value.ics)?; - if object.get_uid() != value.uid { - return Err(rustical_store::Error::IcalError( - rustical_ical::Error::InvalidData(format!( - "uid={} and UID={} don't match", - value.uid, - object.get_uid() - )), - )); + fn try_from(row: CalendarObjectRow) -> Result { + let object = CalendarObject::from_ics(row.ics)?; + if object.get_uid() != row.uid { + warn!( + "Calendar object {}.ics: UID={} and row uid={} do not match", + row.id, + object.get_uid(), + row.uid + ); } - Ok((value.id, object)) + Ok((row.id, object)) } }