Fix JMAP: CalendarEvent/get returns null for requested recurrenceRule and recurrenceOverrides properties on synthetic recurrence instances

This commit is contained in:
Maurus Decimus committed 2026-09-13 08:11:36 +01:00
1 parent 998bc8c557
commit 5081e39769
3 files changed
+43 -4

No files matched your search

+1
View File
@@ -31,6 +31,7 @@ If you are upgrading from v0.16.x, replace the binary (or run `docker pull`). If
- JMAP:
- `CalendarEvent/set` stores `useDefaultAlerts` per user, and `CalendarEvent/get` returns `false` when it was never set.
- `CalendarEvent/get` returns `null` for `baseEventId` unless the id is a synthetic recurrence instance.
- `CalendarEvent/get` returns `null` for requested `recurrenceRule` and `recurrenceOverrides` properties on synthetic recurrence instances.
## [0.16.21] - 2026-09-06
+22 -4
View File
@@ -517,10 +517,28 @@ impl CalendarEventGet for Server {
let mut result = if return_all_properties {
jscal.into_object().unwrap()
} else {
Map::from_iter(jscal.into_expanded_object().filter(|(k, _)| {
k.as_property()
.is_some_and(|p| jscal_properties.contains(p))
}))
let is_synthetic = id.is_synthetic();
let is_null_for_synthetic = |property: &JSCalendarProperty<Id>| {
is_synthetic
&& matches!(
property,
JSCalendarProperty::RecurrenceRule
| JSCalendarProperty::RecurrenceOverrides
)
};
let mut result =
Map::from_iter(jscal.into_expanded_object().filter(|(k, _)| {
k.as_property().is_some_and(|p| {
jscal_properties.contains(p) && !is_null_for_synthetic(p)
})
}));
for property in jscal_properties
.iter()
.filter(|property| is_null_for_synthetic(property))
{
result.insert_unchecked(property.clone(), Value::Null);
}
result
};
for property in &jmap_properties {
+20
View File
@@ -105,6 +105,24 @@ pub async fn test(test: &TestServer) {
"2007-03-07T12:00:00"
);
// Synthetic instances return null recurrence properties when requested
for start in [
"2007-03-05T12:00:00",
"2007-03-06T12:00:00",
"2007-03-07T15:00:00",
"2007-03-08T12:00:00",
"2007-03-09T12:00:00",
] {
let instance = instance(&instances, start);
for property in ["recurrenceRule", "recurrenceOverrides"] {
assert_eq!(
instance.get(property),
Some(&Value::Null),
"{property} on {start}: {instance:?}"
);
}
}
// Unknown instances are reported as not found
let unknown_id =
Id::from_parts(1000, Id::from_str(&recurring_id).unwrap().document_id()).to_string();
@@ -912,6 +930,8 @@ async fn expand_instances(account: &Account, calendar_id: &str) -> Vec<Value> {
"title",
"recurrenceId",
"locations",
"recurrenceRule",
"recurrenceOverrides",
],
ids,
)