diff --git a/crates/caldav/src/calendar/methods/report/calendar_multiget.rs b/crates/caldav/src/calendar/methods/report/calendar_multiget.rs index 6df1bf1..d514cd0 100644 --- a/crates/caldav/src/calendar/methods/report/calendar_multiget.rs +++ b/crates/caldav/src/calendar/methods/report/calendar_multiget.rs @@ -33,7 +33,7 @@ pub async fn get_objects_calendar_multiget( cal_id: &str, store: &C, ) -> Result<(Vec, Vec), Error> { - let resource_def = ResourceDef::prefix(path).join(&ResourceDef::new("/{object_id}")); + let resource_def = ResourceDef::prefix(path).join(&ResourceDef::new("/{object_id}.ics")); let mut result = vec![]; let mut not_found = vec![]; @@ -42,6 +42,7 @@ pub async fn get_objects_calendar_multiget( let mut path = Path::new(href.as_str()); if !resource_def.capture_match_info(&mut path) { not_found.push(href.to_owned()); + continue; }; let object_id = path.get("object_id").unwrap(); match store.get_object(principal, cal_id, object_id).await { @@ -85,7 +86,7 @@ pub async fn handle_calendar_multiget( let mut responses = Vec::new(); for object in objects { - let path = format!("{}/{}", req.path(), object.get_id()); + let path = format!("{}/{}.ics", req.path(), object.get_id()); responses.push( CalendarObjectResource { object, diff --git a/crates/caldav/src/calendar/methods/report/calendar_query.rs b/crates/caldav/src/calendar/methods/report/calendar_query.rs index 4d0115e..8eebe91 100644 --- a/crates/caldav/src/calendar/methods/report/calendar_query.rs +++ b/crates/caldav/src/calendar/methods/report/calendar_query.rs @@ -244,7 +244,11 @@ pub async fn handle_calendar_query( let mut responses = Vec::new(); for object in objects { - let path = format!("{}/{}", req.path().trim_end_matches('/'), object.get_id()); + let path = format!( + "{}/{}.ics", + req.path().trim_end_matches('/'), + object.get_id() + ); responses.push( CalendarObjectResource { object, diff --git a/crates/caldav/src/calendar/methods/report/sync_collection.rs b/crates/caldav/src/calendar/methods/report/sync_collection.rs index 9248992..57d73f7 100644 --- a/crates/caldav/src/calendar/methods/report/sync_collection.rs +++ b/crates/caldav/src/calendar/methods/report/sync_collection.rs @@ -49,7 +49,11 @@ pub async fn handle_sync_collection( let mut responses = Vec::new(); for object in new_objects { - let path = format!("{}/{}", req.path().trim_end_matches('/'), object.get_id()); + let path = format!( + "{}/{}.ics", + req.path().trim_end_matches('/'), + object.get_id() + ); responses.push( CalendarObjectResource { object, @@ -60,7 +64,7 @@ pub async fn handle_sync_collection( } for object_id in deleted_objects { - let path = format!("{}/{}", req.path().trim_end_matches('/'), object_id); + let path = format!("{}/{}.ics", req.path().trim_end_matches('/'), object_id); responses.push(ResponseElement { href: path, status: Some(StatusCode::NOT_FOUND), diff --git a/crates/caldav/src/calendar_object/methods.rs b/crates/caldav/src/calendar_object/methods.rs index 3c2d483..df09328 100644 --- a/crates/caldav/src/calendar_object/methods.rs +++ b/crates/caldav/src/calendar_object/methods.rs @@ -1,9 +1,9 @@ use crate::Error; +use actix_web::HttpRequest; +use actix_web::HttpResponse; use actix_web::http::header; use actix_web::http::header::HeaderValue; use actix_web::web::{Data, Path}; -use actix_web::HttpRequest; -use actix_web::HttpResponse; use rustical_store::auth::User; use rustical_store::{CalendarObject, CalendarStore}; use tracing::instrument; @@ -20,7 +20,7 @@ pub async fn get_event( ) -> Result { let CalendarObjectPathComponents { principal, - cal_id, + calendar_id, object_id, } = path.into_inner(); @@ -28,12 +28,14 @@ pub async fn get_event( return Ok(HttpResponse::Unauthorized().body("")); } - let calendar = store.get_calendar(&principal, &cal_id).await?; + let calendar = store.get_calendar(&principal, &calendar_id).await?; if !user.is_principal(&calendar.principal) { return Ok(HttpResponse::Unauthorized().body("")); } - let event = store.get_object(&principal, &cal_id, &object_id).await?; + let event = store + .get_object(&principal, &calendar_id, &object_id) + .await?; Ok(HttpResponse::Ok() .insert_header(("ETag", event.get_etag())) @@ -52,7 +54,7 @@ pub async fn put_event( ) -> Result { let CalendarObjectPathComponents { principal, - cal_id, + calendar_id, object_id, } = path.into_inner(); @@ -65,7 +67,7 @@ pub async fn put_event( let object = CalendarObject::from_ics(object_id, body)?; store - .put_object(principal, cal_id, object, overwrite) + .put_object(principal, calendar_id, object, overwrite) .await?; Ok(HttpResponse::Created().body("")) diff --git a/crates/caldav/src/calendar_object/resource.rs b/crates/caldav/src/calendar_object/resource.rs index c6983a8..bdee6a8 100644 --- a/crates/caldav/src/calendar_object/resource.rs +++ b/crates/caldav/src/calendar_object/resource.rs @@ -105,31 +105,13 @@ impl Resource for CalendarObjectResource { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Deserialize)] pub struct CalendarObjectPathComponents { pub principal: String, - pub cal_id: String, + pub calendar_id: String, pub object_id: String, } -impl<'de> Deserialize<'de> for CalendarObjectPathComponents { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - type Inner = (String, String, String); - let (principal, calendar, mut object) = Inner::deserialize(deserializer)?; - if object.ends_with(".ics") { - object.truncate(object.len() - 4); - } - Ok(Self { - principal, - cal_id: calendar, - object_id: object, - }) - } -} - #[async_trait(?Send)] impl ResourceService for CalendarObjectResourceService { type PathComponents = CalendarObjectPathComponents; @@ -142,13 +124,13 @@ impl ResourceService for CalendarObjectResourceService { &self, CalendarObjectPathComponents { principal, - cal_id, + calendar_id, object_id, }: &Self::PathComponents, ) -> Result { let object = self .cal_store - .get_object(principal, cal_id, object_id) + .get_object(principal, calendar_id, object_id) .await?; Ok(CalendarObjectResource { object, @@ -160,13 +142,13 @@ impl ResourceService for CalendarObjectResourceService { &self, CalendarObjectPathComponents { principal, - cal_id, + calendar_id, object_id, }: &Self::PathComponents, use_trashbin: bool, ) -> Result<(), Self::Error> { self.cal_store - .delete_object(principal, cal_id, object_id, use_trashbin) + .delete_object(principal, calendar_id, object_id, use_trashbin) .await?; Ok(()) } diff --git a/crates/caldav/src/lib.rs b/crates/caldav/src/lib.rs index bfb7f49..5c86a15 100644 --- a/crates/caldav/src/lib.rs +++ b/crates/caldav/src/lib.rs @@ -75,22 +75,22 @@ pub fn caldav_service< .service(web::scope("/calendar") .service(CalendarSetResourceService::new(store.clone()).actix_resource()) .service( - web::scope("/{calendar}") + web::scope("/{calendar_id}") .service( ResourceServiceRoute(CalendarResourceService::<_, S>::new(store.clone())) ) - .service(web::scope("/{object}").service(CalendarObjectResourceService::new(store.clone()).actix_resource() + .service(web::scope("/{object_id}.ics").service(CalendarObjectResourceService::new(store.clone()).actix_resource() )) ) ) .service(web::scope("/birthdays") .service(CalendarSetResourceService::new(birthday_store.clone()).actix_resource()) .service( - web::scope("/{calendar}") + web::scope("/{calendar_id}") .service( ResourceServiceRoute(CalendarResourceService::<_, S>::new(birthday_store.clone())) ) - .service(web::scope("/{object}").service(CalendarObjectResourceService::new(birthday_store.clone()).actix_resource() + .service(web::scope("/{object_id}.ics").service(CalendarObjectResourceService::new(birthday_store.clone()).actix_resource() )) ) ) diff --git a/crates/carddav/src/address_object/resource.rs b/crates/carddav/src/address_object/resource.rs index 88021bf..1d1b04f 100644 --- a/crates/carddav/src/address_object/resource.rs +++ b/crates/carddav/src/address_object/resource.rs @@ -101,31 +101,13 @@ impl Resource for AddressObjectResource { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Deserialize)] pub struct AddressObjectPathComponents { pub principal: String, pub addressbook_id: String, pub object_id: String, } -impl<'de> Deserialize<'de> for AddressObjectPathComponents { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - type Inner = (String, String, String); - let (principal, addressbook_id, mut object) = Inner::deserialize(deserializer)?; - if object.ends_with(".vcf") { - object.truncate(object.len() - 4); - } - Ok(Self { - principal, - addressbook_id, - object_id: object, - }) - } -} - #[async_trait(?Send)] impl ResourceService for AddressObjectResourceService { type PathComponents = AddressObjectPathComponents; diff --git a/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs b/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs index e8889ae..c82cb1f 100644 --- a/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs +++ b/crates/carddav/src/addressbook/methods/report/addressbook_multiget.rs @@ -31,7 +31,7 @@ pub async fn get_objects_addressbook_multiget( addressbook_id: &str, store: &AS, ) -> Result<(Vec, Vec), Error> { - let resource_def = ResourceDef::prefix(path).join(&ResourceDef::new("/{object_id}")); + let resource_def = ResourceDef::prefix(path).join(&ResourceDef::new("/{object_id}.vcf")); let mut result = vec![]; let mut not_found = vec![]; @@ -83,7 +83,7 @@ pub async fn handle_addressbook_multiget( let mut responses = Vec::new(); for object in objects { - let path = format!("{}/{}", req.path(), object.get_id()); + let path = format!("{}/{}.vcf", req.path(), object.get_id()); responses.push( AddressObjectResource { object, diff --git a/crates/carddav/src/addressbook/methods/report/sync_collection.rs b/crates/carddav/src/addressbook/methods/report/sync_collection.rs index 95f461a..6e9fab0 100644 --- a/crates/carddav/src/addressbook/methods/report/sync_collection.rs +++ b/crates/carddav/src/addressbook/methods/report/sync_collection.rs @@ -1,19 +1,19 @@ use crate::{ - address_object::resource::{AddressObjectPropWrapper, AddressObjectResource}, Error, + address_object::resource::{AddressObjectPropWrapper, AddressObjectResource}, }; -use actix_web::{http::StatusCode, HttpRequest}; +use actix_web::{HttpRequest, http::StatusCode}; use rustical_dav::{ resource::Resource, xml::{ - multistatus::ResponseElement, sync_collection::SyncCollectionRequest, MultistatusElement, - PropElement, PropfindType, + MultistatusElement, PropElement, PropfindType, multistatus::ResponseElement, + sync_collection::SyncCollectionRequest, }, }; use rustical_store::{ + AddressbookStore, auth::User, synctoken::{format_synctoken, parse_synctoken}, - AddressbookStore, }; pub async fn handle_sync_collection( @@ -44,7 +44,11 @@ pub async fn handle_sync_collection( let mut responses = Vec::new(); for object in new_objects { - let path = format!("{}/{}", req.path().trim_end_matches('/'), object.get_id()); + let path = format!( + "{}/{}.vcf", + req.path().trim_end_matches('/'), + object.get_id() + ); responses.push( AddressObjectResource { object, @@ -55,7 +59,7 @@ pub async fn handle_sync_collection( } for object_id in deleted_objects { - let path = format!("{}/{}", req.path().trim_end_matches('/'), object_id); + let path = format!("{}/{}.vcf", req.path().trim_end_matches('/'), object_id); responses.push(ResponseElement { href: path, status: Some(StatusCode::NOT_FOUND), diff --git a/crates/carddav/src/lib.rs b/crates/carddav/src/lib.rs index c230aa2..0fa1b48 100644 --- a/crates/carddav/src/lib.rs +++ b/crates/carddav/src/lib.rs @@ -68,13 +68,13 @@ pub fn carddav_service::new(store.clone()) .actix_resource(), ) .service( - web::scope("/{object}").service( + web::scope("/{object_id}.vcf").service( AddressObjectResourceService::::new(store.clone()) .actix_resource(), ),