diff --git a/crates/caldav/src/calendar/methods/report/calendar_multiget.rs b/crates/caldav/src/calendar/methods/report/calendar_multiget.rs index 2cf61ff..a16c6fa 100644 --- a/crates/caldav/src/calendar/methods/report/calendar_multiget.rs +++ b/crates/caldav/src/calendar/methods/report/calendar_multiget.rs @@ -21,7 +21,7 @@ pub async fn get_objects_calendar_multiget( principal: &str, cal_id: &str, store: &C, -) -> Result<(Vec, Vec), Error> { +) -> Result<(Vec<(String, CalendarObject)>, Vec), Error> { let mut result = vec![]; let mut not_found = vec![]; @@ -32,7 +32,7 @@ pub async fn get_objects_calendar_multiget( let filename = filename.trim_start_matches('/'); if let Some(object_id) = filename.strip_suffix(".ics") { match store.get_object(principal, cal_id, object_id, false).await { - Ok(object) => result.push(object), + Ok(object) => result.push((object_id.to_owned(), object)), Err(rustical_store::Error::NotFound) => not_found.push(href.to_string()), Err(err) => return Err(err.into()), } diff --git a/crates/caldav/src/calendar/methods/report/calendar_query/comp_filter.rs b/crates/caldav/src/calendar/methods/report/calendar_query/comp_filter.rs index 27f10cc..517e486 100644 --- a/crates/caldav/src/calendar/methods/report/calendar_query/comp_filter.rs +++ b/crates/caldav/src/calendar/methods/report/calendar_query/comp_filter.rs @@ -130,7 +130,7 @@ END:VCALENDAR"; #[test] fn test_comp_filter_matching() { - let object = CalendarObject::from_ics(ICS.to_string(), None).unwrap(); + let object = CalendarObject::from_ics(ICS.to_string()).unwrap(); let comp_filter = CompFilterElement { is_not_defined: Some(()), @@ -231,7 +231,7 @@ END:VCALENDAR"; } #[test] fn test_comp_filter_time_range() { - let object = CalendarObject::from_ics(ICS.to_string(), None).unwrap(); + let object = CalendarObject::from_ics(ICS.to_string()).unwrap(); let comp_filter = CompFilterElement { is_not_defined: None, @@ -286,7 +286,7 @@ END:VCALENDAR"; #[test] fn test_match_timezone() { - let object = CalendarObject::from_ics(ICS.to_string(), None).unwrap(); + let object = CalendarObject::from_ics(ICS.to_string()).unwrap(); let comp_filter = CompFilterElement { is_not_defined: None, diff --git a/crates/caldav/src/calendar/methods/report/calendar_query/mod.rs b/crates/caldav/src/calendar/methods/report/calendar_query/mod.rs index b674142..038b03c 100644 --- a/crates/caldav/src/calendar/methods/report/calendar_query/mod.rs +++ b/crates/caldav/src/calendar/methods/report/calendar_query/mod.rs @@ -18,12 +18,12 @@ pub async fn get_objects_calendar_query( principal: &str, cal_id: &str, store: &C, -) -> Result, Error> { +) -> Result, Error> { let mut objects = store .calendar_query(principal, cal_id, cal_query.into()) .await?; if let Some(filter) = &cal_query.filter { - objects.retain(|object| filter.matches(object.get_inner())); + objects.retain(|(_id, object)| filter.matches(object.get_inner())); } Ok(objects) } diff --git a/crates/caldav/src/calendar/methods/report/calendar_query/tests.rs b/crates/caldav/src/calendar/methods/report/calendar_query/tests.rs index 0163158..7f8119b 100644 --- a/crates/caldav/src/calendar/methods/report/calendar_query/tests.rs +++ b/crates/caldav/src/calendar/methods/report/calendar_query/tests.rs @@ -77,7 +77,7 @@ const FILTER_2: &str = r#" #[case(ICS_1, FILTER_1, true)] #[case(ICS_1, FILTER_2, false)] fn yeet(#[case] ics: &str, #[case] filter: &str, #[case] matches: bool) { - let obj = CalendarObject::from_ics(ics.to_owned(), None).unwrap(); + let obj = CalendarObject::from_ics(ics.to_owned()).unwrap(); let filter = FilterElement::parse_str(filter).unwrap(); assert_eq!(matches, filter.matches(obj.get_inner())); } diff --git a/crates/caldav/src/calendar/methods/report/mod.rs b/crates/caldav/src/calendar/methods/report/mod.rs index b6b4bce..8d4e1da 100644 --- a/crates/caldav/src/calendar/methods/report/mod.rs +++ b/crates/caldav/src/calendar/methods/report/mod.rs @@ -51,7 +51,7 @@ impl ReportRequest { } fn objects_response( - objects: Vec, + objects: Vec<(String, CalendarObject)>, not_found: Vec, path: &str, principal: &str, @@ -60,11 +60,12 @@ fn objects_response( prop: &PropfindType, ) -> Result, Error> { let mut responses = Vec::new(); - for object in objects { - let path = format!("{}/{}.ics", path, object.get_id()); + for (object_id, object) in objects { + let path = format!("{path}/{object_id}.ics"); responses.push( CalendarObjectResource { object, + object_id, principal: principal.to_owned(), } .propfind(&path, prop, None, puri, user)?, diff --git a/crates/caldav/src/calendar/methods/report/sync_collection.rs b/crates/caldav/src/calendar/methods/report/sync_collection.rs index 7b70f20..97b6806 100644 --- a/crates/caldav/src/calendar/methods/report/sync_collection.rs +++ b/crates/caldav/src/calendar/methods/report/sync_collection.rs @@ -32,11 +32,12 @@ pub async fn handle_sync_collection( .await?; let mut responses = Vec::new(); - for object in new_objects { - let path = format!("{}/{}.ics", path, object.get_id()); + for (object_id, object) in new_objects { + let path = format!("{}/{}.ics", path, &object_id); responses.push( CalendarObjectResource { object, + object_id, principal: principal.to_owned(), } .propfind(&path, &sync_collection.prop, None, puri, user)?, diff --git a/crates/caldav/src/calendar/service.rs b/crates/caldav/src/calendar/service.rs index ec6384d..2f35acc 100644 --- a/crates/caldav/src/calendar/service.rs +++ b/crates/caldav/src/calendar/service.rs @@ -78,8 +78,9 @@ impl ResourceService for CalendarResourc .get_objects(principal, cal_id) .await? .into_iter() - .map(|object| CalendarObjectResource { + .map(|(object_id, object)| CalendarObjectResource { object, + object_id, principal: principal.to_owned(), }) .collect()) @@ -91,7 +92,7 @@ impl ResourceService for CalendarResourc file: Self::Resource, ) -> Result<(), Self::Error> { self.cal_store - .update_calendar(principal.to_owned(), cal_id.to_owned(), file.into()) + .update_calendar(principal, cal_id, file.into()) .await?; Ok(()) } diff --git a/crates/caldav/src/calendar_object/methods.rs b/crates/caldav/src/calendar_object/methods.rs index 7e475ac..2d7fc3f 100644 --- a/crates/caldav/src/calendar_object/methods.rs +++ b/crates/caldav/src/calendar_object/methods.rs @@ -94,13 +94,13 @@ pub async fn put_event( true }; - let Ok(object) = CalendarObject::from_ics(body.clone(), Some(object_id)) else { + let Ok(object) = CalendarObject::from_ics(body.clone()) else { debug!("invalid calendar data:\n{body}"); return Err(Error::PreconditionFailed(Precondition::ValidCalendarData)); }; let etag = object.get_etag(); cal_store - .put_object(principal, calendar_id, object, overwrite) + .put_object(&principal, &calendar_id, &object_id, object, overwrite) .await?; let mut headers = HeaderMap::new(); diff --git a/crates/caldav/src/calendar_object/resource.rs b/crates/caldav/src/calendar_object/resource.rs index 995b537..61c1571 100644 --- a/crates/caldav/src/calendar_object/resource.rs +++ b/crates/caldav/src/calendar_object/resource.rs @@ -1,5 +1,3 @@ -use std::borrow::Cow; - use super::prop::{ CalendarData, CalendarObjectProp, CalendarObjectPropName, CalendarObjectPropWrapper, CalendarObjectPropWrapperName, @@ -14,16 +12,18 @@ use rustical_dav::{ }; use rustical_ical::CalendarObject; use rustical_store::auth::Principal; +use std::borrow::Cow; #[derive(Clone, From, Into)] pub struct CalendarObjectResource { pub object: CalendarObject, + pub object_id: String, pub principal: String, } impl ResourceName for CalendarObjectResource { fn get_name(&self) -> Cow<'_, str> { - Cow::from(format!("{}.ics", self.object.get_id())) + Cow::from(format!("{}.ics", self.object_id)) } } diff --git a/crates/caldav/src/calendar_object/service.rs b/crates/caldav/src/calendar_object/service.rs index 8a63e12..97f1516 100644 --- a/crates/caldav/src/calendar_object/service.rs +++ b/crates/caldav/src/calendar_object/service.rs @@ -66,6 +66,7 @@ impl ResourceService for CalendarObjectResourceService { .await?; Ok(CalendarObjectResource { object, + object_id: object_id.to_owned(), principal: principal.to_owned(), }) } diff --git a/crates/ical/src/calendar_object.rs b/crates/ical/src/calendar_object.rs index 59bea86..4ddaa19 100644 --- a/crates/ical/src/calendar_object.rs +++ b/crates/ical/src/calendar_object.rs @@ -62,13 +62,12 @@ impl rustical_xml::ValueDeserialize for CalendarObjectType { #[derive(Debug, Clone)] pub struct CalendarObject { - id: String, inner: IcalCalendarObject, ics: String, } impl CalendarObject { - pub fn from_ics(ics: String, id: Option) -> Result { + pub fn from_ics(ics: String) -> Result { let mut parser: ComponentParser<_, IcalCalendarObject> = ComponentParser::new(ics.as_bytes()); let inner = parser.next().ok_or(Error::MissingCalendar)??; @@ -78,11 +77,7 @@ impl CalendarObject { )); } - Ok(Self { - id: id.unwrap_or_else(|| inner.get_uid().to_owned()), - inner, - ics, - }) + Ok(Self { inner, ics }) } #[must_use] @@ -95,11 +90,6 @@ impl CalendarObject { self.inner.get_uid() } - #[must_use] - pub fn get_id(&self) -> &str { - &self.id - } - #[must_use] pub fn get_etag(&self) -> String { let mut hasher = Sha256::new(); diff --git a/crates/ical/tests/test_cal_object.rs b/crates/ical/tests/test_cal_object.rs index 50b5a9f..392affd 100644 --- a/crates/ical/tests/test_cal_object.rs +++ b/crates/ical/tests/test_cal_object.rs @@ -25,6 +25,6 @@ END:VCALENDAR #[test] fn parse_calendar_object() { - let object = CalendarObject::from_ics(MULTI_VEVENT.to_string(), None).unwrap(); + let object = CalendarObject::from_ics(MULTI_VEVENT.to_string()).unwrap(); object.get_inner().expand_recurrence(None, None); } diff --git a/crates/store/src/calendar_store.rs b/crates/store/src/calendar_store.rs index 0c51909..ac9b311 100644 --- a/crates/store/src/calendar_store.rs +++ b/crates/store/src/calendar_store.rs @@ -22,8 +22,8 @@ pub trait CalendarStore: Send + Sync + 'static { async fn update_calendar( &self, - principal: String, - id: String, + principal: &str, + id: &str, calendar: Calendar, ) -> Result<(), Error>; async fn insert_calendar(&self, calendar: Calendar) -> Result<(), Error>; @@ -46,7 +46,7 @@ pub trait CalendarStore: Send + Sync + 'static { principal: &str, cal_id: &str, synctoken: i64, - ) -> Result<(Vec, Vec, i64), Error>; + ) -> Result<(Vec<(String, CalendarObject)>, Vec, i64), Error>; /// Since the rules are rather complex this function /// is only meant to do some prefiltering @@ -55,7 +55,7 @@ pub trait CalendarStore: Send + Sync + 'static { principal: &str, cal_id: &str, _query: CalendarQuery, - ) -> Result, Error> { + ) -> Result, Error> { self.get_objects(principal, cal_id).await } @@ -69,7 +69,7 @@ pub trait CalendarStore: Send + Sync + 'static { &self, principal: &str, cal_id: &str, - ) -> Result, Error>; + ) -> Result, Error>; async fn get_object( &self, principal: &str, @@ -79,20 +79,26 @@ pub trait CalendarStore: Send + Sync + 'static { ) -> Result; async fn put_objects( &self, - principal: String, - cal_id: String, - objects: Vec, + principal: &str, + cal_id: &str, + objects: Vec<(String, CalendarObject)>, overwrite: bool, ) -> Result<(), Error>; async fn put_object( &self, - principal: String, - cal_id: String, + principal: &str, + cal_id: &str, + object_id: &str, object: CalendarObject, overwrite: bool, ) -> Result<(), Error> { - self.put_objects(principal, cal_id, vec![object], overwrite) - .await + self.put_objects( + principal, + cal_id, + vec![(object_id.to_owned(), object)], + overwrite, + ) + .await } async fn delete_object( &self, diff --git a/crates/store/src/combined_calendar_store.rs b/crates/store/src/combined_calendar_store.rs index a83b7e4..e987918 100644 --- a/crates/store/src/combined_calendar_store.rs +++ b/crates/store/src/combined_calendar_store.rs @@ -1,5 +1,6 @@ -use crate::CalendarStore; +use crate::{Calendar, CalendarStore, calendar_store::CalendarQuery}; use async_trait::async_trait; +use rustical_ical::CalendarObject; use std::{collections::HashMap, sync::Arc}; pub trait PrefixedCalendarStore: CalendarStore { @@ -51,11 +52,11 @@ impl CalendarStore for CombinedCalendarStore { async fn update_calendar( &self, - principal: String, - id: String, - calendar: crate::Calendar, + principal: &str, + id: &str, + calendar: Calendar, ) -> Result<(), crate::Error> { - self.store_for_id(&id) + self.store_for_id(id) .update_calendar(principal, id, calendar) .await } @@ -88,7 +89,7 @@ impl CalendarStore for CombinedCalendarStore { principal: &str, cal_id: &str, synctoken: i64, - ) -> Result<(Vec, Vec, i64), crate::Error> { + ) -> Result<(Vec<(String, CalendarObject)>, Vec, i64), crate::Error> { self.store_for_id(cal_id) .sync_changes(principal, cal_id, synctoken) .await @@ -97,7 +98,7 @@ impl CalendarStore for CombinedCalendarStore { async fn import_calendar( &self, calendar: crate::Calendar, - objects: Vec, + objects: Vec, merge_existing: bool, ) -> Result<(), crate::Error> { self.store_for_id(&calendar.id) @@ -109,8 +110,8 @@ impl CalendarStore for CombinedCalendarStore { &self, principal: &str, cal_id: &str, - query: crate::calendar_store::CalendarQuery, - ) -> Result, crate::Error> { + query: CalendarQuery, + ) -> Result, crate::Error> { self.store_for_id(cal_id) .calendar_query(principal, cal_id, query) .await @@ -141,7 +142,7 @@ impl CalendarStore for CombinedCalendarStore { &self, principal: &str, cal_id: &str, - ) -> Result, crate::Error> { + ) -> Result, crate::Error> { self.store_for_id(cal_id) .get_objects(principal, cal_id) .await @@ -149,12 +150,12 @@ impl CalendarStore for CombinedCalendarStore { async fn put_objects( &self, - principal: String, - cal_id: String, - objects: Vec, + principal: &str, + cal_id: &str, + objects: Vec<(String, CalendarObject)>, overwrite: bool, ) -> Result<(), crate::Error> { - self.store_for_id(&cal_id) + self.store_for_id(cal_id) .put_objects(principal, cal_id, objects, overwrite) .await } diff --git a/crates/store_sqlite/benches/insert_calendar_object.rs b/crates/store_sqlite/benches/insert_calendar_object.rs index 02f0d42..4330720 100644 --- a/crates/store_sqlite/benches/insert_calendar_object.rs +++ b/crates/store_sqlite/benches/insert_calendar_object.rs @@ -34,16 +34,19 @@ fn benchmark(c: &mut Criterion) { cal_store }); - let object = CalendarObject::from_ics(include_str!("ical_event.ics").to_owned(), None).unwrap(); + let row = ( + "asd".to_owned(), + CalendarObject::from_ics(include_str!("ical_event.ics").to_owned()).unwrap(), + ); let batch_size = 1000; - let objects: Vec<_> = std::iter::repeat_n(object.clone(), batch_size).collect(); + let objects: Vec<_> = std::iter::repeat_n(row.clone(), batch_size).collect(); c.bench_function("put_batch", |b| { b.to_async(&runtime).iter(async || { // yeet cal_store - .put_objects("user".to_owned(), "okwow".to_owned(), objects.clone(), true) + .put_objects("user", "okwow", objects.clone(), true) .await .unwrap(); }); @@ -54,7 +57,7 @@ fn benchmark(c: &mut Criterion) { // yeet for _ in 0..1000 { cal_store - .put_object("user".to_owned(), "okwow".to_owned(), object.clone(), true) + .put_object("user", "okwow", &row.0, row.1.clone(), true) .await .unwrap(); } diff --git a/crates/store_sqlite/src/addressbook_store/birthday_calendar.rs b/crates/store_sqlite/src/addressbook_store/birthday_calendar.rs index a79d50b..8f49cf3 100644 --- a/crates/store_sqlite/src/addressbook_store/birthday_calendar.rs +++ b/crates/store_sqlite/src/addressbook_store/birthday_calendar.rs @@ -1,7 +1,7 @@ use crate::addressbook_store::SqliteAddressbookStore; use async_trait::async_trait; use chrono::NaiveDateTime; -use rustical_ical::{AddressObject, CalendarObject, CalendarObjectType}; +use rustical_ical::{CalendarObject, CalendarObjectType}; use rustical_store::{ Addressbook, AddressbookStore, Calendar, CalendarMetadata, CalendarStore, CollectionMetadata, Error, PrefixedCalendarStore, @@ -268,10 +268,11 @@ impl CalendarStore for SqliteAddressbookStore { #[instrument] async fn update_calendar( &self, - principal: String, - id: String, + principal: &str, + id: &str, mut calendar: Calendar, ) -> Result<(), Error> { + assert_eq!(principal, calendar.principal); assert_eq!(id, calendar.id); calendar.id = calendar .id @@ -323,7 +324,7 @@ impl CalendarStore for SqliteAddressbookStore { principal: &str, cal_id: &str, synctoken: i64, - ) -> Result<(Vec, Vec, i64), Error> { + ) -> Result<(Vec<(String, CalendarObject)>, Vec, i64), Error> { let cal_id = cal_id .strip_prefix(BIRTHDAYS_PREFIX) .ok_or(Error::NotFound)?; @@ -356,7 +357,7 @@ impl CalendarStore for SqliteAddressbookStore { &self, principal: &str, cal_id: &str, - ) -> Result, Error> { + ) -> Result, Error> { todo!() // let cal_id = cal_id // .strip_prefix(BIRTHDAYS_PREFIX) @@ -397,9 +398,9 @@ impl CalendarStore for SqliteAddressbookStore { #[instrument] async fn put_objects( &self, - _principal: String, - _cal_id: String, - _objects: Vec, + _principal: &str, + _cal_id: &str, + _objects: Vec<(String, CalendarObject)>, _overwrite: bool, ) -> Result<(), Error> { Err(Error::ReadOnly) diff --git a/crates/store_sqlite/src/calendar_store.rs b/crates/store_sqlite/src/calendar_store.rs index 6ed9e80..c0ee83e 100644 --- a/crates/store_sqlite/src/calendar_store.rs +++ b/crates/store_sqlite/src/calendar_store.rs @@ -21,11 +21,11 @@ struct CalendarObjectRow { uid: String, } -impl TryFrom for CalendarObject { +impl TryFrom for (String, CalendarObject) { type Error = rustical_store::Error; fn try_from(value: CalendarObjectRow) -> Result { - let object = Self::from_ics(value.ics, Some(value.id))?; + let object = CalendarObject::from_ics(value.ics)?; if object.get_uid() != value.uid { return Err(rustical_store::Error::IcalError( rustical_ical::Error::InvalidData(format!( @@ -35,7 +35,7 @@ impl TryFrom for CalendarObject { )), )); } - Ok(object) + Ok((value.id, object)) } } @@ -280,8 +280,8 @@ impl SqliteCalendarStore { async fn _update_calendar<'e, E: Executor<'e, Database = Sqlite>>( executor: E, - principal: String, - id: String, + principal: &str, + id: &str, calendar: Calendar, ) -> Result<(), Error> { let comp_event = calendar.components.contains(&CalendarObjectType::Event); @@ -379,7 +379,7 @@ impl SqliteCalendarStore { executor: E, principal: &str, cal_id: &str, - ) -> Result, Error> { + ) -> Result, Error> { sqlx::query_as!( CalendarObjectRow, "SELECT id, uid, ics FROM calendarobjects WHERE principal = ? AND cal_id = ? AND deleted_at IS NULL", @@ -398,7 +398,7 @@ impl SqliteCalendarStore { principal: &str, cal_id: &str, query: CalendarQuery, - ) -> Result, Error> { + ) -> Result, Error> { // We extend our query interval by one day in each direction since we really don't want to // miss any objects because of timezone differences // I've previously tried NaiveDate::MIN,MAX, but it seems like sqlite cannot handle these @@ -434,7 +434,7 @@ impl SqliteCalendarStore { object_id: &str, show_deleted: bool, ) -> Result { - sqlx::query_as!( + let (row_id, object) = sqlx::query_as!( CalendarObjectRow, "SELECT id, uid, ics FROM calendarobjects WHERE (principal, cal_id, id) = (?, ?, ?) AND ((deleted_at IS NULL) OR ?)", principal, @@ -445,7 +445,9 @@ impl SqliteCalendarStore { .fetch_one(executor) .await .map_err(crate::Error::from)? - .try_into() + .try_into()?; + assert_eq!(object_id, row_id); + Ok(object) } #[instrument] @@ -453,10 +455,11 @@ impl SqliteCalendarStore { executor: E, principal: &str, cal_id: &str, + object_id: &str, object: &CalendarObject, overwrite: bool, ) -> Result<(), Error> { - let (object_id, uid, ics) = (object.get_id(), object.get_uid(), object.get_ics()); + let (uid, ics) = (object.get_uid(), object.get_ics()); let first_occurence = object .get_inner() @@ -562,7 +565,7 @@ impl SqliteCalendarStore { principal: &str, cal_id: &str, synctoken: i64, - ) -> Result<(Vec, Vec, i64), Error> { + ) -> Result<(Vec<(String, CalendarObject)>, Vec, i64), Error> { struct Row { object_id: String, synctoken: i64, @@ -589,7 +592,7 @@ impl SqliteCalendarStore { for Row { object_id, .. } in changes { match Self::_get_object(&mut *conn, principal, cal_id, &object_id, false).await { - Ok(object) => objects.push(object), + Ok(object) => objects.push((object_id, object)), Err(rustical_store::Error::NotFound) => deleted_objects.push(object_id), Err(err) => return Err(err), } @@ -629,8 +632,8 @@ impl CalendarStore for SqliteCalendarStore { #[instrument] async fn update_calendar( &self, - principal: String, - id: String, + principal: &str, + id: &str, calendar: Calendar, ) -> Result<(), Error> { Self::_update_calendar(&self.db, principal, id, calendar).await @@ -698,14 +701,23 @@ impl CalendarStore for SqliteCalendarStore { let mut sync_token = None; for object in objects { - Self::_put_object(&mut *tx, &calendar.principal, &calendar.id, &object, false).await?; + let object_id = object.get_uid(); + Self::_put_object( + &mut *tx, + &calendar.principal, + &calendar.id, + object_id, + &object, + false, + ) + .await?; sync_token = Some( Self::log_object_operation( &mut tx, &calendar.principal, &calendar.id, - object.get_id(), + object_id, ChangeOperation::Add, ) .await?, @@ -731,7 +743,7 @@ impl CalendarStore for SqliteCalendarStore { principal: &str, cal_id: &str, query: CalendarQuery, - ) -> Result, Error> { + ) -> Result, Error> { Self::_calendar_query(&self.db, principal, cal_id, query).await } @@ -762,7 +774,7 @@ impl CalendarStore for SqliteCalendarStore { &self, principal: &str, cal_id: &str, - ) -> Result, Error> { + ) -> Result, Error> { Self::_get_objects(&self.db, principal, cal_id).await } @@ -780,9 +792,9 @@ impl CalendarStore for SqliteCalendarStore { #[instrument] async fn put_objects( &self, - principal: String, - cal_id: String, - objects: Vec, + principal: &str, + cal_id: &str, + objects: Vec<(String, CalendarObject)>, overwrite: bool, ) -> Result<(), Error> { let mut tx = self @@ -798,18 +810,21 @@ impl CalendarStore for SqliteCalendarStore { } let mut sync_token = None; - for object in objects { + for (object_id, object) in objects { sync_token = Some( Self::log_object_operation( &mut tx, &principal, &cal_id, - object.get_id(), + &object_id, ChangeOperation::Add, ) .await?, ); - Self::_put_object(&mut *tx, &principal, &cal_id, &object, overwrite).await?; + Self::_put_object( + &mut *tx, &principal, &cal_id, &object_id, &object, overwrite, + ) + .await?; } tx.commit().await.map_err(crate::Error::from)?; @@ -887,7 +902,7 @@ impl CalendarStore for SqliteCalendarStore { principal: &str, cal_id: &str, synctoken: i64, - ) -> Result<(Vec, Vec, i64), Error> { + ) -> Result<(Vec<(String, CalendarObject)>, Vec, i64), Error> { Self::_sync_changes(&self.db, principal, cal_id, synctoken).await }