From 7dcc29302afbf5309c617895954266567c8435e6 Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Sat, 1 Jun 2024 14:24:31 +0200 Subject: [PATCH] Replace more anyhow errors with explicit error types --- .../caldav/src/calendar/methods/mkcalendar.rs | 1 - crates/caldav/src/error.rs | 1 + crates/caldav/src/root/mod.rs | 1 - crates/dav/src/error.rs | 6 +++--- crates/dav/src/propfind.rs | 1 - crates/dav/src/resource.rs | 10 +++++++--- crates/store/src/error.rs | 3 +++ crates/store/src/event.rs | 8 ++++++-- crates/store/src/timestamps.rs | 20 ++++++++++--------- 9 files changed, 31 insertions(+), 20 deletions(-) diff --git a/crates/caldav/src/calendar/methods/mkcalendar.rs b/crates/caldav/src/calendar/methods/mkcalendar.rs index 7603ba1..bfae5b3 100644 --- a/crates/caldav/src/calendar/methods/mkcalendar.rs +++ b/crates/caldav/src/calendar/methods/mkcalendar.rs @@ -2,7 +2,6 @@ use crate::CalDavContext; use crate::Error; use actix_web::web::{Data, Path}; use actix_web::HttpResponse; -use anyhow::Result; use rustical_auth::{AuthInfoExtractor, CheckAuthentication}; use rustical_store::calendar::Calendar; use rustical_store::CalendarStore; diff --git a/crates/caldav/src/error.rs b/crates/caldav/src/error.rs index 93c24eb..5edb3de 100644 --- a/crates/caldav/src/error.rs +++ b/crates/caldav/src/error.rs @@ -29,6 +29,7 @@ impl actix_web::ResponseError for Error { match self { Error::StoreError(err) => match err { rustical_store::Error::NotFound => StatusCode::NOT_FOUND, + rustical_store::Error::InvalidIcs(_) => StatusCode::BAD_REQUEST, _ => StatusCode::INTERNAL_SERVER_ERROR, }, Error::DavError(err) => err.status_code(), diff --git a/crates/caldav/src/root/mod.rs b/crates/caldav/src/root/mod.rs index 96ce499..819c5da 100644 --- a/crates/caldav/src/root/mod.rs +++ b/crates/caldav/src/root/mod.rs @@ -1,6 +1,5 @@ use crate::Error; use actix_web::HttpRequest; -use anyhow::Result; use async_trait::async_trait; use rustical_auth::AuthInfo; use rustical_dav::resource::{Resource, ResourceService}; diff --git a/crates/dav/src/error.rs b/crates/dav/src/error.rs index fb5e571..7f34dac 100644 --- a/crates/dav/src/error.rs +++ b/crates/dav/src/error.rs @@ -7,8 +7,8 @@ use thiserror::Error; pub enum Error { #[error("Not found")] NotFound, - #[error("Bad request")] - BadRequest, + #[error("Bad request: {0}")] + BadRequest(String), #[error("Unauthorized")] Unauthorized, #[error("Internal server error :(")] @@ -25,7 +25,7 @@ impl actix_web::error::ResponseError for Error { Self::InternalError => StatusCode::INTERNAL_SERVER_ERROR, Self::Other(_) => StatusCode::INTERNAL_SERVER_ERROR, Self::NotFound => StatusCode::NOT_FOUND, - Self::BadRequest => StatusCode::BAD_REQUEST, + Self::BadRequest(_) => StatusCode::BAD_REQUEST, Self::Unauthorized => StatusCode::UNAUTHORIZED, Self::XmlDecodeError(_) => StatusCode::BAD_REQUEST, } diff --git a/crates/dav/src/propfind.rs b/crates/dav/src/propfind.rs index d1c2bf5..5764534 100644 --- a/crates/dav/src/propfind.rs +++ b/crates/dav/src/propfind.rs @@ -7,7 +7,6 @@ use crate::Error; use actix_web::http::header::ContentType; use actix_web::web::{Data, Path}; use actix_web::{HttpRequest, HttpResponse}; -use anyhow::Result; use rustical_auth::{AuthInfoExtractor, CheckAuthentication}; use serde::Deserialize; use serde::Serialize; diff --git a/crates/dav/src/resource.rs b/crates/dav/src/resource.rs index b9d4bdf..6d06c32 100644 --- a/crates/dav/src/resource.rs +++ b/crates/dav/src/resource.rs @@ -1,6 +1,6 @@ use crate::xml::tag_list::TagList; +use crate::Error; use actix_web::{http::StatusCode, HttpRequest, ResponseError}; -use anyhow::anyhow; use async_trait::async_trait; use itertools::Itertools; use rustical_auth::AuthInfo; @@ -97,7 +97,9 @@ impl HandlePropfind for R { if props.contains(&"propname") { if props.len() != 1 { // propname MUST be the only queried prop per spec - return Err(anyhow!("propname MUST be the only queried prop").into()); + return Err( + Error::BadRequest("allprop MUST be the only queried prop".to_owned()).into(), + ); } // TODO: implement propname props = R::list_dead_props().into(); @@ -105,7 +107,9 @@ impl HandlePropfind for R { if props.contains(&"allprop") { if props.len() != 1 { // allprop MUST be the only queried prop per spec - return Err(anyhow!("allprop MUST be the only queried prop").into()); + return Err( + Error::BadRequest("allprop MUST be the only queried prop".to_owned()).into(), + ); } props = R::list_dead_props().into(); } diff --git a/crates/store/src/error.rs b/crates/store/src/error.rs index a99d316..eda4127 100644 --- a/crates/store/src/error.rs +++ b/crates/store/src/error.rs @@ -3,6 +3,9 @@ pub enum Error { #[error("Not found")] NotFound, + #[error("Invalid ics input: {0}")] + InvalidIcs(String), + #[error(transparent)] SqlxError(sqlx::Error), diff --git a/crates/store/src/event.rs b/crates/store/src/event.rs index c7082ec..9d7eabe 100644 --- a/crates/store/src/event.rs +++ b/crates/store/src/event.rs @@ -58,10 +58,14 @@ impl Event { let mut parser = ical::IcalParser::new(BufReader::new(ics.as_bytes())); let cal = parser.next().ok_or(Error::NotFound)??; if parser.next().is_some() { - return Err(anyhow!("multiple calendars!").into()); + return Err(Error::InvalidIcs( + "multiple calendars, only one allowed".to_owned(), + )); } if cal.events.len() != 1 { - return Err(anyhow!("multiple or no events").into()); + return Err(Error::InvalidIcs( + "ics calendar must contain exactly one event".to_owned(), + )); } let event = Self { uid, cal, ics }; // Run getters now to validate the input and ensure that they'll work later on diff --git a/crates/store/src/timestamps.rs b/crates/store/src/timestamps.rs index b232e7a..4b9e82b 100644 --- a/crates/store/src/timestamps.rs +++ b/crates/store/src/timestamps.rs @@ -1,30 +1,32 @@ +use crate::Error; +use anyhow::Result; +use chrono::{Duration, NaiveDateTime}; use lazy_static::lazy_static; + lazy_static! { static ref RE_DURATION: regex::Regex = regex::Regex::new(r"^(?[+-])?P((?P\d+)W)?((?P\d+)D)?(T((?P\d+)H)?((?P\d+)M)?((?P\d+)S)?)?$").unwrap(); } -use anyhow::{anyhow, Result}; -use chrono::{Duration, NaiveDateTime}; -pub fn parse_duration(string: &str) -> Result { +pub fn parse_duration(string: &str) -> Result { let captures = RE_DURATION .captures(string) - .ok_or(anyhow!("invalid duration format"))?; + .ok_or(Error::InvalidIcs("Invalid duration format".to_owned()))?; let mut duration = Duration::zero(); if let Some(weeks) = captures.name("W") { - duration += Duration::weeks(weeks.as_str().parse()?); + duration += Duration::weeks(weeks.as_str().parse().unwrap()); } if let Some(days) = captures.name("D") { - duration += Duration::days(days.as_str().parse()?); + duration += Duration::days(days.as_str().parse().unwrap()); } if let Some(hours) = captures.name("H") { - duration += Duration::hours(hours.as_str().parse()?); + duration += Duration::hours(hours.as_str().parse().unwrap()); } if let Some(minutes) = captures.name("M") { - duration += Duration::minutes(minutes.as_str().parse()?); + duration += Duration::minutes(minutes.as_str().parse().unwrap()); } if let Some(seconds) = captures.name("S") { - duration += Duration::seconds(seconds.as_str().parse()?); + duration += Duration::seconds(seconds.as_str().parse().unwrap()); } if let Some(sign) = captures.name("sign") { if sign.as_str() == "-" {