From a2d2649ef92324ccd314ee787577ed504522824a Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Fri, 5 Apr 2024 10:19:07 +0200 Subject: WIP dav integration --- aero-collections/src/calendar/namespace.rs | 2 +- aero-proto/src/dav.rs | 126 ++++++++++++++++------------- 2 files changed, 70 insertions(+), 58 deletions(-) diff --git a/aero-collections/src/calendar/namespace.rs b/aero-collections/src/calendar/namespace.rs index 2fbc364..9c21d19 100644 --- a/aero-collections/src/calendar/namespace.rs +++ b/aero-collections/src/calendar/namespace.rs @@ -17,7 +17,7 @@ pub(crate) const CAL_LIST_SK: &str = "list"; pub(crate) const MAIN_CAL: &str = "Personal"; pub(crate) const MAX_CALNAME_CHARS: usize = 32; -pub(crate) struct CalendarNs(std::sync::Mutex>>); +pub struct CalendarNs(std::sync::Mutex>>); impl CalendarNs { /// Create a new calendar namespace diff --git a/aero-proto/src/dav.rs b/aero-proto/src/dav.rs index 3420f86..72dbc5d 100644 --- a/aero-proto/src/dav.rs +++ b/aero-proto/src/dav.rs @@ -1,7 +1,7 @@ use std::net::SocketAddr; use std::sync::Arc; -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, bail, Result}; use base64::Engine; use hyper::service::service_fn; use hyper::{Request, Response, body::Bytes}; @@ -20,7 +20,7 @@ use rustls_pemfile::{certs, private_key}; use aero_user::config::{DavConfig, DavUnsecureConfig}; use aero_user::login::ArcLoginProvider; -use aero_collections::user::User; +use aero_collections::{user::User, calendar::Calendar}; use aero_dav::types as dav; use aero_dav::caltypes as cal; use aero_dav::acltypes as acl; @@ -230,6 +230,7 @@ async fn router(user: std::sync::Arc, req: Request) -> Result = path.split("/").filter(|s| *s != "").collect(); let method = req.method().as_str().to_uppercase(); + let node = match (RootNode {}).fetch(&user, &path_segments) { Ok(v) => v, Err(e) => { @@ -252,6 +253,12 @@ async fn router(user: std::sync::Arc, req: Request) -> Result { + todo!(); + }, + "DELETE" => { + todo!(); + }, "PROPFIND" => propfind(user, req, node).await, "REPORT" => report(user, req, node).await, _ => return Ok(Response::builder() @@ -260,48 +267,6 @@ async fn router(user: std::sync::Arc, req: Request) -> Result -// -// -// -// -// -// -// - - -// -// -// -// -// -// -// -// -// -// -// - -// -// -// -// -// -// -// -// -// -// -// - -// -// -// -// -// -// /alice/calendar/personal/something.ics -// - const ALLPROP: [dav::PropertyRequest; 10] = [ dav::PropertyRequest::CreationDate, dav::PropertyRequest::DisplayName, @@ -501,13 +466,14 @@ async fn deserialize>(req: Request) -> Result { } //--- - +use futures::{future, future::BoxFuture, future::FutureExt}; trait DavNode: Send { // ------- specialized logic // recurence - fn children(&self, user: &ArcUser) -> Vec>; - fn fetch(&self, user: &ArcUser, path: &[&str]) -> Result>; + // @FIXME not satisfied by BoxFutures but I have no better idea currently + fn children<'a>(&self, user: &'a ArcUser) -> BoxFuture<'a, Vec>>; + fn fetch<'a>(&self, user: &'a ArcUser, path: &'a [&str]) -> BoxFuture<'a, Result>>; // node properties fn path(&self, user: &ArcUser) -> String; @@ -573,17 +539,18 @@ trait DavNode: Send { #[derive(Clone)] struct RootNode {} impl DavNode for RootNode { - fn fetch(&self, user: &ArcUser, path: &[&str]) -> Result> { + fn fetch<'a>(&self, user: &'a ArcUser, path: &'a [&str]) -> BoxFuture<'a, Result>> { if path.len() == 0 { - return Ok(Box::new(self.clone())) + let this = self.clone(); + return async { Ok(Box::new(this) as Box) }.boxed(); } if path[0] == user.username { let child = Box::new(HomeNode {}); - return child.fetch(user, &path[1..]) + return child.fetch(user, &path[1..]); } - Err(anyhow!("Not found")) + async { Err(anyhow!("Not found")) }.boxed() } fn path(&self, user: &ArcUser) -> String { @@ -664,26 +631,29 @@ impl DavNode for HomeNode { #[derive(Clone)] struct CalendarListNode {} impl DavNode for CalendarListNode { - fn fetch(&self, user: &ArcUser, path: &[&str]) -> Result> { + async fn fetch(&self, user: &ArcUser, path: &[&str]) -> Result> { if path.len() == 0 { return Ok(Box::new(self.clone())) } //@FIXME hardcoded logic - if path[0] == "personal" { + /*if path[0] == "personal" { let child = Box::new(CalendarNode { name: "personal".to_string() }); return child.fetch(user, &path[1..]) + }*/ + if !user.calendars.has(user, path[0]).await? { + bail!("Not found"); } - - Err(anyhow!("Not found")) + let child = Box::new(CalendarNode { name: path[0].to_string() }); + child.fetch(user, &path[1..]) } fn path(&self, user: &ArcUser) -> String { format!("/{}/calendar/", user.username) } - fn children(&self, user: &ArcUser) -> Vec> { - vec![Box::new(CalendarNode { name: "personal".into() })] + async fn children(&self, user: &ArcUser) -> Vec> { + user.calendars.list(user).await.map(|name| Box::new(CalendarNode { name: name.to_string() })).collect() } fn supported_properties(&self, user: &ArcUser) -> dav::PropName { dav::PropName(vec![ @@ -832,3 +802,45 @@ impl DavNode for EventNode { } + +// +// +// +// +// +// +// +// + + +// +// +// +// +// +// +// +// +// +// +// + +// +// +// +// +// +// +// +// +// +// +// + +// +// +// +// +// +// /alice/calendar/personal/something.ics +// -- cgit v1.2.3