Skip to content

fix: default ACL to full access when remote server omits privilege info#81

Open
stephan1827 wants to merge 1 commit into
nextcloud:mainfrom
stephan1827:fix/default-acl-when-omitted
Open

fix: default ACL to full access when remote server omits privilege info#81
stephan1827 wants to merge 1 commit into
nextcloud:mainfrom
stephan1827:fix/default-acl-when-omitted

Conversation

@stephan1827

Copy link
Copy Markdown
Contributor

Summary

  • Fastmail/Cyrus IMAP does not include {DAV:}acl in PROPFIND responses for calendar and address-book collections.
  • This left permissions as [] in the local DB, causing EventCollection and ContactCollection to return only {DAV:}read from getACL().
  • Sabre's ACL plugin then rejected PROPPATCH requests (rename/recolor a calendar) with 403, which the Nextcloud Calendar widget surfaced as "Kalendername oder -farbe konnte nicht gespeichert werden".
  • Default to {DAV:}all when no ACL information is available from the remote server, since these are the authenticated user's own synchronized collections.

Test plan

  • Connect a Fastmail account and enable a calendar
  • In the Nextcloud Calendar widget, try renaming or changing the color of the synced calendar
  • Verify the operation succeeds without a 403 error

@SebastianKrupinski SebastianKrupinski left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already implemented in a different place

In the remote collection conversion code.

@stephan1827

Copy link
Copy Markdown
Contributor Author

Thanks for the pointer! I'm aware of the elseif branch in RemoteEventsService / RemoteContactsService that tries to infer {DAV:}all when the owner matches the authenticated principal — that was my first thought too.

The problem is that the comparison doesn't hold for Fastmail (and likely other servers): {DAV:}owner in a collection PROPFIND response comes back as an absolute URL (e.g. https://caldav.fastmail.com/dav/principals/user/me@fastmail.com/), while getPrincipalUrl() returns the relative path stored during discovery (e.g. /dav/principals/user/me@fastmail.com/). Strict string equality fails, so the else branch fires and permissions ends up as [].

With empty permissions, getACL() currently falls back to ['{DAV:}read'], which causes Sabre's ACL plugin to reject any PROPPATCH (rename, recolor) with a 403 — the bug this PR addresses.

The cleanest fix for the root cause would be to normalize URLs before comparing in RemoteEventsService/RemoteContactsService, but that would be a separate change and doesn't help the collections already stored with permissions = [] in the database. This PR fixes it at the getACL() layer, which is the point where Sabre actually enforces permissions and where the fallback semantics are clear: if we have no ACL info, treat the calendar as fully accessible to its owner.

Happy to adjust the approach if you'd prefer a URL normalization fix instead, or a combination of both.

@stephan1827 stephan1827 force-pushed the fix/default-acl-when-omitted branch from 86c8c07 to f80b0f7 Compare June 25, 2026 19:00
@SebastianKrupinski

Copy link
Copy Markdown
Collaborator

The problem is that the comparison doesn't hold for Fastmail (and likely other servers): {DAV:}owner in a collection PROPFIND response comes back as an absolute URL (e.g. https://caldav.fastmail.com/dav/principals/user/me@fastmail.com/), while getPrincipalUrl() returns the relative path stored during discovery (e.g. /dav/principals/user/me@fastmail.com/). Strict string equality fails, so the else branch fires and permissions ends up as [].

With empty permissions, getACL() currently falls back to ['{DAV:}read'], which causes Sabre's ACL plugin to reject any PROPPATCH (rename, recolor) with a 403 — the bug this PR addresses.

  • For this we can add "{DAV:}write-properties" this will allow the modification of the color or name

The cleanest fix for the root cause would be to normalize URLs before comparing in RemoteEventsService/RemoteContactsService, but that would be a separate change and doesn't help the collections already stored with permissions = [] in the database. This PR fixes it at the getACL() layer, which is the point where Sabre actually enforces permissions and where the fallback semantics are clear: if we have no ACL info, treat the calendar as fully accessible to its owner.

  • I would rather fix the cause, not do a band-aid fix that breaks later on. and yes it does help the already stored collection, the permissions are refreshed on each harmonization cycle and updated in the database

Fastmail/Cyrus IMAP does not include {DAV:}acl in PROPFIND responses for
calendar and address-book collections. This left permissions as [] in the
local DB, causing EventCollection and ContactCollection to return only
{DAV:}read from getACL(). Sabre's ACL plugin then rejected PROPPATCH
requests with 403, which the Nextcloud Calendar widget surfaced as
"Kalendername oder -farbe konnte nicht gespeichert werden."

Default to {DAV:}all when no ACL information is available, since these are
the authenticated user's own synchronized collections.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@stephan1827 stephan1827 force-pushed the fix/default-acl-when-omitted branch from f80b0f7 to 7bf1175 Compare June 26, 2026 05:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants