Skip to content

[Bug]: "Limit to groups" picker (2FA enforcement) can never show some groups, and shows raw group ID instead of display name #63760

Description

@NikolausDemmel

Bug description

Settings > Administration > Security > "Two-Factor Authentication" > "Limit to groups" (the "Enforced groups"/"Excluded groups" pickers) uses a group picker (apps/settings/src/components/AdminTwoFactor.vue) with two related problems:

  1. On page load, before typing anything, it calls GET /ocs/v2.php/cloud/groups with an empty search string and limit=20. The backend (OC\Group\Database::getGroups()) orders results ORDER BY gid ASC - the raw internal group ID, not the display name. If 20+ groups exist whose gid sorts alphabetically before the group you're looking for, that group can never appear in the unfiltered dropdown, no matter how far you scroll - the request only ever returns the first 20 rows by gid. This is especially visible for groups created by an app/plugin with a non-human-readable gid prefix (e.g. pluginname_1234), since those gids cluster together and can easily fall entirely outside the first 20 results once an installation has more than a couple dozen groups total.

  2. Even when a group IS found - e.g. by typing part of its display name into the search box (OC\Group\Database::getGroups($search) does correctly match displayname ILIKE %search% too, so search-by-name works) - the result is unusable: Provisioning_API\Controller\GroupsController::getGroups() (the controller behind cloud/groups) returns only $group->getGID() for each match, never the display name. So a group with a friendly display name but an opaque gid shows up in the dropdown as that opaque gid, not its name - there's no way to visually confirm you found the right one.

Both were verified against the actual source and a real deployment, not deployment-specific quirks.

Steps to reproduce

  1. Have more than ~20 total Nextcloud groups, including at least one whose gid differs from its display name (e.g. created via an app using IGroupManager::createGroup($opaqueId) + setDisplayName($friendlyName)), with enough other groups sorting alphabetically before that gid to push it past the first 20 results.
  2. Go to Settings > Administration > Security.
  3. Enable "Enforce two-factor authentication".
  4. Open the "Enforced groups" (or "Excluded groups") dropdown without typing anything.
  5. The group with the opaque gid never appears, no matter how far you scroll - only the first 20 alphabetical-by-gid results are ever loaded.
  6. Type a substring of that group's actual display name into the search box.
  7. The group is now found and can be selected - but it displays as its raw internal ID (e.g. pluginname_1234), not its display name.

Expected behavior

  • The initial (empty-search) group list shouldn't systematically exclude entire classes of groups just because of alphabetical gid ordering + a small fixed cap - e.g. order by display name instead, or drop the artificial 20-item cap for the initial load.
  • Dropdown entries should show the group's display name (already available via cloud/groups/details), not the raw gid.

Where this comes from

  • apps/settings/src/components/AdminTwoFactor.vue: calls searchGroup('') on mount, hitting cloud/groups?search=&limit=20.
  • apps/provisioning_api/lib/Controller/GroupsController.php::getGroups(): returns array_map(fn($group) => $group->getGID(), $groups) - no display name.
  • lib/private/Group/Database.php::getGroups(): ORDER BY gid ASC; the WHERE clause does correctly search both gid and displayname.

#46634 looked related at first glance but is a different, already-fixed bug (the app-permissions group picker losing its checked state on reload) - not this cutoff/display-name problem, so I don't believe this is a duplicate.

Installation method

Community Docker image

Nextcloud Server version

33

Operating system

Linux

PHP engine version

PHP 8.3

Web server

Apache (supported)

Database engine version

MariaDB

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

Unknown - this looks like a long-standing logic issue rather than a recent regression, but I haven't bisected further back than 33.

Are you using the Nextcloud Server Encryption module?

Encryption is Disabled

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status
    To triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions