From 6b6788ec9899ba21ed3be9e700257ce980b8b92b Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Tue, 5 Sep 2023 17:00:32 +0200 Subject: [PATCH] Extend the app state --- crates/dav/src/lib.rs | 15 ++++++++-- crates/dav/src/propfind_extractor.rs | 42 ++++++++++++++++++++++++++++ crates/dav/src/routes/calendar.rs | 12 ++++---- crates/dav/src/routes/event.rs | 18 ++++++------ crates/dav/src/routes/principal.rs | 8 +++--- crates/davfs/Cargo.toml | 8 ++++++ crates/davfs/src/main.rs | 3 ++ src/main.rs | 11 ++++++-- 8 files changed, 94 insertions(+), 23 deletions(-) create mode 100644 crates/dav/src/propfind_extractor.rs create mode 100644 crates/davfs/Cargo.toml create mode 100644 crates/davfs/src/main.rs diff --git a/crates/dav/src/lib.rs b/crates/dav/src/lib.rs index 073ac82..b0d8e53 100644 --- a/crates/dav/src/lib.rs +++ b/crates/dav/src/lib.rs @@ -6,6 +6,7 @@ use error::Error; use routes::{calendar, event, principal, root}; use rustical_store::calendar::CalendarStore; use std::str::FromStr; +use std::sync::Arc; use tokio::sync::RwLock; pub mod depth_extractor; @@ -14,11 +15,20 @@ pub mod namespace; mod propfind; pub mod routes; +pub struct Context { + pub prefix: String, + pub store: Arc>, +} + pub fn configure_well_known(cfg: &mut web::ServiceConfig, caldav_root: String) { cfg.service(web::redirect("/caldav", caldav_root).permanent()); } -pub fn configure_dav(cfg: &mut web::ServiceConfig, store: Data>) { +pub fn configure_dav( + cfg: &mut web::ServiceConfig, + prefix: String, + store: Arc>, +) { let propfind_method = || Method::from_str("PROPFIND").unwrap(); let report_method = || Method::from_str("REPORT").unwrap(); @@ -31,7 +41,8 @@ pub fn configure_dav(cfg: &mut web::ServiceConfig, store: Data } }); - cfg.app_data(store) + // cfg.app_data(store) + cfg.app_data(Data::new(Context { prefix, store })) .service( web::resource("{path:.*}") // Without the guard this service would handle all requests diff --git a/crates/dav/src/propfind_extractor.rs b/crates/dav/src/propfind_extractor.rs new file mode 100644 index 0000000..5730b55 --- /dev/null +++ b/crates/dav/src/propfind_extractor.rs @@ -0,0 +1,42 @@ +use std::pin::Pin; + +use actix_web::{http::StatusCode, Either, FromRequest, HttpRequest, ResponseError}; +use derive_more::Display; +use futures_util::{ + future::{err, ok, Ready}, + Future, +}; + +#[derive(Debug, Display)] +pub struct BadPropfindRequest {} + +impl ResponseError for BadPropfindRequest { + fn status_code(&self) -> actix_web::http::StatusCode { + StatusCode::BAD_REQUEST + } +} + +#[derive(Debug, PartialEq)] +pub struct Propfind(Vec); + +impl FromRequest for Propfind { + type Error = BadPropfindRequest; + type Future = Either>>; + + fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future {} +} + +pub struct PropfindExtractFut { + body_fut: HttpMessageBody, +} + +impl Future for PropfindExtractFut { + type Output = Result; + + fn poll( + self: Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll { + Pin::new() + } +} diff --git a/crates/dav/src/routes/calendar.rs b/crates/dav/src/routes/calendar.rs index 3d3eafe..d201b52 100644 --- a/crates/dav/src/routes/calendar.rs +++ b/crates/dav/src/routes/calendar.rs @@ -3,7 +3,7 @@ use crate::propfind::{ generate_multistatus, parse_propfind, write_invalid_props_response, write_propstat_response, write_resourcetype, }; -use crate::Error; +use crate::{Context, Error}; use actix_web::http::header::ContentType; use actix_web::http::StatusCode; use actix_web::web::{Data, Path}; @@ -17,7 +17,6 @@ use rustical_store::calendar::{Calendar, CalendarStore, Event}; use std::collections::HashSet; use std::ops::Deref; use std::sync::Arc; -use tokio::sync::RwLock; async fn handle_report_calendar_query( query_node: Node<'_, '_>, @@ -71,7 +70,7 @@ async fn handle_report_calendar_query( } pub async fn route_report_calendar( - store: Data>, + context: Data>, body: String, path: Path<(String, String)>, request: HttpRequest, @@ -80,7 +79,7 @@ pub async fn route_report_calendar( let doc = roxmltree::Document::parse(&body).map_err(|_e| Error::InternalError)?; let query_node = doc.root_element(); - let events = store.read().await.get_events(&cid).await.unwrap(); + let events = context.store.read().await.get_events(&cid).await.unwrap(); // TODO: implement filtering match query_node.tag_name().name() { @@ -173,10 +172,11 @@ pub async fn route_propfind_calendar( body: String, request: HttpRequest, auth: BasicAuth, - store: Data>, + context: Data>, ) -> Result { let (_principal, cid) = path.into_inner(); - let calendar = store + let calendar = context + .store .read() .await .get_calendar(&cid) diff --git a/crates/dav/src/routes/event.rs b/crates/dav/src/routes/event.rs index b6693b6..21651fe 100644 --- a/crates/dav/src/routes/event.rs +++ b/crates/dav/src/routes/event.rs @@ -1,18 +1,18 @@ -use crate::Error; +use crate::{Context, Error}; use actix_web::web::{Data, Path}; use actix_web::HttpResponse; use rustical_store::calendar::CalendarStore; -use tokio::sync::RwLock; pub async fn delete_event( - store: Data>, + context: Data>, path: Path<(String, String, String)>, ) -> Result { let (_principal, mut cid, uid) = path.into_inner(); if cid.ends_with(".ics") { cid.truncate(cid.len() - 4); } - store + context + .store .write() .await .delete_event(&uid) @@ -23,14 +23,15 @@ pub async fn delete_event( } pub async fn get_event( - store: Data>, + context: Data>, path: Path<(String, String, String)>, ) -> Result { let (_principal, mut cid, uid) = path.into_inner(); if cid.ends_with(".ics") { cid.truncate(cid.len() - 4); } - let event = store + let event = context + .store .read() .await .get_event(&uid) @@ -43,7 +44,7 @@ pub async fn get_event( } pub async fn put_event( - store: Data>, + context: Data>, path: Path<(String, String, String)>, body: String, ) -> Result { @@ -53,7 +54,8 @@ pub async fn put_event( cid.truncate(cid.len() - 4); } dbg!(&body); - store + context + .store .write() .await .upsert_event(uid, body) diff --git a/crates/dav/src/routes/principal.rs b/crates/dav/src/routes/principal.rs index 31116a4..86f8330 100644 --- a/crates/dav/src/routes/principal.rs +++ b/crates/dav/src/routes/principal.rs @@ -6,7 +6,7 @@ use crate::{ generate_multistatus, parse_propfind, write_invalid_props_response, write_propstat_response, write_resourcetype, }, - Error, + Context, Error, }; use actix_web::{ http::{header::ContentType, StatusCode}, @@ -20,7 +20,6 @@ use quick_xml::{ Writer, }; use rustical_store::calendar::CalendarStore; -use tokio::sync::RwLock; // Executes the PROPFIND request and returns a XML string to be written into a object. pub async fn generate_propfind_principal_response( @@ -90,7 +89,7 @@ pub async fn route_propfind_principal( body: String, request: HttpRequest, auth: BasicAuth, - store: Data>, + context: Data>, depth: Depth, ) -> Result { let props = parse_propfind(&body).map_err(|_e| Error::BadRequest)?; @@ -98,7 +97,8 @@ pub async fn route_propfind_principal( let mut responses = Vec::new(); // also get calendars: if depth != Depth::Zero { - let cals = store + let cals = context + .store .read() .await .get_calendars() diff --git a/crates/davfs/Cargo.toml b/crates/davfs/Cargo.toml new file mode 100644 index 0000000..1e9dcae --- /dev/null +++ b/crates/davfs/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "davfs" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/crates/davfs/src/main.rs b/crates/davfs/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/crates/davfs/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/src/main.rs b/src/main.rs index 1495620..eebbcf3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ use clap::Parser; use config::{CalendarStoreConfig, JsonCalendarStoreConfig}; use rustical_api::configure_api; use rustical_dav::{configure_dav, configure_well_known}; +use rustical_frontend::configure_frontend; use rustical_store::calendar::JsonCalendarStore; use tokio::sync::RwLock; @@ -45,9 +46,9 @@ async fn main() -> Result<()> { App::new() .wrap(Logger::new("[%s] %r")) .wrap(NormalizePath::trim()) - .service( - web::scope("/dav").configure(|cfg| configure_dav(cfg, cal_store.clone().into())), - ) + .service(web::scope("/caldav").configure(|cfg| { + configure_dav(cfg, "/caldav".to_string(), cal_store.clone().into()) + })) .service( web::scope("/.well-known") .configure(|cfg| configure_well_known(cfg, "/dav".to_string())), @@ -55,6 +56,10 @@ async fn main() -> Result<()> { .service( web::scope("/api").configure(|cfg| configure_api(cfg, cal_store.clone().into())), ) + .service( + web::scope("/frontend") + .configure(|cfg| configure_frontend(cfg, cal_store.clone().into())), + ) }) .bind(("0.0.0.0", 4000))? .run()