Error typing for rustical_store as well as some refactoring

This commit is contained in:
Lennart
2024-06-01 13:00:36 +02:00
parent 7fcd9a17f5
commit 1d763b5c8f
20 changed files with 135 additions and 79 deletions

1
Cargo.lock generated
View File

@@ -1818,6 +1818,7 @@ dependencies = [
"serde", "serde",
"sha2", "sha2",
"sqlx", "sqlx",
"thiserror",
"tokio", "tokio",
"toml", "toml",
] ]

View File

@@ -5,7 +5,7 @@ use actix_web::{
HttpResponse, HttpResponse,
}; };
use rustical_auth::{AuthInfoExtractor, CheckAuthentication}; use rustical_auth::{AuthInfoExtractor, CheckAuthentication};
use rustical_store::store::CalendarStore; use rustical_store::CalendarStore;
pub async fn route_delete_calendar<A: CheckAuthentication, C: CalendarStore + ?Sized>( pub async fn route_delete_calendar<A: CheckAuthentication, C: CalendarStore + ?Sized>(
context: Data<CalDavContext<C>>, context: Data<CalDavContext<C>>,

View File

@@ -5,7 +5,7 @@ use actix_web::HttpResponse;
use anyhow::Result; 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::store::CalendarStore; use rustical_store::CalendarStore;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, Clone, Debug)] #[derive(Deserialize, Serialize, Clone, Debug)]
@@ -69,10 +69,7 @@ pub async fn route_mkcol_calendar<A: CheckAuthentication, C: CalendarStore + ?Si
return Err(Error::Unauthorized); return Err(Error::Unauthorized);
} }
let request: MkcalendarRequest = quick_xml::de::from_str(&body).map_err(|e| { let request: MkcalendarRequest = quick_xml::de::from_str(&body)?;
dbg!(e.to_string());
Error::BadRequest
})?;
let request = request.set.prop; let request = request.set.prop;
let calendar = Calendar { let calendar = Calendar {

View File

@@ -10,7 +10,7 @@ use rustical_dav::{
resource::HandlePropfind, resource::HandlePropfind,
}; };
use rustical_store::event::Event; use rustical_store::event::Event;
use rustical_store::store::CalendarStore; use rustical_store::CalendarStore;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::sync::RwLock; use tokio::sync::RwLock;
@@ -154,10 +154,7 @@ pub async fn route_report_calendar<A: CheckAuthentication, C: CalendarStore + ?S
return Err(Error::Unauthorized); return Err(Error::Unauthorized);
} }
let request: ReportRequest = quick_xml::de::from_str(&body).map_err(|err| { let request: ReportRequest = quick_xml::de::from_str(&body)?;
dbg!(err.to_string());
Error::InternalError
})?;
let events = match request.clone() { let events = match request.clone() {
ReportRequest::CalendarQuery(cal_query) => { ReportRequest::CalendarQuery(cal_query) => {
get_events_calendar_query(cal_query, &cid, &cal_store).await? get_events_calendar_query(cal_query, &cid, &cal_store).await?
@@ -178,7 +175,7 @@ pub async fn route_report_calendar<A: CheckAuthentication, C: CalendarStore + ?S
} }
PropfindType::Propname => { PropfindType::Propname => {
// TODO: Implement // TODO: Implement
return Err(Error::InternalError); return Err(Error::NotImplemented);
} }
PropfindType::Prop(PropElement { prop: prop_tags }) => prop_tags.into(), PropfindType::Prop(PropElement { prop: prop_tags }) => prop_tags.into(),
}; };

View File

@@ -6,7 +6,7 @@ use rustical_dav::error::Error;
use rustical_dav::resource::{Resource, ResourceService}; use rustical_dav::resource::{Resource, ResourceService};
use rustical_dav::xml_snippets::{HrefElement, TextNode}; use rustical_dav::xml_snippets::{HrefElement, TextNode};
use rustical_store::calendar::Calendar; use rustical_store::calendar::Calendar;
use rustical_store::store::CalendarStore; use rustical_store::CalendarStore;
use serde::Serialize; use serde::Serialize;
use std::sync::Arc; use std::sync::Arc;
use strum::{EnumString, IntoStaticStr, VariantNames}; use strum::{EnumString, IntoStaticStr, VariantNames};

View File

@@ -0,0 +1,44 @@
use actix_web::{http::StatusCode, HttpResponse};
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Unauthorized")]
Unauthorized,
#[error("Not implemented")]
NotImplemented,
#[error(transparent)]
StoreError(#[from] rustical_store::Error),
#[error(transparent)]
DavError(#[from] rustical_dav::Error),
#[error(transparent)]
XmlDecodeError(#[from] quick_xml::DeError),
#[error(transparent)]
Other(#[from] anyhow::Error),
}
impl actix_web::ResponseError for Error {
fn status_code(&self) -> actix_web::http::StatusCode {
match self {
Error::StoreError(err) => match err {
rustical_store::Error::NotFound => StatusCode::NOT_FOUND,
_ => StatusCode::INTERNAL_SERVER_ERROR,
},
Error::DavError(err) => err.status_code(),
Error::Unauthorized => StatusCode::UNAUTHORIZED,
Error::XmlDecodeError(_) => StatusCode::BAD_REQUEST,
Error::NotImplemented => StatusCode::INTERNAL_SERVER_ERROR,
Error::Other(_) => StatusCode::INTERNAL_SERVER_ERROR,
}
}
fn error_response(&self) -> actix_web::HttpResponse<actix_web::body::BoxBody> {
match self {
Error::DavError(err) => err.error_response(),
_ => HttpResponse::build(self.status_code()).body(self.to_string()),
}
}
}

View File

@@ -1,27 +1,9 @@
use crate::CalDavContext; use crate::CalDavContext;
use actix_web::http::StatusCode; use crate::Error;
use actix_web::web::{Data, Path}; use actix_web::web::{Data, Path};
use actix_web::{HttpResponse, ResponseError}; use actix_web::HttpResponse;
use rustical_auth::{AuthInfoExtractor, CheckAuthentication}; use rustical_auth::{AuthInfoExtractor, CheckAuthentication};
use rustical_store::store::CalendarStore; use rustical_store::CalendarStore;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error(transparent)]
Other(#[from] anyhow::Error),
}
impl ResponseError for Error {
fn status_code(&self) -> actix_web::http::StatusCode {
match self {
Self::Other(_) => StatusCode::INTERNAL_SERVER_ERROR,
}
}
fn error_response(&self) -> HttpResponse<actix_web::body::BoxBody> {
HttpResponse::build(self.status_code()).body(self.to_string())
}
}
pub async fn delete_event<A: CheckAuthentication, C: CalendarStore + ?Sized>( pub async fn delete_event<A: CheckAuthentication, C: CalendarStore + ?Sized>(
context: Data<CalDavContext<C>>, context: Data<CalDavContext<C>>,

View File

@@ -6,7 +6,7 @@ use rustical_dav::error::Error;
use rustical_dav::resource::{Resource, ResourceService}; use rustical_dav::resource::{Resource, ResourceService};
use rustical_dav::xml_snippets::TextNode; use rustical_dav::xml_snippets::TextNode;
use rustical_store::event::Event; use rustical_store::event::Event;
use rustical_store::store::CalendarStore; use rustical_store::CalendarStore;
use serde::Serialize; use serde::Serialize;
use std::sync::Arc; use std::sync::Arc;
use strum::{EnumString, IntoStaticStr, VariantNames}; use strum::{EnumString, IntoStaticStr, VariantNames};

View File

@@ -6,18 +6,20 @@ use event::resource::EventResource;
use principal::PrincipalResource; use principal::PrincipalResource;
use root::RootResource; use root::RootResource;
use rustical_auth::CheckAuthentication; use rustical_auth::CheckAuthentication;
use rustical_dav::error::Error;
use rustical_dav::propfind::{route_propfind, ServicePrefix}; use rustical_dav::propfind::{route_propfind, ServicePrefix};
use rustical_store::store::CalendarStore; use rustical_store::CalendarStore;
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::RwLock; use tokio::sync::RwLock;
pub mod calendar; pub mod calendar;
pub mod error;
pub mod event; pub mod event;
pub mod principal; pub mod principal;
pub mod root; pub mod root;
pub use error::Error;
pub struct CalDavContext<C: CalendarStore + ?Sized> { pub struct CalDavContext<C: CalendarStore + ?Sized> {
pub store: Arc<RwLock<C>>, pub store: Arc<RwLock<C>>,
} }

View File

@@ -7,7 +7,7 @@ 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};
use rustical_dav::xml_snippets::HrefElement; use rustical_dav::xml_snippets::HrefElement;
use rustical_store::store::CalendarStore; use rustical_store::CalendarStore;
use serde::Serialize; use serde::Serialize;
use strum::{EnumString, IntoStaticStr, VariantNames}; use strum::{EnumString, IntoStaticStr, VariantNames};
use tokio::sync::RwLock; use tokio::sync::RwLock;

View File

@@ -5,3 +5,5 @@ pub mod propfind;
pub mod resource; pub mod resource;
pub mod xml; pub mod xml;
pub mod xml_snippets; pub mod xml_snippets;
pub use error::Error;

View File

@@ -29,3 +29,4 @@ regex = "1.10"
lazy_static = "1.4" lazy_static = "1.4"
rstest = "0.18.2" rstest = "0.18.2"
rstest_reuse = "0.6.0" rstest_reuse = "0.6.0"
thiserror = "1.0.61"

23
crates/store/src/error.rs Normal file
View File

@@ -0,0 +1,23 @@
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Not found")]
NotFound,
#[error(transparent)]
SqlxError(sqlx::Error),
#[error(transparent)]
Other(#[from] anyhow::Error),
#[error(transparent)]
ParserError(#[from] ical::parser::ParserError),
}
impl From<sqlx::Error> for Error {
fn from(value: sqlx::Error) -> Self {
match value {
sqlx::Error::RowNotFound => Error::NotFound,
err => Error::SqlxError(err),
}
}
}

View File

@@ -1,4 +1,7 @@
use crate::timestamps::{parse_datetime, parse_duration}; use crate::{
timestamps::{parse_datetime, parse_duration},
Error,
};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use chrono::{Duration, NaiveDateTime, Timelike}; use chrono::{Duration, NaiveDateTime, Timelike};
use ical::parser::{ical::component::IcalCalendar, Component}; use ical::parser::{ical::component::IcalCalendar, Component};
@@ -51,14 +54,14 @@ impl Serialize for Event {
impl Event { impl Event {
// https://datatracker.ietf.org/doc/html/rfc4791#section-4.1 // https://datatracker.ietf.org/doc/html/rfc4791#section-4.1
// MUST NOT contain more than one calendar objects (VEVENT, VTODO, VJOURNAL) // MUST NOT contain more than one calendar objects (VEVENT, VTODO, VJOURNAL)
pub fn from_ics(uid: String, ics: String) -> Result<Self> { pub fn from_ics(uid: String, ics: String) -> Result<Self, Error> {
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(anyhow!("no calendar :("))??; let cal = parser.next().ok_or(Error::NotFound)??;
if parser.next().is_some() { if parser.next().is_some() {
return Err(anyhow!("multiple calendars!")); return Err(anyhow!("multiple calendars!").into());
} }
if cal.events.len() != 1 { if cal.events.len() != 1 {
return Err(anyhow!("multiple or no events")); return Err(anyhow!("multiple or no events").into());
} }
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,6 +1,9 @@
pub mod calendar; pub mod calendar;
pub mod error;
pub mod event; pub mod event;
pub mod sqlite_store; pub mod sqlite_store;
pub mod store; pub mod store;
pub mod timestamps; pub mod timestamps;
pub mod toml_store; pub mod toml_store;
pub use error::Error;
pub use store::CalendarStore;

View File

@@ -2,7 +2,8 @@ use anyhow::Result;
use async_trait::async_trait; use async_trait::async_trait;
use sqlx::{sqlite::SqliteConnectOptions, Pool, Sqlite, SqlitePool}; use sqlx::{sqlite::SqliteConnectOptions, Pool, Sqlite, SqlitePool};
use crate::{calendar::Calendar, event::Event, store::CalendarStore}; use crate::event::Event;
use crate::{calendar::Calendar, CalendarStore, Error};
#[derive(Debug)] #[derive(Debug)]
pub struct SqliteCalendarStore { pub struct SqliteCalendarStore {
@@ -22,16 +23,16 @@ struct EventRow {
} }
impl TryFrom<EventRow> for Event { impl TryFrom<EventRow> for Event {
type Error = anyhow::Error; type Error = Error;
fn try_from(value: EventRow) -> Result<Self> { fn try_from(value: EventRow) -> Result<Self, Error> {
Event::from_ics(value.uid, value.ics) Event::from_ics(value.uid, value.ics)
} }
} }
#[async_trait] #[async_trait]
impl CalendarStore for SqliteCalendarStore { impl CalendarStore for SqliteCalendarStore {
async fn get_calendar(&self, id: &str) -> Result<Calendar> { async fn get_calendar(&self, id: &str) -> Result<Calendar, Error> {
let cal = sqlx::query_as!( let cal = sqlx::query_as!(
Calendar, Calendar,
"SELECT id, name, owner, description, color, timezone FROM calendars WHERE id = ?", "SELECT id, name, owner, description, color, timezone FROM calendars WHERE id = ?",
@@ -42,7 +43,7 @@ impl CalendarStore for SqliteCalendarStore {
Ok(cal) Ok(cal)
} }
async fn get_calendars(&self, _owner: &str) -> Result<Vec<Calendar>> { async fn get_calendars(&self, _owner: &str) -> Result<Vec<Calendar>, Error> {
let cals = sqlx::query_as!( let cals = sqlx::query_as!(
Calendar, Calendar,
"SELECT id, name, owner, description, color, timezone FROM calendars" "SELECT id, name, owner, description, color, timezone FROM calendars"
@@ -52,7 +53,7 @@ impl CalendarStore for SqliteCalendarStore {
Ok(cals) Ok(cals)
} }
async fn insert_calendar(&mut self, cid: String, calendar: Calendar) -> Result<()> { async fn insert_calendar(&mut self, cid: String, calendar: Calendar) -> Result<(), Error> {
sqlx::query!( sqlx::query!(
"INSERT INTO calendars (id, name, description, owner, color, timezone) VALUES (?, ?, ?, ?, ?, ?)", "INSERT INTO calendars (id, name, description, owner, color, timezone) VALUES (?, ?, ?, ?, ?, ?)",
cid, cid,
@@ -65,14 +66,14 @@ impl CalendarStore for SqliteCalendarStore {
Ok(()) Ok(())
} }
async fn delete_calendar(&mut self, cid: &str) -> Result<()> { async fn delete_calendar(&mut self, cid: &str) -> Result<(), Error> {
sqlx::query!("DELETE FROM calendars WHERE id = ?", cid) sqlx::query!("DELETE FROM calendars WHERE id = ?", cid)
.execute(&self.db) .execute(&self.db)
.await?; .await?;
Ok(()) Ok(())
} }
async fn get_events(&self, cid: &str) -> Result<Vec<Event>> { async fn get_events(&self, cid: &str) -> Result<Vec<Event>, Error> {
sqlx::query_as!(EventRow, "SELECT uid, ics FROM events WHERE cid = ?", cid) sqlx::query_as!(EventRow, "SELECT uid, ics FROM events WHERE cid = ?", cid)
.fetch_all(&self.db) .fetch_all(&self.db)
.await? .await?
@@ -81,7 +82,7 @@ impl CalendarStore for SqliteCalendarStore {
.collect() .collect()
} }
async fn get_event(&self, cid: &str, uid: &str) -> Result<Event> { async fn get_event(&self, cid: &str, uid: &str) -> Result<Event, Error> {
let event = sqlx::query_as!( let event = sqlx::query_as!(
EventRow, EventRow,
"SELECT uid, ics FROM events where cid = ? AND uid = ?", "SELECT uid, ics FROM events where cid = ? AND uid = ?",
@@ -94,7 +95,7 @@ impl CalendarStore for SqliteCalendarStore {
Ok(event) Ok(event)
} }
async fn upsert_event(&mut self, cid: String, uid: String, ics: String) -> Result<()> { async fn upsert_event(&mut self, cid: String, uid: String, ics: String) -> Result<(), Error> {
// Do this extra step to ensure that the input is actually valid // Do this extra step to ensure that the input is actually valid
let _ = Event::from_ics(uid.to_owned(), ics.to_owned())?; let _ = Event::from_ics(uid.to_owned(), ics.to_owned())?;
sqlx::query!( sqlx::query!(
@@ -108,7 +109,7 @@ impl CalendarStore for SqliteCalendarStore {
Ok(()) Ok(())
} }
async fn delete_event(&mut self, cid: &str, uid: &str) -> Result<()> { async fn delete_event(&mut self, cid: &str, uid: &str) -> Result<(), Error> {
sqlx::query!("DELETE FROM events WHERE cid = ? AND uid = ?", cid, uid) sqlx::query!("DELETE FROM events WHERE cid = ? AND uid = ?", cid, uid)
.execute(&self.db) .execute(&self.db)
.await?; .await?;

View File

@@ -1,17 +1,18 @@
use anyhow::Result; use anyhow::Result;
use async_trait::async_trait; use async_trait::async_trait;
use crate::error::Error;
use crate::{calendar::Calendar, event::Event}; use crate::{calendar::Calendar, event::Event};
#[async_trait] #[async_trait]
pub trait CalendarStore: Send + Sync + 'static { pub trait CalendarStore: Send + Sync + 'static {
async fn get_calendar(&self, id: &str) -> Result<Calendar>; async fn get_calendar(&self, id: &str) -> Result<Calendar, Error>;
async fn get_calendars(&self, owner: &str) -> Result<Vec<Calendar>>; async fn get_calendars(&self, owner: &str) -> Result<Vec<Calendar>, Error>;
async fn insert_calendar(&mut self, cid: String, calendar: Calendar) -> Result<()>; async fn insert_calendar(&mut self, cid: String, calendar: Calendar) -> Result<(), Error>;
async fn delete_calendar(&mut self, cid: &str) -> Result<()>; async fn delete_calendar(&mut self, cid: &str) -> Result<(), Error>;
async fn get_events(&self, cid: &str) -> Result<Vec<Event>>; async fn get_events(&self, cid: &str) -> Result<Vec<Event>, Error>;
async fn get_event(&self, cid: &str, uid: &str) -> Result<Event>; async fn get_event(&self, cid: &str, uid: &str) -> Result<Event, Error>;
async fn upsert_event(&mut self, cid: String, uid: String, ics: String) -> Result<()>; async fn upsert_event(&mut self, cid: String, uid: String, ics: String) -> Result<(), Error>;
async fn delete_event(&mut self, cid: &str, uid: &str) -> Result<()>; async fn delete_event(&mut self, cid: &str, uid: &str) -> Result<(), Error>;
} }

View File

@@ -1,7 +1,6 @@
use crate::calendar::Calendar;
use crate::event::Event; use crate::event::Event;
use crate::store::CalendarStore; use crate::{calendar::Calendar, CalendarStore, Error};
use anyhow::{anyhow, Result}; use anyhow::anyhow;
use async_trait::async_trait; use async_trait::async_trait;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::{hash_map::Entry, HashMap}; use std::collections::{hash_map::Entry, HashMap};
@@ -31,7 +30,7 @@ impl TomlCalendarStore {
} }
} }
pub async fn save(&self) -> Result<()> { pub async fn save(&self) -> anyhow::Result<()> {
let output = toml::to_string_pretty(&self)?; let output = toml::to_string_pretty(&self)?;
if let Some(path) = &self.path { if let Some(path) = &self.path {
let mut file = File::create(path).await?; let mut file = File::create(path).await?;
@@ -43,11 +42,11 @@ impl TomlCalendarStore {
#[async_trait] #[async_trait]
impl CalendarStore for TomlCalendarStore { impl CalendarStore for TomlCalendarStore {
async fn get_calendar(&self, id: &str) -> Result<Calendar> { async fn get_calendar(&self, id: &str) -> Result<Calendar, Error> {
Ok(self.calendars.get(id).ok_or(anyhow!("not found"))?.clone()) Ok(self.calendars.get(id).ok_or(Error::NotFound)?.clone())
} }
async fn get_calendars(&self, user: &str) -> Result<Vec<Calendar>> { async fn get_calendars(&self, user: &str) -> Result<Vec<Calendar>, Error> {
Ok(self Ok(self
.calendars .calendars
.values() .values()
@@ -56,9 +55,9 @@ impl CalendarStore for TomlCalendarStore {
.collect()) .collect())
} }
async fn insert_calendar(&mut self, cid: String, calendar: Calendar) -> Result<()> { async fn insert_calendar(&mut self, cid: String, calendar: Calendar) -> Result<(), Error> {
match self.calendars.entry(cid) { match self.calendars.entry(cid) {
Entry::Occupied(_) => Err(anyhow!("calendar already exists")), Entry::Occupied(_) => Err(anyhow!("calendar already exists").into()),
Entry::Vacant(v) => { Entry::Vacant(v) => {
v.insert(calendar); v.insert(calendar);
self.save().await.unwrap(); self.save().await.unwrap();
@@ -67,13 +66,13 @@ impl CalendarStore for TomlCalendarStore {
} }
} }
async fn delete_calendar(&mut self, cid: &str) -> Result<()> { async fn delete_calendar(&mut self, cid: &str) -> Result<(), Error> {
self.events.remove(cid); self.events.remove(cid);
self.save().await.unwrap(); self.save().await.unwrap();
Ok(()) Ok(())
} }
async fn get_events(&self, cid: &str) -> Result<Vec<Event>> { async fn get_events(&self, cid: &str) -> Result<Vec<Event>, Error> {
if let Some(events) = self.events.get(cid) { if let Some(events) = self.events.get(cid) {
Ok(events.values().cloned().collect()) Ok(events.values().cloned().collect())
} else { } else {
@@ -81,19 +80,19 @@ impl CalendarStore for TomlCalendarStore {
} }
} }
async fn get_event(&self, cid: &str, uid: &str) -> Result<Event> { async fn get_event(&self, cid: &str, uid: &str) -> Result<Event, Error> {
let events = self.events.get(cid).ok_or(anyhow!("not found"))?; let events = self.events.get(cid).ok_or(anyhow!("not found"))?;
Ok(events.get(uid).ok_or(anyhow!("not found"))?.clone()) Ok(events.get(uid).ok_or(Error::NotFound)?.clone())
} }
async fn upsert_event(&mut self, cid: String, uid: String, ics: String) -> Result<()> { async fn upsert_event(&mut self, cid: String, uid: String, ics: String) -> Result<(), Error> {
let events = self.events.entry(cid).or_default(); let events = self.events.entry(cid).or_default();
events.insert(uid.clone(), Event::from_ics(uid, ics)?); events.insert(uid.clone(), Event::from_ics(uid, ics)?);
self.save().await.unwrap(); self.save().await.unwrap();
Ok(()) Ok(())
} }
async fn delete_event(&mut self, cid: &str, uid: &str) -> Result<()> { async fn delete_event(&mut self, cid: &str, uid: &str) -> Result<(), Error> {
if let Some(events) = self.events.get_mut(cid) { if let Some(events) = self.events.get_mut(cid) {
events.remove(uid); events.remove(uid);
self.save().await?; self.save().await?;

View File

@@ -5,7 +5,7 @@ use actix_web::dev::{ServiceFactory, ServiceRequest, ServiceResponse};
use actix_web::middleware::{Logger, NormalizePath}; use actix_web::middleware::{Logger, NormalizePath};
use actix_web::{web, App}; use actix_web::{web, App};
use rustical_auth::CheckAuthentication; use rustical_auth::CheckAuthentication;
use rustical_store::store::CalendarStore; use rustical_store::CalendarStore;
use tokio::sync::RwLock; use tokio::sync::RwLock;
pub fn make_app<CS: CalendarStore + ?Sized, A: CheckAuthentication>( pub fn make_app<CS: CalendarStore + ?Sized, A: CheckAuthentication>(

View File

@@ -6,8 +6,8 @@ use clap::Parser;
use config::{CalendarStoreConfig, SqliteCalendarStoreConfig, TomlCalendarStoreConfig}; use config::{CalendarStoreConfig, SqliteCalendarStoreConfig, TomlCalendarStoreConfig};
use rustical_auth::AuthProvider; use rustical_auth::AuthProvider;
use rustical_store::sqlite_store::{create_db_pool, SqliteCalendarStore}; use rustical_store::sqlite_store::{create_db_pool, SqliteCalendarStore};
use rustical_store::store::CalendarStore;
use rustical_store::toml_store::TomlCalendarStore; use rustical_store::toml_store::TomlCalendarStore;
use rustical_store::CalendarStore;
use std::fs; use std::fs;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::RwLock; use tokio::sync::RwLock;