Skip to content

fix(dav): read a cached subscription's own changes in sync-collection - #66045

Open
SelfRef wants to merge 1 commit into
nextcloud:masterfrom
SelfRef:fix/cached-subscription-sync-changes
Open

SelfRef wants to merge 1 commit into
nextcloud:masterfrom
SelfRef:fix/cached-subscription-sync-changes

Conversation

@SelfRef

@SelfRef SelfRef commented Oct 30, 2026

Copy link
Copy Markdown

Summary

A sync-collection REPORT on a cached webcal subscription (X-NC-CalDAV-Webcal-Caching: On) answers with another calendar's changes. CachedSubscription::getChanges() passes the call on to Sabre\CalDAV\Calendar::getChanges(), which calls getChangesForCalendar() without a calendar type. The backend then uses the default CALENDAR_TYPE_CALENDAR, so it reads oc_calendars and oc_calendarchanges for the regular calendar whose id matches the subscription's id.

What clients see:

  • An initial sync lists none of the subscription's events. The other calendar's object URIs are not children of the subscription, so Sabre drops them.
  • The sync token belongs to that other calendar, so later syncs follow its changes, not the subscription's.
  • With no regular calendar of that id, the backend returns null.

The other methods of CachedSubscription (getChild, getChildren, getMultipleChildren, childExists, calendarQuery) already pass CALENDAR_TYPE_SUBSCRIPTION. getChanges() now does too. The refresh job already records the subscription's changes under that type (addChanges(…, CALENDAR_TYPE_SUBSCRIPTION)), so incremental sync works as it does for regular calendars.

Reproduce

On a fresh instance (allow_local_remote_servers on, so the feed can be served locally):

  1. Create a calendar and add an event to personal (calendar id 1).
  2. Subscribe to an ICS feed with one event (subscription id 1) and run its RefreshWebcalJob.
  3. Send sync-collection with an empty token to the subscription, with X-NC-CalDAV-Webcal-Caching: On.

Before (oc_calendars: personal synctoken 3; oc_calendarsubscriptions: feed synctoken 2):

<d:sync-token>http://sabre.io/ns/sync/3</d:sync-token>

No events, and personal's token.

After:

<d:href>/remote.php/dav/calendars/admin/feed/35674c97-3d50-4ced-abeb-416a09bba6ca.ics</d:href>
<d:status>HTTP/1.1 200 OK</d:status>
<d:sync-token>http://sabre.io/ns/sync/2</d:sync-token>

The feed's event, and the subscription's own token.

Found while adding support for subscriptions to a CalDAV client, which uses sync-collection for every calendar.

TODO

  • Fix
  • Unit test (CachedSubscriptionTest::testGetChanges; it fails without the fix)

Checklist

AI (if applicable)

  • The content of this PR was partly or fully generated using AI

@kesselb

kesselb commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

/backport to stable35

@kesselb

kesselb commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

/backport to stable34

@kesselb

kesselb commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

/backport to stable33

@kesselb

kesselb commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

/backport to stable32

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants