Skip to content

group_restrictions not enforced in getPrincipalsByPrefix/getPrincipalByPath: restricted rooms stay visible in Calendar's "Show rooms" dialog #63681

Description

@Rikdekker

⚠️ This issue respects the following points: ⚠️

  • This is a bug, not a question or a configuration issue.
  • This issue is not already reported on GitHub (I've searched it).

Bug description

group_restrictions on a calendar room or resource are enforced in some of AbstractPrincipalBackend's read paths but not in others. As a result a restricted room stays visible to users outside the allowed group in Nextcloud Calendar's "Show rooms" dialog, while the attendee type-ahead correctly hides it.

isAllowedToAccessResource() is called from searchPrincipals() and findByUri(), but not from getPrincipalsByPrefix() or getPrincipalByPath() — those two do not even select the group_restrictions column:

Method Selects group_restrictions Calls isAllowedToAccessResource()
getPrincipalsByPrefix() (L70) no no
getPrincipalByPath() (L121) no no
searchPrincipals() (L204) yes yes
findByUri() (L400) yes yes

Calendar fills the "Show rooms" dialog via fetchRoomAndResourcePrincipals(), which does a PROPFIND on dav/principals/calendar-rooms/ — i.e. straight through getPrincipalsByPrefix().

Only the room's name, email and metadata leak; booking is still rejected server-side. But room names and locations can reveal organisational structure, which is exactly what the restriction is meant to prevent.

Steps to reproduce

  1. Have a room backend providing at least one room (any app implementing IRoomBackend).
  2. Give that room a group_restrictions value, e.g. ["test"], and let the hourly UpdateCalendarResourcesRoomsBackgroundJob write it to oc_calendar_rooms.
  3. Log in as a user who is not in that group.
  4. Create an event in Calendar → ResourcesShow rooms.

Expected behaviour

The restricted room is not listed, consistent with the attendee type-ahead.

Actual behaviour

The room is listed with its name, email and metadata.

Measured directly against the backend on a live NC 34 instance, with two test accounts differing only in group membership:

user            groups     searchPrincipals   getPrincipalsByPrefix
roomtest-in     [test]     1                  1
roomtest-uit    []         0                  1     <-- should be 0

Setting the restriction back to [] makes both users see the room again through both paths, which confirms the restriction itself is stored and evaluated correctly — one of the two read paths simply skips the check.

Note for whoever picks this up

AbstractPrincipalBackendTestCase::testGetPrincipalsByPrefix() currently asserts that all six fixtures are returned, including res5 (["foo", "bar"]) and res6 (["group1", "bar"]), and it does not mock a user session. So the present behaviour is pinned by a test — fixing this means deciding that the test encodes a bug rather than an intent, which felt like a call for a maintainer rather than something to settle in a drive-by PR.

There is also a question I could not answer from the outside: searchPrincipals() and findByUri() both bail out when there is no session (return [] / return null), but getPrincipalsByPrefix() has no such guard, and the backend is used both by the principal collection and by CalendarRoot in RootCollection.php. If some path reaches it without a session, adding a filter there would hide every room instead of the restricted ones — a worse regression than the bug.

Happy to prepare a PR once you indicate the preferred direction (filter in the backend vs. filter in the Calendar dialog).

Nextcloud Server version

34

Operating system

Other

PHP engine version

PHP 8.4

Web server

Apache (supported)

Database engine version

PostgreSQL

Is this bug present after an update or on a fresh install?

Updated to a major version (ex. 32.0.9 to 33.0.4)

Are you using the Nextcloud Server Encryption module?

Encryption is Disabled

Are you using an external user-backend, if yes which one?

  • LDAP/ Active Directory
  • SSO - SAML
  • Other

Server configuration detail

Calendar app 6.5.4. Room provided by a third-party IRoomBackend implementation; the same code path applies to any room backend.

Nextcloud Signing status

No response

Nextcloud Logs

No response

Additional info

Related: the same dialog also renders the literal string undefined inside busy blocks — that one is a Calendar-side issue and is being fixed separately in nextcloud/calendar#8780.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    To triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions