From 3338d16a2442c8544d39529ae24be6d387faf22d Mon Sep 17 00:00:00 2001 From: mdecimus Date: Thu, 23 Oct 2025 15:52:16 +0200 Subject: [PATCH] JMAP: Fix ContactCard/CalendarEvent deletion (fixes #2308) --- crates/jmap/src/calendar_event/set.rs | 2 +- crates/jmap/src/contact/set.rs | 2 +- tests/src/jmap/calendar/event.rs | 33 +++++++++++++++++++++++++++ tests/src/jmap/contacts/contact.rs | 31 +++++++++++++++++++++++++ tests/src/jmap/mod.rs | 4 ++-- 5 files changed, 68 insertions(+), 4 deletions(-) diff --git a/crates/jmap/src/calendar_event/set.rs b/crates/jmap/src/calendar_event/set.rs index 843d9935..fd567ae9 100644 --- a/crates/jmap/src/calendar_event/set.rs +++ b/crates/jmap/src/calendar_event/set.rs @@ -430,7 +430,7 @@ impl CalendarEventSet for Server { 'destroy: for id in will_destroy { let document_id = id.document_id(); - if !cache.has_container_id(&document_id) { + if !cache.has_item_id(&document_id) { response.not_destroyed.append(id, SetError::not_found()); continue; } else if id.is_synthetic() { diff --git a/crates/jmap/src/contact/set.rs b/crates/jmap/src/contact/set.rs index 34d8597b..f90ba36d 100644 --- a/crates/jmap/src/contact/set.rs +++ b/crates/jmap/src/contact/set.rs @@ -275,7 +275,7 @@ impl ContactCardSet for Server { 'destroy: for id in will_destroy { let document_id = id.document_id(); - if !cache.has_container_id(&document_id) { + if !cache.has_item_id(&document_id) { response.not_destroyed.append(id, SetError::not_found()); continue; }; diff --git a/tests/src/jmap/calendar/event.rs b/tests/src/jmap/calendar/event.rs index ee82749c..ae3f5416 100644 --- a/tests/src/jmap/calendar/event.rs +++ b/tests/src/jmap/calendar/event.rs @@ -72,6 +72,10 @@ pub async fn test(params: &mut JMAPTest) { JSCalendarProperty::::CalendarIds, [calendar1_id.as_str(), calendar2_id.as_str()].into_jmap_set(), ); + let event_4 = test_jscalendar_4().with_property( + JSCalendarProperty::::CalendarIds, + [calendar1_id.as_str()].into_jmap_set(), + ); let response = account .jmap_create( MethodObject::CalendarEvent, @@ -86,6 +90,7 @@ pub async fn test(params: &mut JMAPTest) { .clone() .with_property(JSCalendarProperty::::UseDefaultAlerts, true), event_3.clone(), + event_4, ], Vec::<(&str, &str)>::new(), ) @@ -93,6 +98,21 @@ pub async fn test(params: &mut JMAPTest) { let event_1_id = response.created(0).id().to_string(); let event_2_id = response.created(1).id().to_string(); let event_3_id = response.created(2).id().to_string(); + let event_4_id = response.created(3).id().to_string(); + + // Destroy tmp event + assert_eq!( + account + .jmap_destroy( + MethodObject::CalendarEvent, + [event_4_id.as_str()], + Vec::<(&str, &str)>::new(), + ) + .await + .destroyed() + .next(), + Some(event_4_id.as_str()) + ); // Validate changes assert_eq!( @@ -771,6 +791,19 @@ pub fn test_jscalendar_3() -> Value { }) } +pub fn test_jscalendar_4() -> Value { + json!({ + "duration": "PT1H", + "@type": "Event", + "description": "Tmp Event", + "updated": "2006-02-06T00:11:02Z", + "timeZone": "US/Eastern", + "start": "2006-01-02T10:00:00", + "title": "Tmp Event", + "uid": "tmp-event@example.com" + }) +} + const TEST_ICAL_1: &str = r#"BEGIN:VCALENDAR BEGIN:VEVENT DTSTART;TZID=US/Eastern:20060102T100000 diff --git a/tests/src/jmap/contacts/contact.rs b/tests/src/jmap/contacts/contact.rs index 233c777f..943affc3 100644 --- a/tests/src/jmap/contacts/contact.rs +++ b/tests/src/jmap/contacts/contact.rs @@ -62,6 +62,10 @@ pub async fn test(params: &mut JMAPTest) { JSContactProperty::::AddressBookIds, [book1_id.as_str(), book2_id.as_str()].into_jmap_set(), ); + let tmp_contact = test_jscontact_4().with_property( + JSContactProperty::::AddressBookIds, + [book2_id.as_str()].into_jmap_set(), + ); let response = account .jmap_create( MethodObject::ContactCard, @@ -69,6 +73,7 @@ pub async fn test(params: &mut JMAPTest) { sarah_contact.clone(), carlos_contact.clone(), acme_contact.clone(), + tmp_contact, ], Vec::<(&str, &str)>::new(), ) @@ -76,6 +81,21 @@ pub async fn test(params: &mut JMAPTest) { let sarah_contact_id = response.created(0).id().to_string(); let carlos_contact_id = response.created(1).id().to_string(); let acme_contact_id = response.created(2).id().to_string(); + let tmp_contact_id = response.created(3).id().to_string(); + + // Destroy tmp contact + assert_eq!( + account + .jmap_destroy( + MethodObject::ContactCard, + [tmp_contact_id.as_str()], + Vec::<(&str, &str)>::new(), + ) + .await + .destroyed() + .next(), + Some(tmp_contact_id.as_str()) + ); // Validate changes assert_eq!( @@ -1171,6 +1191,17 @@ fn test_jscontact_3() -> Value { }) } +fn test_jscontact_4() -> Value { + json!({ + "@type": "Card", + "version": "1.0", + "kind": "individual", + "name": { + "@type": "Name", + "full": "Temporary Contact" + }}) +} + const TEST_VCARD_1: &str = r#"BEGIN:VCARD VERSION:4.0 UID:urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6 diff --git a/tests/src/jmap/mod.rs b/tests/src/jmap/mod.rs index baf81b69..13880af8 100644 --- a/tests/src/jmap/mod.rs +++ b/tests/src/jmap/mod.rs @@ -105,8 +105,8 @@ async fn jmap_tests() { auth::limits::test(&mut params).await; auth::oauth::test(&mut params).await; - auth::quota::test(&mut params).await;*/ - auth::permissions::test(¶ms).await; + auth::quota::test(&mut params).await; + auth::permissions::test(¶ms).await;*/ contacts::addressbook::test(&mut params).await; contacts::contact::test(&mut params).await;