Replace more anyhow errors with explicit error types

This commit is contained in:
Lennart
2024-06-01 14:24:31 +02:00
parent 943b964da0
commit 7dcc29302a
9 changed files with 31 additions and 20 deletions

View File

@@ -2,7 +2,6 @@ use crate::CalDavContext;
use crate::Error; use crate::Error;
use actix_web::web::{Data, Path}; use actix_web::web::{Data, Path};
use actix_web::HttpResponse; use actix_web::HttpResponse;
use anyhow::Result;
use rustical_auth::{AuthInfoExtractor, CheckAuthentication}; use rustical_auth::{AuthInfoExtractor, CheckAuthentication};
use rustical_store::calendar::Calendar; use rustical_store::calendar::Calendar;
use rustical_store::CalendarStore; use rustical_store::CalendarStore;

View File

@@ -29,6 +29,7 @@ impl actix_web::ResponseError for Error {
match self { match self {
Error::StoreError(err) => match err { Error::StoreError(err) => match err {
rustical_store::Error::NotFound => StatusCode::NOT_FOUND, rustical_store::Error::NotFound => StatusCode::NOT_FOUND,
rustical_store::Error::InvalidIcs(_) => StatusCode::BAD_REQUEST,
_ => StatusCode::INTERNAL_SERVER_ERROR, _ => StatusCode::INTERNAL_SERVER_ERROR,
}, },
Error::DavError(err) => err.status_code(), Error::DavError(err) => err.status_code(),

View File

@@ -1,6 +1,5 @@
use crate::Error; use crate::Error;
use actix_web::HttpRequest; use actix_web::HttpRequest;
use anyhow::Result;
use async_trait::async_trait; use async_trait::async_trait;
use rustical_auth::AuthInfo; use rustical_auth::AuthInfo;
use rustical_dav::resource::{Resource, ResourceService}; use rustical_dav::resource::{Resource, ResourceService};

View File

@@ -7,8 +7,8 @@ use thiserror::Error;
pub enum Error { pub enum Error {
#[error("Not found")] #[error("Not found")]
NotFound, NotFound,
#[error("Bad request")] #[error("Bad request: {0}")]
BadRequest, BadRequest(String),
#[error("Unauthorized")] #[error("Unauthorized")]
Unauthorized, Unauthorized,
#[error("Internal server error :(")] #[error("Internal server error :(")]
@@ -25,7 +25,7 @@ impl actix_web::error::ResponseError for Error {
Self::InternalError => StatusCode::INTERNAL_SERVER_ERROR, Self::InternalError => StatusCode::INTERNAL_SERVER_ERROR,
Self::Other(_) => StatusCode::INTERNAL_SERVER_ERROR, Self::Other(_) => StatusCode::INTERNAL_SERVER_ERROR,
Self::NotFound => StatusCode::NOT_FOUND, Self::NotFound => StatusCode::NOT_FOUND,
Self::BadRequest => StatusCode::BAD_REQUEST, Self::BadRequest(_) => StatusCode::BAD_REQUEST,
Self::Unauthorized => StatusCode::UNAUTHORIZED, Self::Unauthorized => StatusCode::UNAUTHORIZED,
Self::XmlDecodeError(_) => StatusCode::BAD_REQUEST, Self::XmlDecodeError(_) => StatusCode::BAD_REQUEST,
} }

View File

@@ -7,7 +7,6 @@ use crate::Error;
use actix_web::http::header::ContentType; use actix_web::http::header::ContentType;
use actix_web::web::{Data, Path}; use actix_web::web::{Data, Path};
use actix_web::{HttpRequest, HttpResponse}; use actix_web::{HttpRequest, HttpResponse};
use anyhow::Result;
use rustical_auth::{AuthInfoExtractor, CheckAuthentication}; use rustical_auth::{AuthInfoExtractor, CheckAuthentication};
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;

View File

@@ -1,6 +1,6 @@
use crate::xml::tag_list::TagList; use crate::xml::tag_list::TagList;
use crate::Error;
use actix_web::{http::StatusCode, HttpRequest, ResponseError}; use actix_web::{http::StatusCode, HttpRequest, ResponseError};
use anyhow::anyhow;
use async_trait::async_trait; use async_trait::async_trait;
use itertools::Itertools; use itertools::Itertools;
use rustical_auth::AuthInfo; use rustical_auth::AuthInfo;
@@ -97,7 +97,9 @@ impl<R: Resource> HandlePropfind for R {
if props.contains(&"propname") { if props.contains(&"propname") {
if props.len() != 1 { if props.len() != 1 {
// propname MUST be the only queried prop per spec // 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 // TODO: implement propname
props = R::list_dead_props().into(); props = R::list_dead_props().into();
@@ -105,7 +107,9 @@ impl<R: Resource> HandlePropfind for R {
if props.contains(&"allprop") { if props.contains(&"allprop") {
if props.len() != 1 { if props.len() != 1 {
// allprop MUST be the only queried prop per spec // 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(); props = R::list_dead_props().into();
} }

View File

@@ -3,6 +3,9 @@ pub enum Error {
#[error("Not found")] #[error("Not found")]
NotFound, NotFound,
#[error("Invalid ics input: {0}")]
InvalidIcs(String),
#[error(transparent)] #[error(transparent)]
SqlxError(sqlx::Error), SqlxError(sqlx::Error),

View File

@@ -58,10 +58,14 @@ impl Event {
let mut parser = ical::IcalParser::new(BufReader::new(ics.as_bytes())); let mut parser = ical::IcalParser::new(BufReader::new(ics.as_bytes()));
let cal = parser.next().ok_or(Error::NotFound)??; let cal = parser.next().ok_or(Error::NotFound)??;
if parser.next().is_some() { 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 { 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 }; let event = Self { uid, cal, ics };
// Run getters now to validate the input and ensure that they'll work later on // Run getters now to validate the input and ensure that they'll work later on

View File

@@ -1,30 +1,32 @@
use crate::Error;
use anyhow::Result;
use chrono::{Duration, NaiveDateTime};
use lazy_static::lazy_static; use lazy_static::lazy_static;
lazy_static! { lazy_static! {
static ref RE_DURATION: regex::Regex = regex::Regex::new(r"^(?<sign>[+-])?P((?P<W>\d+)W)?((?P<D>\d+)D)?(T((?P<H>\d+)H)?((?P<M>\d+)M)?((?P<S>\d+)S)?)?$").unwrap(); static ref RE_DURATION: regex::Regex = regex::Regex::new(r"^(?<sign>[+-])?P((?P<W>\d+)W)?((?P<D>\d+)D)?(T((?P<H>\d+)H)?((?P<M>\d+)M)?((?P<S>\d+)S)?)?$").unwrap();
} }
use anyhow::{anyhow, Result};
use chrono::{Duration, NaiveDateTime};
pub fn parse_duration(string: &str) -> Result<Duration> { pub fn parse_duration(string: &str) -> Result<Duration, Error> {
let captures = RE_DURATION let captures = RE_DURATION
.captures(string) .captures(string)
.ok_or(anyhow!("invalid duration format"))?; .ok_or(Error::InvalidIcs("Invalid duration format".to_owned()))?;
let mut duration = Duration::zero(); let mut duration = Duration::zero();
if let Some(weeks) = captures.name("W") { 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") { 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") { 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") { 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") { 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 let Some(sign) = captures.name("sign") {
if sign.as_str() == "-" { if sign.as_str() == "-" {