aboutsummaryrefslogtreecommitdiff
path: root/aero-proto/src/dav/resource.rs
diff options
context:
space:
mode:
authorQuentin Dufour <quentin@deuxfleurs.fr>2024-05-28 17:21:30 +0200
committerQuentin Dufour <quentin@deuxfleurs.fr>2024-05-28 17:21:30 +0200
commita2f5b451bd32780d60be69c6412cb351a54b765b (patch)
treedc8dc26889d9f447dffd1b2f0968c348386cfcd7 /aero-proto/src/dav/resource.rs
parent18f2154151b2cf81e03bdda28fa2ea5d685e33d1 (diff)
downloadaerogramme-caldav.tar.gz
aerogramme-caldav.zip
initial implementation of sync-collectioncaldav
Diffstat (limited to 'aero-proto/src/dav/resource.rs')
-rw-r--r--aero-proto/src/dav/resource.rs96
1 files changed, 93 insertions, 3 deletions
diff --git a/aero-proto/src/dav/resource.rs b/aero-proto/src/dav/resource.rs
index 1ae766c..297a1c1 100644
--- a/aero-proto/src/dav/resource.rs
+++ b/aero-proto/src/dav/resource.rs
@@ -8,7 +8,7 @@ use futures::{future::BoxFuture, future::FutureExt};
use aero_collections::{
calendar::Calendar,
- davdag::{BlobId, Etag},
+ davdag::{BlobId, Etag, SyncChange, Token},
user::User,
};
use aero_dav::acltypes as acl;
@@ -21,6 +21,8 @@ use aero_dav::versioningtypes as vers;
use super::node::PropertyStream;
use crate::dav::node::{Content, DavNode, PutPolicy};
+pub const BASE_TOKEN_URI: &str = "https://aerogramme.0/sync/";
+
#[derive(Clone)]
pub(crate) struct RootNode {}
impl DavNode for RootNode {
@@ -117,6 +119,16 @@ impl DavNode for RootNode {
fn delete(&self) -> BoxFuture<std::result::Result<(), std::io::Error>> {
async { Err(std::io::Error::from(std::io::ErrorKind::PermissionDenied)) }.boxed()
}
+
+ fn diff<'a>(
+ &self,
+ _sync_token: Option<Token>,
+ ) -> BoxFuture<
+ 'a,
+ std::result::Result<(Token, Vec<Box<dyn DavNode>>, Vec<dav::Href>), std::io::Error>,
+ > {
+ async { Err(std::io::Error::from(std::io::ErrorKind::Unsupported)) }.boxed()
+ }
}
#[derive(Clone)]
@@ -229,6 +241,15 @@ impl DavNode for HomeNode {
fn delete(&self) -> BoxFuture<std::result::Result<(), std::io::Error>> {
async { Err(std::io::Error::from(std::io::ErrorKind::PermissionDenied)) }.boxed()
}
+ fn diff<'a>(
+ &self,
+ _sync_token: Option<Token>,
+ ) -> BoxFuture<
+ 'a,
+ std::result::Result<(Token, Vec<Box<dyn DavNode>>, Vec<dav::Href>), std::io::Error>,
+ > {
+ async { Err(std::io::Error::from(std::io::ErrorKind::Unsupported)) }.boxed()
+ }
}
#[derive(Clone)]
@@ -353,6 +374,15 @@ impl DavNode for CalendarListNode {
fn delete(&self) -> BoxFuture<std::result::Result<(), std::io::Error>> {
async { Err(std::io::Error::from(std::io::ErrorKind::PermissionDenied)) }.boxed()
}
+ fn diff<'a>(
+ &self,
+ _sync_token: Option<Token>,
+ ) -> BoxFuture<
+ 'a,
+ std::result::Result<(Token, Vec<Box<dyn DavNode>>, Vec<dav::Href>), std::io::Error>,
+ > {
+ async { Err(std::io::Error::from(std::io::ErrorKind::Unsupported)) }.boxed()
+ }
}
#[derive(Clone)]
@@ -480,8 +510,8 @@ impl DavNode for CalendarNode {
)) => match col.token().await {
Ok(token) => dav::Property::Extension(all::Property::Sync(
sync::Property::SyncToken(sync::SyncToken(format!(
- "https://aerogramme.0/sync/{}",
- token
+ "{}{}",
+ BASE_TOKEN_URI, token
))),
)),
_ => return Err(n.clone()),
@@ -535,6 +565,48 @@ impl DavNode for CalendarNode {
fn delete(&self) -> BoxFuture<std::result::Result<(), std::io::Error>> {
async { Err(std::io::Error::from(std::io::ErrorKind::PermissionDenied)) }.boxed()
}
+ fn diff<'a>(
+ &self,
+ sync_token: Option<Token>,
+ ) -> BoxFuture<
+ 'a,
+ std::result::Result<(Token, Vec<Box<dyn DavNode>>, Vec<dav::Href>), std::io::Error>,
+ > {
+ let col = self.col.clone();
+ let calname = self.calname.clone();
+ async move {
+ let sync_token = sync_token.unwrap();
+ let (new_token, listed_changes) = match col.diff(sync_token).await {
+ Ok(v) => v,
+ Err(e) => {
+ tracing::info!(err=?e, "token resolution failed, maybe a forgotten token");
+ return Err(std::io::Error::from(std::io::ErrorKind::NotFound));
+ }
+ };
+
+ let mut ok_nodes: Vec<Box<dyn DavNode>> = vec![];
+ let mut rm_nodes: Vec<dav::Href> = vec![];
+ for change in listed_changes.into_iter() {
+ match change {
+ SyncChange::Ok((filename, blob_id)) => {
+ let child = Box::new(EventNode {
+ col: col.clone(),
+ calname: calname.clone(),
+ filename,
+ blob_id,
+ });
+ ok_nodes.push(child);
+ }
+ SyncChange::NotFound(filename) => {
+ rm_nodes.push(dav::Href(filename));
+ }
+ }
+ }
+
+ Ok((new_token, ok_nodes, rm_nodes))
+ }
+ .boxed()
+ }
}
#[derive(Clone)]
@@ -757,6 +829,15 @@ impl DavNode for EventNode {
}
.boxed()
}
+ fn diff<'a>(
+ &self,
+ _sync_token: Option<Token>,
+ ) -> BoxFuture<
+ 'a,
+ std::result::Result<(Token, Vec<Box<dyn DavNode>>, Vec<dav::Href>), std::io::Error>,
+ > {
+ async { Err(std::io::Error::from(std::io::ErrorKind::Unsupported)) }.boxed()
+ }
}
#[derive(Clone)]
@@ -849,4 +930,13 @@ impl DavNode for CreateEventNode {
// Nothing to delete
async { Ok(()) }.boxed()
}
+ fn diff<'a>(
+ &self,
+ _sync_token: Option<Token>,
+ ) -> BoxFuture<
+ 'a,
+ std::result::Result<(Token, Vec<Box<dyn DavNode>>, Vec<dav::Href>), std::io::Error>,
+ > {
+ async { Err(std::io::Error::from(std::io::ErrorKind::Unsupported)) }.boxed()
+ }
}